Abbey Docs
  • 👋Welcome
  • Getting Started
    • Quickstart
    • Step-by-Step Tutorials
      • AWS: Managing Access to Identity Center Groups
      • AWS: Managing Access to Identity Center Permission Sets
      • AWS: Managing Access to IAM Groups
      • Azure AD: Managing Access to Groups
      • Confluent: Managing Access to Kafka ACLs
      • Databricks: Managing Access to Managed Tables in Unity Catalog
      • Databricks: Managing Access to Groups
      • GitHub: Managing Access to Teams
      • Google Cloud: Managing Access to Groups
      • Google Workspace: Managing Access to Google Groups
      • Kafka: Managing Access to ACLs
      • Okta: Managing Access to Groups
      • Postgres: Managing Access to Roles
      • Snowflake: Managing Access to Tables
      • Tabular: Managing Access to Apache Iceberg Roles
      • Tailscale: Managing Access to ACLs
      • Vault: Managing Access to Groups and Policies
      • Integrating Abbey with Terraform Cloud
      • Using Abbey with Atlantis
      • Using Abbey with Spacelift
    • Starter Kits
  • How Abbey Works
    • How Abbey Works
    • Key Concepts
  • Build a Grant Kit
    • Get a Starter Kit
    • Connect a Repo
    • Create a Grant Kit
    • Link Identities
    • Write Access Policies
    • Deploy Your Grant Kit
    • Request Access
    • Approve or Deny Access Requests
  • Use Cases
    • Time-Based Access
      • Expire After a Duration
      • Expire At a Specific Time
    • Approval Workflows
      • Using a Single Approval Step
      • Using Multiple Approval Steps
      • Conditionally Skip Approval Steps
  • Admin
    • User Roles
    • Sign-in and MFA
      • Sign-in Methods
      • Multifactor Authentication (MFA)
      • Enabling Single Sign-On
    • Sources
      • PagerDuty
      • Directory Sync
    • End User Notifications
    • Manage API Tokens
  • Reference
    • Grant Kits
      • Workflows
      • Policies
      • Outputs
    • Referencing Users and Groups
    • Linking Application Identities into Abbey
      • Why do I need to link application identities?
      • How do I Link Application Identities?
      • Supported Application Identity Types and Schemas
      • Application Data Object
    • Access Policies
      • Types of Access Policies
      • Policy Bundles
      • Inline Policies
      • Helper Functions
      • Policy Examples
    • Terms of Service
    • FAQ
      • Troubleshooting
  • Resources
    • Abbey Labs
    • Terraform Registry
    • GitHub
    • System Status
    • Privacy Policy
    • Logo
Powered by GitBook
On this page
  • Polices Spec
  • Access Policies
  • Workflow Policies
  • Configuring Policies For Your Grant Kit
  • Bundles
  • Queries
  • Writing Policies For Your Grant Kit
  • Define Your Logic Using Rego
  • Use Policy Inputs and Enriched Data In Your Logic
  • Policy Evaluation
  • Guardrail Policies
  • Troubleshooting
  1. Reference
  2. Grant Kits

Policies

PreviousWorkflowsNextOutputs

Last updated 1 year ago

Policies, written as (OPA) Policies in , define if someone should get access.

There are two types of Policies:

  1. Access Policies define if someone should get access.

  2. Workflow Policies define if a should be skipped.

Polices Spec

Access Policies

policies = [
    # Access Policies
    {
        bundle = "github://organization/repo/path/to/policies[.tar.gz]"
        # or,
        # query = <<-EOT
        #     package main
        #
        #     ...
        # EOT
    },
    ...   
]

Workflow Policies

workflow = {
    steps = [
        {
            ...
            # Workflow Policies
            skip_if = [
                {
                    # bundle = "..."
                    # query = "..."
                }
            ]
        }
    ]
}

Configuring Policies For Your Grant Kit

Access Policies and Workflow Policies are configured in identical ways.

  • For Access Policies, put your policies in the policies attribute.

  • For Workflow Policies, use the skip_if attribute.

Example Policy Configurations
// Grant Kit with an Access Policy containing a single bundle.
policies = [
    { bundle = "..." }
]

// Grant Kit with an Access Policy containing two bundles.
policies = [
    { bundle = "..." },
    { bundle = "..." },
]

// Grant Kit with an Access Policy containing two bundles and a single policy.
policies = [
    { bundle = "..." },
    { bundle = "..." },
    { query = "..." },
]

// Grant Kit with a single step configured with a Workflow Policy that
// contains a single bundle.
steps = [
    {
        skip_if = [
            { bundle = "..." }
        ]
    }
]

// Grant Kit with two steps, one of which is configured with
// a Workflow Policy that contains a single bundle and the
// other with a Workflow Policy that contain a bundle and a query.
steps = [
    {
        skip_if = [
            { bundle = "..." }
        ]
    },
    {
        skip_if = [
            { bundle = "..." },
            { query = "..." }
        ]
    }
]

Bundles

Bundles are configured using an RFC 3986 URI string for the bundle attribute. This string must point to the location of your bundle in your code repository.

Bundle Spec

github://{organization}/{repository}/path/to/my/bundle[.tar.gz]
Example Bundle Configurations
// Organization: abbeylabs
// Repository: starter-kit-quickstart
// Path to policy bundle: /policies/soc2.tar.gz
//
// This example assumes the soc2.tar.gz was built ahead of time
// using `opa build` and is committed directly to the
// `starter-kit-quickstart` repository.
github://abbeylabs/starter-kit-quickstart/policies/soc2.tar.gz

// Organization: jeffchao (personal, not a GitHub org)
// Repository: my-starter-kit
// Path to policy bundle: /policies/access-policies/hipaa
//
// This example assumes `opa build` was not used and instead prefers
// Abbey to build the bundle instead. Abbey will inspect the `hipaa`
// directory and recursively add all OPA Policies defined with
// the `.rego` extension to the bundle.
github://jeffchao/my-starter-kit/policies/access-policies/hipaa

Currently Abbey supports the github:// scheme. Future schemes such as file://, s3://, and https:// coming soon.

Organizing Bundles

Bundles are great for distributing and reusing policies.

Before building bundles, you should first organize your policies into a directory structure that represents the functionality of the bundle, for example:

❯ tree -a
.
└── policies
    ├── soc2
    │   ├── .manifest
    │   └── soc2-type2
    │       └── example.rego
    └── privacy
        ├── .manifest
        └── privacy-gdpr
            └── example.rego

5 directories, 4 files

The above setup has a policies directory that contains 2 bundles, each with 1 package in them. The bundles contain a .manifest file to define the packages it knows about and is used to avoid package conflicts.

Example .manifest file
{
    "roots": [
        "soc2-type2",
        "privacy-gdpr"
    ]
}

.manifest files are required if you're using OPA bundles. They help avoid package conflicts. As we add more packages, we add their paths to the .manifest file.

Building Bundles

# Build the `soc2-type2` bundle from the `soc2` directory and
# Output the bundle to the `policies/soc2` directory.
opa build -b policies/soc2/soc2-type2 -o policies/soc2/soc2-type2.tar.gz

# Build the `privacy-gdpr` bundle from the `privacy` directory and
# Output the bundle to the `policies/privacy` directory.
opa build -b policies/privacy/privacy-gdpr -o policies/privacy/privacy-gdpr.tar.gz

Queries

A Query represents a single OPA Policy. Queries are typically used for simple one-off rules that don't require the hierarchical rule organization that Bundles provide and aren't intended to be distributed.

Queries must be defined using the main namespace for Abbey to evaluate it.

Example Query Configurations
// Policies defined using `query` must use `package main`.

// This example shows the use of a multiline Heredoc string to define a simple
// Policy that always denies access.
query = <<-EOT
    package main
    
    deny[msg] {
        true
        msg := "always deny access because we're always returning true"
    }
EOT

// This example shows the same policy above, but using a single line string.
// The result is the same but the configuration is harder to read.
query = "package main\n\ndeny[msg] {\n\ttrue\n\tmsg := \"always deny access because we're always returning true\"\n}"

Writing Policies For Your Grant Kit

Writing Policies consists of three steps:

Define Your Logic Using Rego

Access Policies and Workflow Policies are implemented using identical schemas.

Writing Access Policies

Access Policies are written using the following schema:

allow[msg] {
    // Policy logic goes here.
    msg := "return an explanation for why the policy passes"
}
Example Access Policies
// Access Policy that always grants access because the rule will always
// return `true`.
allow[msg] {
    true
    msg := "granting access for non-sensitive resource"
}

// Access Policy that always grants access, but expires after 24 hours.
// Assumes you added `import data.abbey.functions` in your policy.
allow[msg] {
    true; functions.expire_after("24h")
    msg := "always approves access but will eventually expire"
}

// Access Policy that always grants access, but expires at a specific date.
// Assumes you added `import data.abbey.functions` in your policy.
allow[msg] {
    true; functions.expire_at("2023-06-16T07:15:58+00:00"
    msg := "always approves but will expire at a specific time"
}

// Access Policy that grants access to sensitive infrastructure if the
// requester is currently on call.
// `input` comes from infrastructure changes, generally `tfplan.json` via
// your CI's `terraform plan` output.
// `data` is automatically enriched for you by Abbey.
allow[msg] {
    input.resource_changes[_].change.after.database_name == "pii_customers"
    data.system.abbey.pagerduty.isoncall == true
    msg := "for the pii_customers database, grant access only to on-calls. everyone else is denied by default"
}

Automatic Revocation

Once access is granted, Abbey will continuously monitor your policies and revoke access in realtime if they evaluate to false. This may happen if you set an expiration through functions.expire_at or functions.expire_after, a user's attribute has changed (e.g., they went off-call), or infrastructure has changed (e.g., a database was now marked as sensitive). You get this functionality out-of-the-box without having to configure anything extra.

Writing Workflow Policies

Workflow Policies are written using the following schema:

skip[msg] {
    // Policy logic goes here.
    msg := "return an explanation for why this step was skipped"
}
Example Workflow Policies
// Workflow Policy that always skips its step because the `skip` rule
// always evaluates to `true`.
skip[msg] {
    true
    msg := "always skip this step"
}

Use Policy Inputs and Enriched Data In Your Logic

In order to write meaningful policies, you need to be able to compare properties across different systems.

For example, you might want to create a policy that denies access to a sensitive database table by default, unless they're an engineer and active on an on-call rotation. "Sensitive database table", "engineer", and "active on an on-call rotation" are properties from systems such as Terraform Plan, GitHub Teams, and PagerDuty Schedules.

Abbey provides two categories of external data for you when writing your policies:

Policy Inputs

Usage

  • To use Policy Inputs, use the input object in your Rego code.

For example, given the following Terraform Plan output as your input:

{
    "resource_changes": [
        {
            "change": {
                "after": {
                    "role_name": "PII_READONLY"
                }
            }
        }
    ]
}

You can define an Access Policy that automatically denies access to anyone attempting to get access to the PII_READONLY role:

deny[msg] {
    input.resource_changes.change.after.role_name == "PII_READONLY"
    msg := "auto deny anyone attempting to get access to the PII_READONLY role"
}

The input schema is native to Terraform and has many other attributes available for you to use.

Full Example of input
input.json
{
  "format_version": "1.1",
  "terraform_version": "1.4.2",
  "variables": {
    "account": {
      "value": "***"
    },
    "password": "***",
    "username": {
      "value": "***"
    }
  },
  "planned_values": {
    "root_module": {
      "resources": [
        {
          "address": "abbey_grant_kit.role__pii_readonly",
          "mode": "managed",
          "type": "abbey_grant_kit",
          "name": "role__pii_readonly",
          "provider_name": "registry.terraform.io/abbeylabs/abbey",
          "schema_version": 0,
          "values": {
            "description": "Grants access to the PII READONLY Snowflake Role Grant.\n",
            "name": "Abbey Alpha Demo: PII READONLY role grant",
            "output": {
              "append": "resource \"snowflake_role_grants\" \"pii_readonly__{{ .data.system.abbey.secondary_identities.snowflake.username }}\" {\n  role_name = \"PII_READONLY\"\n  users     = [\"{{ .data.system.abbey.secondary_identities.snowflake.username }}\"]\n}\n",
              "location": "github://organization/repo/access.tf",
              "overwrite": null
            },
            "policies": [
              {
                "bundle": null,
                "query": "package main\n\nwarn[msg] {\n  input.resource_changes[_].change.after.database_name == \"DATABASE\"\n  msg := \"be careful granting access to sensitive data\"\n}\n"
              }
            ],
            "workflow": {
              "steps": [
                {
                  "reviewers": {
                    "all_of": null,
                    "one_of": [
                      "replace-me@abbey.so"
                    ]
                  },
                  "skip_if": null
                }
              ]
            }
          },
          "sensitive_values": {
            "output": {},
            "policies": [],
            "workflow": {
              "steps": [
                {
                  "reviewers": {
                    "one_of": [
                      false
                    ]
                  }
                }
              ]
            }
          }
        },
        {
          "address": "snowflake_role_grants.pii_readonly__REPLACE_ME",
          "mode": "managed",
          "type": "snowflake_role_grants",
          "name": "pii_readonly__REPLACE_ME",
          "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
          "schema_version": 0,
          "values": {
            "enable_multiple_grants": false,
            "role_name": "PII_READONLY",
            "roles": null,
            "users": [
              "REPLACE_ME"
            ]
          },
          "sensitive_values": {
            "users": [
              false
            ]
          }
        },
        {
          "address": "snowflake_table_grant.pii_readonly__can_read__pii__table",
          "mode": "managed",
          "type": "snowflake_table_grant",
          "name": "pii_readonly__can_read__pii__table",
          "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
          "schema_version": 0,
          "values": {
            "database_name": "DATABASE",
            "enable_multiple_grants": false,
            "on_future": false,
            "privilege": "SELECT",
            "roles": [
              "PII_READONLY"
            ],
            "schema_name": "SCHEMA",
            "shares": null,
            "table_name": "TABLE",
            "with_grant_option": false
          },
          "sensitive_values": {
            "roles": [
              false
            ]
          }
        }
      ]
    }
  },
  "resource_changes": [
    {
      "address": "abbey_grant_kit.role__pii_readonly",
      "mode": "managed",
      "type": "abbey_grant_kit",
      "name": "role__pii_readonly",
      "provider_name": "registry.terraform.io/abbeylabs/abbey",
      "change": {
        "actions": [
          "create"
        ],
        "before": null,
        "after": {
          "description": "Grants access to the PII READONLY Snowflake Role Grant.\n",
          "name": "Name",
          "output": {
            "append": "resource \"snowflake_role_grants\" \"pii_readonly__{{ .data.system.abbey.secondary_identities.snowflake.username }}\" {\n  role_name = \"PII_READONLY\"\n  users     = [\"{{ .data.system.abbey.secondary_identities.snowflake.username }}\"]\n}\n",
            "location": "github://organization/repo/access.tf",
            "overwrite": null
          },
          "policies": [
            {
              "bundle": null,
              "query": "package main\n\nwarn[msg] {\n  input.resource_changes[_].change.after.database_name == \"DATABASE\"\n  msg := \"be careful granting access to sensitive data\"\n}\n"
            }
          ],
          "workflow": {
            "steps": [
              {
                "reviewers": {
                  "all_of": null,
                  "one_of": [
                    "replace-me@example.com"
                  ]
                },
                "skip_if": null
              }
            ]
          }
        },
        "after_unknown": {
          "id": true,
          "output": {},
          "policies": [],
          "workflow": {
            "steps": [
              {
                "reviewers": {
                  "one_of": [
                    false
                  ]
                }
              }
            ]
          }
        },
        "before_sensitive": false,
        "after_sensitive": {
          "output": {},
          "policies": ,
          "workflow": {
            "steps": [
              {
                "reviewers": {
                  "one_of": [
                    false
                  ]
                }
              }
            ]
          }
        }
      }
    },
    {
      "address": "snowflake_role_grants.pii_readonly__REPLACE_ME",
      "mode": "managed",
      "type": "snowflake_role_grants",
      "name": "pii_readonly__REPLACE_ME",
      "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
      "change": {
        "actions": [
          "create"
        ],
        "before": null,
        "after": {
          "enable_multiple_grants": false,
          "role_name": "PII_READONLY",
          "roles": null,
          "users": [
            "***"
          ]
        },
        "after_unknown": {
          "id": true,
          "users": [
            false
          ]
        },
        "before_sensitive": false,
        "after_sensitive": {
          "users": [
            false
          ]
        }
      }
    },
    {
      "address": "snowflake_table_grant.pii_readonly__can_read__pii__table",
      "mode": "managed",
      "type": "snowflake_table_grant",
      "name": "pii_readonly__can_read__pii__table",
      "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
      "change": {
        "actions": [
          "create"
        ],
        "before": null,
        "after": {
          "database_name": "DATABASE",
          "enable_multiple_grants": false,
          "on_future": false,
          "privilege": "SELECT",
          "roles": [
            "PII_READONLY"
          ],
          "schema_name": "SCHEMA",
          "shares": null,
          "table_name": "TABLE",
          "with_grant_option": false
        },
        "after_unknown": {
          "id": true,
          "roles": [
            false
          ]
        },
        "before_sensitive": false,
        "after_sensitive": {
          "roles": [
            false
          ]
        }
      }
    }
  ],
  "prior_state": {
    "format_version": "1.0",
    "terraform_version": "1.4.2",
    "values": {
      "root_module": {
        "resources": [
          {
            "address": "data.snowflake_database.pii_database",
            "mode": "data",
            "type": "snowflake_database",
            "name": "pii_database",
            "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
            "schema_version": 0,
            "values": {
              "comment": "",
              "created_on": "DATE",
              "id": "DATABASE",
              "is_current": false,
              "is_default": false,
              "name": "DATABASE",
              "options": "",
              "origin": "",
              "owner": "ACCOUNTADMIN",
              "retention_time": 1
            },
            "sensitive_values": {}
          },
          {
            "address": "data.snowflake_role.pii_readonly_role",
            "mode": "data",
            "type": "snowflake_role",
            "name": "pii_readonly_role",
            "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
            "schema_version": 0,
            "values": {
              "comment": "This role allows identities to read tables which contain PII",
              "id": "PII_READONLY",
              "name": "PII_READONLY"
            },
            "sensitive_values": {}
          },
          {
            "address": "data.snowflake_users.my_snowflake_user",
            "mode": "data",
            "type": "snowflake_users",
            "name": "my_snowflake_user",
            "provider_name": "registry.terraform.io/snowflake-labs/snowflake",
            "schema_version": 0,
            "values": {
              "id": "VMB31206.AWS_US_WEST_2",
              "pattern": "REPLACE_ME",
              "users": [
                {
                  "comment": "",
                  "default_namespace": "",
                  "default_role": "ROLE",
                  "default_secondary_roles": [
                    ""
                  ],
                  "default_warehouse": "",
                  "disabled": false,
                  "display_name": "REPLACE_ME",
                  "email": "replace-me-snowflake@abbey.so",
                  "first_name": "Firstname",
                  "has_rsa_public_key": false,
                  "last_name": "Lastname",
                  "login_name": "REPLACE_ME",
                  "name": "REPLACE_ME"
                }
              ]
            },
            "sensitive_values": {
              "users": [
                {
                  "default_secondary_roles": [
                    false
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  },
  "configuration": {
    "provider_config": {
      "abbey": {
        "name": "abbey",
        "full_name": "registry.terraform.io/abbeylabs/abbey",
        "version_constraint": "0.1.2"
      },
      "snowflake": {
        "name": "snowflake",
        "full_name": "registry.terraform.io/snowflake-labs/snowflake",
        "version_constraint": "0.56.5",
        "expressions": {
          "account": {
            "references": [
              "var.account"
            ]
          },
          "password": {
            "references": [
              "var.password"
            ]
          },
          "username": {
            "references": [
              "var.username"
            ]
          }
        }
      }
    },
    "root_module": {
      "resources": [
        {
          "address": "abbey_grant_kit.role__pii_readonly",
          "mode": "managed",
          "type": "abbey_grant_kit",
          "name": "role__pii_readonly",
          "provider_config_key": "abbey",
          "expressions": {
            "description": {
              "constant_value": "Grants access to the PII READONLY Snowflake Role Grant.\n"
            },
            "name": {
              "constant_value": "Name"
            },
            "output": {
              "references": [
                "data.snowflake_role.pii_readonly_role.name",
                "data.snowflake_role.pii_readonly_role"
              ]
            },
            "policies": {
              "references": [
                "data.snowflake_database.pii_database.name",
                "data.snowflake_database.pii_database"
              ]
            },
            "workflow": {
              "constant_value": {
                "steps": [
                  {
                    "reviewers": {
                      "one_of": [
                        "replace-me@abbey.so"
                      ]
                    }
                  }
                ]
              }
            }
          },
          "schema_version": 0
        },
        {
          "address": "snowflake_role_grants.pii_readonly__REPLACE_ME",
          "mode": "managed",
          "type": "snowflake_role_grants",
          "name": "pii_readonly__REPLACE_ME",
          "provider_config_key": "snowflake",
          "expressions": {
            "role_name": {
              "constant_value": "PII_READONLY"
            },
            "users": {
              "constant_value": [
                "REPLACE_ME"
              ]
            }
          },
          "schema_version": 0
        },
        {
          "address": "snowflake_table_grant.pii_readonly__can_read__pii__table",
          "mode": "managed",
          "type": "snowflake_table_grant",
          "name": "pii_readonly__can_read__pii__table",
          "provider_config_key": "snowflake",
          "expressions": {
            "database_name": {
              "references": [
                "data.snowflake_database.pii_database.name",
                "data.snowflake_database.pii_database"
              ]
            },
            "privilege": {
              "constant_value": "SELECT"
            },
            "roles": {
              "references": [
                "data.snowflake_role.pii_readonly_role.name",
                "data.snowflake_role.pii_readonly_role"
              ]
            },
            "schema_name": {
              "constant_value": "SCHEMA"
            },
            "table_name": {
              "constant_value": "TABLE"
            },
            "with_grant_option": {
              "constant_value": false
            }
          },
          "schema_version": 0
        },
        {
          "address": "data.snowflake_database.pii_database",
          "mode": "data",
          "type": "snowflake_database",
          "name": "pii_database",
          "provider_config_key": "snowflake",
          "expressions": {
            "name": {
              "constant_value": "DATABASE"
            }
          },
          "schema_version": 0
        },
        {
          "address": "data.snowflake_role.pii_readonly_role",
          "mode": "data",
          "type": "snowflake_role",
          "name": "pii_readonly_role",
          "provider_config_key": "snowflake",
          "expressions": {
            "name": {
              "constant_value": "PII_READONLY"
            }
          },
          "schema_version": 0
        },
        {
          "address": "data.snowflake_users.my_snowflake_user",
          "mode": "data",
          "type": "snowflake_users",
          "name": "my_snowflake_user",
          "provider_config_key": "snowflake",
          "expressions": {
            "pattern": {
              "constant_value": "REPLACE_ME"
            }
          },
          "schema_version": 0
        }
      ],
      "variables": {
        "account": {
          "description": "Snowflake account",
          "sensitive": true
        },
        "password": {
          "description": "Snowflake password",
          "sensitive": true
        },
        "username": {
          "description": "Snowflake username",
          "sensitive": true
        }
      }
    }
  },
  "relevant_attributes": [
    {
      "resource": "data.snowflake_role.pii_readonly_role",
      "attribute": [
        "name"
      ]
    },
    {
      "resource": "data.snowflake_database.pii_database",
      "attribute": [
        "name"
      ]
    }
  ]
}

input is accessible for both Access Policies and Workflow Policies.

Enriched Data

Enriched Data represents properties from external applications that generally contain information about who someone is. This allows you to write policies based on roles, relationships, or attributes of a person. Abbey automatically enriches data for you, based on identities you or your admin have imported into Abbey. For more information about importing application data, go toLink Identities.

Usage

  • To use Enriched Data, use the data object in your code with the user namespace.

For example, given the following data:

{
    "user": {
        "abbey": {
            "email": "alice@example.com"
        },
        "pagerduty": {
            "isoncall": true
        },
        "github": {
            "username": "Alice"
        }
    }
}

You can define an Access Policy that automatically denies access to someone if they're not on-call:

deny[msg] {
    data.user.pagerduty.isoncall == false
}

The data schema is a component of the Abbey OPA Constraint Framework. As you connect more systems to the Abbey Platform, Abbey will automatically pick them up and enrich the data for you to use in your policies.

Schema of data
data.json
{
    "user": {
        "abbey": {
            "abbey":{
                "email":...
            }
            "snowflake": {
                ...
            },
            "pagerduty": {
                ...
            },
            "aws_iam": {
                ...
            },
            "gcp": {
                ...
            },
            "github": {
                ...
            },
            "okta": {
                ...
            },
            "other-identity": {
                ...
            }
        },
        "system": {
            "abbey": {
                "target": {
                    "grant": {
                        "granted_at": "RFC 3339",
                        "revoked_at": "RFC 3339"
                    }
                }            
            }
        },
    }
}

data is accessible in all Policy types: Access, Revocation, and Workflow.

Policy Evaluation

Abbey evaluates your policies using Abbey's distributed Policy Evaluation Engine. This engine will evaluate your Access, Revocation, and Workflow Policies.

Policy Evaluation has four stages:

  1. Get Policy Input.

    • This is typically the output of your tfplan.json from your terraform plan command.

  2. Fetch and enrich Data.

    • Abbey will automatically fetch and enrich data for any system you have connected.

  3. Evaluate your OPA Policies.

    • Pass in your Policy Input and Enriched Data as parameters.

  4. Output evaluation results and warning details.

    • Output a single boolean value along with a key-value object of evaluation and warning details.

Guardrail Policies

There are two primary use cases:

  1. You're a member of a security or IT team that wants to instill set guardrails around access for the rest of your company. For example, set some sort of non-overridable policy around PII data.

  2. You don't want to write your own policies. Instead, you prefer to leverage existing, battle-tested policies. For example, you can pass in an OPA bundle in your Grant Kit that already has all the necessary Rego rules for compliance for a specific target system.

To create a Guardrail Policy, create a policy or bundle as you would normally and import it into any other policy you want to use in your Grant Kits.

Troubleshooting

A common deployment failure for grant kits is a misconfigured bundle field in the policies block

  • Double check it starts with github://

  • Double check repository and username or org name is correct

    • These fields are case-sensitive so double check any upper/lowercase letters

  • Double check for any extra : or /'s

  • Double check the path to your policies exists

These attributes represent a list of OPA Policies as either a or a .

A Bundle is a native that represents a group of OPA Policies. Bundles are typically either a directory or a gzipped tarball.

Once you have your directory set up, you can build your bundles using the , for example:

Queries are configured by writing native Rego code directly as a string, typically a multiline for better visibility.

Policies are implemented using the Abbey OPA Constraint Framework. This Framework is simplified subset of the that makes working with OPA and Rego easier.

.

.

Policy Inputs represent the output that contains the preview of changes that Terraform plans to make to your infrastructure. This allows you to write policies based on what your infrastructure looks like.

Abbey supports reusable policies that can be distributed using . You can leverage this feature to provide Guardrail Policies. These are policies that can be imported into other policies and cannot be overridden.

OPA Bundle
OPA CLI
Heredoc string
OPA Constraint Framework
Terraform Plan
bundle
query
Define your logic using Rego
Use policy inputs and enriched data in your logic
Policy Inputs
Enriched Data
Bundles
Open Policy Agent
Rego
Workflow Step
Policy Evaluation.
Policy Evaluation