Skip to main content

Announcing Sentinel, HashiCorp’s Policy as Code Framework

Today at HashiConf we released Sentinel. Sentinel is an embedded policy as code framework in the HashiCorp Enterprise products to enable fine-grained, logic-based policy decisions that can be extended to source external information to make decisions.

»Policy as Code

Our suite of infrastructure automation products to provision, secure, connect, and run any infrastructure empowers users to create and manage infrastructure. They are built on a foundation of infrastructure as code to codify and automate infrastructure management at scale. This ability to create, change, and destroy infrastructure at scale comes with risks in large organizations as less experienced users or incorrectly configured automation can make significant mistakes that impact business operations.

Sentinel introduces policy as code as a powerful framework built-in to HashiCorp Enterprise tooling to allow guardrails, business requirements, legal compliance, and more to be actively enforced by running systems in real-time.

Sentinel limits exposure by codifying business and regulatory policies to ensure infrastructure changes are safe. Together infrastructure as code and policy as code empower users to safely automate infrastructure management.

»Sentinel

Most systems today have some degree of access control. You are able to define identities and what they have access to. These ACL systems solve an immediate and necessary problem of locking down a system in very broad strokes. Sentinel is a reusable system for more advanced software policy decisions. Sentinel enables:

Policy as Code. Treat policy like an application — version control, code review, test, and automate. High level logic and traditional programming constructs can determine policy decisions beyond the limited constraints of typical ACL systems. The Sentinel Simulator provides a way to develop and test policies locally, outside of the systems they execute in.

Fine-grained, condition-based policy. Reject actions on any available input rather than coarse-grained read, write, and admin policies. Make policy decisions conditional on request data or sourced from external systems.

Embedded. Sentinel is embedded within HashiCorp products. Once you upgrade your enterprise HashiCorp product to the next version, it will be Sentinel-enabled. This enables policy enforcement in the data path to actively reject violating behavior.

Multiple Enforcement Levels. Advisory, soft-mandatory, and hard-mandatory levels allow policy writers to warn on or reject offending behavior with the appropriate severity. Soft mandatory policies can be overridden with sufficient permissions, but provide an audit trail and non-repudiation.

External Information. Source external information to make holistic policy decisions. Plugins to access external information from custom systems can be written by anyone using the public Sentinel SDK. For example, a HashiCorp Terraform policy can be written to disallow infrastructure change while HashiCorp Consul health checks are failing. This allows Sentinel to be integrated into existing workflows and tools such as change management systems.

Multi-cloud Compatible. Ensure infrastructure changes are within business and regulatory policy on every infrastructure provider. Sentinel uses the same powerful language and workflow with every cloud provider.

»Example Sentinel policies

Sentinel is embedded within Terraform Enterprise, Vault Enterprise, Consul Enterprise, and Nomad Enterprise to add a layer of fine-grained policy enforcement. Sentinel builds upon and naturally extends the existing ACL systems.

»Terraform

Sentinel policies are enforced between a Terraform plan and Terraform apply. This allows users to first show what infrastructure changes will happen with a plan, validate those changes with Sentinel, and then apply the changes if they pass the policy check. The policies have access to the Terraform plan, state, and configuration. Here are some examples:

Example: Do not allow resources to be provisioned without tags.

import "tfplan"

main = rule {
	all tfplan.resources as r {
		r.attr contains "tags" and
		length(r.attr.tags) > 0
	}
}

Example: Limit Google Cloud compute resources to anything below n1-standard-16

import "tfplan"

allowed_machine_types = [
		"n1-standard-1",
		"n1-standard-2",
		"n1-standard-4",
		"n1-standard-8",
]

main = rule {
		all tfplan.resources as r {
				r.attr.machine_type in allowed_machine_types
		}
}

»Vault

Vault exposes Sentinel in two different contexts: Role Governing Policies (RGP) and Endpoint Governing Policies (EGP). RGPs add an additional layer of fine-grained logic to the existing role-based access controls within Vault. EGPs are enforced in front of specified Vault APIs across all roles and add an additional layer of global policy to Vault. The global enforcement of EGPs simplifies regulatory compliance by providing mandatory, auditable policy enforcement. Both provide more control and depth to Vault's security model and policy system.

Example: Ensure that any token generated more than four hours ago cannot be used on any endpoint.

import "time"

main = rule {
		time.now.sub(time.load(token.creation_time)) < 4 * time.hour
}

Example: When logging into LDAP, Ping MFA is required and the request must come from the internal IP address space.

import "sockaddr"

// We expect logins to come only from our private IP range
cidrcheck = rule {
		sockaddr.is_contained(request.connection.remote_addr, "10.20.0.0/16")
}

// Require MFA along with LDAP credentials
ping_valid = rule {
		mfa.ping.is_valid
}

main = rule when request.path is "auth/ldap/login" {
		ping_valid and cidrcheck
}

»Consul

Sentinel policies are enforced on Consul K/V and services modifications. Future versions of Consul will extend Sentinel coverage across more endpoints.

Example: Key/value must be in proper format (such as integer, text, etc.).

required = [
	["port", "\\d+"], // port must be int
	["name", "\\w+"], // name must be one or more words
]

valid_key = func() {
	for required as v {
		if request.kv.key is v[0] {
			return request.kv.value matches v[1]
		}
	}

	// Unknown key
	return false
}

is_kv_request = rule {
	request.path matches "^/kv" and
	request.method is "PUT"
}

main = rule when is_kv_request { valid_key() }

Example: Consul keys can only be updated during business hours

import "time"

main = rule { time.hour > 8 and time.hour < 17 }

»Nomad

Sentinel policies in Nomad are enforced before accepting new jobs or updating existing jobs. Policies can additionally enforce that only trusted artifacts or applications are allowed to run.

Example: Only allow Docker workloads.

allowed_drivers = ["docker"]

main = rule {
		all job.task_groups as tg {
				all tg.tasks as t { t.driver in allowed_drivers }
		}
}

Example: Limit jobs to only 5 GB of memory resources.

func sum_tasks(tg) {
		count = 0
		for tg.tasks as t { count += t.resources.memory else 0 }
		return count
}

func sum_job(job) {
		count = 0
		for job.task_groups as tg {
				if tg.count < 0 {
						fail("unreasonable count value: %d", tg.count)
				}

				count += sumTasks(tg) * tg.count
		}

		return count
}

main = rule { sum_job(job) <= 5000 }

»Conclusion

Sentinel and policy as code are important additions to the HashiCorp product suite. We're excited to see how customers use the flexible language to enforce policies and enable more users to safely provision, secure, connect, and run any infrastructure for any application.

Learn more about Sentinel at https://www.hashicorp.com/sentinel.

Sign up for the latest HashiCorp news

By submitting this form, you acknowledge and agree that HashiCorp will process your personal information in accordance with the Privacy Policy.