Skip to content

Commit

Permalink
feat(ic-http-certification): add certification builder
Browse files Browse the repository at this point in the history
improve underlying cel structures to prevent invalid cel expressions from being created
  • Loading branch information
nathanosdev committed Jan 3, 2024
1 parent c25ea12 commit 457de9d
Show file tree
Hide file tree
Showing 18 changed files with 1,059 additions and 466 deletions.
6 changes: 0 additions & 6 deletions .vscode/settings.json

This file was deleted.

242 changes: 168 additions & 74 deletions packages/ic-http-certification/README.md

Large diffs are not rendered by default.

52 changes: 26 additions & 26 deletions packages/ic-http-certification/src/cel/cel_builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{
CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification,
CelExpression, DefaultCelExpression, DefaultFullCelExpression, DefaultRequestCertification,
DefaultResponseCertification, DefaultResponseOnlyCelExpression,
};
use std::borrow::Cow;

Expand All @@ -10,20 +11,20 @@ pub struct DefaultCelBuilder {}
impl DefaultCelBuilder {
/// Create a CEL expression that skips certification entirely.
pub fn skip_certification<'a>() -> CelExpression<'a> {
CelExpression::DefaultCertification(None)
CelExpression::Default(DefaultCelExpression::Skip)
}

/// Creates a builder for a CEL expression that will only certify a response.
/// Request certification will not be included with this builder.
/// See [DefaultResponseCelBuilder] for more details on this builder's interface.
/// See [DefaultResponseOnlyCelBuilder] for more details on this builder's interface.
/// See [full_certification](DefaultCelBuilder::full_certification()) for a builder that will certify both the request and response.
pub fn response_certification<'a>() -> DefaultResponseCelBuilder<'a> {
pub fn response_only_certification<'a>() -> DefaultResponseOnlyCelBuilder<'a> {
Default::default()
}

/// Creates a builder for a CEL expression that will certify both the request and response.
/// See [DefaultFullCelExpressionBuilder] for more details on this builder's interface.
/// See [response_certification](DefaultCelBuilder::response_certification()) for a builder that will only certify the response.
/// See [response_only_certification](DefaultCelBuilder::response_only_certification()) for a builder that will only certify the response.
pub fn full_certification<'a>() -> DefaultFullCelExpressionBuilder<'a> {
Default::default()
}
Expand All @@ -32,11 +33,11 @@ impl DefaultCelBuilder {
/// A CEL expression builder for creating expressions that will only certify a response.
/// To create an expression that certifies both the request and response, see [DefaultFullCelExpressionBuilder].
#[derive(Debug, Clone, Default)]
pub struct DefaultResponseCelBuilder<'a> {
pub struct DefaultResponseOnlyCelBuilder<'a> {
response_certification: DefaultResponseCertification<'a>,
}

impl<'a> DefaultResponseCelBuilder<'a> {
impl<'a> DefaultResponseOnlyCelBuilder<'a> {
/// Configure the response headers that will be included in certification.
///
/// See [DefaultResponseCertification] for details on how to configure this.
Expand All @@ -51,16 +52,15 @@ impl<'a> DefaultResponseCelBuilder<'a> {
}

/// Build the CEL expression, consuming the builder.
pub fn build(self) -> CelExpression<'a> {
CelExpression::DefaultCertification(Some(DefaultCertification {
request_certification: None,
response_certification: self.response_certification,
}))
pub fn build(self) -> DefaultResponseOnlyCelExpression<'a> {
DefaultResponseOnlyCelExpression {
response: self.response_certification,
}
}
}

/// A CEL expression builder for creating expressions that will certify both the request and response.
/// To create an expression that only certifies the response, see [DefaultResponseCelBuilder].
/// To create an expression that only certifies the response, see [DefaultResponseOnlyCelBuilder].
#[derive(Debug, Clone, Default)]
pub struct DefaultFullCelExpressionBuilder<'a> {
request_headers: &'a [&'a str],
Expand Down Expand Up @@ -103,16 +103,16 @@ impl<'a> DefaultFullCelExpressionBuilder<'a> {
}

/// Build the CEL expression, consuming the builder.
pub fn build(self) -> CelExpression<'a> {
let request_certification = Some(DefaultRequestCertification {
pub fn build(self) -> DefaultFullCelExpression<'a> {
let request_certification = DefaultRequestCertification {
headers: Cow::Borrowed(self.request_headers),
query_parameters: Cow::Borrowed(self.request_query_parameters),
});
};

CelExpression::DefaultCertification(Some(DefaultCertification {
request_certification,
response_certification: self.response_certification,
}))
DefaultFullCelExpression {
request: request_certification,
response: self.response_certification,
}
}
}

Expand All @@ -131,7 +131,7 @@ mod tests {

#[rstest]
fn no_request_response_inclusions(no_request_response_inclusions_cel: String) {
let cel_expr = DefaultCelBuilder::response_certification()
let cel_expr = DefaultCelBuilder::response_only_certification()
.with_response_certification(DefaultResponseCertification::certified_response_headers(
&[
"Cache-Control",
Expand All @@ -149,7 +149,7 @@ mod tests {

#[rstest]
fn no_request_response_exclusions(no_request_response_exclusions_cel: String) {
let cel_expr = DefaultCelBuilder::response_certification()
let cel_expr = DefaultCelBuilder::response_only_certification()
.with_response_certification(DefaultResponseCertification::response_header_exclusions(
&["Date", "Cookie", "Set-Cookie"],
))
Expand All @@ -161,16 +161,16 @@ mod tests {

#[rstest]
fn no_request_empty_response_inclusions(no_request_empty_response_inclusions_cel: String) {
let implicit_cel_expr = DefaultCelBuilder::response_certification()
let implicit_cel_expr = DefaultCelBuilder::response_only_certification()
.build()
.to_string();
let explicit_cel_expr = DefaultCelBuilder::response_certification()
let explicit_cel_expr = DefaultCelBuilder::response_only_certification()
.with_response_certification(DefaultResponseCertification::certified_response_headers(
&[],
))
.build()
.to_string();
let default_cel_expr = DefaultCelBuilder::response_certification()
let default_cel_expr = DefaultCelBuilder::response_only_certification()
.with_response_certification(DefaultResponseCertification::default())
.build()
.to_string();
Expand All @@ -182,7 +182,7 @@ mod tests {

#[rstest]
fn no_request_empty_response_exclusions(no_request_empty_response_exclusions_cel: String) {
let cel_expr = DefaultCelBuilder::response_certification()
let cel_expr = DefaultCelBuilder::response_only_certification()
.with_response_certification(DefaultResponseCertification::response_header_exclusions(
&[],
))
Expand Down
106 changes: 87 additions & 19 deletions packages/ic-http-certification/src/cel/cel_types.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
use super::create_cel_expr;
use super::{
create_cel_expr, create_default_cel_expr, create_default_full_cel_expr,
create_default_response_only_cel_expr,
};
use std::borrow::Cow;

/// A certification CEL expression defintion.
/// Contains an enum variant for each CEL function supported for certification.
/// Currently only one variant is supported: [CelExpression::DefaultCertification].
/// Currently only one variant is supported: [CelExpression::Default].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CelExpression<'a> {
/// A certification CEL expression definition that uses the `default_certification` function.
/// This is currently the only supported function.
///
/// The enum's inner value is an [Option] to allow for opting in, or out of certification.
/// Providing [None] will opt out of certification, while providing [Some] will opt in to certification.
/// See [DefaultCertification] for more details on its available parameters.
DefaultCertification(Option<DefaultCertification<'a>>),
/// See [DefaultCelExpression] for more details on its available parameters.
Default(DefaultCelExpression<'a>),
}

impl<'a> CelExpression<'a> {
Expand All @@ -23,24 +26,83 @@ impl<'a> CelExpression<'a> {
}
}

/// A certification CEL expression definition that uses the `default_certification` function.
/// A certification CEL expression definition that uses the default CEL function.
///
/// [request_certification](DefaultCertification::request_certification) is used for configuring request certification, and
/// [response_certification](DefaultCertification::response_certification) is used for configuring response certification.
/// This enum has three variants:
///
/// - The [Full](DefaultCelExpression::Full) variant includes both the [HTTP request](crate::HttpRequest) and the
/// corresponding [HTTP response](crate::HttpResponse) in certification. See the [DefaultFullCelExpression] struct
/// for details on how to configure this variant.
///
/// - The [ResponseOnly](DefaultCelExpression::ResponseOnly) variant includes the
/// [HTTP response](crate::HttpResponse) in certification, but excludes the corresponding
/// [HTTP request](crate::HttpRequest) from certification. See the [DefaultResponseOnlyCelExpression] struct for
/// details on how to configure this variant.
///
/// - The [Skip](DefaultCelExpression::Skip) variant excludes both the [HTTP request](crate::HttpRequest) and the
/// corresponding [HTTP response](crate::HttpResponse) from certification. This variant does not require any
/// configuration.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DefaultCertification<'a> {
/// Options for configuring certification of a request.
///
/// This is an [Option] to allow for opting in, or out of request certification.
/// See [DefaultRequestCertification] for more details on its available parameters.
pub request_certification: Option<DefaultRequestCertification<'a>>,
pub enum DefaultCelExpression<'a> {
/// Includes both the [HTTP request](crate::HttpRequest) and the corresponding
/// [HTTP response](crate::HttpResponse) in certification.
Full(DefaultFullCelExpression<'a>),

/// Options for configuring certification of a response.
///
/// This is not an [Option] because response certification is the minimum required
/// when certifying a request and response pair.
/// See [DefaultResponseCertification] for more details on its available parameters.
pub response_certification: DefaultResponseCertification<'a>,
/// Includes an [HTTP response](crate::HttpResponse) in certification, but excludes the corresponding
/// [HTTP request](crate::HttpRequest) from certification.
ResponseOnly(DefaultResponseOnlyCelExpression<'a>),

/// Skips certification entirely by excluding both the [HTTP request](crate::HttpRequest) and
/// [HTTP response](crate::HttpResponse) from certification.
Skip,
}

impl<'a> DefaultCelExpression<'a> {
/// Converts a [DefaultCelExpression] object into it's [String] representation.
///
/// Alias of [create_default_cel_expr](create_default_cel_expr()).
pub fn to_string(&self) -> String {
create_default_cel_expr(self)
}
}

/// Options for configuring a CEL expression that includes only the [HTTP response](crate::HttpResponse) in
/// certification and excludes the [HTTP request](crate::HttpRequest) from certification.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DefaultResponseOnlyCelExpression<'a> {
/// Options for configuring response certification for this CEL expression.
/// See [DefaultResponseCertification] for details on how to configure response certification.
pub response: DefaultResponseCertification<'a>,
}

impl<'a> DefaultResponseOnlyCelExpression<'a> {
/// Converts a [DefaultResponseOnlyCelExpression] object into it's [String] representation.
///
/// Alias of [create_default_response_only_cel_expr](create_default_response_only_cel_expr()).
pub fn to_string(&self) -> String {
create_default_response_only_cel_expr(self)
}
}

/// Options for configuring a CEL expression that includes both the [HTTP response](crate::HttpResponse) and
/// [HTTP request](crate::HttpRequest) in certification.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DefaultFullCelExpression<'a> {
/// Options for configuring request certification for this CEL expression.
/// See [DefaultRequestCertification] for details on how to configure request certification.
pub request: DefaultRequestCertification<'a>,

/// Options for configuring response certification for this CEL expression.
/// See [DefaultResponseCertification] for details on how to configure response certification.
pub response: DefaultResponseCertification<'a>,
}

impl<'a> DefaultFullCelExpression<'a> {
/// Converts a [DefaultFullCelExpression] object into it's [String] representation.
/// Alias of [create_default_full_cel_expr](create_default_full_cel_expr()).
pub fn to_string(&self) -> String {
create_default_full_cel_expr(self)
}
}

/// Options for configuring certification of a request.
Expand Down Expand Up @@ -76,12 +138,18 @@ pub enum DefaultResponseCertification<'a> {
///
/// As many or as little headers can be provided as desired.
/// Providing an empty list will result in no response headers being certified.
///
/// See [certified_response_headers](DefaultResponseCertification::certified_response_headers())
/// for a more ergonomic way of doing this.
CertifiedResponseHeaders(Cow<'a, [&'a str]>),

/// A list of response headers to exclude from certification.
///
/// As many or as little headers can be provided as desired.
/// Providing an empty list will result in all response headers being certified.
///
/// See [response_header_exclusions](DefaultResponseCertification::response_header_exclusions())
/// for a more ergonomic way of doing this.
ResponseHeaderExclusions(Cow<'a, [&'a str]>),
}

Expand Down
Loading

0 comments on commit 457de9d

Please sign in to comment.