Policy as Code - Sentinel
HashiCorp Sentinel is a robust policy as code framework. By integrating with HCP Terraform, Sentinel advances infrastructure lifecycle management by enabling the codification and automation of policies, governance, risk management and compliance directly into the process.
Please note that HashiCorp supports Sentinel and Open Policy Agent (OPA) as frameworks for implementing policy as languages. Sentinel or OPA can be used in workflows.
If trying to decide between Sentinel and OPA, we recommend that Sentinel is leveraged because of its maturity and performance characteristics. OPA is recommended when an organization has standardized with OPA and has existing policies that can be brought into the platform. Hybrid situations where sentinel and OPA are jointly used because of the availability of policies in both languages are also encouraged.
Benefits of using Sentinel
- Mitigate risk
- Reducing risks is a key driver for all organizations and especially those with regulatory requirements. Sentinel mitigates risk by automating policy provisions.
- Sentinel actively works to lower the chances of errors and vulnerabilities. By enforcing rules during the planning and execution phases, it acts as a shield against unwanted surprises, ensuring the stability and security of your digital assets.
- Regulatory governance and policy enforcement
- Sentinel ensures that every action aligns with the established organizational policies, regulatory guidelines, and security standards.
- Large scale policy and governance can be managed in a cohesive and concise manner.
- Auditing becomes straightforward, and reduces company time spent by Platform Team staff with auditors.
- Separation of concerns
- Sentinel policies can be defined, managed and applied by platform, compliance, security, or regulatory functions within the business, separate from the application teams deploying infrastructure.
- Unlike other forms of testing and validation, Sentinel policies are not defined in the same codebase as the infrastructure to which the policies apply.
- Project or workspace owners cannot opt out of policies unless given explicit permissions to do so. This is an important enabler for self-service workflows, reducing time-to-value for application teams, while ensuring compliance through policy-as-code.
- Sandboxing
- Policies act as core guardrails. With the increasing complexity of IT systems over time, the need arises to shield them from potentially harmful actions.
- Manual verification is less efficient, prompting the adoption of policies represented as code.
- Codification
- The representation of policy logic as code makes governance clearer, more efficient, consistent, and operationally reproducible.
- Encoding policy logic eliminates reliance on oral traditions and removes risk of misinterpretation.
- Fosters transparency and aids the dissemination of knowledge within the organization.
- Version control
- Version control provides history tracking, diffs, pull requests and other modern collaboration practices.
- It controls policy evolution tracking by implementing demonstrable and auditable change.
- Testing
- Treating policies as code facilitates syntax and behavior validation.
- Sentinel ensures that policies align with expected outcomes, establishing a baseline for policy correctness.
- Automated CI testing is possible through the built-in Sentinel testing framework which reduces TCO for governance, particularly given how complex modern systems have become.
- Automation
- Policy-as-code means automation of policy deployment which is far faster than current manual work and requires fewer humans.
- Automation allows consistency of governance at scale, across the entire infrastructure.
- Reduces manual intervention and mitigates the risk of human error.
Explanation of the policy enforcement workflow
The policy enforcement workflow with HashiCorp Sentinel is a structured process.
Organizations begin by defining policies that articulate the rules governing their infrastructure.
- Customers are advised to render their governance and compliance policies in such a way so that Sentinel policies are then authored to satisfy each.
- Doing so will enable your business to operationalize governance and controls through automated means.
- Typical policies customers start with include governance of maintenance windows protecting software components from adverse change at the wrong time, and enforcement of metadata tagging of cloud resources, and infrastructure-as-code style such as ensuring Terraform module versions are pinned and usable only from your organization's private registry.
The next step is to code the policy using the Sentinel language. See below for more on how code repositories are structured.
Policies are arranged in sets.
Policy sets are scoped to an entire organization or to one or more projects and/or workspaces in your HCP Terraform organization.
Scoping policy sets at the project level allows policy enforcement to be integrated into self-service workflows, which typically create new workspaces on the fly then run them immediately. Any new self-service workspace will inherit the policy sets that are scoped to the parent project.
Sentinel is configured to operate according to the policies in the policy sets that are scoped to the running workspace.
- Depending on the enforcement level (advisory, soft- or hard-mandatory) of the policy, Sentinel will either allow or deny the apply phase of the workspace run.
Key people and their responsibilities
- Sentinel policies should be owned by the Security team, with input taken from other areas of the business who are responsible for regulatory compliance.
- The CCoE/Platform Team typically will understand both Sentinel code, and the means to employ it effectively in production pipelines.
- The CCoE/Platform Team should thus partner with the Security Team to manage ownership and RBAC over Sentinel policy code and its application to ensure sufficient protection of the code repositories and the automation used to employ it.
Sentinel policy authoring best practices
These guidelines will help you create and manage Sentinel policies that are effective, maintainable, and keep your Terraform environments secure. Whether you're new or an experienced Sentinel practitioner, these best practices enhance the effectiveness and maintainability of your policies.
Note
The guidance here does not apply to individual policy library contributions to the public registry which has different requirements and is covered [here](https://developer.hashicorp.com/terraform/registry/policy-libraries/publishing).Repository organization
- Organizing your HashiCorp Terraform Sentinel Policies in a clear and structured manner is crucial for collaboration and maintainability. Your repository structure should resemble the structure shown below.
- policies/: This is where you store main Sentinel policies, organized by environment — the same as for the policy sets themselves. Under each environment subdirectory, the policies are contained with a further test subdirectory under which the test files, generated mock data and Terraform configuration used to generate the mock data are stored. This keeps the test data all together and is a pattern we have found very common in our customer base.
- modules/: Create, organize and store your reusable policy modules here. Each module contains its own policies. Per the illustration above, the common tf import functions, which have been available free from HashiCorp, are stored together with site-specific ones for your business, contained in files with illustrative names so a simple, flat structure can be used.
- docs/: Always fully document your policies, and their tests so that you can come back to them after they have been working for months unchanged. This is the best practice for all code.
Writing policies
- In order to author Sentinel policies for your organization, acquire the IT security policies relevant to the deployment of IT infrastructure, if it exists. The set of policies for your organization should be translated into policy-as-code so that company policy can be asserted automatically with HCP Terraform. A set of policies required for implementation should be derived from company policy.
- If such a policy list does not exist, a general set of controls should be agreed and documented internally to the Platform Team, in terms of public and/or private cloud infrastructure deployment best practices. This set of controls should be designed to be extended over time.
- If a CCoE exists, the policy list should be communicated to the CCoE team for publication on your internal documentation platform as a reference for what developers should expect to be bound by when they develop IaC.
- Next, it is imperative that staff responsible for policy development understand the Sentinel language. The language documentation should be read so that developers are familiar with the available language constructs.
- We strongly recommend that developers attend the HashiCorp Sentinel Academy training, which teaches how to write and implement policies, integrate Sentinel with Terraform, and more. It also includes hands-on labs and real-world examples. Reach out to your HashiCorp Solution Engineer or Customer Success Manager to get access to this resource.
- Sentinel 0.15.0 introduced the concept of modules, which allow you to specify reusable functions that significantly reduce the length of your codebase. More information is in the Extending Sentinel section in the language site. We recommend that developers clone the terraform-sentinel-policies GitHub repository because this provides both a set of prewritten policies that work for a set of public and private cloud providers and also a set of common reusable modules (there called functions), which will allow you to work more efficiently. These policies work with v2 Terraform imports. The content provides an excellent example from which to derive your own policies. Many customers start with these policies, generating a global policy set from a subset of the policies contained in the repository, and extend from there.
- From the policies stored in the repository, read all that apply to your work. We recommend extensive experimentation so policies are well-understood.
- Policy authoring software development life cycle is covered in the section below.
- Document the policies in use.
- Peruse the HashiCorp public registry as it has a set of policies already available. Note that this is a free resource, and we recommend developers should read and understand the policies present on the public registry prior to using them, and only in development to start with, as they may need modifying prior to use in production. The policies in the terraform-sentinel-policies repository is being migrated to the public registry over time.
Enforcement level
The assignment of enforcement levels to policies is recorded in a configuration file named sentinel.hcl
, residing in the same repository as the policies. The example below illustrates how this is applied.
policy "restrict-expensive-workspaces" {
source = "./restrict-expensive-workspaces/restrict-expensive-workspaces.sentinel"
enforcement_level = "hard-mandatory"
}
There are three enforcement levels which may be applied to Sentinel policies. Typically, we advise using advisory in development environments in order to help advise developers where policies may restrict configurations in high environments, but this depends on your organizational requirements.
- Advisory: This enforcement level offers warnings of non-conformance but does not obstruct the Terraform workflow. As such, this level is useful for suggesting improvements or pointing out potential issues without imposing strict requirements.
- Soft Mandatory: Failure of a configuration to conform to a soft mandatory policy causes the Terraform workflow to stop and provides a meaningful output. It lets an organization owner or a user with override privileges proceed with the run in the event of failure.They are suitable for providing guidance and best practices to users without preventing them from proceeding with their Terraform actions.
- Hard Mandatory: The hard mandatory enforcement level imposes strict requirements and prevents non-compliant actions during the Terraform workflow. This enforcement level is critical for enforcing security, compliance, or other essential constraints that must be adhered to without exceptions.
Testing policies
Unit test
- Read the public document on testing Sentinel policies. This section focuses the reader on standardizing your organization's approach to the unit testing of Sentinel policies.
- Use the Sentinel command line utility for testing policy authoring, because it is quicker than iteratively committing change to a policy repository and testing through a Terraform workspace.
- Standardize on HCL instead of JSON for the syntax of Sentinel Configuration files.
- Use this standard structure for testing Sentinel policies, bearing in mind the opinion referred in the linked document above:
- Using a repository which contains a set of policies (for example called policy1, policy2 and policy3), individual policy tests should be run with
name=policy1.sentinel make test
- To test the whole set with this method, running
make tests
will iteratively test all the policies in the repository. - Note that the individual test command is verbose. Standardize your approach by testing your policies individually to start with and then for convenience, run unit tests on the whole set.
- The key differences here are that you:
- Use a local simulator which is faster
- Use a Makefile for convenience and speed
- Use the command line, so integration with CI/CD pipelines is also straightforward.
- We recommend a CI tool to automate policy testing with the following considerations:
- The time it takes for an orchestrator to deploy a runner which clones the policy repository and run unit tests is about the same as it would to commit the changes to a feature branch and get HCP Terraform to run a workspace to test it.
- HashiCorp wrote the Sentinel CLI tool to reduce the time the developer waits for this process to occur, so we recommend keeping as tight a loop as possible for unit testing, and use the CI tool for more complex integration testing as below.
- Mock data used for testing Sentinel policies should be handled in accordance with the public documentation on the subject.
- HashiCorp's upcoming “HVD Terraform Operating Guide — Scale” will cover how to set up scaled policy authoring, including automated mock generation for unit testing.
Integration test
- When you have many policy sets, testing becomes more complex. We recommend use of the strategic CI tool your organization already uses for continuous integration testing.
- Before setting up your Sentinel integrations, you'll need to plan your testing. Come up with test scenarios that combine different policy sets and reflect your unique policies. Especially in regulated industries, make sure you can show how each scenario maps to the specific regulations you must follow. This upfront planning will ensure your Sentinel setup keeps you in compliance.
- Sentinel policy sets are also applicable at the project level. As we recommend the application of projects to app teams, the use of the
tfe_project_policy_set
Terraform Enterprise provider resource should be used to apply policy sets designed at the project/app team level should also be tested in this context. - Use a Platform Team-specific instance of Terraform Enterprise, such as the one the team uses for upgrade testing, or a dedicated Terraform Enterprise instance depending on cost. This keeps the registration of test policy sets away from the production instance(s). Alternatively, use a dedicated HCP Terraform organization.
- Within the test organization, workspaces should be used to run the Terraform code which deploys the test workspaces and projects used for testing, and also the policy set assignments. Typically, these runs will not be subject to Sentinel policies due to the foundational nature of the work.
- Write pipeline automation to run the tests against workspaces in HCP Terraform.
- Use the Terraform Cloud/Enterprise provider to automate the creation and configuration of test workspaces and projects. This should also involve deployment of representative variable sets at both workspace and project levels accordingly, containing organization-specific values and authentication data for workflow identity, so the workspaces run correctly to properly scope success criteria. We also assume that the root module code and child modules called by it are error-free via the use of
terraform test
referred elsewhere in this HVD. - Use the Terraform Cloud/Enterprise provider to automate the assignment of policy sets to the test workspaces and projects. Bear in mind the
tfe_policy_set_parameter
resource which should be used for KV as applicable. - At this point, your test Terraform Enterprise or HCP Terraform instance will have one or more workspaces for running deployment of test objects, and once run, commensurate test workspaces and projects with test policy sets registered.
- The Platform Team should also have prepared Terraform configurations to which the policies you need to test will run against. These configurations will run in the provisioned project/workspace contexts allowing you to test the success criteria of potentially multiple policy sets, again combinations of workspaces and projects accordingly.
- Once the tests complete, the pipeline should remove the workspace(s) and policy set(s). Always aim for a nominal set of zero infrastructural objects and configuration irrespective of success or failure of the test, in order to remove cloud waste. The tests should be documented in the CCoE for developers whose configurations will be subject to the policies applied.
- The aim of this section is to ensure that the deployment of test workspaces and projects works, that the application of policy set changes works as expected, and that the changes in the contained policies operate as expected against relevant Terraform configurations.
Policy Sets
Boundaries
- While general architectural guidance for IaC is to avoid monorepos, for policy-as-code, we see customers most successfully versioning their policy data in a single repository. This also allows for the maintenance of one set of common modules all policies can refer to. The exception to this would be in rare cases where there are multiple, completely separate governance/security teams that are required to manage/isolate their own policy set(s).
- Organize your policy sets by provider, what they target (e.g., security, networking), and which environments they apply to. This flexibility will make it easier to apply them correctly. For example, you might have one AWS networking policy set for all workspaces, a stricter one just for development, and yet another set specifically for Vault infrastructure, regardless of environment:
- AWS - networking - Global
- AWS - networking - Development-only
- AWS - networking - Vault
- AWS - compute
- GCP - networking
- GCP - databases
- Cloud agnostic
- ...
Policy Set structure
- Policy sets should map to the repository structure which stores the policies and provides the opinionated directory layout required by the Sentinel CLI during unit testing.
- The best practices for policy set structure should be followed irrespective of whether you intend to publish your policy set to the public registry.
Sentinel Policy Set management
- The ideal state for your policy-as-code is to have reached a production-ready state where your organization's list of policies has been coded and tested. However, as with all modern software development life cycles, this process should be ongoing. An agile approach will help you manage your policy backlog effectively.
- Recognizing that there will be a backlog with perennial, outstanding tasks as you move constantly to ensure your business remains agile in its marketplace means assigning a product owner, scrum master and development team to the task of managing policy-as-code, or equivalents respectively.
- Policy sets are scoped globally, or to sets of projects and/or workspaces. For segregation of duty, we recommend that you deploy development, test and production infrastructure from separate workspaces, labeled as such. As such, the application of policy sets should be based on:
- Global guardrails. There will always be a significant number of policies which need to be applied to everyone. At a minimum, the following guardrails should be applied globally:
- Restrict allowed providers to those signed-off for use.
- Restrict provisioners from being used; these should be avoided if possible and only considered a last resort.
- All child module calls are pinned to a version; this prevents workspace runs from using unexpected versions of child modules.
- All providers are pinned to a version to protect against changes to the underlying provider.
- All child modules are used from the private registry; this removes risk of developers using git source strings in their child module calls in workspace configurations, and thus possibly unstable branches.
- Minimum allowed Terraform binary versions to reduce the risk of unexpected behavior..
- All variables should have descriptions - this enforces good Terraform code hygiene.
- Projects. Some teams will have different needs from others. Many project teams have specific requirements which can be catered for by policies explicitly scoped at the project level, such as those with exceptions to use specific providers which all other teams are prohibited from using.
- Environments. Your business may allow development workspaces to access certain resource types for experimental purposes which are not allowed in production. As such, you will need to author specific policies that are only applied in development, test and production.
- Exclusions. It may be necessary to maintain a small number of workspaces that are excluded from what would otherwise be global or project-scoped policies. This is possible using Policy set exclusions and the “exclude from” feature.
- Global guardrails. There will always be a significant number of policies which need to be applied to everyone. At a minimum, the following guardrails should be applied globally:
Sentinel SDLC
General points
- We anticipate that your organization's policies, from which your Sentinel code will be derived, must not be made public. However, we recommend that you still follow best practices.
- Over time, you will accumulate a series of repositories named policy-library-X, following the creation, test and application detailed above. Continue to ensure write permissions on these repositories are closely managed and monitored as these repositories provide your business with compliance, and will be audited.
- Ensure to use git best practices including feature branches pull requests, even if only one team has write access. Always ensure another human reads your changes before they are applied to the default branch.
- Ensure that your repositories are documented with a README.md file, and also each policy is correctly documented in the repositories under docs/policies/<policy-name>/md so that your future self can refer back to the code many months after you originally wrote it and quickly get back to adding modifications required. Not doing this will waste more time than it takes to write it.
- Be aware that applying a new policy set, or updating an existing policy set, may block workspace runs that were previously successful, thus affecting application provisioning. Ideally workspace owners should be given the opportunity to review the effect of any proposed policy changes, and adapt their Terraform code if necessary to make it compliant, before the policy change is implemented. There are various strategies to manage this:
- Make use of on-demand policy evaluation to check the effect of any policy changes before applying the new or updated policy set
- Apply an advisory-only version of each proposed new or updated policy set for a trial period before making the change, allowing workspace owners to observe the effect without risking any runs being blocked
Dev-Test-Prod
- Development should proceed based on the internal policy list likely published to the Platform Team by the Security Team. This should be the initial focus in order to move from where you are today to a place of compliance through policy-as-code.
- Your work will result in a series of repositories with version tags.
- Start your work with a version of the Sentinel binary which is used by your Terraform Enterprise or Cloud instance (generally the latest version of Sentinel will be available to HCP Terraform users).
- Continue your development with the same version of Sentinel, even if a new version is released.
- Structure your testing time so that you can unit test all policy repositories with the next version of Sentinel separately, and sign-off that there are no errors.
- Perform a full set of integration tests using the new version of Sentinel prior to raising a change request to apply this new version of Sentinel to the policy sets you have registered in your Terraform Enterprise or HCP Terraform organization.
- Continue processing your development backlog on the new version of Sentinel.
- Unit and integration testing should follow the provisions laid out above, and automation will be needed to allow easy regression testing for the policy estate at scale.
Summary
- Sentinel allows you to automate policy-as-code and thus your governance and compliance work.
- As Sentinel is a policy-as-code framework, it means you can apply standard software management, company SDLC policy and git best practices to the provisioning of guardrails for your development community.
- We recommend that you implement automation as standard where possible, with the exception of mock data generation at this standardization stage.
- Turn your organization's policies and requirements into Sentinel code.
Additional resources for Sentinel