Sentinel Background Graphic

Sentinel

Policy as code framework for HashiCorp Enterprise Products.

What is Sentinel

Sentinel is an embeddable policy as code framework to enable fine-grained, logic-based policy decisions that can be extended to source external information to make decisions.

  • Policy as code

    Treat policy like an application — version control, pull review, and automate tests. Use real programming constructs to determine policy decisions beyond the limited constraints of typical ACL systems.

  • Fine-grained, condition-based policy

    Reject actions on any available input rather than coarse-grained read, write, and admin policies. Make policy decisions based on the condition of other values.

  • Embedded

    Sentinel is embedded to enable policy enforcement in the data path to actively reject violating behavior instead of passively detecting.

  • Multiple enforcement levels

    Advisory, soft-mandatory, and hard-mandatory levels allow policy writers to warn on or reject offending behavior.

  • External information

    Source external information to make holistic policy decisions. For example, Terraform cannot execute while Consul health checks are failing.

  • Multi-cloud compatible

    Ensure infrastructure changes are within business and regulatory policy on every infrastructure provider.

    Sentinel across our Product Suite

    How Sentinel integrates into HashiCorp Enterprise Products

    Policy as Code in Terraform Enterprise

    • Policies are enforced in Terraform Enterprise between the plan and apply.
    • Policies validate information in the Terraform plan, state, and configuration.
    • Do not allow resources to be provisioned without tags
    • Do not allow non-admin users to provision GCP resources above n1-standard-16
    • Do not allow AWS security groups to have egress set to 0.0.0.0
    Code Sample
    import "tfplan"
    
    main = rule {
      all tfplan.resources.aws_instance as _, instances {
        all instances as _, r {
          (length(r.applied.tags) else 0) > 0
        }
      }
    }
    
    import "env"
    import "tfplan"
    
    valid_regions = { "staging": "us-west-1", "production": "us-east-1" }
    
    main = rule {
        all tfplan.config.providers as p {
            p.type is not "aws" or
            p.config.region == valid_regions[env.ENV]
        }
    }
    
    import "tfplan"
    
    main = rule {
      all tfplan.resources.aws_security_group as _, instances {
        all instances as _, sg {
          all sg.applied.egress as egress {
            egress.cidr_blocks not contains "0.0.0.0/0"
          }
        }
      }
    }
    
    Learn More

    Policy as Code in Vault Enterprise

    • Policies are enforced in front of all Vault APIs.
    • Policies extend Vault's ACL system with fine-grained logic.
    • Ensure that modification of critical data can only be performed by authorized sysops with valid MFA
    • Require LDAP logins to come from internal IP space and successfully pass a Ping MFA check
    • Applied to all endpoints in response to a breach, ensure that any token generated more than four hours ago cannot be used
    Code Sample
    import "strings"
    // Scope this policy only to operations that change data within our dangerous
    // area
    pathcheck = rule {
        strings.has_prefix(request.path, "secret/dangerous/") and
            request.operation in ["create", "update", "delete"]
    }
    // Ensure that for this dangerous operation we've passed an Okta MFA check
    oktacheck = rule {
        mfa.okta.is_valid
    }
    // Make sure the caller is a member of the sysops group
    idcheck = rule {
        "sysops" in identity.groups
    }
    main = rule when pathcheck {
        oktacheck and idcheck
    }
    
    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
    }
    
    import "time"
    
    main = rule {
      time.now.sub(time.load(token.creation_time)) < 4 * time.hour
    }
    
    Learn More

    Policy as Code in Nomad Enterprise

    • Policies are enforced before accepting new jobs or updating existing jobs.
    • Policies extend Nomad's ACL system with fine-grained logic.
    • Policies can enforce only trusted artifacts or applications are allowed to run.
    • Only allow Docker workloads
    • Limit jobs to only 5 GB of memory resources
    Code Sample
    allowed_drivers = ["docker"]
    
    main = rule {
        all job.task_groups as tg {
            all tg.tasks as t { t.driver in allowed_drivers }
        }
    }
    
    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 }
    
    Learn More

    Policy as Code in Consul Enterprise

    • Policies are enforced in front Consul's K/V and services APIs.
    • Policies extend Consul's ACL system with fine-grained logic.
    • Key/value must be in proper format (such as integer, text, etc.).
    • Consul keys can only be updated during business hours
    Code Sample
    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() }
    
    import "time"
    
    main = rule { time.hour > 8 and time.hour < 17 }
    
    Learn More

    Policy as code is the next phase of infrastructure automation

    Infrastructure as Code was the first phase, which enables codification and automation for the four main components of infrastructure — provision, secure, connect, and run. Infrastructure as Code empowers more users to create and manage infrastructure; however, that comes with risks as less experienced users could make significant mistakes that impact business operations.

    Policy as code 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 and quickly provision, secure, connect, and run any infrastructure for any application.

    Ready to get started?

    Get in touch or start exploring the documentation.

    close modal

    Request a Demo

    Fill out the form below and we'll reach out to discuss a product demo.

    check mark
    check mark
    check mark
    check mark
    Trusted by
    • Adobe Logo
    • Barclays Logo
    • Cisco Logo
    • Citadel Logo
    • Digital Ocean Logo
    • Hewlett Packard Enterprise Logo
    • SAP Arabia Logo
    • New Relic Logo
    • Pinterest Logo
    • Segment Logo
    • Spaceflight Logo
    • Stripe Logo