Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schnauzer: add aws-config helper #4271

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions sources/api/schnauzer/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,82 @@ pub fn tuf_prefix(
Ok(())
}

/// The `aws-config` helper is used to create an AWS config file
/// with `use_fips_endpoint` value set based on if the variant is FIPS enabled.
///
/// # Fallback
///
/// If this helper runs and `settings.aws.config` is set or `settings.aws.config`
/// is set to a profile other than "default" the helper will return early, leaving the
/// existing `settings.aws.config` setting in place.
///
/// # Example
///
/// The AWS config value is generated via
/// `{{ aws-config settings.aws.config settings.aws.profile }}`
///
/// This would result in something like:
/// ```toml
/// [default]
/// use_fips_endpoint=false
/// ```
///
/// The helper will then base64 encode this content and set as `settings.aws.config`.
pub fn aws_config(
helper: &Helper<'_, '_>,
_: &Handlebars,
_: &Context,
renderctx: &mut RenderContext<'_, '_>,
out: &mut dyn Output,
) -> Result<(), RenderError> {
trace!("Starting aws-config helper");
let template_name = template_name(renderctx);

check_param_count(helper, template_name, 2)?;

let aws_config = get_param(helper, 0)?;
if !aws_config.is_null() {
trace!("settings.aws.config already configured. Exiting aws-config helper early");
return Ok(());
}

// settings.aws.profile may be null. If so, we'll use the "default" profile in constructing
// the AWS config.
let aws_profile = match get_param(helper, 1)? {
Value::Null => "default",
Value::String(s) => s,

_ => {
return Err(RenderError::from(
error::TemplateHelperError::InvalidTemplateValue {
expected: "string",
value: get_param(helper, 1)?.to_owned(),
template: template_name.to_owned(),
},
))
}
};

if aws_profile != "default" {
return Ok(());
}

// construct the base64 encoded AWS config
let aws_config_str = format!(
r#"[default]
use_fips_endpoint={}"#,
fips_enabled()
);
let new_aws_config = base64::engine::general_purpose::STANDARD.encode(&aws_config_str);

out.write(&new_aws_config)
.with_context(|_| error::TemplateWriteSnafu {
template: template_name.to_owned(),
})?;

Ok(())
}

/// Utility function to determine if a variant is in FIPS mode based
/// on /proc/sys/crypto/fips_enabled.
fn fips_enabled() -> bool {
Expand Down Expand Up @@ -2458,6 +2534,63 @@ mod test_tuf_repository {
}
}

#[cfg(test)]
mod test_aws_config_fips_endpoint {
use super::*;
use handlebars::RenderError;
use serde::Serialize;
use serde_json::json;

// A thin wrapper around the handlebars render_template method that includes
// setup and registration of helpers
fn setup_and_render_template<T>(tmpl: &str, data: &T) -> Result<String, RenderError>
where
T: Serialize,
{
let mut aws_config_helper = Handlebars::new();
aws_config_helper.register_helper("aws-config", Box::new(aws_config));

aws_config_helper.render_template(tmpl, data)
}

const METADATA_TEMPLATE: &str = "{{ aws-config settings.aws.config settings.aws.profile }}";

// base64 encoded string:
// [default]
// use_fips_endpoint=false
const EXPECTED_CONFIG_DEFAULT: &str = "W2RlZmF1bHRdCnVzZV9maXBzX2VuZHBvaW50PWZhbHNl";

#[test]
fn config_default() {
let result = setup_and_render_template(
METADATA_TEMPLATE,
&json!({"settings": {"aws": {"profile": "default"}}}),
)
.unwrap();
assert_eq!(result, EXPECTED_CONFIG_DEFAULT);
}

#[test]
fn config_already_exists() {
let result = setup_and_render_template(
METADATA_TEMPLATE,
&json!({"settings": {"aws": {"profile": "default", "config": "abc"}}}),
)
.unwrap();
assert_eq!(result, "");
}

#[test]
fn config_non_default_profile() {
let result = setup_and_render_template(
METADATA_TEMPLATE,
&json!({"settings": {"aws": {"profile": "custom"}}}),
)
.unwrap();
assert_eq!(result, "");
}
}

#[cfg(test)]
mod test_host {
use super::*;
Expand Down
1 change: 1 addition & 0 deletions sources/api/schnauzer/src/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ pub fn build_template_registry() -> Result<handlebars::Handlebars<'static>> {
template_registry.register_helper("join_node_taints", Box::new(helpers::join_node_taints));
template_registry.register_helper("default", Box::new(helpers::default));
template_registry.register_helper("ecr-prefix", Box::new(helpers::ecr_prefix));
template_registry.register_helper("aws-config", Box::new(helpers::aws_config));
template_registry.register_helper("tuf-prefix", Box::new(helpers::tuf_prefix));
template_registry.register_helper("metadata-prefix", Box::new(helpers::metadata_prefix));
template_registry.register_helper("host", Box::new(helpers::host));
Expand Down
1 change: 1 addition & 0 deletions sources/api/schnauzer/src/v2/import/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn all_helpers() -> HashMap<ExtensionName, HashMap<HelperName, Box<dyn HelperDef
hashmap! {
"aws" => hashmap! {
"ecr-prefix" => helper!(handlebars_helpers::ecr_prefix),
"aws-config" => helper!(handlebars_helpers::aws_config),
},

"ecs" => hashmap! {
Expand Down