AWS Cloud Operations & Migrations Blog

Enforce best practices in AWS Systems Manager documents leveraging CFN Guard

Many of us use AWS Systems Manager (SSM) documents to help automate various tasks. As we author documents and move them toward deployment, we’ll likely enforce certain standards and best practices. The AWS CloudFormation team released a general-purpose tool called AWS CloudFormation Guard that we can use to help enforce these best practices. In this post, we will review a simple use case that demonstrates how you can leverage AWS CloudFormation Guard (cfn-guard) when developing and deploying your SSM documents.

As an organization, you may want to enforce various rules on your SSM documents. Depending on the document type, you may want to require a description, require parameters, enforce specific runtimes, and more. This is where cfn-guard can help. Cfn-guard is a general-purpose tool developed by the CloudFormation team for expressing policy-as-code that can be enforced against structured hierarchical data, such as JSON or YAML. Furthermore, AWS has started leveraging cfn-guard themselves to enforce certain standards when publishing SSM documents. Let’s see what we can do with a use case.

Use case example

Annie is an architect responsible for SSM documents. They want to enforce some simple best practices for everyone who authors SSM documents at their company. The rules they want to enforce are outlined as follows and are organized by the SSM document type.

Automation document requirements

  • schemaVersion must be 0.3
  • The assumeRole must be defined
  • Each mainSteps[].description must be defined
  • Only allow python3.8 as the runtime for aws:executeScript actions

Command document requirements

  • schemaVersion must be 2.2
  • Each mainSteps[].inputs.timeoutSeconds must be defined

Generic document requirements

  • The document’s description must be defined
  • Parameter validation must be defined using either allowedPattern or allowedValues
  • Each parameter’s description must be defined

To do this, they define a set of cfn-guard rules and add a step in the pipeline to validate any SSM documents using the defined rules. As the pipeline executes the rules against the SSM documents, the pipeline will be halted if it finds a violation based on the rules.

To get started, Annie downloads and sets up cfn-guard locally, and begins to author and test the following set of rules:

automation-docs.guard

The following file content matches the automation document requirements above.

#schemaVersion must be 0.3
rule schema_version_03 {
  schemaVersion == '0.3'
}

#The assumeRole must be defined
rule assume_role_defined {
  assumeRole !empty
}

#Each mainSteps[].description must be defined
let get_main_steps = mainSteps.*
rule non_empty_step_descriptions {
  %get_main_steps.description !empty
}

#Only allow python3.8 as the runtime for aws:executeScript actions
rule aws_execute_script_runtime {
  when %get_main_steps.action == 'aws:executeScript' {
    %get_main_steps.inputs.Runtime IN ['python3.8']
  }
}

command-docs.guard

The following file content matches the command document requirements above.

#schemaVersion must be 2.2
rule schema_version_10 {
  schemaVersion == '2.2'
}

#Each mainSteps[].inputs.timeoutSeconds must be defined
let get_main_steps = mainSteps.*
rule non_empty_step_timeout {
  %get_main_steps.inputs.timeoutSeconds !empty
}

all-docs.guard

The following file content matches the generic document requirements above.

#description must be defined
rule non_empty_description {
  description !empty
}

#Each parameter’s allowedPattern and allowedValues must be defined
rule parameter_input_validation {
  %get_parameters.allowedPattern !empty or
  %get_parameters.allowedValues !empty
}

#Each parameter’s description must be defined
let get_parameters = parameters.*
rule non_empty_parameter_descriptions {
  %get_parameters.description !empty
}

These files are added to the repo so that validations can be run on SSM documents using the defined cfn-guard rules. Furthermore, tests are added to invoke the cfn-guard CLI for any documents, applying the appropriate set of .guard files.

For instance, let’s assume an SSM document is missing the assumeRole property. When cfn-guard is invoked, it will detect the missing property as an error before the document is created within their AWS account.

Conclusion

We looked at how an organization can use cfn-guard in their processes to enforce standards and best practices for SSM documents. In our example use case, we created three rules that we can either invoke manually or as part of a pipeline to validate that SSM documents meet the defined standards.

To get started using cfn-guard, see the GitHub repo for installation instructions and detailed documentation on how to write your own policies to enforce standards in your SSM documents.

About the author

Adam Spicer

Spicer is a Senior Migration Delivery Consultant for AWS Professional Services. He works with enterprise customers to design and build their cloud infrastructure and automation to accelerate their migration to AWS. He is an avid Seminole fan who loves to be on outside adventures with his family.