Sentinel and Terraform Enterprise: Applying policy as code to infrastructure provisioning
Infrastructure as code with HashiCorp Terraform enables operators to automate provisioning at scale. This comes with risks, as every action can have larger effects. Sentinel policy as code places guardrails to protect users from creating infrastructure changes that fall outside of business and/or regulatory policies. Example constraints might include:
- Not allowing resources to be provisioned without tags
- Not allowing “development” resources to be provisioned in “us-east-1”
- Restricting AWS security group ingress and egress settings by CIDR block
- Not allowing resources to be provisioned outside of business hours
Manual enforcement of these constraints becomes increasingly difficult as the demand for infrastructure provisioning grows. Providing policy as code allows these types of constraints to be codified and automated with Sentinel in Terraform Enterprise.
» Sentinel
Sentinel is HashiCorp's language and framework for embedding policy as code into existing software, enabling fine-grained, logic-based policy decisions. A policy describes under what circumstances certain behaviors are allowed. Sentinel is embedded into the Enterprise version of each of HashiCorp's products including Terraform, Vault, Consul, and Nomad. More details are in the Announcing Sentinel, HashiCorp’s Policy as Code Framework blog.
» Terraform Enterprise and policy as code management
Terraform Enterprise provides a safe workflow for modifying infrastructure by first planning the changes to be made and then applying them if confirmed. Sentinel adds a new step to this process between the plan and apply, where any configured policies will be enforced. Terraform’s plan, configuration, and state data is made available to Sentinel through the tfplan plugin, enabling policy enforcements based on proposed changes to the infrastructure.
» Configuring a policy
Sentinel policies are configured on an organization and are applied to all runs on all workspaces within that organization. This is useful for defining organization-wide policies, such as “Disallow wide-open AWS Security Group Ingress”. Policies will also be configurable directly on workspaces in the future, which is a more suitable place to configure environment-specific policies such as “Development environments cannot have more than two app instances”. Policy code is entered into Terraform Enterprise using the API or the web UI, and will soon support VCS integration. The screenshot below shows entering an organization policy in the web UI:
All policies in Terraform Enterprise have a few configurable attributes:
Policy Name is a simple string used to identify Sentinel policies in Sentinel’s output. This is a detail required for entering policies in the UI or API.
Enforcement mode determines what happens in policy failure scenarios. There are 3 levels to choose from:
- Advisory mode logs warnings, but does not prevent runs from being applied. This is useful for teaching users good habits without preventing actions.
- Soft mandatory mode requires an operator with appropriate permissions to override any policy failures prior to an apply. This is useful for policies like "Users cannot provision outside of business hours", which require a failsafe.
- Hard mandatory mode does not allow any override, and policies must pass prior to an apply. This is useful for policies that enforce regulatory requirements like "All database volumes must be encrypted."
Policy code is where the Sentinel policy is entered. Detailed syntax documentation and examples are available at https://docs.hashicorp.com/sentinel.
» Writing policies in Terraform Enterprise
Sentinel has a pluggable architecture which allows the core language to be extended for each product it is embedded into. The following policy uses the tfplan plugin to check that all AWS security groups do not allow wide-open ingress:
import "tfplan"
disallowed_cidr_blocks = [
"0.0.0.0/0",
]
main = rule {
all tfplan.resources.aws_security_group as _, instances {
all instances as _, sg {
all sg.applied.ingress as ingress {
all disallowed_cidr_blocks as block {
ingress.cidr_blocks not contains block
}
}
}
}
}
As you can see, the “tfplan” plugin is imported, and then used to access the set of Terraform resources we are interested in (in this case, AWS security groups). The found resources are then iterated upon and each resource’s applied value is tested against the disallowed_cidr_blocks. The applied resource represents what the value would be, if the plan were applied. This is useful for checking proposed changes to the infrastructure.
All Terraform resource and module attributes are available for use within policies. Terraform plans also contain the full state and config data, which are both also available through the “tfplan” plugin.
» Policy Enforcement
Sentinel policies in Terraform Enterprise are enforced immediately after a plan completes. This is reflected on the Runs view page. The “Policy Check” section will appear when the plan completes, if policies are present:
The “cidr-blocks” policy has failed in the above example. The plan output above shows that the Terraform configuration contains a security group with ingress allowed from “0.0.0.0/0”, which is expressly denied in our Sentinel policy. In this case, the enforcement mode for the policy was set to soft-mandatory, which allows an organization owner to bypass the policy failure for exceptional circumstances. Overriding the policy puts the run into position to be confirmed and applied, which can be done by a workspace owner or an organization owner. A comment box allows the organization owner to comment on why the policy is being overridden. After overriding a policy, the prompt on the run page will look like this:
In advisory enforcement mode, the failure would look very similar, only no intervention by the organization owner would be necessary to confirm and apply the plan. The “Confirm & Apply” button would appear normally, as shown below:
In hard-mandatory enforcement mode, the policy check would not have any override option for any user. Modifications to the Terraform configuration or Sentinel policy would be required prior to being able to apply changes in this scenario, as shown below:
After adjusting the Terraform configuration to satisfy the policy requirements, the policy check should pass, as shown below:
The workspace owner is able to confirm and apply a run that passes policy checks freely.
» Terraform Enterprise Demo
A demo of Terraform Enterprise Workspace management and Sentinel policy as code is shown below.
» Conclusion
Policy as code management is available as part of Terraform Enterprise. For more information on Terraform Enterprise or to get started with your free trial, visit the Terraform product page.
Sign up for the latest HashiCorp news
More blog posts like this one
5 ways to improve DevEx and security for infrastructure provisioning
Still using manual scripting and provisioning processes? Learn how to accelerate provisioning using five best practices for Infrastructure Lifecycle Management.
Fix the developers vs. security conflict by shifting further left
Resolve the friction between dev and security teams with platform-led workflows that make cloud security seamless and scalable.
HashiCorp at AWS re:Invent: Your blueprint to cloud success
If you’re attending AWS re:Invent in Las Vegas, Dec. 2 - Dec. 6th, visit us for breakout sessions, expert talks, and product demos to learn how to take a unified approach to Infrastructure and Security Lifecycle Management.