Every company has rules that it follows to be in business. These controls derive from both external requirements and internal factors and decisions to manage risk and reward.
Forces that drive these practices include:
A business often establishes a program to oversee all these decisions, under perhaps the Legal or CFO on the organization chart. A substantial part of that program will consider the Security Governance, Risk, and Compliance requirements inherent to the forces listed above.
The GRC Program will gather and review all requirements and use them to develop policies. These policies will reference common standards and business logic to guide business units. From this the IT functions should, under best practices, establish a hardened baseline configuration (or two, depending on the application stack). This ensures adherence to the rules, or policies, that the business needs to stay in compliance and follows their decisions from policies to their business logic. At this point, they share the hardened image with testing incorporated into the software build, so that developers can focus on the differentiating business software and data warehouses that will add value.
This hardened baseline informs the Software Development Lifecycle, or SDLC. And here’s where the goodness in automation begins but how do you get from policy to code? Where’s the start and where’s the end?
Policy as code is a powerful tool we can use to ensure developers follow company policies from the very beginning. In this case, a policy can be any rule, requirement, or process that governs IT operations. For example, a policy could define the requirements to be compliant with a security control and continue to deployment. In incident response, this could be the execution of a set of actions in response to a security event.
To break down this example further, a company may have a Cryptography Policy, to demonstrate compliance with NIST SP 800-53, System and Communications Protections, Control SC-28.
The control from NIST reads like this:
Control Identifier | Control Name | Control Text |
---|---|---|
SC-28 | Protection of Information at Rest | Protect the [Selection (one or more): confidentiality; integrity] of the following information at rest: [Assignment: organization-defined information at rest]. |
A company may write a policy built to demonstrate planned compliance with this control within the business like the below:
3.0 Policy
A. Cryptographic Controls
- this section covers the use of cryptography to encrypt sensitive data:
Cryptographic controls must be utilized for sensitive information classified by our company as {PROTECTED} or {RESTRICTED} including, but not limited to: Personally Identifiable Information (PII), Protected Health Information (PHI), credit card numbers, passwords, intellectual property (define), budget or contract proposals, legal correspondence and research and development information. All encryption mechanisms utilized by our company must be authorized by the appropriate authority.
To simplify the language of the above control, it should read “Encrypt all information at rest.” When broken down to its essential components, policy as code will facilitate a test that compares the current and desired configurations of a resource. When the code does not pass the policy test, the developer will be prevented from creating the non-compliant resources. With sufficient test case design, the developer can even be given a detailed punch list of items to fix.. In an era of shifting left, this is about as far left as you can get!
Now, let’s take a look at one instance of how we can enforce the above policy using policy as code.
A resource built using infrastructure as code likely looks different than what you imagine when thinking of a cloud resource. However, it’s helpful in understanding what the computer is comparing when enforcing policy as code. This example is testing whether AWS EBS, or elastic block storage, is encrypting the files it is storing. AWS EBS is often used as the primary storage for file systems, databases, or for applications that require fine granular updates and access to raw, unformatted, block-level storage. This is the basic code you will see describing an encrypted EBS Volume:
{
"Type": "AWS::EC2::Volume",
"Properties": {
"Size": 100,
"Encrypted": true,
"AvailabilityZone": "us-east-1"
}
}
If we walk through each line and translate it to a more human readable form, it looks like this:
“Type”
→ This is the type of resource that is being created, An EC2 EBS Volume in this case.
“Properties”
→ Begins the block of any properties that we want to include in our EBS Volume.
“Size”
→ EBS volume size of 100gb
“Encrypted”
→ States whether encryption should be on the volume. True for this instance.
“AvailabilityZone”
→ The availability zone to launch the volume in.
With the resource defined, let’s apply policy as code to ensure that this resource will always have proper encryption. The below is a policy that ensures “AWS::EC2::Volume”
has encryption set to “true”.
#Rego
default compliant := false
compliant = true if {
input.Type == "AWS::EC2::Volume"
input.Properties.Encrypted == true
}
default compliant = false
→ The value of compliant defaults to false, this value will update later on if the statements we provide evaluate to true.
compliant = true {
→ This block contains the statements that we want to check. If BOTH of these statements prove to be true, the value of compliant will update to true.
input.Type == “AWS::EC2::Volume”
→ Input is the data that we give the rule to run against, in this example that would be the JSON that we looked at earlier. Within that input, this rule checks that the input Type is “AWS::EC2::Volume”. Which we know to be true.
Input.Properties.Encrypted == true
→ Checks that encrypted is set to true within the input data. This is also true.
This rule would come back as compliant since the Type is set to “AWS::EC2::Volume” and the encryption option is set to “true”. Note that if we were to change the encryption option to false or not include it within the input data, this would return compliant = false.
Utilizing policy as code can ensure proper configuration of all resources before deployment. Think about how helpful that is! When used properly, we can dramatically improve security and compliance. This is only one example rule of many needed to fully enforce the policy mentioned. If I’ve caught your attention and you’re interested in seeing more in depth examples, stay tuned!