# Welcome

## Abbey secures cloud infrastructure by enabling any engineer to automate user access directly in Terraform.&#x20;

***

### How Abbey Works

When it comes to employee access to cloud infrastructure, Workflows allow for definition of how someone should get access (who should approve), and Policies define whether someone should have access (or when access should be revoked).

Abbey is built for the Infrastructure engineer, allowing them to define both Workflows and Policies via the Abbey Terraform Provider. Any team can deploy Abbey quickly utilizing your existing Git repository, CI/CD pipeline, and Terraform orchestration system.

Infrastructure engineers can define how access should be granted and when access should be revoked, reducing their manual workload. End users get frictionless access. Security teams can rest easy knowing that a model of least privilege is being followed. And Compliance teams get an automated audit trail of all changes.

{% embed url="<https://www.youtube.com/watch?v=8aNHkpIFeKM>" fullWidth="false" %}
*Abbey in 3 minutes*
{% endembed %}

***

## Get Started

<table data-view="cards"><thead><tr><th align="center"></th><th align="center"></th><th data-hidden align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden align="center"></th><th data-hidden align="center"></th><th data-hidden></th></tr></thead><tbody><tr><td align="center"><mark style="color:blue;"><strong>Deploy Abbey in 30 Minutes</strong></mark></td><td align="center">Run a full end-to-end demo to see Abbey in action</td><td align="center"></td><td><a href="/pages/mLf1JjBfIXwRkhehH0xL">/pages/mLf1JjBfIXwRkhehH0xL</a></td><td><a href="/files/XcfiwVnJdEpfYogTxyfj">/files/XcfiwVnJdEpfYogTxyfj</a></td><td align="center"></td><td align="center"></td><td></td></tr><tr><td align="center"><p><mark style="color:blue;"><strong>Tutorials</strong></mark></p><p></p><p>Secure access to critical cloud infrastructure</p></td><td align="center"></td><td align="center"> <strong>GCP, AWS, Databricks, Snowflake, and more</strong></td><td><a href="/pages/wZCefzH0vIZb4yf5HpgY">/pages/wZCefzH0vIZb4yf5HpgY</a></td><td><a href="/files/nbWyuBW72e4AP1tcK2db">/files/nbWyuBW72e4AP1tcK2db</a></td><td align="center"><mark style="color:purple;">Tutorials</mark></td><td align="center"><mark style="color:purple;"><strong>Tutorials</strong></mark></td><td></td></tr><tr><td align="center"><mark style="color:blue;"><strong>Explore Key Concepts</strong></mark></td><td align="center">Deep dive into Grant Kits, Workflows, and Policies to understand how we secure access at Abbey</td><td align="center"></td><td><a href="/pages/qSgKApwpNqkMzcCZKCWw">/pages/qSgKApwpNqkMzcCZKCWw</a></td><td><a href="/files/kiHKKTp6RshCpOiSGgnT">/files/kiHKKTp6RshCpOiSGgnT</a></td><td align="center"></td><td align="center">Deep dive into Grant Kits, Workflows, and Policies</td><td></td></tr></tbody></table>

## Top Tutorials

<table data-view="cards"><thead><tr><th align="center"></th><th align="center"></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><mark style="color:blue;"><strong>Databricks</strong></mark></td><td align="center">Managing Access to Managed Tables in Unity Catalog</td><td></td><td><a href="/pages/qUN34liShXLFnVVVcaS8">/pages/qUN34liShXLFnVVVcaS8</a></td></tr><tr><td align="center"><mark style="color:blue;"><strong>Google Cloud</strong></mark></td><td align="center">Managing Access to Groups</td><td></td><td><a href="/pages/WmE4mYi1tQkCJg3YnZ1S">/pages/WmE4mYi1tQkCJg3YnZ1S</a></td></tr><tr><td align="center"><mark style="color:blue;"><strong>AWS</strong></mark></td><td align="center">Secure Access to IAM Groups</td><td></td><td><a href="/pages/UY1WPcScKDaKYDPdkkbZ">/pages/UY1WPcScKDaKYDPdkkbZ</a></td></tr></tbody></table>


# Quickstart

## Introduction

Abbey is an access governance platform that helps you automate access requests and approvals, making it easier for people to get access to resources like AWS S3 or Google Groups. This helps you get access to the resources you need, when you need it.

This tutorial teaches you how to get Abbey up and running, define time-bound access policies, and go through the request/approval flow for getting access to a resource.

## Before you start

1. Create an [Abbey Account](https://accounts.abbey.io/sign-up) - keep this page open, you'll need it for the rest of the tutorial!
2. Log into your [GitHub](https://github.com/) account

{% hint style="info" %}
Abbey works with both GitHub and GitHub Enterprise (Cloud).
{% endhint %}

## Check the Demo Site

Go to [Abbey Demo Site](https://app.abbey.io/demo), login, and you'll see the following screen below

<figure><img src="/files/XopElmHKTcTObzDouyHk" alt=""><figcaption><p>No access to demo site</p></figcaption></figure>

{% hint style="info" %}
:checkered\_flag: That's expected! You don't have access yet. This Quickstart will allow you to configure a Grant Kit for the demo site so you can request and approve access.&#x20;
{% endhint %}

## Step 1: Clone this Repo in Git

{% hint style="info" %}
For this step, you'll be working in

* Github
  {% endhint %}

First, we'll create a new repo in your GitHub account based off our quickstart template repo.

1. Go to our [Quickstart on Gitub](https://github.com/abbeylabs/abbey-starter-kit-quickstart)
2. Click on **Use this template**

   <figure><img src="/files/JhOLUI5mX7o6kHXw3zmw" alt=""><figcaption></figcaption></figure>
3. Click on **Create a new repository** to create the repository
4. Fill out the **Repository name**
5. Click **Create repository**

<figure><img src="/files/9DEoUzs2kEWWScGtMsng" alt=""><figcaption><p>Create new repository from abbey quickstart template repo</p></figcaption></figure>

{% hint style="info" %}
:checkered\_flag: At this point, you should have a repository in your own GitHub account that is based off the Abbey Quickstart Repository
{% endhint %}

## Step 2: Connect Abbey to your Repo

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
* GitHub
  {% endhint %}

To use Abbey for access requests, you'll need to connect Abbey to your GitHub.

### Create a Connection

1. Go to the Abbey App ([app.abbey.io](https://app.abbey.io))
2. Go to the **Settings > Version Control** page and click :heavy\_plus\_sign:**Create a Connection**

   <figure><img src="/files/ikQXnWP2sNVV0DOdZAD3" alt=""><figcaption></figcaption></figure>
3. Choose a name for your connection, then click **Create**. You'll be redirected to GitHub to install Abbey on your GitHub account.

   <figure><img src="/files/gre7tE9xpSXzCjlDI2Wl" alt=""><figcaption></figcaption></figure>
4. In the Github App Permissions screen, choose either **All Repositories** or **Only select repositories** with the repository you created earlier in Step 1 selected

   <figure><img src="/files/yZtgd6W7wwwWkOxQPJNF" alt=""><figcaption></figcaption></figure>

&#x20;5\. Once you click **Install & Authorize**, you'll be redirected back to the Abbey App, and your connection will be created :tada:

<figure><img src="/files/xrneMuko2pVCss0BSIj4" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
:checkered\_flag: Congrats! You've now authorized Abbey to talk with the newly created GitHub repo in your personal account

At this point you should&#x20;

1. Have a connection to GitHub under the Abbey Settings -> Version Control tab
2. Have created a repo into your own GitHub account based off the Abbey Labs Quickstart Repo
3. Have cloned the newly created repo into your own terminal to work with
   {% endhint %}

## Step 3: Configure Permissions for Abbey

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
* Github
  {% endhint %}

### Create an Abbey Token

1. Go to Abbey API Tokens via **Settings -> API Tokens** in the Abbey app
2. Click on the **+ New API Token**
3. Enter a name for your new API token or leave as is
4. Configure the **Expires At** field or leave it blank to have the token never expire
5. Click **Create** to make the new key
6. Copy the key - you'll need this for the next step!

<figure><img src="/files/lVYuTFYeo9fmzNNDj7gE" alt=""><figcaption><p>Create an Abbey API Token</p></figcaption></figure>

### Add your Abbey token to Github

1. Navigate to the repo you created in your own GitHub account
2. Go to the **Settings** tab
3. Select **Secrets and Variables -> Actions** on the left side
4. Create a new **Repository Secret**&#x20;

   <figure><img src="/files/LAUrsKfaa8QxlTPS3lw3" alt=""><figcaption><p>Create a new repository secret</p></figcaption></figure>
5. For the **Name,** enter in `ABBEY_TOKEN`
6. For the **Secret,** enter in the value of the Abbey API token you created in the last step.
   1. :warning: Make sure you don't have any newlines or spaces when copy/pasting this
7. Click **Add Secret** to finish adding the repository secret

<figure><img src="/files/UQw8dKeqXz5XYTWKoqsB" alt=""><figcaption><p>Save ABBEY_TOKEN as a Repository Secret</p></figcaption></figure>

<details>

<summary>What should it look like?</summary>

![](/files/kbDsZTHLunZOznjMX7CV)

</details>

### Update Repo Permissions

Abbey needs a few permissions to operate in your GitHub repo.

1. Go to the **Settings** tab of the same repo you added the API token
2. Select **Actions -> General** on the left side
3. Scroll to the **Workflow Permissions** section
4. Select the **Read and write permissions** button
5. Click on **Save** in the **Workflow Permissions** section

   <figure><img src="/files/CeQBXtzojUbo9pf9sGF5" alt=""><figcaption><p><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> There are multiple Save buttons - make sure to click the Save button in the Workflow permissions section, not the others.</p></figcaption></figure>

{% hint style="info" %}
:checkered\_flag: Great! Now you've allowed Abbey to interact with the new repository you just created to manage access requests.
{% endhint %}

## Step 4: Configure your Grant Kit

{% hint style="info" %}
For this step, you'll be working in

* GitHub Web IDE (github.dev)
  {% endhint %}

We'll now edit the files within the cloned Github repo.&#x20;

We recommend using Github's native code editor, but feel free to edit the files with whatever tools you prefer.&#x20;

<details>

<summary>[Recommended] Using the github.dev web-based editor</summary>

Go to your repository on Github that you just created

1. Open `main.tf` in your repository

   <figure><img src="/files/KvSV5b8hXILJnQH3ienp" alt=""><figcaption></figcaption></figure>
2. Press `.` or click on the arrow next to the pencil icon to select **Open with... -> github.dev**

   &#x20;![](/files/H8FfgXH2Q0G5pT4wxSCy)
3. This will open up the `github.dev` editor - you can make changes to your files here, and directly push them to your repository.

   <figure><img src="/files/1w7OnMi16EyYlxxxG2rz" alt=""><figcaption></figcaption></figure>

   <figure><img src="/files/4h84lZkh3SDFjUxXfVjw" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Using your own Terminal</summary>

1. Click on the **<> Code** dropdown
2. Copy the text under **HTTPS** starting with *https\://*
3. Clone the repository in your development environment by running `git clone` followed by the `https://` URL copied from the previous step in your terminal of choice.

![](/files/Hexds0GN58hXaigEvI7U)

Once you copy the URL of the new repo from GitHub, you should

1. Open your terminal (Terminal, iTerm, etc)
2. Type `git clone` followed by your repo
   1. Example: `git clone https://github.com/alice/abbey-starter-kit-quickstart.git`&#x20;
3. `cd` to the directory via `cd abbey-starter-kit-quickstart`

![](/files/hWkNJwO77SMTWHWkpFoG)

More instructions can be found in the [GitHub docs](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) if you run into issues while cloning.

</details>

**Grant Kits** define who can approve an access request, how long that access should last, and what resource the request is granting access to.&#x20;

The repository you cloned in the previous step contains the grant kit that we'll be modifying below to grant access to the demo site.

### Configuring Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configuring Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "abbey_demo" {
   name = "Abbey_Demo_Site"
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

### Configuring Policies

**Policies** are used to define rules around access requests, such as time-based access or automatic approval if a user is on-call in PagerDuty.

Update the policy in `policies/common/common.rego` so that access to the Demo Site automatically expires after 1 hour, not 6 hours.

<pre class="language-diff" data-title="common.rego"><code class="lang-diff"> allow[msg] {
-     functions.expire_after("6h")
+     functions.expire_after("1h")    
<strong>-     msg := "granting access for 6 hours"
</strong>+     msg := "granting access for 1 hour"
  }
</code></pre>

{% hint style="info" %}
:checkered\_flag: Great job, you're almost there! Now your grant kit has been fully configured with updated reviewers, policies, and output. Double check that all the lines with `#CHANGEME` have been updated before moving on to the next step.

We'll commit and push these changes in the next step.
{% endhint %}

## Step 5: Deploy your Grant Kit

{% hint style="info" %}
For this step, you'll be working in

* GitHub Web IDE (github.dev)
  {% endhint %}

Now we're going to take the Grant Kit you modified in the previous step and deploy it to GitHub.&#x20;

<details>

<summary>[Recommended] Deploying through the github.dev editor</summary>

Once you make a change, there will be an icon on the left-side that will pop up. If this doesn't make sure your edits were in the github.dev editor and they were saved.

![](/files/LqYJNtZnVhnEQnzt9jbK)

To submit those changes and deploy your grant kit:

1. Click on the icon circled above
2. Type a commit reason in the box with the label message
3. Click on **Commit & Push**

   <figure><img src="/files/W7i87rkm3aIRYguAOVBe" alt=""><figcaption></figcaption></figure>

![](/files/vb2fLVbBp7lFagQfGFxx)

</details>

<details>

<summary>Deploying using your terminal</summary>

To deploy, push to your default branch from your terminal within your repository:

```sh
git push origin main
```

</details>

Abbey works with any CI system to deploy your grant kit through Terraform, and for this quickstart we use GitHub Actions - you can look at the *Actions* tab of your GitHub repo to see Terraform runs.&#x20;

{% hint style="info" %}
:tada: Congrats! At this point, you should see your deployed grant kit under Abbey Resources. In the next step, we'll show you how to use the grant kit to get access to the demo site.&#x20;

If it's not showing up, it likely has a configuration issue causing the deployment to fail - open up the Troubleshooting section below for common steps to resolve.&#x20;
{% endhint %}

<details>

<summary>Troubleshooting</summary>

![](/files/7qwEXwzkbQvFwqMa1e30)

1. Open the Actions tab in your GitHub repository
2. Find the corresponding action run to the commit where you added the grant kit and see if it ran successfully. If it failed, open the run to see the failure exception.
   1. A failed run will have a :x: next to it instead of :white\_check\_mark:

![](/files/U5qyRFky65DjFiBkCCGd)

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

* Double check it starts with `github://`
* Double check repository and username or org name is correct
* Double check for any extra `:` or `/`'s

If these don't solve the issue or the error message is unclear, you can always reach us at <hello@abbey.io> or in our [Slack](https://join.slack.com/t/abbey-io/shared_invite/zt-28t1taumd-mI7Kg4pN0X9RYkcTB7NkIw) - we'd love to help!

</details>

## Step 6: Make an Access Request

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
  {% endhint %}

We've now completed all the steps for an admin to automate access grants to the Abbey demo site.&#x20;

Now let's go through the experience as an end user making a request for access.&#x20;

1. Go to the Resources tab of the Abbey App
2. Find the grant kit with the name **Abbey\_Demo\_Site**
3. Click on the **Request**
4. Click on the **Expire after** dropdown to customize the time the access should last, otherwise skip to step 5
5. Enter in a reason, then hit **Confirm** to submit the request

<figure><img src="/files/H1wUgSxVL6m0x47SfGwI" alt=""><figcaption><p>Make an Access Request</p></figcaption></figure>

{% hint style="info" %}
:tada: You just submitted your first access request using Abbey! In the next step, we'll approve the request and then you'll be able to access the demo site.
{% endhint %}

## Step 7: Approve an Access Request

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
  {% endhint %}

For this grant kit, we've set ourselves as the reviewer to make things simple. In a real-world use-case you'd typically set a manager or another team as the approvers.

To approve the request:

1. Go to the Approvals tab of the Abbey App
2. Find the request you just made (there should only be one)
3. Click **Approve** to the right of the request
4. Enter in a reason, then hit **Approve** to submit

<figure><img src="/files/3kSiGqsxKuyDnCB77Xlr" alt=""><figcaption><p>Approve an Access Request</p></figcaption></figure>

## Step 8: Request Access to the Demo Site

Your access request has been approved, so go ahead and check out the [Abbey Demo Site](https://app.abbey.io/demo). You should see the following screen!

<figure><img src="/files/BU9LeN6Qxsber9UAgWCa" alt=""><figcaption></figcaption></figure>

## Wrap up

Congrats :tada: In this guide, you were able to&#x20;

* Create a Grant Kit defining access to the Abbey Demo Site
* Add yourself as a reviewer for access requests
* Configure a time-based policy for limiting access to 1 hour max
* Make, and approve, an access request for yourself to gain access to the Demo Site

There are a lot of moving pieces involved, so if you'd like to learn more you can

* :books: Check out our [How Abbey Works](/how-abbey-works/reference) docs for a high level breakdown
* :construction\_worker: Get hands on with our [Step-by-Step Tutorials](/getting-started/tutorials) that integrate other services like AWS, GCP, Azure and more&#x20;


# Step-by-Step Tutorials


# AWS: Managing Access to Identity Center Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an AWS Identity Center Group by attaching AWS Identity Center Group Membership resources. This use case models Role-Based Access Control (RBAC) using AWS Identity Center Groups.

This example has two accounts and two groups; we model access to a Staging and a Production account. Here we have two groups: R\&D and Prod Access. Members of the R\&D groups are allowed full access to resources within the Staging account and read-only access to resources within the Production Account. Members of the Prod Access group are given full access to EC2 and S3 inside the Production Account.

We will be using Abbey to allow a user to request EC2 or S3 access to the Production account by being adding them to the Prod Access group.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * An AWS Identity Center instance with the [IAMFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/IAMFullAccess.html) policy
2. **Make sure you setup:**
   * An [AWS Identity Center Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-aws-identity-center-groups) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   * A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Create Accounts Resources

The starter kit has two example accounts, *Staging* and *Production*, to get you started.

{% code title="accounts.tf" %}

```diff
resource "aws_organizations_account" "staging" {
  name = "Staging"
-  email = "replace-me@example.com" #CHANGEME
+  email = "staging_owner@example.com" # Use the email of an account in Identity Center.
}

resource "aws_organizations_account" "production" {
  name = "Production"
-  email = "replace-me@example.com" #CHANGEME
+  email = "production_owner@example.com" # Use the email of an account in Identity Center.
}
```

{% endcode %}

## Step 2: Configure your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link AWS Identity Center with Abbey

Now you'll need to link [AWS Identity Center with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff

curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "aws_identitystore", "data": {"id": "<your AWS Identity Center user ID>"}}'
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo's repository secrets:

* `AWS_ACCESS_KEY_ID`
* `AWS_SECRET_ACCESS_KEY`
* `ABBEY_TOKEN`

You can find the AWS keys in your AWS account.

The ABBEY\_TOKEN is your API token.

<details>

<summary>What should it look like?</summary>

<img src="/files/lkVnjzRO5AHI0ATdbHyd" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you should be able to see that the Identity Center User has been added to the Group in the AWS Identity Center console, and that they have an associated AWS Identity Center Permission Set for the account where the assignment was made.

<figure><img src="/files/k58fVmeOD5vdC9TBOywk" alt=""><figcaption><p>Read-Only Access to the Production account for this user</p></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# AWS: Managing Access to Identity Center Permission Sets

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an AWS Identity Center Permission Set by assigning Identity Center Users to Permission Sets.

This example has two accounts and two groups; we model access to a Staging and a Production account. Here we have two groups: R\&D and Prod Access. Members of the R\&D groups are allowed full access to resources within the Staging account and read-only access to resources within the Production Account. Members of the Prod Access group are given full access to EC2 and S3 inside the Production Account.

We will be using Abbey to allow a user to request `ComputeFullAccess` to the Sandbox account by being adding users to a Permission Set.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * An AWS Identity Center instance with the [IAMFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/IAMFullAccess.html) policy
2. **Make sure you setup:**
   * An [AWS Identity Center Permission Sets Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-aws-identity-permission-sets) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   * A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure AWS Resources

### Configure Sandbox Account ID

{% code title="modules/aws/main.tf" overflow="wrap" lineNumbers="true" %}

```diff
locals {
  ...
-  organizations_account_sandbox_id = [for a in data.aws_organizations_organization.org.accounts : a.id if a.id == "replaceme"][0] # Replace with your AWS Account ID.
+  organizations_account_sandbox_id = [for a in data.aws_organizations_organization.org.accounts : a.id if a.id == "1234"][0]
}
```

{% endcode %}

### Configure Provider Configuration

{% code title="modules/aws/provider.tf" lineNumbers="true" %}

```diff
provider "aws" {
-  region = "us-east-1" # Replace with your region.
+  region = "us-east-1"
  ...
}
```

{% endcode %}

## Step 2: Configure your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="modules/aws-access/main.tf" overflow="wrap" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="modules/aws-access/main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link AWS Identity Center with Abbey

Now you'll need to link [AWS Identity Center with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "aws_identitystore", "data": {"id": "<your AWS Identity Center user ID>"}}'
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo's repository secrets:

* `AWS_ACCESS_KEY_ID`
* `AWS_SECRET_ACCESS_KEY`
* `ABBEY_TOKEN`

You can find the AWS keys in your AWS account.

The ABBEY\_TOKEN is your API token.

<details>

<summary>What should it look like?</summary>

<img src="/files/lkVnjzRO5AHI0ATdbHyd" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you will be able to see that the Identity Center User has been added to the Permission Set in the AWS Identity Center console.

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# AWS: Managing Access to IAM Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an AWS IAM Group by attaching [AWS IAM Group Memberships](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_group_membership). This use case models Role-Based Access Control (RBAC) using core AWS IAM components.

We will be using the [AWS IAM Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-aws-iam) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Key](broken://pages/6QiRXA0iBy1kivg4addP#creating-new-api-keys)
   * An AWS User with the [IAMFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/IAMFullAccess.html) policy&#x20;
2. **Make sure you setup:**
   * An [AWS IAM Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-aws-iam) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   * A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Create Your User and Group

In the AWS IAM Console, create a new user and group. Do not add the user to the group at this time.

<figure><img src="/files/TlA84U6uVwZrpB1mA51g" alt=""><figcaption><p>Add a User</p></figcaption></figure>

<figure><img src="/files/96dmUieoNPAF2SQjUPEb" alt=""><figcaption><p>Add a Group</p></figcaption></figure>

## Step 2: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

### (optional) Configure AWS Region

The default for this Starter Kit uses `us-east-1`. If your AWS infrastructure is in another region, you can replace it in `providers.tf`.

{% code title="providers.tf" lineNumbers="true" %}

```hcl
provider "aws" {
  region = "us-east-1"  # CHANGEME (if necessary)
}
```

{% endcode %}

## Step 3: Link AWS IAM with Abbey

Now you'll need to link [AWS IAM with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "aws_iam", "data": {"id": "<your AWS IAM user ID>"}}'
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo's repository secrets:

* `AWS_ACCESS_KEY_ID`
* `AWS_SECRET_ACCESS_KEY`
* `ABBEY_TOKEN`

You can find the AWS keys in your AWS account.

The ABBEY\_TOKEN is your API key.

<details>

<summary>What should it look like?</summary>

![](/files/lkVnjzRO5AHI0ATdbHyd)

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you should be able to see that the User has been added to the Group in the AWS console. <br>

<figure><img src="/files/W5njgnsYjd3gS2TV0qAf" alt=""><figcaption></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Azure AD: Managing Access to Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to add users to groups. This use case models Group-based access control.

To make this example simple, you can act as both the Azure user gaining access to the system and the approver of the system. This will allow you to go through the flow of requesting and approving access from the same account. In a more common production scenario, these calls would be happening from two separate accounts.

We will be using the [Azure Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-azure) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * An Azure user
2. **Make sure you setup:**
   * An [Azure Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-azure) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   * A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Configure the Azure User

In the Azure console, find your User and copy the **User Principal Name.** Replace the stub with it.

{% code title="main.tf" lineNumbers="true" %}

```diff
data "azuread_user" "dev_azure_user" {
-  user_principal_name = "replace-me-EXT-MICROSOFT_UPN@example.com" # need to use azure userPrincipalName
+  user_principal_name = "alice-EXT-MICROSOFT_UPN@example.com"
}
```

{% endcode %}

This will allow terraform to grab the Azure user ID to generate the grant that adds the user to the group.

## Step 3: Deploy Your Starter Kit

This repo uses Azure in the Github Actions job when generating terraform resources. We'll need to [install the Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). On Mac:

```bash
brew update && brew install azure-cli
az login
```

Then we'll need to create a set of credentials for use by Github via:

```bash
az ad sp create-for-rbac --name "myApp" --role contributor \
                            --scopes /subscriptions/{subscription-id} \
                            --sdk-auth
```

The command should output a JSON object similar to this:

```json
  {
    "clientId": "<GUID>", # AZURE_CLIENT_ID
    "clientSecret": "<GUID>", # AZURE_CLIENT_SECRET
    "subscriptionId": "<GUID>", # AZURE_SUBSCRIPTION_ID
    "tenantId": "<GUID>", # AZURE_TENANT_ID
    (...)
  }
```

Next, add the following repository secrets so Github Actions can access these credentials.

1. `AZURE_CLIENT_ID`
2. `AZURE_CLIENT_SECRET`
3. `AZURE_SUBSCRIPTION_ID`
4. `AZURE_TENANT_ID`
5. `ABBEY_TOKEN` - API token taken from [**Settings > API Tokens**](https://app.abbey.io/settings/developers)

You can do this via **Github repo page -> Settings -> Secrets and Variables -> Actions -> New Repository Secret** and create with the above names. You can take the values from the JSON output of the `az ad sp` command.

<details>

<summary>What should it look like?</summary>

<img src="/files/LAcRxAAwAQmCX1jLfgGZ" alt="" data-size="original">

</details>

We also will need to add the correct permissions to the role we created during the `az ad sp create-for-rbac` command. This will allow the Azure client using the secrets in the github actions job to add the user to the desired group.

Find the role by navigating to the Azure Console , then

1. App Registrations
2. View all registrations in Directory
3. Select "myApp" (the app we created as part of the `az` command).
4. API Permissions
5. Add a Permissions
6. Microsoft Graph
7. Add Directory.ReadWrite.All with "Grant Admin Consent for Default Directory" enabled

Your final page in permissions should look like this:

<figure><img src="/files/BKH74BQQZgJzrccq0TyQ" alt=""><figcaption></figcaption></figure>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you should be able to see that the User has been added to the Group in the Azure console. Note that because this starter kit comes with a time-based policy by default, the user will automatically be removed after 1 hour.

<figure><img src="/files/WujU4W4PYO1ympW9ckYa" alt=""><figcaption></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Confluent: Managing Access to Kafka ACLs

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Kafka ACL](https://registry.terraform.io/providers/confluentinc/confluent/latest/docs/resources/confluent_kafka_acl) for Confluent. This use case models [Role-Based Access Control (RBAC) within the Confluent](https://docs.confluent.io/platform/current/security/rbac/index.html) ecosystem to manage a single Kafka cluster in the same Terraform workspace.

We will be using the [Confluent Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-confluent) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Confluent account.
2. **Make sure you setup:**
   1. A [Confluent Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-confluent) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link Confluent with Abbey

Now you'll need to link [Confluent with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "confluent", "data": {"principal": "<your Confluent principal>"}}'
```

{% endcode %}

## Step 3: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `CONFLUENT_CLOUD_API_KEY`
* `CONFLUENT_CLOU_API_SECRET`
* `KAFKA_API_KEY`
* `KAFKA_API_SECRET`

You can find this information in your Confluent account.

<details>

<summary>What should it look like?</summary>

<img src="/files/lj9uPKOZLjlK4mcAiVtF" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 4: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Databricks: Managing Access to Managed Tables in Unity Catalog

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access and revocation to a securable object in the [Databricks Unity Catalog](https://docs.databricks.com/data-governance/unity-catalog/index.html). This use case allows you to model fine-grained access for your Databricks deployment.

We will be using the Databricks [Databricks: Managing Access to Groups](/getting-started/tutorials/databricks-managing-access-to-groups) Starter Kit as a base and modify it to work with the Databricks Unity Catalog.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Databricks account
2. **Make sure you setup:**
   1. A [Databricks Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-databricks) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)
   3. Your account to [enable Databricks Unity Catalog](https://docs.databricks.com/data-governance/unity-catalog/get-started.html#overview-of-unity-catalog-setup)

## Step 1: Configure a Managed Table Grant

Unity Catalog allows you to configure fine-grained access to securable objects such as:

1. Metastore
2. Catalogs
3. Schemas (Databases)
4. Tables
5. Views
6. Storage Credentials
7. Storage Locations
8. Delta Sharing Share Grants

Permission grants for securable objects are hierarchical. This means, for example, granting access to a Catalog or Schema automatically grants the privilege to current and all future objects within the Catalog or Schema, with the exception of Metastore grants.

For our use case, let's manage access to a [Managed Table](https://docs.databricks.com/data-governance/unity-catalog/index.html#tables).

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "databricks_pii_group" {
  ...

  output = {
    ...

    append = <<-EOT
-      resource "databricks_group_member" "group_member_{{ .data.system.abbey.identities.databricks.tf_resource_id }}" {
-        group_id  = ${databricks_group.pii_group.id}
-        member_id = {{ .data.system.abbey.identities.databricks.tf_resource_id }}
+      resource "databricks_grant" "grant_pii_table" {
+        table = "main.reporting.pii_customers"
+
+        grant {
+          principal  = ${databricks_group.pii_group.id}
+          privileges = ["MODIFY", "SELECT"]
+        }
      }
    EOT
  }
}
```

{% endcode %}

Instead of using the `databricks_group_member` resource, we want to use the `databricks_grant` resource and specify a `table` alongside a `grant` attribute. We're able to reuse our `databricks_group.pii_group.id` as the principal. This resource was configured in the Databricks [Databricks: Managing Access to Groups](/getting-started/tutorials/databricks-managing-access-to-groups) guide.

{% hint style="info" %}
For more ideas on how you can manage other securable objects, visit the official [Databricks Terraform Provider documentation on Grants](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/grants).
{% endhint %}

## Step 2: Deploy Your Starter Kit

Follow instructions from the Databricks [Databricks: Managing Access to Groups](/getting-started/tutorials/databricks-managing-access-to-groups) to deploy your newly configured Grant Kit with Unity Catalog.

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Databricks: Managing Access to Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Databricks Group](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/group) by attaching [Group Members](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/group_member). This use case models Role-Based Access Control (RBAC) for Databricks.

We will be using the [Databricks Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-databricks) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Databricks account
2. **Make sure you setup:**
   1. A [Databricks Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-databricks) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link Databricks with Abbey

Now you'll need to link [Databricks with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "databricks", "data": {"user_name": "<your Databricks user name", "tf_resource_id": "<the id of the Terraform resource for your user>"}}'
```

{% endcode %}

## Step 3: Replace Databricks-Related Stubs

You'll need to log into your Databricks account to get your database, role, user(s), table schema, and table name.

{% code title="main.tf" lineNumbers="true" %}

```diff
...

resource "databricks_group" "pii_group" {
  display_name               = "PII Group"
  allow_cluster_create       = true
  allow_instance_pool_create = true
}

- resource "databricks_user" "replace_me_user" {
+ resource "databricks_user" "alice_user" {
-  user_name    = "replace-me@example.com"
+  user_name    = "alice@example.com"
}

...
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your Databricks-related secrets to your repo:

* `DATABRICKS_HOST`
* `DATABRICKS_TOKEN`

You can find this information in your Databricks account.

<details>

<summary>What should it look like?</summary>

<img src="/files/4KX2u7weKZgrxz3kVQO3" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Databricks Group for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# GitHub: Managing Access to Teams

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [GitHub Team](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team) by attaching [Team Membership](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_membership). This use case models Role-Based Access Control (RBAC) for GitHub.

We will be using the [GitHub Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-github) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A GitHub account
2. **Make sure you setup:**
   1. A [GitHub Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-github) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link GitHub with Abbey

Now you'll need to link [GitHub with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "github", "data": {"username": "<your GitHub username>"}}'
```

{% endcode %}

## Step 3: Replace GitHub Stubs

{% code title="main.tf" lineNumbers="true" %}

```diff
provider "github" {
-  owner = "replace-me"
+  owner = "abbeylabs" # Replace with your own organization
   token = var.token
}

resource "github_team" "abbey_test_team" {
+ name = "AbbeyTestTeam" # You may replace this with your own team name
  description = "This team is testing Abbey."
}
```

{% endcode %}

## Step 3: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `ABBEY_TOKEN`
* `GH_TOKEN`

`ABBEY_TOKEN` is your Abbey API Token. Make sure that your `GH_TOKEN` is for your organization and has the following permissions

* Read and Write for `Members`

<details>

<summary>What should it look like?</summary>

<img src="/files/UWJlqfbZyAl0sFMG6jhZ" alt="" data-size="original">

<img src="/files/6tjGPR96ppqECMaOLv35" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 4: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Google Cloud: Managing Access to Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an [Google Cloud Identity Group](https://cloud.google.com/identity/docs/groups#group-types) by attaching a [Google Cloud Identity Group Membership](https://cloud.google.com/identity/docs/groups#memberships_and_membership_properties). This use case models granting new users memberships to a GCP group.

The main terraform resources we'll be using for GCP are:

```hcl
google_cloud_identity_group
google_cloud_identity_group_membership
```

We will be using the [GCP Identity Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-gcp-identity) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A GCP account
   * [`gcloud` CLI](https://cloud.google.com/sdk/gcloud) set up
2. **Make sure you setup:**
   1. An [GCP Identity Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-gcp-identity) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link GCP with Abbey

Now you'll need to link [GCP with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "google", "data": {"id": "<your GCP id>"}}'
```

{% endcode %}

## Step 3: Configure GCP for Terraform

### **Configure GCP User**

{% hint style="info" %}
You can skip this step if your GCP user email address matches your Abbey email address.
{% endhint %}

Replace the value for `gcp_member` in the locals block to the google email address for the user you wish to add to group.

{% code title="main.tf" lineNumbers="true" %}

```diff
locals {
-  gcp_member = "{{ .user.google.id }}"
+  gcp_member = your-username@gmail.com
   ...
}
```

{% endcode %}

### **Configure GCP Billing Project**

Replace the `billing_project` field in the google provider block with your project ID and correct region.

{% code title="providers.tf" lineNumbers="true" %}

```diff
provider "google" {
-  billing_project     = "replace-me"
+  billing_project     = "your-project-id"
-  region              = "replace-me"
+  region              = "your-region"
}
```

{% endcode %}

### **Configure GCP Customer ID**

In the terminal run `gcloud organizations list`, which should output something like

```
DISPLAY_NAME            ID  DIRECTORY_CUSTOMER_ID
abbey.io      00000000              C1111111
```

Update the value for `gcp_customer_id` in the locals block with the DIRECTORY\_CUSTOMER\_ID

{% code title="main.tf" lineNumbers="true" %}

```diff
locals {
  ...
-  gcp_customer_id = "$replace-me-with-gcp-customer-id"
+  gcp_customer_id = "C1111111"
}
```

{% endcode %}

## Step 4: Configure GCP Permissions

{% hint style="info" %}
In this step we will

* Create and use GCP resources (Project, Service Account, Workload Identity Pool & Provider)
* Add Repository Secrets so Github Actions to make calls to GCP
  {% endhint %}

Create a new GCP project or use an existing one. Make sure that the **Cloud Identity API** is enabled for your project (<https://console.cloud.google.com/apis/api/cloudidentity.googleapis.com>)

After that, we need to configure Workload Identity Federation to allow Github Actions to make calls from your repo when managing the group membership. This allows Github to only gain secure temporary access tokens rather than exporting long-lived JSON secrets.

Follow these instructions to set it up <https://github.com/google-github-actions/auth#setting-up-workload-identity-federation>. Don't worry about making any changes to the actions YAML file, just save the Service Account email and the Workload Identity Provider ID - we'll add those as repository secrets.

Next, add the following repository secrets so Github Actions can access these credentials.

1. `GCP_SERVICE_ACCOUNT`
2. `GCP_WORKLOAD_IDENTITY_PROVIDER`
3. `ABBEY_TOKEN` - API token taken from [**Settings > API Tokens**](https://app.abbey.io/settings/developers)

You can do this via **Github repo page -> Settings -> Secrets and Variables -> Actions -> New Repository Secret** and create with the above names.

<details>

<summary>What should it look like?</summary>

<img src="/files/YYsxETIscBH5Svd39XJ1" alt="" data-size="original">

</details>

## Step 5: Deploy Your Starter Kit

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 6: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you should be able to see that the user has been added to the google group.

1. Navigate to <https://groups.google.com/all-groups>
2. Select the group you are adding a member to
3. View members

Finally, this starter kit comes with a time-based policy by default, the user will automatically be removed after 1 hour.

<figure><img src="/files/WujU4W4PYO1ympW9ckYa" alt=""><figcaption></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Google Workspace: Managing Access to Google Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an Google Workspace Group by attaching a Google Workspace Group Membership. This use case models granting new users memberships to a Google Workspace group.

The main terraform resources we'll be using for Google Workspace are:

```hcl
googleworkspace_group
googleworkspace_group_member
```

We will be using the [Google Workspace Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-google-workspace-groups) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A GCP account
   * Access to your organization's [Google Workspace admin portal](https://admin.google.com)
2. **Make sure you setup:**
   1. A [Google Workspace Starter Kit](https://github.com/hatim-khan/abbey-example-google-workspace-groups) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link GSuite with Abbey

Now you'll need to link [GSuite with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "googleworkspace", "data": {"email": "<your Google Workspace email>"}}'
```

{% endcode %}

## Step 3: Configure Google Workspace for Terraform

### **Configure Google Workspace Customer ID**

Navigate to <https://admin.google.com/ac/accountsettings/profile> and copy the **Customer ID** under your profile.

<figure><img src="/files/kPUNoxYJ9MAK4rKjkDzO" alt=""><figcaption></figcaption></figure>

Update the value for `google_customer_id` in the locals block with that value

{% code title="main.tf" lineNumbers="true" %}

```diff
locals {
  ...
-  google_customer_id = "$replace-me-with-gcp-customer-id"
+  google_customer_id = "C1111111"
}
```

{% endcode %}

## Step 4: Configure Google Workspace Permissions

{% hint style="info" %}
In this step we will

* Create or use an existing GCP service account
* Give our GCP service account admin role in Google Workspace
* Add Repository Secrets so Github Actions to make calls to GCP
  {% endhint %}

### Setting up the Service Account

Make sure that the **Admin SDK API** and is enabled for your project. You can check by navigating to <https://console.cloud.google.com/apis/api/admin.googleapis.com>.

If you don't already have a service account, create one via <https://console.cloud.google.com/iam-admin/serviceaccounts> with owner role. Keep track of the service account email address, it should something like google-workspace-groups-demo@\<project-id>.iam.gserviceaccount.com.&#x20;

Once you have a service account, create a new Key through the console

<figure><img src="/files/RzQ1vsiKtmKDitLTzqVi" alt=""><figcaption></figcaption></figure>

Save the JSON file, we'll be using the contents later with Github Actions.

### Linking the Service Account to Google Workspace

Navigate to the [Google Workspace Admin Portal](https://admin.google.com/) and go to Account -> Admin Roles.

<figure><img src="/files/4wsfS1a280e8Yfx7LsVa" alt=""><figcaption></figcaption></figure>

Hover on the Groups Admin row and click on **Assign Admin**. It'll open up to a new page:

<figure><img src="/files/f0TRWSzdntoi9CuQLdOi" alt=""><figcaption></figcaption></figure>

Now, click on **Assign service accounts** and enter in the service account email address from the earlier step. Confirm assigning the role and now your service account has access to the Google Workspace groups APIs :tada:

Next, add the following repository secrets so Github Actions can access these credentials.

1. `GOOGLE_CREDENTIALS` - copy paste the contents from the credentials key JSON as the value.
2. `ABBEY_TOKEN` - API token taken from [**Settings > API Tokens**](https://app.abbey.io/settings/developers)

You can do this via **Github repo page -> Settings -> Secrets and Variables -> Actions -> New Repository Secret** and create with the above names.

<details>

<summary>What should it look like?</summary>

<img src="/files/YYsxETIscBH5Svd39XJ1" alt="" data-size="original">

</details>

## Step 5: Deploy Your Starter Kit

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 6: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

After approving the request, you should be able to see that the user has been added to the google group.

1. Navigate to <https://groups.google.com/all-groups>
2. Select the group you are adding a member to
3. View members

Finally, this starter kit comes with a time-based policy by default, the user will automatically be removed after 1 hour.

<figure><img src="/files/WujU4W4PYO1ympW9ckYa" alt=""><figcaption></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Kafka: Managing Access to ACLs

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Kafka ACL](https://registry.terraform.io/providers/Mongey/kafka/latest/docs/resources/acl). This use case models [Role-Based Access Control (RBAC) using core Kafka](https://docs.confluent.io/platform/current/security/rbac/index.html) components.

We will be using the [Kafka Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-kafka) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
2. **Make sure you setup:**
   1. A [Kafka Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-kafka) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link Kafka with Abbey

Now you'll need to link [Kafka with Abbey](https://developers.abbey.io/#operation/createAppData).

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "kafka", "data": {"principal": "<your Kafka principal>"}}'
```

{% endcode %}

## Step 3: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `BOOTSTRAP_SERVERS`

The `BOOTSTRAP_SERVERS` secret takes a [List type](https://developer.hashicorp.com/terraform/language/values/variables#type-constraints). You can specify a list of bootstrap servers by:

```
# Evaluates to BOOTSTRAP_SERVERS='["host1:port", "host2:port", "host3:port"]'
["host1:port", "host2:port", "host3:port"]
```

<details>

<summary>What should it look like?</summary>

<img src="/files/qDfkBtMO0B1xxnKz3pgB" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 4: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Okta: Managing Access to Groups

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an Okta User Group by attaching [Okta User Group Memberships](https://registry.terraform.io/providers/okta/okta/latest/docs/resources/user_group_memberships). This use case models Role-Based Access Control (RBAC) using core Okta components.

We will be using the [Okta Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-okta) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * An Okta account
2. **Make sure you setup:**
   1. An [Okta Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-okta) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Set Up Okta

In Okta, create a group named `Has nice things`

<figure><img src="/files/VhgBhrea6wRjkH90twpN" alt=""><figcaption></figcaption></figure>

## Step 2: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link Okta with Abbey

Now you'll need to link [Okta with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "okta", "data": {"user_id": "<your Okta User ID>"}}'
```

{% endcode %}

## Step 4: Configure your Okta Settings

Replace the following settings in `variables.tf`

<pre class="language-diff" data-title="variables.tf" data-line-numbers><code class="lang-diff">variable "okta_org_name" {
  type = string
  sensitive = true
<strong>- default = "dev-12345"
</strong>+ default = "dev-12345" # Use your own Okta org
}

variable "okta_base_url" {
  type = string
  sensitive = true
- default = "oktapreview.com" # CHANGEME
+ default = "okta.com" # Use the okta base where you created your API Token
}
</code></pre>

## Step 5: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `OKTA_API_TOKEN`
* `ABBEY_TOKEN`

You can find the OKTA\_API\_TOKEN in your Okta account. ABBEY\_TOKEN is your API token

<details>

<summary>What should it look like?</summary>

<img src="/files/jV36ihDqEjr0zucgFGOr" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 6: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Step 7: Check approved requests in Okta

Go to the okta UI and confirm that the resource you created has appeared

<figure><img src="/files/fOSMlvEpTWWGHRAxgf5A" alt=""><figcaption></figcaption></figure>

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).&#x20;

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Postgres: Managing Access to Roles

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Postgres Role](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs/resources/postgresql_grant_role). This use case models Role-Based Access Control (RBAC) using core Postgres components.

We will be using the [Postgres Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-postgres) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
2. **Make sure you setup:**
   1. A [Postgres Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-postgres) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link Postgres with Abbey

Now you'll need to link [Postgres with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "postgres", "data": {"role": "<your Postgres role>"}}'
```

{% endcode %}

## Step 3: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `PG_PASSWORD`

<details>

<summary>What should it look like?</summary>

<img src="/files/P8jRvjoGq7OTbM4B3ffn" alt="" data-size="original">

</details>

You can optionally set the following variables as secrets or just provide a default.

{% code title="variables.tf" lineNumbers="true" %}

```hcl
variable "pg_host" {
  type = string
  default = "postgres_server_ip" # CHANGEME
  sensitive = true
}
variable "pg_port" {
  type = number
  default = 5432
  sensitive = true
}
variable "pg_db" {
  type = string
  default = "postgres" # CHANGEME
  sensitive = true
}
variable "pg_username" {
  type = string
  default = "postgres_user" # CHANGEME
  sensitive = true
}
variable "pg_password" {
  type = string
  default = "postgres_password" # CHANGEME
  sensitive = true
}

variable "pg_connect_timeout" {
  type = number
  default = 15
}
```

{% endcode %}

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 4: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Snowflake: Managing Access to Tables

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Snowflake Table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/table_grant).

We will be using the [Snowflake Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-snowflake) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Snowflake account
2. **Make sure you setup:**
   1. A [Snowflake Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-snowflake) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Link Snowflake with Abbey

Now you'll need to link [Snowflake with Abbey](https://developers.abbey.io/#operation/createAppData).&#x20;

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "snowflake", "data": {"username": "<your Snowflake username>"}}'
```

{% endcode %}

## Step 3: Replace Snowflake Stubs

You'll need to log into your Snowflake account to get your database, role, user(s), table schema, and table name.

{% code title="main.tf" lineNumbers="true" %}

```diff
...

data "snowflake_database" "pii_database" {
-  name = "REPLACE_ME"
+  name = "PII_DATABASE" # Use your own name.
}

data "snowflake_role" "pii_readonly_role" {
-  name = "REPLACE_ME"
+  name = "PII_ROLE" # Use your own role.
}

data "snowflake_users" "my_snowflake_user" {
-  pattern = "REPLACE_ME"
+  pattern = "USERNAME" # Use your own username.
}

resource "snowflake_table_grant" "pii_readonly__can_read__pii__table" {
  database_name     = data.snowflake_database.pii_database.name
-  schema_name       = "REPLACE_ME"
+  schema_name       = "PII_SCHEMA" # Use your own schema.
-  table_name        = "REPLACE_ME"
+  table_name        = "PII_TABLE" # Use your own table.
  privilege         = "SELECT"
  roles             = [data.snowflake_role.pii_readonly_role.name]
  with_grant_option = false
}

...
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your Snowflake-related secrets to your repo:

* `SNOWFLAKE_ACCOUNT`
* `SNOWFLAKE_PASSWORD`
* `SNOWFLAKE_USERNAME`

You can find this information in your Snowflake account.

<details>

<summary>What should it look like?</summary>

<img src="/files/BB1jNAWRW30KPrCRAyMk" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

{% hint style="warning" %}
If you received an error for `terraform plan` with the message:

```
Error: 260008 (08004): failed to connect to db. verify account name is correct. HTTP: 403
```

This means you didn't configure the correct Snowflake `account`, `username`, or `password`. The Snowflake Terraform Provider requires correct credentials.

Also keep in mind if Snowflake requires you to have a valid database name, otherwise you'll see the error message:

```
The argument "database_name" is required, but no definition was found.
```

{% endhint %}

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Snowflake Table for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Tabular: Managing Access to Apache Iceberg Roles

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Tabular Role](https://registry.terraform.io/providers/tabular-io/tabular/latest/docs/resources/role_membership). Tabular is the cloud-hosted service for Apache Iceberg. This use case models [Role-Based Access Control (RBAC) within the Tabular](https://docs.tabular.io/roles) ecosystem.

We will be using the [Tabular Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-tabular) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Tabular account.
2. **Make sure you setup:**
   1. A [Tabular Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-tabular) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Configure Tabular Admin

{% code title="main.tf" lineNumbers="true" %}

```diff
locals {
  ...
-  admin_email = "" # CHANGEME
+  admin_email = "alice+admin@example.com"
}
```

{% endcode %}

{% hint style="warning" %}
Tabular Roles require both `admin_members` and `members` to exist, otherwise the `terraform apply` will fail.

Make sure to have an admin and a member for this role assignment.

**Keep in mind an admin and a member cannot be the same person.**
{% endhint %}

## Step 3: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `TABULAR_CREDENTIAL`

You can find this information in your Tabular account.

<details>

<summary>What should it look like?</summary>

<img src="/files/wdqeZIaSHgnEuZe5cYUU" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 4: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Tailscale: Managing Access to ACLs

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to a [Tailscale ACL](https://registry.terraform.io/providers/tailscale/tailscale/latest/docs/resources/acl). This use case allows you to lock down your Tailscale VPN.

We will be using the [Tailscale Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-tailscale) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * A Tailscale account
2. **Make sure you setup:**
   1. A [Tailscale Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-tailscale) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 2: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `TAILSCALE_API_KEY`
* `TAILNET`

You can find this information in your GitHub account.

<details>

<summary>What should it look like?</summary>

<img src="/files/AQ0h78wBhMP2KCwUcctz" alt="" data-size="original">

</details>

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 3: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).


# Vault: Managing Access to Groups and Policies

In this tutorial, you'll learn how to configure [Key Concepts](/how-abbey-works/concepts#grant-kits) to automate access requests to an admin access either by:

1. Adding yourself to an "oncall" vault group via [vault\_identity\_group\_member\_entity\_ids](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_group_member_entity_ids), or
2. Assigning the admin policy directly to yourself via [vault\_identity\_group\_member\_entity\_ids](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_group_member_entity_ids).

This use case models Role-Based Access Control (RBAC) using core Vault components.

We will be using the [Vault Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-vault) as a base and replace configuration stubs for our use case.

## Before you start

1. **Make sure you have:**
   * An [Abbey account](https://app.abbey.so/sign-up)
   * An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
   * An Vault account
2. **Make sure you setup:**
   1. An [Vault Starter Kit](https://github.com/abbeylabs/abbey-starter-kit-vault) by following [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit)
   2. A Connection to a repo by following [Connect a Repo](/build-a-grant-kit/connect-a-repo)

## Step 1: Set Up Vault

Make sure your Vault account is good and ready to go. This Starter Kit will be creating 3 vault resources listed in `vault.tf`:

1. `vault_policy.admin_policy`
2. `vault_identity_group.oncall`
3. `vault_identity_entity.user1`

so make sure these don't already exist on your account to avoid conflicts.

## Step 2: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

## Step 3: Link Vault with Abbey

Now you'll need to link [Vault with Abbey](https://developers.abbey.io/#operation/createAppData).

{% code title="" %}

```diff
curl -X POST \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  https://api.abbey.io/v1/users/<user_id>/apps \
  -d '{"type": "vault", "data": {"user_id": "<your Vault User ID>"}}'
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

First, add your GitHub-related secrets to your repo:

* `VAULT_ADDR`
* `VAULT_TOKEN`
* `ABBEY_TOKEN`

You can find the `VAULT_ADDR` and `VAULT_TOKEN` by going to <https://portal.cloud.hashicorp.com> and clicking on your Vault cluster for its details. `ABBEY_TOKEN` is your API token.

To deploy your Starter Kit, follow instructions from [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit).

## Step 5: Automate Access Management

:tada: Congratulations! Abbey is now managing permissions to your Resource for you. :tada:

You can now start requesting and approving access by following the [Request Access](/build-a-grant-kit/requesting-access) and [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) guides.

{% hint style="success" %}
Abbey strives to help you automate and secure access management without being intrusive.

To that end, this Pull Request contains native Terraform HCL code using normal open source Terraform Provider libraries. It represents the permissions change. In this case, it's just a simple creation of a new Terraform Resource.
{% endhint %}

## Step 6: Check approved requests in Vault

Go to the vault UI and confirm that the user is either (1) assigned to the oncall group, or (2) assigned the admin policy, depending on the resource you requested on Abbey.

## Next Steps

To learn more about what you can configure, try one of the [Data Integration](https://github.com/abbeylabs/docs/blob/main/getting-started/tutorials/broken-reference/README.md) tutorials. You can also look at [Infrastructure Integrations](https://github.com/abbeylabs/docs/blob/main/getting-started/tutorials/broken-reference/README.md) or get set up with a [TACOS](https://github.com/abbeylabs/docs/blob/main/getting-started/tutorials/broken-reference/README.md) of your choice.

For more information on how Abbey works, visit the [Key Concepts](/how-abbey-works/concepts) or [Grant Kits](/reference/grant-kits) page.


# Integrating Abbey with Terraform Cloud

In this Quickstart, you'll learn how to set up and use Abbey using [Terraform Cloud](https://developer.hashicorp.com/terraform/cloud-docs).

Abbey helps you manage the workflows for access requests and approvals, making it easier for people to get access to [Resources](/how-abbey-works/concepts#resources).

We allow engineers to integrate these workflows directly into the Infrastructure provisioning process. Since you are already using an Infrastructure as Code (IaC) tool like Terraform, Abbey extends your IaC deployment through a [Grant Kit](/reference/grant-kits).

A resource can be a production database or a cloud IAM role. In this Quickstart we will use the **Abbey Demo Site** as a resource example.

\--> Go to [Abbey Demo Site](https://app.abbey.io/demo)

Whoops, looks like you don't have access. Let's fix this and get you access. :hammer\_pick:

## Before you start

1. Create an [Abbey Account](https://accounts.abbey.io/sign-up)
2. Log into your [Terraform Cloud](https://app.terraform.io) account
3. Log into your [GitHub](https://github.com/) account

## Step 1: Clone this Repo

Clone [abbeylabs/abbey-starter-kit-terraform-cloud](https://github.com/abbeylabs/abbey-starter-kit-terraform-cloud) into your local development environment by following the instructions in [Get a Starter Kit](/build-a-grant-kit/get-a-starter-kit).

## Step 2: Configure GitHub

Follow the instructions in [Connect a Repo](/build-a-grant-kit/connect-a-repo) to connect Abbey to your GitHub account.

### Enable VCS Integration on Terraform Cloud

Go to [Terraform Cloud](https://app.terraform.io/)'s **Projects & workspaces** to [create a new Workspace](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/creating#create-a-workspace) and connect it with the quickstart GitHub repository.

1. Go to [Terraform Cloud](https://app.terraform.io/)'s **Projects & workspaces**
2. Click New > Workspace
3. In **Choose Type**, choose **Version control workflow**
4. In **Connect to VCS**, choose **GitHub**
5. In **Choose a repository**, choose the quickstart repo you created in **Step 1**
6. In **Configure settings** > Advanced opitons,
   * Under **Apply Method**, choose **Auto Apply**
   * Under **VCS Triggers**, choose **Always trigger runs**
   * Under **Pull Requests**, toggle on **Automatic speculative plans**
7. Click **Create workspace**
8. Configure `abbey_token` Terraform variable
   * Find your API Token from the [**Settings > API Tokens**](https://app.abbey.io/settings/developers) page from your side navigation in the Abbey App.

## Step 3: Configure Your Grant Kit

### Configure Output

Grant Kits rely on your GitHub account and repository name to output access changes, which we'll set through Terraform local variables. Update the `locals` block in `main.tf` with your `account_name` and `repo_name`

{% code title="main.tf" %}

```hcl
 locals {
  account_name = "" #CHANGEME
  repo_name = "" #CHANGEME
  ...
}
```

{% endcode %}

### Configure Reviewers

Workflow defines who should approve an access request.&#x20;

Let's update the `reviewers` block by adding yourself as the reviewer by switching `replace-me@example.com` with the email address you use to sign into Abbey.&#x20;

{% code title="main.tf" %}

```diff
 resource "abbey_grant_kit" "..." {
   ...
   workflow = {
     steps = [
       {
         reviewers = {
-          one_of = ["replace-me@example.com"] # CHANGEME
+          one_of = ["alice@example.com"]
```

{% endcode %}

### Update Terraform Cloud Backend Configuration

Update [Terraform Cloud Configuration](https://developer.hashicorp.com/terraform/language/settings/terraform-cloud) inside `terraform` block with your Terraform organization and workspace names.

{% code title="backend.tf" lineNumbers="true" %}

```diff
 terraform {
   cloud {
-    organization = "replace-me-with-organization" # CHANGEME
+    organization = "my-terraform-org" # Use your own organization name
     workspaces {
-      name = "replace-me-with-workspace" # CHANGEME
+      name = "my-terraform-workspace" # Use your own workspace name here
     }
   }
```

{% endcode %}

## Step 4: Deploy Your Starter Kit

To deploy your Starter Kit, push to your `main` branch:

```sh
git push origin main
```

{% hint style="info" %}
The deploy registers your resources with Abbey and effectively says "Hey Abbey, from this point forward, please manage permissions for these resources for me."
{% endhint %}

## Step 5: Make a Request

Visit the Abbey web application, click on [Resources](https://app.abbey.io/resources), and click Request next to the Demo resource. There are detailed instructions in [Request Access](/build-a-grant-kit/requesting-access) doc.

Since all changes are backed by Git, you will see a PR get created in your repo with comments that outline the requested change in permissions.

## Step 6: Approve the Request

To make things simple, we have configured the grant kit so that you are your own Approver. Click the [Approvals](https://app.abbey.io/approvals) tab and click Approve. See [Approve or Deny Access Requests](/build-a-grant-kit/approving-or-denying-access-requests) for detailed instructions.

You'll see that the PR in GitHub was merged within a few minutes.

## Step 7: Access the Demo Site

Now let's go back to the [Abbey Demo Site](https://app.abbey.io/demo).

:tada: Congrats! You should now have access. :tada:

### Revoke Access

Once your 5 minutes is up, your access is automatically revoked. In your repo's Pull requests history, you can find a closed PR with the title "**Revoking access to Abbey\_demo from ...**", and you will no longer be able to access the [Abbey Demo Site](https://app.abbey.io/demo).

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).


# Using Abbey with Atlantis

{% hint style="info" %}
**Estimated time:** \~15 minutes
{% endhint %}

In this tutorial, you'll learn how to use Abbey with [Atlantis](https://www.runatlantis.io/).

Abbey helps you manage the workflows for access requests and approvals, making it easier for people to get access to [Resources](/how-abbey-works/concepts#resources).

Atlantis is an application for automating Terraform via pull requests. It is deployed as a standalone application into your infrastructure. No third-party has access to your credentials.

By using Abbey and Atlantis together, you can:

1. Scalably manage your infrastructure access.
2. Standardize your workflows.
3. Increase visibility for how and when Terraform changes occur.

## Before you start

1. Create an [Abbey ](https://accounts.abbey.io/sign-up)account.
2. Have a [GitHub](https://docs.github.com/en/get-started/quickstart/creating-an-account-on-github) account.

## Atlantis Setup

Setting up Atlantis contains 5 steps:

1. [#step-1-choose-an-atlantis-deployment-type](#step-1-choose-an-atlantis-deployment-type "mention")
2. [#step-2-set-up-your-github-app](#step-2-set-up-your-github-app "mention")
3. [#step-3-configure-atlantis-secrets](#step-3-configure-atlantis-secrets "mention")
4. [#step-4-configure-terraform-provider-credentials](#step-4-configure-terraform-provider-credentials "mention")
5. [#step-5-set-up-a-state-backend](#step-5-set-up-a-state-backend "mention")

## Step 1: Choose An Atlantis Deployment Type

First, follow the official Atlantis docs to [choose a deployment type](https://www.runatlantis.io/docs/deployment.html#deployment-1) for deploying an Atlantis server.

## Step 2: Set Up Your GitHub App

Follow the official instructions to [create a GitHub App Using Atlantis](https://www.runatlantis.io/docs/access-credentials.html#github-app).

{% hint style="warning" %}
Make sure to follow instructions on the Atlantis installation screen titled "**Visit <https://github.com/apps/installation//installations/new> to install the app for your user or organization…**".

Your connection won't be complete without doing this step.
{% endhint %}

<figure><img src="/files/39a3dpFWjw5Ro04YAUM1" alt=""><figcaption><p>Atlantis installation screen.</p></figcaption></figure>

You will be redirected to GitHub's website to perform the typical OAuth flow. Select repo scopes for your app, then install.

{% hint style="warning" %}

If you miss some of the above steps, you'll see an error when launching Atlantis:

{% code overflow="wrap" %}

```log
Error: initializing server: error initializing github authentication transport: wrong number of installations, expected 1, found 0
```

{% endcode %}
{% endhint %}

{% hint style="success" %}
Because you have set up GitHub using Atlantis's native GitHub App setup flow, you won't have to configure webhook secrets and a webhook URL.
{% endhint %}

<figure><img src="/files/844ZQyYhK2y0Kx0doVmo" alt=""><figcaption><p>Note about webhooks from the Atlantis docs.</p></figcaption></figure>

## Step 3: Configure Atlantis Secrets

You may configure Atlantis Secrets in one of two ways:

1. Using `atlantis.yaml`
2. Using environment variables

### Using `atlantis.yaml`

Modify your Atlantis server's [server config](https://www.runatlantis.io/docs/server-configuration.html) to configure required configurations, such as:

1. GitHub App ID
2. App Key
3. Webhook Secret
4. Web Basic Auth
5. Web Username
6. Web Password

This is where you can also configure optional configurations such as your Repo Allowlist.

### Using environment variables

You may also configure these same configuration variables via [environment variables](https://www.runatlantis.io/docs/server-configuration.html#environment-variables).

To do this, you will prefix your variables with `ATLANTIS`.

<figure><img src="https://lh7-us.googleusercontent.com/MSUgLD92RInrz3LEB0X9G1clnjK_MVEKsrIGQEPfqudBAHdy3GIFuFphN3BiB55rUHeYPKk-M4ma5-bB6HYlzP7zBMzBMmEi16ecdp37G5WilS-wwV73hDcVYpJodwd0B234jxHwdDzTjjsSVbCnkbY" alt="" width="375"><figcaption><p>Example Atlantis config using environment variables.</p></figcaption></figure>

## Step 4: Configure Terraform Provider Credentials

Now you will configure your Terraform provider credentials.

For each Terraform Provider or Module you have in your repo, you will need to add credentials so Atlantis can make API calls (via the providers) to each of their services.

For example, if you have infrastructure configuration for GitHub, AWS, and Okta, you will need 3 sets of credentials, one for each of those services.

You will add your provider credentials similar to step 3 above, either using the `atlantis.yaml` or environment variables.

## Step 5: Set Up a State Backend

Atlantis by default does not come with a state backend.

Some of the usual options for a state backend are:

1. AWS S3 to hold state with AWS Dynamo DB for state locking
2. Terraform Cloud (only for state)

{% hint style="info" %}
You may use Abbey's HTTP-based state backend for sandbox or prototyping, but it is not recommended for production use at scale.
{% endhint %}

{% hint style="warning" %}
You must not use file state with Atlantis because [Atlantis does not have permanent storage and does not commit it back to version control](https://www.runatlantis.io/docs/requirements.html#terraform-state).
{% endhint %}

## :tada: Wrap up

That's it! Congrats, you have now set up Abbey with Atlantis!

When your users request access to resources in Abbey, a Pull Request will be created on GitHub. Once all policy and workflow checks pass, reviewers will be notified to approve or deny the request.

You can then perform `atlantis apply` as usual.

After that, you can approve the request on the Abbey App. Abbey will merge the Pull Request.

If your resource has an auto revocation policy, then Abbey will automatically revoke access in which another Pull Request will be created and the same git-based flow will occur, this time undoing the previous access grant.

## Recommendations

### Project Structure

```shell-session
.
├── LICENSE
├── README.md
├── atlantis.yaml
├── environments
│   ├── prod
│   |   ├── main.tf
│   |   ├── terragrunt.hcl
│   |   └── variables.tf
│   └── staging
|
├── modules
│   ├── <app>
│   │   ├── README.md
│   │   ├── access.tf
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── provider.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   └── <app>-access
│       ├── README.md
│       ├── main.tf
│       ├── outputs.tf
│       ├── provider.tf
│       ├── variables.tf
│       └── versions.tf
└── policies
    └── soc2
        └── cc1.rego
```

### Atlantis Repo Config

{% code lineNumbers="true" %}

```yaml
version: 3

projects:
- name: sandbox-atlantis
  branch: /main/
  dir: environments/sandbox-atlantis
  workflow: terragrunt
  autoplan:
    when_modified: ["*.tf"]
    enabled: true

workflows:
  terragrunt:
    plan:
      steps:
        - env:
            name: TERRAGRUNT_TFPATH
            command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
        - env:
            # Reduce Terraform suggestion output
            name: TF_IN_AUTOMATION
            value: 'true'
        - run:
            command: terragrunt plan -input=false -out=$PLANFILE
            output: strip_refreshing
    apply:
      steps:
        - env:
            name: TERRAGRUNT_TFPATH
            command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
        - env:
            # Reduce Terraform suggestion output
            name: TF_IN_AUTOMATION
            value: 'true'
        - run: terragrunt apply $PLANFILE
```

{% endcode %}

### Security Best Practices

1. Hold your sensitive variables in a secrets manager such as [Hashicorp Vault](https://www.hashicorp.com/products/vault), [Doppler](https://www.doppler.com/), or AWS [Secrets Manager](https://aws.amazon.com/secrets-manager/) (or their Azure and GCP equivalent).
2. Atlantis needs to be exposed to GitHub.
   * If via the public internet, configure Basic Auth with a strong password for your Atlantis server.
   * If via VPC, then make sure to have a proxy to relay/route traffic from GitHub to your private/isolated Atlantis server.
3. Make sure that you properly scope your access to repos specific to Atlantis and have appropriate number of members and member privileges to those repos.
4. Make sure to configure a webhook secret if using GitHub. This is the way to authenticate Atlantis against GitHub.
5. Make sure to configure a Repo Allowlist to only repos you want Atlantis to watch. This helps with security scope and scalability as Atlantis will only need to watch a select number of repos.

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).


# Using Abbey with Spacelift

{% hint style="info" %}
**Estimated time:** \~5 minutes
{% endhint %}

In this tutorial, you'll learn how to use Abbey with [Spacelift](https://spacelift.io/).

Abbey helps you manage the workflows for access requests and approvals, making it easier for people to get access to [Resources](/how-abbey-works/concepts#resources).

Spacelift is a sophisticated CI/CD platform for OpenTofu, Terraform, and Terragrunt.

By using Abbey and Spacelift together, you can:

1. Scalably manage your infrastructure access.
2. Securely manage your Terraform state.
3. Easily and securely manage your secrets.

## Before you start

1. Create an [Abbey ](https://accounts.abbey.io/sign-up)account.
2. Have a [Spacelift ](https://docs.spacelift.io/getting-started#step-1-create-your-spacelift-account)account.
3. Have a [GitHub](https://docs.github.com/en/get-started/quickstart/creating-an-account-on-github) account.

## Spacelift Setup

Setting up Spacelift contains 3 steps:

1. [#connect-a-github-repo-to-your-spacelift-account](#connect-a-github-repo-to-your-spacelift-account "mention")
2. [#create-a-stack-on-spacelift](#create-a-stack-on-spacelift "mention")
3. [#add-your-abbey-token-in-spacelift](#add-your-abbey-token-in-spacelift "mention")

## Connect a GitHub repo to your Spacelift account

To get started, we need to add your GitHub repo containing your Terraform files for your Abbey Terraform Resources.

{% hint style="info" %}
If you don't have a GitHub repo with Abbey Terraform Resources, you can easily create one by following one of the [Step-by-Step Tutorials](/getting-started/tutorials).
{% endhint %}

### Navigate to Spacelift Organization Settings

Go to your Spacelift account and navigate to your **Organization Settings**.

<figure><img src="/files/fz0Z4c7WD9zK3jlj4XAM" alt=""><figcaption></figcaption></figure>

### Navigate to Source Code Settings

On the left side panel, navigate to **Source Code** under **OTHER**, then click on **SET UP** in the **GitHub (custom App)** section.

<figure><img src="/files/UnVIAQUoS25eupj8B8WX" alt=""><figcaption></figcaption></figure>

### Use the wizard to configure GitHub

<figure><img src="/files/QybnWYsQNKABc9x7Snq6" alt=""><figcaption></figcaption></figure>

Follow the prompts. You'll be asked to select GitHub.com or a Self-hosted installation, followed by Personal or Organization, and then to confirm to be redirected to GitHub to create your Spacelift GitHub App.

<figure><img src="/files/VL1QItmxwCVMF7FlYsM3" alt=""><figcaption></figcaption></figure>

### Create Spacelift GitHub App

Use the default name supplied by Spacelift and click on **Create GitHub App**

<figure><img src="/files/6Jputa0Kn0JtkBgXPSEe" alt=""><figcaption></figcaption></figure>

Once created, you'll be redirected back to Spacelift.

<figure><img src="/files/lMk05uT3q3Cenf5MHxxZ" alt=""><figcaption></figcaption></figure>

### Navigate to GitHub Developer Settings

You're not done yet! Now you'll need to go to GitHub and navigate to **Developer Settings** to install your newly-created Spacelift GitHub App.

<figure><img src="/files/PkPa0h7FlS2tZGMDeSIT" alt="" width="375"><figcaption></figcaption></figure>

### Edit Spacelift GitHub App

Click on **Edit** next to your Spacelift GitHub App.

<figure><img src="/files/0xNSqgloFmXOuTWExLfQ" alt=""><figcaption></figcaption></figure>

### Install Spacelift GitHub App

Click on **Install** to install your App.

<figure><img src="/files/fsONqdd6gQO4terKqa17" alt=""><figcaption></figcaption></figure>

### Select your repo

This is where you get to scope down the app's permissions. Select the repo containing your Terraform files for your Abbey Terraform Resources.

<figure><img src="/files/xiuf4BoLXD9dvdUXO4a3" alt=""><figcaption></figcaption></figure>

Once you install the app, you'll be redirected back to Spacelift.

## Create a Stack on Spacelift

Now you can create a [Stack](https://docs.spacelift.io/concepts/stack/). You will need a Stack to connect your source control and manage your Terraform state.

### Create Stack

Click on **Create Stack** on the top right.

<figure><img src="/files/SedyYaTZWIffELnRl168" alt=""><figcaption></figcaption></figure>

### Add Stack details

<figure><img src="/files/X3iKV7N24KzfN8Cb5ooF" alt=""><figcaption></figcaption></figure>

### Integrate VCS

<figure><img src="/files/bbeQlpaExSIr4qSL8QTK" alt=""><figcaption></figcaption></figure>

From here, you can choose to go through the rest of the Spacelift screens or simply click on **Skip to summary**.

### Review Summary

Review your choices and then click on **Create Stack**.

<figure><img src="/files/D1tfIrSHdJ6mhqMcQDiP" alt=""><figcaption></figcaption></figure>

## Add your Abbey Token in Spacelift

Now that you have your GitHub repo connected to Spacelift and your Stack created, you'll need to add your Abbey Token as a secret in Spacelift.

### Navigate to your Stack's Environment

Click on your Stack, then click on the **Environment** tab near the top.

<figure><img src="/files/WpMrZeAXchU5w60BfrgO" alt=""><figcaption></figcaption></figure>

### Add your Abbey Token secret

Click on **Edit**, then fill in your `TF_VAR_abbey_token` with your [Abbey Token from the Abbey App](/admin/managing-api-tokens). Now click on **Done** on the top right.

<figure><img src="/files/Xhw2WsF97gTVqwqDvkEF" alt=""><figcaption></figcaption></figure>

## :tada: Wrap up

That's it! Congrats, you have now set up Abbey with Spacelift!

When your users request access to resources in Abbey, a Pull Request will be created on GitHub. Once all policy and workflow checks pass, reviewers will be notified to approve or deny the request. Upon approval, Abbey will merge the Pull Request, followed by Spacelift performing a `plan`. If you have auto-deploy configured in Spacelift, it will then run an `apply`, otherwise you can review a final time and manually `apply` via the Spacelift UI.

If your resource has an auto revocation policy, then Abbey will automatically revoke access in which another Pull Request will be created and the same git-based flow will occur, this time undoing the previous access grant.

## Next Steps

To learn more about what [Resources](/resources/privacy-policy) you can configure, try one of our [Step-by-Step Tutorials](/getting-started/tutorials).


# How Abbey Works

## How does Abbey work?

Abbey acts as a companion to your existing infrastructure by automating access management for you. Your employees request access, Abbey collaborates with your infrastructure to provision access, they use the resources, and access is revoked when they're done.

<figure><img src="/files/pGqkApoNe6PRWDQW3TY7" alt="Requesting access with Abbey"><figcaption><p>Requesting access with Abbey.</p></figcaption></figure>

The core of Abbey consists of 3 components:

1. The **Abbey Terraform Provider** that you use to delegate access management to Abbey.
2. The **Abbey Platform** contains Abbey's Policy Evaluation Engine and Workflow Engine.
3. The **Abbey App** for your employees to discover resources and request access and for your security teams to get visibility into identity and access.

The high-level flow of Abbey has 3 stages:

1. [Delegate access](#delegate-access).
2. [Request access](#request-access).
3. [Grant and revoke access](#grant-and-revoke-access).

### Configuring a Grant Kit

In order to automate access management with Abbey, you use the [Abbey Terraform Provider](https://registry.terraform.io/providers/abbeylabs/abbey/latest/docs) and add [Grant Kit](/reference/grant-kits) resources to your existing Terraform setup.

<figure><img src="/files/1ixEmCzawmFxzO0ZC6F5" alt="Delegate access to Abbey using Terraform"><figcaption><p>Delegate access to Abbey using Terraform.</p></figcaption></figure>

A Grant Kit is a Terraform resource that represents any resource in your infrastructure that you want Abbey to manage for you. You define and configure a Grant Kit for resources, add Access Policies, and deploy normally.&#x20;

The deploy registers your resources with Abbey and effectively says "Hey Abbey, from this point forward, please manage permissions for these resources for me."

{% hint style="info" %}
Resources can be arbitrarily granular and point to any resource you want as long as it's available in the Terraform Registry.
{% endhint %}

### Request Access

After registering your resources with Abbey, your employees can discover and request access to them through familiar UI and chat-based experiences.&#x20;

<figure><img src="/files/OuEZkgOZlJjvLkyTrhYp" alt="" width="563"><figcaption></figcaption></figure>

When someone requests access, Abbey will stage new permissions change in a Pull Request for you. Abbey leverages Pull Requests and Git history to give you secure native capabilities around audit logs and visibility to simplify your compliance story.

<figure><img src="/files/uzXgL8Rj70vIfTri6rD6" alt="Employees discover and request access"><figcaption><p>Employees discover and request access.</p></figcaption></figure>

### Grant and Revoke Access

<figure><img src="/files/AErKr8a96gUAlczjV3N6" alt="Abbey automates granting access"><figcaption><p>Abbey automates granting access.</p></figcaption></figure>

Once your CI/CD checks pass for the Pull Request, Abbey will start the Grant Kit process for granting access.

First, Abbey will evaluate your Access Policies. If any of these policy checks produce a violation, Abbey will automatically deny the access request for you and close the Pull Request.

If the policy checks pass, then Abbey will trigger your approvals workflow and route notifications to the right reviewers to approve or deny the access request. If anyone denies the request, Abbey will again close the Pull Request for you. If all approval conditions are met, then Abbey will merge your Pull Request and materialize the access changes from the request. At this point, the employee will be able to access the resource.

{% hint style="info" %}
Abbey works well with your preferred Terraform setup, whether it's Terraform natively or using one of the many wrappers such as [Terraform Cloud](/getting-started/tutorials/integrating-abbey-with-terraform-cloud).&#x20;
{% endhint %}

Once the employee is done using the resource, you can have their access automatically revoked. Revocation can be configured for a number of use cases, such as on-/offboarding for new hires or team changes, on-call rotations, and more.

<figure><img src="/files/Wkt60VMiapJxxbQl53kD" alt="Abbey automates revoking access"><figcaption><p>Abbey automates revoking access.</p></figcaption></figure>

Abbey's Policy Evaluation Engine is a distributed runtime that continuously evaluates your Revocation Policies. If any of these policies result in a revoke, then Abbey perform the same steps it did for granting permissions, but this time for revoking permissions. Abbey will generate the appropriate change in Terraform and leverage your infrastructure to materialize the revocation changes.

{% hint style="info" %}
To maximize interoperability with other systems, Abbey uses [Open Policy Agent](https://www.openpolicyagent.org/) (OPA) Policies with rules written in Rego.

[Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) rules are written against the Abbey OPA Constraint Framework, which is a minimal version of the [OPA Constraint Framework](https://github.com/open-policy-agent/frameworks/tree/master/constraint).
{% endhint %}


# Key Concepts

## Grant Kits

Grant Kits are what you configure in code to control and automatically right-size permissions for resources. A Grant Kit has 3 components:

1. [Workflow](https://docs.abbey.io/reference/grant-kits/grant-workflows) to configure *how* someone should get access.
2. [Policies](https://docs.abbey.io/reference/grant-kits/policies) to configure *if* someone should get access.
3. [Output](https://docs.abbey.io/reference/grant-kits/outputs) to configure how and where Grants should materialize.

## Access Requests & Approvals

Access Requests are automated processes for someone to be granted access to a [Resource](#resources). An Access Request typically involves:

1. A policy check, typically against a list of security and compliance policies.
2. A list of steps, with each step having a list of reviewers required to approve or deny the request.
3. A Terraform-native code change, backed by your Version Control System and Pull Requests.

## Access Grants

Grants are the result of an approved access request without any policy violations.

## Resources

Resources are what people access. A Resource can be coarse- or fine-grained to any granularity.

Some examples are:

1. Role-Based Access Control (RBAC) such as Okta Groups, Google Groups, AWS IAM Profiles, or GitHub Teams.
2. Direct Access to a database cluster, a database, a table, a Trino query, or a streaming or batch job.
3. Direct Access to an an API cluster, instance, or a bastion.
4. Access to a Tailscale VPN.
5. Federated Access to any of the above through RBAC.

## Linking Identities

Resources can require identity information from an external application. For example, if you're controlling a resource through Github, you may need data associated with Github, say your Github Username, to control access to resources. Abbey lets you link application data from commonly-used applications such as Github so you can use them in creating Grant Kits.


# Get a Starter Kit

Abbey provides a number of official Starter Kits to help you get started quickly with services like AWS, Databricks, etc. In this tutorial, you'll learn where to find Starter Kits and how to set them up.

{% hint style="info" %}
For these steps, you'll be working in

* Github
  {% endhint %}

## Step 1: Clone the starter kit in Git

First, we'll create a new repo in your GitHub account based off our quickstart template repo.

1. Choose a starter kit from the list of [official starter kits](https://github.com/abbeylabs?q=abbey-starter-kit\&type=all\&language=\&sort=)
2. Click on **Use this template**

<figure><img src="/files/RNMf3iHnuA5g2prKMxT0" alt=""><figcaption></figcaption></figure>

3. Click on **Create a new repository** to create the repository
4. Fill out the **Repository name**
5. Click **Create repository**

Here's an example cloning the Abbey Quickstart Repository

<figure><img src="/files/9xSYGtwv3yciPQWeaMiM" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
:checkered\_flag: At this point, you should have a repository in your own GitHub account that is based off an Abbey starter kit
{% endhint %}


# Connect a Repo

In order for Abbey to orchestrate your access requests flows, you'll need to connect a code repository that holds your Terraform files.

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
* GitHub
  {% endhint %}

<details>

<summary>Already set up a starter kit before?</summary>

If you've already set up a connection from Abbey <- -> Github, just make sure the Abbey Github App has permissions for your repo. Either select **All Repositories** or make sure your repo is added to the **Only select repositories** list.

Once that's saved, skip ahead to [Create a Grant Kit](/build-a-grant-kit/create-a-grant-kit) :tada:

<img src="/files/PIv7yVdclfAMSjSdEUd0" alt="" data-size="original">

</details>

## Step 1: Connect Abbey to your Repo

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
* GitHub
  {% endhint %}

To use Abbey for access requests, you'll need to connect Abbey to your GitHub.

### Create a Connection

1. Go to the Abbey App ([app.abbey.io](https://app.abbey.io))
2. Go to the **Settings > Version Control** page and click :heavy\_plus\_sign:**Create a Connection**

<figure><img src="/files/MKebUDZmzzBhTEJtS2Bi" alt=""><figcaption></figcaption></figure>

3. Choose a name for your connection, then click **Create**. You'll be redirected to GitHub to install Abbey on your GitHub account.
4. In the Github App Permissions screen, choose either **All Repositories** or **Only select repositories** with the repository you created earlier in Step 1 selected

<figure><img src="/files/3s2DFvdhZDUsTmPIMoIK" alt=""><figcaption></figcaption></figure>

&#x20;5\. Once you click **Install & Authorize**, you'll be redirected back to the Abbey App, and your connection will be created :tada:

{% hint style="info" %}
:checkered\_flag: Congrats! You've now authorized Abbey to talk with the newly created GitHub repo in your personal account

At this point you should&#x20;

1. Have a connection to GitHub under the Abbey Settings -> Version Control tab
2. Have created a repo into your own GitHub account based off the Abbey Labs Quickstart Repo
3. Have cloned the newly created repo into your own terminal to work with
   {% endhint %}

## Step 2: Configure Permissions for Abbey

{% hint style="info" %}
For this step, you'll be working in

* Abbey App
* Github
  {% endhint %}

### Create an Abbey Token

1. Go to Abbey API Tokens via **Settings -> API Tokens** in the Abbey app
2. Click on the **+ New API Token**
3. Enter a name for your new API token or leave as is
4. Configure the **Expires At** field or leave it blank to have the token never expire
5. Click **Create** to make the new key
6. Copy the key - you'll need this for the next step!

<figure><img src="/files/p9g4isF6G76fEobS1vqC" alt=""><figcaption></figcaption></figure>

### Add your Abbey token to Github

1. Navigate to the repo you created in your own GitHub account
2. Go to the **Settings** tab
3. Select **Secrets and Variables -> Actions** on the left side
4. Create a new **Repository Secret**&#x20;

<figure><img src="/files/svFZDvO535d8YmFTMeTl" alt=""><figcaption></figcaption></figure>

5. For the **Name,** enter in `ABBEY_TOKEN`
6. For the **Secret,** enter in the value of the Abbey API token you created in the last step.
   1. :warning: Make sure you don't have any newlines or spaces when copy/pasting this
7. Click **Add Secret** to finish adding the repository secret

<details>

<summary>What should it look like?</summary>

![](/files/kbDsZTHLunZOznjMX7CV)

</details>

### Update Repo Permissions

Abbey needs a few permissions to operate in your GitHub repo.

1. Go to the **Settings** tab of the same repo you added the API token
2. Select **Actions -> General** on the left side
3. Scroll to the **Workflow Permissions** section
4. Select the **Read and write permissions** button
5. Click on **Save** in the **Workflow Permissions** section

<figure><img src="/files/MIEbqrlEX1voKFqqNP34" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
&#x20;Great! Now you've allowed Abbey to interact with your terraform repository.
{% endhint %}


# Create a Grant Kit

The [Grant Kit](/reference/grant-kits) is the core building block for Abbey. In order to create your first Grant Kit, you can clone one of our [Starter Kits](/build-a-grant-kit/get-a-starter-kit) or you can follow the steps below and use our Grant Kit Builder.&#x20;

{% hint style="info" %}
For this step, you'll be working in

* GitHub Web IDE (github.dev)
* Abbey App
  {% endhint %}

## Step 1: Navigate to Grant Kit Builder

Go to **Resources** page at <https://app.abbey.io/resources> and click on the **+ New Resource** button. Or go directly to <https://app.abbey.io/resources/new>.

<figure><img src="/files/LMlda59TU5R3Mb0KDi9H" alt=""><figcaption><p>Click on the <strong>+New Resource</strong> button</p></figcaption></figure>

## Step 2: Fill Out the Form

Fill out the form. Please note that the **Copy** button at the bottom right will stay disabled until all the required fields have been filled.

<figure><img src="/files/7wWxELNFsgCVmSTCXgYt" alt=""><figcaption></figcaption></figure>

## Step 3: Copy

Once all the required fields have been filled out and the **Copy** button is enabled, you can click it to copy the Grant Kit to your clipboard. Copy the grant kit block into your Terraform repo.

<figure><img src="/files/opkVo7gdSe2SrUfjd9Z2" alt=""><figcaption></figcaption></figure>

Follow instructions in [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit) next.


# Link Identities

## Overview

For a user to request access to a resource in another application, sometimes an identity in this external application is required. For example, if you have a resource which controls access for your Github User to a Github Team, then Abbey needs a mechanism to link a user's central account (often their Abbey account, which is often email) to an identifier in the downstream system.&#x20;

For example:

* Github has [usernames](https://docs.github.com/en/enterprise-server@3.7/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-user-account-settings/changing-your-github-username)
* AWS Identity Center has an [Identity Center ID](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html)
* etc&#x20;

We call this process linking.&#x20;

## What Does it Mean to Link Identities?

Linking an application identity is the process by which we associate the application's identity with your Abbey user. Once identity data has been linked for an external application, Abbey can use this identity data in its grant kits.

Below is an example of linking Github data into Abbey:

```
curl -X POST -d '{"type": "github", "data": {"username": "Alice"}}'
```

This links the Abbey user with Github, and lets Abbey know that the Github username for the Abbey user is "Alice". Now we can refer to this in a grant kit output block using the `user` object as follows:

```hcl
output = {
    location = "..."
    append = <<-EOT
      resource "github_team_membership" "eng_team_membership" {
        team_id = github_team.eng_team.id
        username = {{ .user.github.username }}
        role = "member"
      }
    EOT
}
```

Now when this grant kit is applied, Alice will become part of the `eng_team` Github team. Note that Github specific application information is found in `user.github` and a field named `username` contains the Github username you linked earlier.

## When do I need to link Identities?

By default Abbey provides access to your Abbey email in the `user` object as `user.email` for use in Grant Kits and policies. If the resource you're controlling access to only requires the email you signed up for Abbey with, then you don't need to link any application identity data!

## Which Applications does Abbey Linking with?

Abbey supports linking data from any external application! Abbey does however have first-class support for a set of applications which require linking application data in a specific way.

For more info about linking from first-class supported Abbey applications or just more information about Linking Application Identity Data in general, read [Linking Application Identities into Abbey](/reference/linking-application-identities-into-abbey).


# Write Access Policies

## What are Access Policies?

Access Policies are a way to specify the rules under which a user can get access to a resource.

Access Policies can be of different [types](/reference/access-policies/types-of-access-policies) and be used to allow or deny a request, skip specific workflow steps, or expire access after a certain period of time. For example:&#x20;

* Only Engineers can get access to a table containing PII
* Revoke access after a maximum of 24 hours.
* Require manager approval unless the request is from someone in Engineering

Policies are written in Rego and run by Open Policy Agent, and Abbey evaluates these policies on your behalf. Policies evaluate to either true or false, and if a policy or set of policies evaluate to false, then a user will not be granted access.&#x20;

Policies used to evaluate Access Requests are specified inside Abbey Grant Kit Policy blocks.

## What is Open Policy Agent?

Open Policy Agent (OPA) is an open source, general-purpose policy engine. Open Policy Agent is used to evaluate policies against structured data to make sure that the data passes the policy checks. OPA evaluates policies specified in Abbey Grant Kits and resolve as true or false when an Access Request is made. Abbey creates a structured data payload based on attributes and other information about a user, which is used as input to Policy Evaluation. On a false evaluation, the policy check fails, and the Access Request is denied.

Learn more about OPA [here](https://www.openpolicyagent.org/docs/latest/).

## What is Rego?

Rego is the Open Policy Agent language. Rego is a declarative language based on the well-known query language of Datalog. Rego is the policy language that Abbey and OPA use to evaluate policies. You can find documentation on the Rego language [here](https://www.openpolicyagent.org/docs/latest/).

## How do I write Policies?

There are two ways to write policies:

1. Policy Bundles
2. Inline Policies

Policy Bundles are sets of files that define a Rego package. Policy Bundles allow you to reuse policy code. You can write Policy code once, store it in a Bundle, and refer back to it as many times as you like.&#x20;

Inline Policies are used for simple policies, which don't require the complexity of multiple files. Inline Policies are specified within the definition of an Abbey Grant Kit and can be used for simple policies which require little Rego code in them.&#x20;

Policies can also be used to skip steps a workflow. Details about this and the differences between skipping workflow steps and using a policy for approval are found in [Types of Access Policies](/reference/access-policies/types-of-access-policies).

More information on writing Policy Bundles can be found in the [Policy Bundles](/reference/access-policies/policy-bundles). More information on writing Inline Policies can be found in the [Inline Policies](/reference/access-policies/inline-policies) section.

## Example Policies

The [Policy Examples](/reference/access-policies/policy-examples) section has examples of policies you can use with Abbey.


# Deploy Your Grant Kit

Once you have a [Grant Kit configured](/build-a-grant-kit/get-a-starter-kit) and a [repo connected](/build-a-grant-kit/connect-a-repo), you can deploy your Grant Kit. You would typically do this through your CI.

If you created a Grant Kit using one of the [official Starter Kits](https://github.com/abbeylabs?q=abbey-starter-kit\&type=all\&language=\&sort=), you'll already have GitHub Actions configured for you. You can use these or provide your own. Additionally, they use Terraform State hosted by Abbey, but it's recommended you point your state backends to your own, that way reducing security risk on your end from having state external to your infrastructure.

## Deploy Your Grant Kit

You'll want to commit your grant kit changes to your [default branch in GitHub](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches#about-the-default-branch). For most users, that will be the `main` branch.

To deploy, push to your default branch:

```sh
git push origin main
```

{% hint style="info" %}
The deploy registers your resources with Abbey and effectively says "Hey Abbey, from this point forward, please manage permissions for these resources for me."
{% endhint %}

<details>

<summary>(Optional) Deploy without using CI</summary>

You can optionally deploy from your local machine without going through CI. To do this, you'll need to have Terraform installed. Once installed, you'll need to:

Initialize your Terraform configuration:

```sh
cd $PATH_TO_YOUR_CLONED_REPO
terraform init
```

(Optional) Plan your Terraform configuration:

You can optionally run `terraform plan` to get a sense of what changes would be made.

```sh
terraform plan -var-file=dev.tfvars
```

Before you deploy, make sure you push any changes to your repository. That way, Abbey has the latest changes when generating your Terraform output.

Deploy your Terraform configuration:

```sh
ABBEY_TOKEN=<your API token> TF_HTTP_USERNAME=<http backend username> TF_HTTP_PASSWORD=<abbey token> terraform apply -var-file=dev.tfvars
```

To use the same state backend as your CI/CD, your `TF_HTTP_USERNAME` can be found in your `.github/workflows/abbey-grant-kit-materialize.yaml` file. Your `TF_HTTP_PASSWORD` will be the same value as your `ABBEY_TOKEN`.

</details>

At this point, you should see your deployed grant kit under [app.abbey.io/resources](https://app.abbey.io/resources). If it's not showing up, it likely has a configuration issue causing the deployment to fail.

Go to your CI (or wherever you deploy Terraform) to check for any failed runs during the Terraform plan or apply steps.

If you're following the quickstart, this will be in your GitHub repo under the Actions tab i.e. `https://github.com/{username|org-name}/{repo-name}/actions`. Find the corresponding action run to the commit where you added the grant kit and see if it ran successfully. If it failed, open the run to see the failure exception.

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

* Double check it starts with `github://`
* Double check repository and username or org name is correct
* Double check for any extra `:` or `/`'s


# Request Access

You can request and manage access permissions via the Abbey Web App.

1. Go to the Resources tab of the Abbey App
2. Find the resource you want to request access to
3. Click on the **Request**
4. Click on the **Expire after** dropdown to customize the time the access should last, otherwise skip to step 5
5. Enter in a reason, then hit **Confirm** to submit the request

<figure><img src="/files/ZcBrxqUHceJpwfrLdT9N" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
:tada: You just submitted an access request using Abbey
{% endhint %}

### Canceling a Request

If there's an issue with your request, or you don't need the access anymore - you can cancel it using the **Cancel request** button to the right of the request in the **My Requests** page of the Abbey App.

<figure><img src="/files/miM0GRRsXW5M7eHf2phN" alt=""><figcaption></figcaption></figure>

Follow through the confirmation pop-up to cancel

<figure><img src="/files/axKVqD6mG1lTUx5BvETl" alt=""><figcaption></figcaption></figure>


# Approve or Deny Access Requests

You can review access requests and approve or deny them via the Abbey Web App.

1. Go to the Approvals tab of the Abbey App
2. Find the request you just made (there should only be one)
3. Click **Approve** to the right of the request
4. Enter in a reason, then hit **Approve** to submit

<figure><img src="/files/Fsa790smcGX0lQ6etH8d" alt=""><figcaption></figcaption></figure>

To deny the request, click on the **Deny** button and fill in a reason for denial.

<figure><img src="/files/rwkghvou0bc6z0o8kUEv" alt=""><figcaption><p>Deny an access request.</p></figcaption></figure>


# Time-Based Access

Time-Based Access Policies let you create time-bound access requests. One type of time-based access policy can expire an Access Request after an hour. Another type of time-based access policy can expire an Access Request at a specific time. This means you can offer time-limited access to sensitive resources, or expire access at a certain time.

Check out the following links for specific examples

<table data-view="cards"><thead><tr><th></th><th align="center"></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td align="center"><strong>Expire After a Duration</strong></td><td></td><td><a href="/pages/VQb3wqXRoYMSvnuRGwYu">/pages/VQb3wqXRoYMSvnuRGwYu</a></td></tr><tr><td></td><td align="center"><strong>Expire At a Specific Time</strong></td><td></td><td><a href="/pages/gBbHkI4yXwPktUitLoJk">/pages/gBbHkI4yXwPktUitLoJk</a></td></tr></tbody></table>


# Expire After a Duration

In this guide, you'll learn how you can configure a Grant Kit to automatically revoke access to a grant after some duration. You'll do this by importing and using an expiration policy Abbey provides out-of-the-box.

We will be using the [Quickstart](/getting-started/quickstart) as a base and modify it to this use case.

## Step 1: Add a Directory for Your Policy

In your repo, add a directory to put your policies.

{% code title="/" %}

```diff
.github/
+ policies/
+   .manifest
+   common.rego
.gitignore
.terraform.lock.hcl
LICENSE
README.md
access.tf
main.tf
outputs.tf
variables.tf
```

{% endcode %}

{% hint style="info" %}
Abbey will automatically build your policies for you using the standard Open Policy Agent (OPA) CLI via `opa build`.
{% endhint %}

## Step 2: Configure Your Manifest and Policy

First, configure your Manifest in your `.manifest` file. This will tell the Policy Engine where your policy file is located.

```diff
+ {"roots": ["common"]}
```

Next, write your policy using Abbey's expiration helper functions.

{% code title="common.rego" lineNumbers="true" %}

```rego
package common

import data.abbey.functions

allow[msg] {
  functions.expire_after("24h")
  msg := "granting access for 24 hours."
}
```

{% endcode %}

{% hint style="info" %}
Abbey revokes grants in realtime. When 24 hours has passed, the grant will be revoked immediately.
{% endhint %}

{% hint style="success" %}
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
{% endhint %}

## Step 3: Add Your Policy

Now that you have your policy set up, you can add it to your Grant Kit.

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "null_grant" {
  ...
  
+  policies = [
+    {
+      bundle = "github://example-org/example-repo/policies"
+    }
+  ]

  ...
}
```

{% endcode %}


# Expire At a Specific Time

In this guide, you'll learn how you can configure a Grant Kit to automatically revoke access to a grant after some date. You'll do this by importing and using an expiration policy Abbey provides out-of-the-box.

We will be using the [Expire After a Duration](/use-cases/time-based-access/expire-after-a-duration) guide as a base and modify it to this use case.

## Step 1: Configure Your Policy

Write your policy using Abbey's expiration helper functions.

{% code title="common.rego" lineNumbers="true" %}

```rego
package common

import data.abbey.functions

allow[msg] {
  functions.expire_at("2023-06-15T04:00:00+00:00")
  msg := "granting access funtil 06/15/2023 4am UTC."
}
```

{% endcode %}

Unlike the `functions.expire_after` helper which uses a duration, the `functions.expire_at` takes an RFC 3339 datetime string.

{% hint style="info" %}
Abbey revokes grants in realtime. When the date and time is reached, the grant will be revoked immediately.
{% endhint %}


# Approval Workflows

Abbey provides opinionated, yet flexible building blocks for you to easily and maintainably configure approval workflows to meet various security and compliance use cases.

<table data-view="cards"><thead><tr><th></th><th align="center"></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td align="center"><strong>Using a Single Approval Step</strong></td><td></td><td><a href="/pages/7CtrK5Tgfy4dl32qxVgd">/pages/7CtrK5Tgfy4dl32qxVgd</a></td></tr><tr><td></td><td align="center"><strong>Using Multiple Approval Steps</strong></td><td></td><td><a href="/pages/2KxYs8U6wOVHdFREmdZO">/pages/2KxYs8U6wOVHdFREmdZO</a></td></tr><tr><td></td><td align="center"><strong>Conditionally Skip Approval Steps</strong></td><td></td><td><a href="/pages/rJPrPn1rQx5M6wEjaCtJ">/pages/rJPrPn1rQx5M6wEjaCtJ</a></td></tr></tbody></table>


# Using a Single Approval Step

In this guide, you'll learn how you can configure a Grant Kit to have a single review step. The step will contain a list of reviewers required to approve or deny an access request.

We will be using the [Quickstart](/getting-started/quickstart) as a base and modify it to this use case.

## Step 1. Add a Workflow Step

Add a workflow step to your Grant Kit. Other configuration fields such as `policies` and `output` are omitted for brevity.

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "null_grant" {
  ...

+  workflow = {
+    steps = [
+      {
+        reviewers = {
+          one_of = ["alice@example.com"]
+        }
+      }
+    ]
+  }

  ...
}
```

{% endcode %}

We now have a workflow with one step.

First, Alice will be notified to review. If she approves, the access request will be approved overall. This is because there's no one else in the list to require a review from.

If Alice denies the request, then the access request overall will be denied.

{% hint style="info" %}
By default, Abbey waits for 1 week for pending access requests before automatically denying them. This is to reduce access request debt and ensure you have more tidy access management.
{% endhint %}


# Using Multiple Approval Steps

In this guide, you'll learn how you can configure a Grant Kit to have multiple review steps. Each step will contain a list of reviewers required to approve or deny an access request.

We will be using the [Using a Single Approval Step](/use-cases/approval-workflows/using-a-single-approval-step) as a base and modify it to this use case.

## Step 1. Add Another Workflow Step

Add another step to our workflow, but this time add an additional reviewer

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "null_grant" {
  ...

  workflow = {
    steps = [
      {
        reviewers = {
          one_of = ["alice@example.com"]
        }
-      }
+      },
+      {
+        reviewers = {
+          one_of = ["bob@example.com", "carol@example.com"]
+        }
+      }
    ]
  }

  ...
}
```

{% endcode %}

We now have a workflow with two steps. These steps will run serially.

First, Alice will be notified to review. If she approves, Bob and Carol will be notified to review. If Alice denies the request, then the access request overall will be denied. Bob and Carol wouldn't be notified at all in this scenario.

Second, Bob and Carol are requested to review. Either of them may approve the request because of the `one_of` constraint was configured. Further, if Bob approved and Carol hasn't responded, the overall step will be considered approved.

## Step 2: Add Another, Stricter Workflow Step

Add another workflow step and have a stricter constraint for reviewers.

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "null_grant" {
  ...

  workflow = {
    steps = [
      {
        reviewers = {
          one_of = ["alice@example.com"]
        }
      }
      },
      {
        reviewers = {
          one_of = ["bob@example.com", "carol@example.com"]
        }
-      }
+      },
+      {
+        reviewers = {
+          all_of = ["dan@example.com", "eve@example.com", "frank@example.com"]
+        }
+      }
    ]
  }

  ...
}
```

{% endcode %}

We now have a 3 step workflow. The last step requires all reviewers in the list to review.

If one of these reviewers deny the request, then the overall request will be denied. If less than all reviewers approve, then the step will wait until everyone approves.

{% hint style="info" %}
By default, Abbey waits for 1 week for pending access requests before automatically denying them. This is to reduce access request debt and ensure you have more tidy access management.
{% endhint %}


# Conditionally Skip Approval Steps

In this guide, you'll learn how you can configure a Grant Kit to have multiple review steps. Each step will contain a list of reviewers required to approve or deny an access request. One of these steps will be skipped based on a condition we define in a policy.

We will be using the [Using Multiple Approval Steps](/use-cases/approval-workflows/using-multiple-approval-steps) as a base and modify it to this use case.

## Step 1. Add a Policy to Skip a Step

Let's make the second step skippable. We may want to do this for many reasons. Here are some ideas:

1. Skip a step if someone has a privilege, for example, they're on-call.
2. Skip a step if someone belongs to a privileged team, for example, if they're an account manager.
3. Skip a step if someone is above a certain level in their organization.

For this example, let's skip the last step if someone is on-call, as determined by PagerDuty.

{% code title="main.tf" lineNumbers="true" %}

```diff
resource "abbey_grant_kit" "null_grant" {
  ...

  workflow = {
    steps = [
      {
        reviewers = {
          one_of = ["alice@example.com"]
        }
      }
      },
      {
        reviewers = {
          one_of = ["bob@example.com", "carol@example.com"]
        }
      }
      },
      {
        reviewers = {
          all_of = ["dan@example.com", "eve@example.com", "frank@example.com"]
        }
+        skip_if = [
+          { bundle = "github://example-org/example-repo/policies/on-call" }
+        ]
+      }
    ]
  }

  ...
}
```

{% endcode %}

**Note**: This github repo should be the same as the repo defined in your [Outputs](/reference/grant-kits/outputs)

We added a Policy Bundle that contains rules for skipping if someone is on-call. This bundle was prebuilt using Open Policy Agent and exists within the same repo as the `main.tf` file.

To get a sense of the logic, take a look at the policy:

{% code title="policies/on-call/pagerduty.rego" lineNumbers="true" %}

```rego
package pagerduty

skip[msg] {
  user.pagerduty.isoncall == true
  msg := "skipping review step for on-calls"
}
```

{% endcode %}


# User Roles

Abbey lets you distinguish between roles so that you can ensure the integrity of your organization's settings by preventing accidental or unauthorized changes.

There are two types of users in Abbey: Admins and Members.&#x20;

### Admin

Admin roles provide members with full access to manage all aspects of the organization, including its resources, memberships, and settings. This includes the capabilities to add, update, and delete Grant Kit Resources, as well as modify Abbey Settings.

### Member

The standard Member role within an organization allows users to view Grant Kit Resources and handle access requests, including both requesting and approving them, allowing participation and collaboration within the organization.

<table><thead><tr><th width="269">Action</th><th width="182" align="center">Admin</th><th align="center">Member</th></tr></thead><tbody><tr><td>View Resources</td><td align="center">✅ </td><td align="center">✅</td></tr><tr><td>Update/delete Resources</td><td align="center">✅ </td><td align="center">❌</td></tr><tr><td>Request Access</td><td align="center">✅</td><td align="center">✅</td></tr><tr><td>Approve Access</td><td align="center">✅</td><td align="center">✅</td></tr><tr><td>Manage Abbey</td><td align="center">✅</td><td align="center">❌</td></tr></tbody></table>

## How to Assign a Role

{% hint style="info" %}
You must be an admin to assign roles.
{% endhint %}

### New User

1. Click on the organization name on the side menu bar\
   ![](/files/DTbIPHx0ATIZNLu161uB)
2. Click **Manage Organization** to open the modal
3. Click on **Members > Invitations > Invite**<br>

   <figure><img src="/files/n2Dmznz6kegfB2vUv0qe" alt=""><figcaption></figcaption></figure>
4. Type the email address of the user you are trying to invite
5. Select the desired **Role** for the user
6. Click **Send Invitations** button<br>

   <figure><img src="/files/x6izyxN1v8Z6eKvWSLDc" alt=""><figcaption></figcaption></figure>

### Existing User

1. Click on the organization name on the side menu bar\
   ![](/files/DTbIPHx0ATIZNLu161uB)
2. Click **Manage Organization** to open the modal
3. Click on **Members > Members**
4. Find the user in the list of users
5. Use the **Role** dropdown to configure the desired role for the user<br>

   <figure><img src="/files/TpnrtlJZz9CWP37EJepb" alt=""><figcaption></figcaption></figure>


# Sign-in and MFA


# Sign-in Methods

Users can sign-in using one of three methods:&#x20;

* **Credential:** An email and a password set by the user that adheres to [NIST guidelines](https://clerk.com/docs/security/password-protection), including enforcing character limits and ensuring that the password isn't compromised in prior breaches
* **Social Providers:** Abbey currently supports Social Login via Google, Github, or Microsoft.&#x20;
* **Magic Link:** A user will get a link to sign-in via their email with a verification code, creating a fully passwordless experience.&#x20;


# Multifactor Authentication (MFA)

The usage of Multifactor Authentication (MFA) helps users add an additional layer of security above and beyond their [initial sign-in mechanism](/admin/sign-in-and-mfa/sign-in-methods). &#x20;

Abbey supports the following MFA methods:&#x20;

* **Authenticator Apps:** These include Google Authenticator, Duo, and others. These apps generate a one-time code that the user then inputs into Abbey on sign-in.&#x20;
* **Backup Codes:** A user can generate a list of unique codes they can save and use once.&#x20;

It is currently configured on a per-user basis and is optional. A user can configure MFA by selecting their profile within the Abbey application, and clicking **Manage Account**.&#x20;

<figure><img src="/files/aNqq3aydbZpbvMpNF1vK" alt="" width="375"><figcaption></figcaption></figure>

Under **Security**, they then select **Add two-step verification**, and complete the registration flow for a new factor.&#x20;

<figure><img src="/files/RJaXGjH1SVllhJ5TBHob" alt="" width="375"><figcaption></figcaption></figure>


# Enabling Single Sign-On

## Overview

Single Sign On (SSO) delegates authentication to a 3rd party identity provider such as Okta, Google Workspace, or Azure AD. Abbey supports SSO via the use of a standardized authentication protocol, SAML.&#x20;

Abbey currently supports SSO via Google Workspace and Okta, with more providers on the way.&#x20;

## Setup

* [Setup SSO with Google Workspace](#google-workspace)
* [Setup SSO Okta](#okta)
* [Using SSO](#using-single-sign-on)

### Google Workspace

1. Navigate to the SSO Page under <https://app.abbey.io/>

<figure><img src="/files/t3RAB4cdptE3fsaD307a" alt=""><figcaption><p>SSO Connections</p></figcaption></figure>

2. Go to Google Workspaces and navigate to Apps -> Web and mobile apps

<figure><img src="/files/drdcfI32YRatqznMdbtf" alt=""><figcaption><p>Web and Mobile Apps</p></figcaption></figure>

3. Click Add app -> Add custom SAML app

<figure><img src="/files/GSC4LpHfkvM66y38enP2" alt=""><figcaption></figcaption></figure>

4. Enter in basic details about your SAML Application

<figure><img src="/files/t6nUQwNNS3824PPsULV9" alt=""><figcaption><p>Basic App Info</p></figcaption></figure>

5. Now you'll be presented with a screen in the Google Admin console with Identity Provider information. Use that to create a new SSO connection in Abbey.

<figure><img src="/files/ka0pbWw6UOK2TzcUKBb2" alt=""><figcaption><p>Identity Provider Metadata</p></figcaption></figure>

6. Click on *New SSO Connection* and fill in the information presented above

<figure><img src="/files/j8syvlWnpc0WFDrPtlVX" alt=""><figcaption><p>New SSO Connection</p></figcaption></figure>

7. Now you'll see your new SSO connection. Click on it to get the URLs needed by Google Workspaces to finish the SSO connection process.

<figure><img src="/files/DjfRK475wVvEhQWd5KmR" alt=""><figcaption><p>Connection Created</p></figcaption></figure>

<figure><img src="/files/lt9shjunAfrug6aQ4u5S" alt=""><figcaption><p>URLs needed by Google Workspace</p></figcaption></figure>

8. Copy over those values into the next screen for the Google Workspace setup

<figure><img src="/files/LjKAEHhiTJlYLX5aVura" alt=""><figcaption><p>Service Provider Details</p></figcaption></figure>

9. Finish the wizard

<figure><img src="/files/jEVWVHOcaZQDXRIJkNIF" alt=""><figcaption><p>Finish the wizard</p></figcaption></figure>

10. Grant permission to users who you want to grant Abbey access to the permission to use the new SAML app you created

<figure><img src="/files/uYJtswyTLxZaCjOTFpYT" alt=""><figcaption><p>Example of turning Abbey on for everyone</p></figcaption></figure>

11. Click the *Activate* slider to activate the SAML Connection. Confirm in the modal.

<figure><img src="/files/dIkHsZdE7OnMgt1khruo" alt=""><figcaption></figcaption></figure>

###

### Okta

1. Navigate to the SSO page

<figure><img src="/files/t3RAB4cdptE3fsaD307a" alt=""><figcaption><p>SSO Connections</p></figcaption></figure>

2. Create a new SSO Connection but do not fill in the IDP SSO URL, IDP Entity ID, and IDP Certificate fields

<figure><img src="/files/TPqoLz1ya8B3nYaGlTfn" alt=""><figcaption><p>New SAML SSO Connection</p></figcaption></figure>

3. Once you create the connection, click on it to find metadata associated with the SAML SSO Connection

<figure><img src="/files/0370GelA7ZhoTpCqK4gm" alt=""><figcaption><p>SSO SAML Connection Details</p></figcaption></figure>

4. Navigate to the Applications screen underneath the Applications sidebar entry

<figure><img src="/files/HiUD74cJKwjE397Lt1E9" alt=""><figcaption><p>Applications -> Applications</p></figcaption></figure>

5. Click Create App Integration and select SAML 2.0 for the app integration type

<div><figure><img src="/files/GIR8H4uZRgfGcKIqVZ4M" alt=""><figcaption><p>Create App Integration</p></figcaption></figure> <figure><img src="/files/u7Vix3FfaGg9hZGZ8JCH" alt=""><figcaption><p>SAML 2.0 Integration Type</p></figcaption></figure></div>

6. Give your SAML Integration App a name and click Next

<figure><img src="/files/4v6a5lHPg1YZKa5gF7rv" alt=""><figcaption><p>SAML Integration General Settings</p></figcaption></figure>

7. Copy/paste the values shown in the Abbey SSO SAML Connections Screen into this Okta screen. The ACS Provider URL corresponds to the Single sign-on URL in Okta and the SP Entity ID corresponds to the Audience URI (SP Entity ID) field in Okta. Hit Next.

<figure><img src="/files/tiQtY6nntjuN0qk9bJvE" alt=""><figcaption><p>Fill in general SAML Settings Values</p></figcaption></figure>

8. Click the radio button for "I'm an Okta customer adding an internal app" and fill in the other fields as you see fit. Then finish the process. This completes the Okta end of the setup.

<figure><img src="/files/ZfxESCu3L3qptK2qqBbD" alt=""><figcaption><p>Okta Support Information</p></figcaption></figure>

9. Go to your Applications and click on the new Application you just created. Click on the Sign On tab. Scroll down under the SAML 2.0 section until you see the "Show Details" text. Click it to see relevant SAML details that you will need to copy/paste into Abbey to complete the Abbey side of the SAML connection.

<figure><img src="/files/7Q0xz9mtGgGuqEBQmijz" alt=""><figcaption><p>Application Sign On Tab</p></figcaption></figure>

###

<figure><img src="/files/9vYhzZBJtfnRE9LorXFU" alt=""><figcaption><p>Show Details for Application</p></figcaption></figure>

10. Copy the Sign on URL field into the Abbey IDP SSO URL field, copy the Issuer URL into the Abbey IDP Entity ID field and copy the Signing Certificate into the IDP Certificate field. Then hit Update.

<figure><img src="/files/BVuvN2c99kQpuqcm2ycZ" alt=""><figcaption><p>Finish Abbey SAML Connection Details</p></figcaption></figure>

11. Once you see your SAML connections, activate your new SAML Connection

<figure><img src="/files/RXmBu5eUmpvIeb2xYXBp" alt=""><figcaption><p>Activate your SAML Connection</p></figcaption></figure>

## Using Single Sign On

Simply put the email address associated with your user into the login screen, and Abbey will check to see if you are logged in with your IDP.&#x20;

If the user has an active session, they'll proceed seamlessly. If not, they'll be asked to log in, after which they'll be signed into Abbey.&#x20;

<figure><img src="/files/rsiIrkMHLiwx1VRFWkqK" alt=""><figcaption><p>SSO Login</p></figcaption></figure>


# Sources


# PagerDuty

This feature enables you to setup a connection between PagerDuty and Abbey so that Abbey can collect the on-call status of a given user. This status can then be used in policies to either auto-deny access (if a user is not on-call) or skip specific approval steps (in the event a user is on-call).

## Add a PagerDuty Connection

1. Go to [**Settings > Sources**](https://app.abbey.io/settings/sources/) page
2. Click on either **+ Add a New Source** or **+ New Source** button

   <figure><img src="/files/Uh05gxv68GHP7C6BpCPo" alt=""><figcaption><p>Settings > Sources page</p></figcaption></figure>
3. In the **"Select a source type"** dropdown, pick **PagerDuty** as the source type
4. Choose a name for your connection, and click **Create** to be redirected to PagerDuty<br>

   <figure><img src="/files/pBl6NIrkov4ymlwS4sjQ" alt=""><figcaption></figcaption></figure>
5. Log into PagerDuty.<br>

   <figure><img src="/files/3uUpQtIyZP7Ucn3TlSbE" alt=""><figcaption></figcaption></figure>
6. Click **Submit Consent** to authorize Abbey Labs to read your on-call details

   <figure><img src="/files/OiW4uDyErtDnQzADoisB" alt=""><figcaption></figcaption></figure>
7. After that, it should automatically redirect you back to Abbey, and your PagerDuty connection is now created. You're now all set to use PagerDuty on-call status in your policies and outputs

   <figure><img src="/files/LJPvYuQwyZeGTtCgRL6r" alt=""><figcaption></figcaption></figure>

## Use PagerDuty On-Call Status&#x20;

Now that you have set up a PagerDuty connection, you can reference PagerDuty on-call schedules in policies skip certain approval steps.

### Add a Policy to Skip a Step

1. Add a rego policy to skip a workflow if the user is on-call in PagerDuty

   <pre class="language-rego" data-title="policies/on-call/pagerduty.rego" data-line-numbers><code class="lang-rego"><strong>package pagerduty
   </strong>
   skip[msg] {
     data.user.pagerduty.is_on_call
     msg := sprintf("skipping oncall: %v", [data.user.pagerduty.is_on_call])
   }
   </code></pre>

   Make sure to add `.manifest` as well

   <pre class="language-json" data-title="policies/on-call/.manifest" data-line-numbers><code class="lang-json">{"roots": ["pagerduty"]}
   </code></pre>

2. Add `skip_if` block to the workflow you want to skip.

   <pre class="language-diff" data-title="main.tf" data-line-numbers><code class="lang-diff">resource "abbey_grant_kit" "null_grant" {
     ...

     workflow = {
       steps = [
         {
           reviewers = {
             all_of = [
               "alice@example.com",
               "bob@example.com",
               "carol@example.com"
             ]
           }
   +        skip_if = [
   +          { bundle = "github://example-org/example-repo/policies/on-call" }
   +        ]
   +      }
       ]
     }

     ...
   }
   </code></pre>

3. Now that you have updated your Grant Kit, [Deploy Your Grant Kit](/build-a-grant-kit/deploying-your-grant-kit)

And that's it.

* When a user requests access and they **are** on-call, they will skip the review process and will be granted access right away.
* When a user requests access and they are **not** on-call, their request has to be reviewed by one of the reviewers as usual.


# Directory Sync

Directory Sync is allows you to bring information into Abbey about users and groups from an Identity Provider such as Okta or G Suite.

This information can then be used to write more effective [Policies](/reference/grant-kits/policies) and [Grant Kits](/reference/grant-kits).

For example:

* A user can be automatically granted access via a group membership in G Suite
* A user can be automatically denied access based on an attribute in Okta.

{% hint style="info" %}
Supported Integrations:

* G Suite
* Okta
  {% endhint %}

## Setting up Directory Sync

In order to set up Directory Sync, click on the Directory Sync tab in the sidepanel on the Abbey Labs app. Click on "Create a Directory" to begin setup.

<figure><img src="/files/saCeCFFeMPJiDAgCvuES" alt=""><figcaption><p>Directory Sync Setup Page</p></figcaption></figure>

On the next page, enter the name for your Directory and the domain you want to retrieve data from.

<figure><img src="/files/BxVvhgqzLZs7Ryivzsne" alt=""><figcaption><p>New Directory Sync options</p></figcaption></figure>

Next, click on the Complete button to complete the setup required by your Identity Provider

<figure><img src="/files/nUiszxL33QiNl6Z6tE87" alt=""><figcaption><p>Complete Setup Screen</p></figcaption></figure>

Choose your Identity Provider. Currently we only officially support Google Workspace for writing policies and grant kits.

<figure><img src="/files/AljKW27x7MKWZKRqfF11" alt=""><figcaption></figcaption></figure>

Complete the steps indicated for your Identity provider. Example steps are given below.

### ![](/files/WxqFI9VcrmFvYbGosJfe)![](/files/4IdCBXRLI6mnhigZqL6A)

When you're done setting up you will see a screen similar to the following. You can then return to the Directory Sync page in the Abbey App, and can view your user data in the Users page.

<figure><img src="/files/eUG24I84gryK6DW4xZuI" alt=""><figcaption><p>Directory Sync Setup Complete</p></figcaption></figure>

<figure><img src="/files/A5dDss6sua5gQJ28RQNX" alt=""><figcaption><p>Directory Sync Status Page in Abbey App.</p></figcaption></figure>

### Users Info

The Users page displays information retrieved from Directory Sync.

<figure><img src="/files/X45EwxhpmCeU7L3Scdli" alt=""><figcaption><p>Users Page</p></figcaption></figure>

For detailed information on the user object, click the icon. This information is the same format as in [Policies](/reference/grant-kits/policies#enriched-data)\\

<figure><img src="/files/F0VvzPoqoSk65jxFSyov" alt=""><figcaption><p>Detailed User Object</p></figcaption></figure>


# End User Notifications

## Overview

Abbey supports notifications via email and Slack.&#x20;

## Email Notifications

Email notifications are on by default; there's no setup required. Abbey will notify the user via the email associated with their Abbey account.&#x20;

Abbey notifies users via email from **<notifications@abbey.io>** on the following events:&#x20;

| Event                          | User Notified |
| ------------------------------ | ------------- |
| User Requests Access           | Requester     |
| Request was Approved           | Requester     |
| Request was Denied             | Requester     |
| Grant Expired                  | Requester     |
| Approval is Required           | Approver      |
| Approval is No Longer Required | Approver      |

## Slack Notifications

Abbey supports DM-based notifications via Slack. We'll notify reviewers when an access request requires their approval.&#x20;

### Setup

Navigate to Settings -> [Notifications](https://app.abbey.io/settings/notifications)&#x20;

<figure><img src="/files/230spBxB7awh3vOG1yvP" alt=""><figcaption></figcaption></figure>

Click on **+ New Notification** to set up the Slack integration. This will take you to another screen with a **Add to Slack option**.

After clicking "Add to Slack", you'll be directed to an app install page by Slack. Pick a channel - any channel is fine, we only sends DMs to users for notifications.

<figure><img src="/files/19Ear5biCrRFuBcBs9zG" alt=""><figcaption></figcaption></figure>

After this, you should see your Connection configured under the [Notifications](https://app.abbey.io/settings/notifications) tab. :tada:


# Manage API Tokens

API Tokens allow you or a service such as Github to programmatically access Abbey.

API Tokens can be accessed through the [**Settings > API Tokens**](https://app.abbey.io/settings/developers) page on the Abbey App. From here you can access, view, create, and delete new API Tokens.

<figure><img src="/files/NAXTo7w2rYJsETx81edN" alt=""><figcaption></figcaption></figure>

## Creating new API Tokens

To create a new API Token, click on the **+ New API Token** button. From there, you can enter the name of the API Token and click **Create** to create your new key. To make your token never expire, click on the datepicker and click **Clear** to clear the date.

<figure><img src="/files/p3WjIoOKOoAIMD0H3C8K" alt=""><figcaption></figcaption></figure>

## Deleting API Tokens

To delete an API Token, click the trashcan icon next to the API Token you wish to delete. Then click on **Delete** button to confirm that you want to delete the key.

<figure><img src="/files/5PPrTYtAIKGkyLkuBueP" alt=""><figcaption></figcaption></figure>


# Grant Kits

A Grant Kit allows you to automatically control and right-size permissions to sensitive resources. Grant Kits allow you to define [Workflows](/reference/grant-kits/grant-workflows) (how someone should get access), [Policies](/reference/grant-kits/policies) (if they should get access), and an [Outputs](/reference/grant-kits/outputs)  template (how and where you want the automated permission grants to materialize) for a specific Target resource.

## Grant Kit Spec

```hcl
resource "abbey_grant_kit" "this" {
    workflow = { ... } # _how_ an identity should get access.
    policies = { ... } # _if_ an identity should get access.
    output = { ... }   # _how_ and _where_ permission grants should be materialized.
}
```


# Workflows

A Workflow, written natively in [Terraform](https://www.terraform.io/) using [HCL](https://developer.hashicorp.com/terraform/language/syntax/configuration), defines *how* someone should get access to a Resource.

## Workflow Spec

```hcl
workflow = {
    steps = [
        {
            reviewers = {
                # one_of = ["...", "...", ...]
                # all_of = ["...", "...", ...]
            },
            skip_if = [
                {
                    # bundle = "..."
                    # query = "..."
                }
            ]
        }
    ]
}
```

## Writing Workflows For Your Grant Kit

Workflows are written using the Grant Kit's Workflows DSL as native Terraform HCL code.

Writing Workflows consists of three steps:

1. [Add your steps](#add-your-steps).
2. [For each step, choose a Reviewer Constraint](#for-each-step-choose-a-reviewer-constraint).
3. [For each step, optionally add a Workflow Policy](#for-each-step-optionally-add-a-workflow-policy).

### Add Your Steps

Workflows can have one or more steps. Each step is an object that you configure in a list as defined in the [Workflow Spec](#workflow-spec).

<details>

<summary>Example Workflow Step Configurations</summary>

```hcl
// Workflow with a single step.
steps = [
    { ... }
]

// Workflow with 3 steps.
steps = [
    { ... },
    { ... },
    { ... }
]
```

</details>

{% hint style="info" %}
There's no practical limit to the number of Workflow Steps you can have.
{% endhint %}

### For Each Step, Choose a Reviewer Constraint

Each step must have a Reviewer Constraint that represents how many of the reviewers must approve an access request for the current step to be considered approved overall.

Abbey supports two types of Reviewer Constraints:

1. `one_of`: Require only one of the reviewers in the list of reviewers to approve.
2. `all_of`: Require all of the reviewers in the list of reviewers to approve.

<details>

<summary>Example Workflow Step Configurations with Reviewer Constraints</summary>

```hcl
# Workflow with multiple steps.
#
# The first step only requires one out of 3 reviewers to approve.
#
# The second step requires all reviewers (2 out of 2) to approve.
#
# The third step only requires one reviewer to approve, but
# effectively behaves like an `all_of` because there's only
# one reviewer in the list.
steps = [
    {
        reviewers = {
            one_of = ["alice@example.com", "bob@example.com", "carol@example.com"]
        }
    },
    {
        reviewers = {
            all_of = ["dan@example.com", "eve@example.com"]
        }
    },
    {
        reviewers = {
            one_of = ["frank@example.com"]
        }
    }
]
```

</details>

### For Each Step, Optionally Add a Workflow Policy

Each step may optionally have Workflow Policies attached to it. Workflow Policies define *when* or *if* someone should have their access revoked.

<details>

<summary>Example Workflow Step Configurations with Reviewer Constraints and Workflow Policies</summary>

```hcl
# Workflow with multiple steps.
#
# The first step has a single Workflow Policy attached.
# If the policy check passes, then the step will be skipped and
# none of the reviewers will be notified to review the access request.
#
# The second step has two Workflow Policies attached.
# Both of these policy checks must pass in order for the step to be skipped.
#
# The third step doesn't have a Workflow Policy.
# This means the step is required and will always be run.
steps = [
    {
        reviewers = {
            one_of = ["alice@example.com", "bob@example.com", "carol@example.com"]
        }
        skip_if = [
            { ... }
        ]
    },
    {
        reviewers = {
            all_of = ["dan@example.com", "eve@example.com"]
        }
        skip_if = [
            { ... },
            { ... }
        ]
    },
    {
        reviewers = {
            one_of = ["frank@example.com"]
        }
    }
]

```

</details>

For more information on how to add Workflow Policies, visit the [Policies](/reference/grant-kits/policies#configuring-policies-for-your-grant-kit) page.

## Workflow Step Evaluation

Abbey runs your Grant Kit Workflows using Abbey's distributed Workflow Engine. Workflows consist of a series of Workflow Steps you configure for an access request for access to be approved.

Workflow Steps are evaluated serially as shown in the following diagram:

<figure><img src="/files/PhIIer78K8crgbM8z5nW" alt="Workflow Step Evaluation"><figcaption><p>Workflow Step Evaluation.</p></figcaption></figure>

This diagram shows a Workflow with two Steps. For each Step, it will:

1. Evaluate Workflow Policies.
   * If the policies result in a `skip = true`, then this step will be skipped. As a result, none of the reviewers in the reviewer list will be notified to approve or deny the access request.
2. Notify reviewers.
   * Each Step must contain a list of reviewers. This is a list of strings that represent someone's [Primary Identity](/how-abbey-works/concepts#primary-identity).
   * Each reviewer may contain different notification channels, such as the Abbey App or Slack.
   * The Notification Router will notify reviewers on all of these channels.
3. Wait for the Reviewer Constraint to be met.
   * The list of reviewers are configured with a [Reviewer Constraint](#for-each-step-choose-a-reviewer-constraint), either `one_of` or `all_of`.
   * If using `one_of`, then only one reviewer from the list needs to approve for the Step to be considered approved. The Workflow Engine will then advance to the next step.
     * If no one has approved the access request yet and a deny is received from a reviewer, the Workflow Engine will auto-deny the step. This auto-deny will bubble up to the Workflow and result in access being denied overall.
   * If using `all_of`, then all reviewers from the list must approve for the Step to be considered approved. The Workflow Engine will advance to the next step only after this condition is met.
     * If some, but not all, approvals have been received, and a deny is received from a reviewer, the Workflow Engine will auto-deny the step.This auto-deny will bubble up to the Workflow and result in access being denied overall.

Once all Steps are approved, access will be granted.


# Policies

Policies, written as [Open Policy Agent](https://www.openpolicyagent.org/) (OPA) Policies in [Rego](https://www.openpolicyagent.org/docs/latest/#rego), 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 [Workflow Step](/reference/grant-kits/grant-workflows#steps) should be skipped.

## Polices Spec

### Access Policies

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

### Workflow Policies

```hcl
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.

These attributes represent a list of OPA Policies as either a [`bundle`](#bundles) or a [`query`](#queries).

<details>

<summary>Example Policy Configurations</summary>

{% code lineNumbers="true" %}

```hcl
// 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 = "..." }
        ]
    }
]
```

{% endcode %}

</details>

### Bundles

A Bundle is a native [OPA Bundle](https://www.openpolicyagent.org/docs/latest/management-bundles/#bundle-build) that represents a group of OPA Policies. Bundles are typically either a directory or a gzipped tarball.

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

```shell-session
github://{organization}/{repository}/path/to/my/bundle[.tar.gz]
```

<details>

<summary>Example Bundle Configurations</summary>

```
// 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
```

</details>

{% hint style="info" %}
Currently Abbey supports the `github://` scheme. Future schemes such as `file://`, `s3://`, and `https://` coming soon.
{% endhint %}

#### 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:

```shell-session
❯ 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.

<details>

<summary>Example <code>.manifest</code> file</summary>

```json
{
    "roots": [
        "soc2-type2",
        "privacy-gdpr"
    ]
}
```

</details>

{% hint style="warning" %}
`.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.
{% endhint %}

#### Building Bundles

Once you have your directory set up, you can build your bundles using the [OPA CLI](https://www.openpolicyagent.org/docs/latest/cli/#opa-build), for example:

```shell-session
# 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 are configured by writing native Rego code directly as a string, typically a multiline [Heredoc string](https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings) for better visibility.

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

<details>

<summary>Example Query Configurations</summary>

```hcl
// 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}"
```

</details>

## Writing Policies For Your Grant Kit

Policies are implemented using the Abbey OPA Constraint Framework. This Framework is simplified subset of the [OPA Constraint Framework](https://github.com/open-policy-agent/frameworks/tree/master/constraint) that makes working with OPA and Rego easier.

Writing Policies consists of three steps:

1. [Define your logic using Rego](#define-your-logic-using-rego).
2. [Use policy inputs and enriched data in your logic](#use-policy-inputs-and-enriched-data-in-your-logic).

### 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:

{% code lineNumbers="true" %}

```rego
allow[msg] {
    // Policy logic goes here.
    msg := "return an explanation for why the policy passes"
}
```

{% endcode %}

<details>

<summary>Example Access Policies</summary>

{% code lineNumbers="true" %}

```rego
// 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"
}
```

{% endcode %}

</details>

#### 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:

{% code lineNumbers="true" %}

```rego
skip[msg] {
    // Policy logic goes here.
    msg := "return an explanation for why this step was skipped"
}
```

{% endcode %}

<details>

<summary>Example Workflow Policies</summary>

{% code lineNumbers="true" %}

```rego
// Workflow Policy that always skips its step because the `skip` rule
// always evaluates to `true`.
skip[msg] {
    true
    msg := "always skip this step"
}
```

{% endcode %}

</details>

### 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:

1. [Policy Inputs](#policy-inputs)
2. [Enriched Data](#enriched-data)

#### Policy Inputs

Policy Inputs represent the [Terraform Plan](https://developer.hashicorp.com/terraform/cli/commands/plan) 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.

*Usage*

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

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

```json
{
    "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:

```rego
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.

<details>

<summary>Full Example of <code>input</code></summary>

{% code title="input.json" %}

```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"
      ]
    }
  ]
}
```

{% endcode %}

</details>

{% hint style="success" %}
`input` is accessible for both Access Policies and Workflow Policies.
{% endhint %}

#### 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 to[Link Identities](/build-a-grant-kit/link-application-identity-data).

*Usage*

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

For example, given the following `data`:

```json
{
    "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:

```rego
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.

<details>

<summary>Schema of <code>data</code></summary>

{% code title="data.json" %}

```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"
                    }
                }            
            }
        },
    }
}
```

{% endcode %}

</details>

{% hint style="success" %}
`data` is accessible in all Policy types: Access, Revocation, and Workflow.
{% endhint %}

## Policy Evaluation

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

<figure><img src="/files/ZdoV6VrmTPEowGbqbF2w" alt="Policy Evaluation"><figcaption><p>Policy Evaluation.</p></figcaption></figure>

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

Abbey supports reusable policies that can be distributed using [Bundles](#bundles). You can leverage this feature to provide Guardrail Policies. These are policies that can be imported into other policies and cannot be overridden.

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


# Outputs

Outputs are templates that defines *how* and *where* your grants should materialize. An Output will generate native Terraform code to be stored in your Version Control System (VCS).

## Output Spec

```hcl
output = {
    # RFC 3986 URI string that points to the location of your generated HCL code.
    # Example: github://{organization}/{repository}/path/to/my/access.tf
    location = "..."
    append = <<-EOT
    EOT
}
```

## Writing Outputs For Your Grant Kit

Outputs are written using the Grant Kit's Workflows DSL as native Terraform HCL code.

Writing Outputs consists of four steps:

1. [Define a `location`](#define-a-location).
2. [Choose an Output Strategy](#choose-an-output-strategy).
3. [Leverage Terraform Providers](#leverage-terraform-providers).
4. [Optionally interpolate variables](#optionally-interpolate-variables).

### Define a `location`

A Grant Kit's Output defines *how* and *where* your access grants should materialize. The `location` attribute represents the *where*.

The `location` defines which file and at what path you want your access changes to materialize into. This is a RFC 3986 URI string. You can configure any path and any file name. Abbey will create the paths and file for you if they don't exist.

<details>

<summary>Example <code>location</code> Configurations</summary>

```hcl
// Organization: abbeylabs
// Repository: starter-kit-quickstart
// Access changes are materialized to: access.tf at the directory root
location = "github://abbeylabs/starter-kit-quickstart/access.tf"

// Organization: jeffchao (personal, not a GitHub org)
// Repository: my-starter-kit
// Access changes are materialized to: access.tf at the abbey-managed subdirectory.
location = "github://jeffchao/my-starter-kit/abbey-managed/access.tf"

// Organization: jeffchao (personal, not a GitHub org)
// Repository: my-starter-kit
// Access changes are materialized to: access.tf
//   under `resource "github_team_membership" "my_group"`
location = "github://jeffchao/my-starter-kit/abbey-managed/access.tf#github_team_membership.my_group"

// Organization: jeffchao (personal, not a GitHub org)
// Repository: my-starter-kit
// Access changes are materialized to: access.tf
//   under `resource "okta_group_memberships" "my_group"`
//   appended to users attribute
location = "github://jeffchao/my-starter-kit/abbey-managed/access.tf#okta_group_memberships.my_group.users"
```

</details>

{% hint style="info" %}
Currently Abbey supports the `github://` scheme. Future schemes such as `file://`, `s3://`, and `https://` coming soon.
{% endhint %}

### Choose an Output Strategy

Abbey will automatically manage access through the file you specified at `location`.

Abbey supports one Output Strategy:

1. `append`: Access changes are treated as a new Terraform Resource block and appended to the access Terraform file at `location`.

### Leverage Terraform Providers

A Grant Kit's Output defines *how* and *where* your access grants should materialize. The Output's `append` block represents the *how*.

It contains a string value, typically a multiline [Heredoc string](https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings) for better visibility. The contents of this string is HCL code generally using OSS Terraform Providers from the [Terraform Provider Registry](https://registry.terraform.io/) that map to the resources you want Abbey to manage.

<details>

<summary>Examples of Leveraging Terraform Providers in Your Grant Kit Output</summary>

```hcl
# Statically append to your `access.tf` file the `snowflake_role_grants` resource.
append = <<-EOT
    resource "snowflake_role_grants" "pii_role" {
        role_name = "ROLE"
        users     = ["USER"]
    }
EOT

# Statically append to your `access.tf` file the `mongodbatlas_database_user`
# resource with the `readWrite` role for the database `dbforApp`.
append = <<-EOT
    resource "mongodbatlas_database_user" "test" {
        username           = "test-acc-username"
        password           = "test-acc-password"
        project_id         = "<PROJECT-ID>"
        auth_database_name = "admin"

        roles {
            role_name     = "readWrite"
            database_name = "dbforApp"
        }
    } 
EOT
```

</details>

### Optionally Interpolate Variables

In order to configure meaningful Grant Kit Outputs, you need to be able to configure dynamic strings rather that static strings from the examples above. Abbey supports this through variable interpolation.

When an access request is made, Abbey performs two layers of variable interpolation:

1. [Terraform String Interpolation](#terraform-string-interpolation).
2. Go text/template Interpolation.

#### Terraform String Interpolation

Abbey will first perform [Terraform String Interpolation](https://developer.hashicorp.com/terraform/language/expressions/strings#interpolation). This happens when an access request is made it's now time to generate Output based on your `append` block.

Since the contents of the `append` block is a Terraform string, Abbey will interpolate variables using [native Terraform syntax](https://developer.hashicorp.com/terraform/language/expressions/references).

*Usage*

* To interpolate variables, use `${some_variable_name}`.
* You can interpolate any of your existing Terraform objects such as `resource` and `data` objects.

<details>

<summary>Example</summary>

<pre class="language-hcl"><code class="lang-hcl"># This example builds on the above. It shows how you can replace
# the value at `role_name` with the `name` attribute of
# a `snowflake_role_grants` Terraform resource named `pii_readonly_role__...`.
#
# This example assumes a `snowflake_role_grants` resource
# named `pii_readonly_role` already exists.
#
# The value is replaced when when `terraform apply` is run.
append = &#x3C;&#x3C;-EOT
    resource "snowflake_role_grants" "pii_readonly__USERNAME" {
        role_name = "<a data-footnote-ref href="#user-content-fn-1">${data.snowflake_role_grants.pii_readonly_role.name}</a>"
        users     = ["USER"]
    }
EOT
</code></pre>

</details>

* You can also interpolate the resource name of the output. This can be used to create multiple of the same resources for different requests.

<details>

<summary>Example</summary>

<pre class="language-hcl"><code class="lang-hcl"># NOTE: Due to how terraform generates random values, issuing multiple requests 
# at once will cause the this following example to use the same random string.
# The random string is changed every time terraform apply is called.
append = &#x3C;&#x3C;-EOT
      resource "abbey_demo" "grant_read_write_access_${random_pet.random_pet_name.id}" {
        permission = "read_write"
        email = "{{ .user.email }}"
      }
EOT
<strong>
</strong><strong>resource "random_pet" "random_pet_name" {
</strong>  keepers = {
    first = "${timestamp()}"
  }
  length = 5
  separator = "_"
}
</code></pre>

</details>

#### Go text/template Interpolation

Next, Abbey will perform Go [text/template](https://pkg.go.dev/text/template) Interpolation. This happens after the output of [Terraform String Interpolation](#terraform-string-interpolation).

*Usage*

* To interpolate variables, use `{{ .some_variable_name }}`.
* Abbey provides [Enriched Data](/reference/grant-kits/policies#enriched-data) as variables for you to interpolate.

<details>

<summary>Example</summary>

<pre class="language-hcl"><code class="lang-hcl"># This example shows how you can replace the statically-named
# `pii_readonly` role with a dynamically-named name using the
# `snowflake.username` attribute from Enriched Data.
append = &#x3C;&#x3C;-EOT
    resource "snowflake_role_grants" "pii_readonly__<a data-footnote-ref href="#user-content-fn-2">{{ .user.snowflake.username }}</a>" {
        role_name = "ROLE"
        users     = ["USER"]
    }
EOT
</code></pre>

</details>

{% hint style="info" %}
Notice the preceding `.` in the string template. This is required to access the object.

Also notice that even though Abbey uses Go's text/template, Abbey automatically converts this to snake\_case naming so the experience is consistent across the entire Grant Kit configuration flow.
{% endhint %}

## Output Materialization

Abbey materializes output to a Terraform file based on what you configured in your `append` block and after applying [Terraform String Interpolation](#terraform-string-interpolation) and [Go text/template Interpolation](#go-text-template-interpolation).

<figure><img src="/files/ILkKusOrLEVW9mTf2vwy" alt="Output Materialization"><figcaption><p>Output Materialization.</p></figcaption></figure>

Output Materialization has three stages:

1. Interpolate Terraform variables.
2. Interpolate Enriched Data variables.
3. Generate Output to your `location`.

## Troubleshooting

A common deployment failure for grant kits is a misconfigured `location` field in the `output` 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 output location exists
  * Note: Abbey will create the *file* for you if it doesn't exist, but will not create *directories*.

[^1]: This variable will be replaced with the `snowflake_role_grants.pii_readonly_role` resource.

[^2]: This variable will be replaced with the `snowflake.username` that you imported into Abbey as linked application data.


# Referencing Users and Groups

## Overview

Abbey has the ability to reference users and group members stored externally for use in Grant Kits.&#x20;

These are most commonly used in two places:&#x20;

* Building a Workflow (I'd like Bob to approve, or members of this group to approve)
* Creating an Output (assign the requester a permission)

For understanding how these data can be used in Access Policies, please see [Policy Examples](/reference/access-policies/policy-examples).&#x20;

## User References

An Output block is templatized code change that assigns a user to a particular permission. In order to do that, we need to reference the identifier for a user.&#x20;

Below shows how an example for AWS Identity Center.&#x20;

```
member_id = "{{ user.aws_identitystore.id }}"
```

## Group References

Abbey has the ability to use Group Memberships in the context of a workflow.&#x20;

For example, the below references a set of Users in a Google Workspace group. Abbey will send an approval to all members of that group, with only one (due to `one_of`)  needing to approve for a user to get access.&#x20;

```
one_of = ["{{ groups.googleworkspace.03oy7u2934pbgyw }}"]
```


# Linking Application Identities into Abbey


# Why do I need to link application identities?

Abbey can be used to control access to resources in external applications. Abbey knows the email you sign up with in the app, and this can be used when creating Abbey grant kits. However, if you are referencing an external application, Abbey needs to know about your identity data in an external application in order to control access to resources in the application.

Let's take a look at the output block of the following Grant Kit:

```hcl
  output = {
    # Replace with your own path pointing to where you want your access changes to manifest.
    # Path is an RFC 3986 URI, such as `github://{organization}/{repo}/path/to/file.tf`.
    location = "github://organization/repo/access.tf"
    append = <<-EOT
      resource "github_team_membership" "gh_mem_{{ .user.github.username }}" {
        team_id = github_team.test_team.id
        username = "{{ .user.github.username }}"
        role = "member"
      }
    EOT
  }
```

In this example, when the grant kit approves access to the `github_team_membership` resource, Abbey creates a Terraform resource which associates the username with the team. Here we refer to the username as `.user.github.username`. However, Abbey has no way of knowing this username until you link the Github username into Abbey!


# How do I Link Application Identities?

## Before you start

**Make sure you have:**

* An [Abbey account](https://app.abbey.so/sign-up)
* An [Abbey API Token](/admin/managing-api-tokens#creating-new-api-tokens)
* The User ID of the Abbey user you want to link identity data for

## Step 1: Identify which application you are linking data for

Abbey has first-class support for linking data for certain applications. Other applications can also have application identity data linked, but Abbey enforces a certain structure on first-class applications to make sure that you have all the identity data you need to successfully use Abbey.

To find out what the structure of your app data payload should be, take a look at [Supported Application Identity Types and Schemas](/reference/linking-application-identities-into-abbey/supported-application-identity-types-and-schemas)

In this page we'll be linking Github application identity data.

## Step 2: Make an API request to our Users API to link identity data

We'll be making a request to the [Users API](https://developers.abbey.io/#operation/createAppData) to link data an external identity to an Abbey identity.&#x20;

```sh
curl \
  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -X POST "https://api.abbey.io/v1/users/<userID>/apps" \
  -d '{"type": "<app type>", "data": { ... app data ... }}'
```

As an example, we wish to link this user's Github username:

<pre class="language-sh"><code class="lang-sh"><strong>curl \
</strong>  -H "Authorization: Bearer $ABBEY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -X POST "https://api.abbey.io/v1/users/user/user_2U4vhAMp6hByuOVA7EGwEwmI5NK/apps" \
  -d '{"type": "github", "data": {"username": "Alice"}}'
</code></pre>

Let's take a closer look at the JSON payload we're POSTing:

```json
{"type": "github", "data": {"username": "Alice"}}
```

Here we're specifying that the type of application we're linking data for is `github` and that we have a data payload which contains a `username` key whose value is `Alice`. The structure of the `data` payload differs per application, and is unspecified for app types not supported. Look at [Supported Application Identity Types and Schemas](/reference/linking-application-identities-into-abbey/supported-application-identity-types-and-schemas) to see a list of custom applications and the structure of each application type.

## Step 3: Use your Imported Identity Data in a Grant Kit

When creating a grant kit, in your output block you can make references to imported application data and Abbey will fill in these references with the data you imported in the above step. For example:

```
{{ .user.github.username }}
```

will resolve to a Github username linked through the API.

Here's an example:

Let's create the output block of a grant kit which uses the application identity data we just imported to grant access to a resource:

```hcl
  output = {
    # Replace with your own path pointing to where you want your access changes to manifest.
    # Path is an RFC 3986 URI, such as `github://{organization}/{repo}/path/to/file.tf`.
    location = "github://organization/repo/access.tf"
    append = <<-EOT
      resource "github_team_membership" "gh_mem_{{ .user.github.username }}" {
        team_id = github_team.test_team.id
        username = "{{ .user.github.username }}"
        role = "member"
      }
    EOT
  }
```

Note that the `username` block will be templated by the Github username we linked in Step 2.

That's it! Now you've imported your application identity information into Abbey.


# Supported Application Identity Types and Schemas

## Identity Linking JSON Shapes

Identities are linked by POSTing to the `/v1/users/<userID>/apps` endpoint. Payloads are of the following shape:

```
{"type": "<application type>", "data": { ... application data ... }}
```

The `data` payload of each application type must contain certain keys that Abbey uses to make sure that an application has had its data linked properly.

For more details on APIs used to link apps, take a look at <https://developers.abbey.io/#operation/createAppData>.

## Application Identity Types

| Application Type    | Application Name    | Required Keys      |
| ------------------- | ------------------- | ------------------ |
| `aws_iam`           | AWS IAM Account     | `account_id`, `id` |
| `aws_identitystore` | AWS Identity Center | `id`               |
| `github`            | Github              | `username`         |
| `okta`              | Okta                | `user_id`          |
| `google`            | Google Cloud        | `id`               |
| `googleworkspace`   | Google Workspace    | `email`            |

Note that `aws_iam` is a special application type. `account_id` *must* be unique.

## Custom Identity Types

Any identity type not covered in the above table is considered a custom identity types. There is no set of required keys needed to link application identity data for a custom identity type. For example the below payload:

```json
{"type": "my-custom-app", "data": {"foo": "bar"}}
```

now allows references of the form:

* `.user.my-custom-app.foo` in grant kits
* `data.user.my-custom-app.foo` in policy code


# Application Data Object

## Application Data

Once data has been imported for an application, a data object can be used in Grant Kits and policy code to refer to imported application data. The object looks like the following:

```
{
  "<application-type>": { ... required keys here ... },
}
```

Here's an example:

```
{
  "github": {"username":"alice"},
  "aws_identitystore": {"id": "1234"}
}
```

The user Alice has two pieces of data imported about them. Data for `github` and `aws_identitystore` is available.

## Referring to Application Data in Grant Kits

You can refer to application data in grant kits in the following way:

```
{{ .user.<app>.<key> }}
```

For example:

```
{{ .user.github.username }}
```

Refers to the Github username of a user.

## Referring to Application Data in Policies

You can refer to application data in grant kits in the following way:

```
data.user.<app>.<keyname>
```

For example:

```
data.user.github.username == "Alice"
```

checks whether a Github username matches `Alice`


# Access Policies


# Types of Access Policies

Abbey supports 3 types of policies:&#x20;

* [#allow-or-deny-access](#allow-or-deny-access "mention")
* [#expire-access](#expire-access "mention")
* [#skip-a-workflow-step](#skip-a-workflow-step "mention")

## Allow or Deny Access

Policies which allow or deny access to a user can be specified in the `policies` field of a Grant Kit. For example:

```hcl
resource "abbey_grant_kit" "abbey_example_kit" {
  name = "Abbey_Example"
  description = <<-EOT
    Grants access to Abbey's Demo Page.
  EOT

  workflow = {
    steps = [
      {
        reviewers = {
          one_of = ["bob@example.com"]
        }
      }
    ]
  }

  policies = [
    { bundle = "github://example-org/example-repo/policies" }
  ]

  output = ...
  }
}
```

Look at the `policies` field. The policy bundle specified must pass or Access Requests to this Grant Kit are denied. Policies used this way must use an `allow` variable such as below.&#x20;

```rego
allow[msg] {
  in_group("Marketing")
  msg := "allow marketing folks"
}
```

If attributes about a user change and make the policy invalid, then the policy access will be revoked. For example, if a user was granted access in the above policy and then gets moved out of the "Marketing" group, Abbey will revoke access.

## Expire Access

Abbey continues to check if policies for a given Access Request are valid. This can let you write access policies which expire access after a certain amount of time. Expiry based policies are also written in an `allow` Rego variable.

```rego
import data.abbey.functions

allow[msg] {
    functions.expire_after("60m")
    msg := "granting access for 60 minutes"
}
```

The above policy will allow access for 60 minutes, and then fail after 60 minutes. The failure will revoke access.

## Skip a Workflow Step

You can also use policies to skip Workflow steps. Look at the following example.

```hcl
resource "abbey_grant_kit" "abbey_example_kit" {
  name = "Abbey_Example"
  description = <<-EOT
    Grants access to Abbey's Demo Page.
  EOT

  workflow = {
    steps = [
      {
        reviewers = {
          one_of = ["bob@example.com"]
        }
        
        skip_if = [
          { bundle = "github://example-org/example-repo/policies/rbac" }
        ]
      }
    ]
  }

  policies = ...

  output = ...
  }
}
```

In the example, a review is required from `bob@example.com` to grant access through this Grant Kit. The review step may be skipped if the policy referred to in the `skip_if` section passes.

Policies given in a `skip_if` section must be placed in a `skip` variable such as below.

```rego
skip[msg] {
  in_group("Engineering")
  msg := "skipping review step for engineers"
}
```


# Policy Bundles

A policy bundle is a collection of Rego code placed within a location accessible by the Abbey Github app. Rego code is read from this location and then evaluated in our policy evaluator during the access request flow. If the policy evaluation step fails, then access will not be granted to a given resource.

In this example we'll be looking at the included policy bundle in the [Quickstart Policy Bundle](https://github.com/abbeylabs/abbey-starter-kit-quickstart/tree/main/policies/common).

## .manifest

Take a look at the `.manifest` file.&#x20;

```
{"roots": ["common"]}
```

This specifies that the root package of the bundle is the `common` package.

## common.rego

```rego
package common

import data.abbey.functions

allow[msg] {
    functions.expire_after("5m")
    msg := "granting access for 5 minutes"
}
```

`common.rego` contains the actual policy code that is being executed. In this case, we're using an Abbey provided function called `expire_after` (defined [here](https://github.com/abbeylabs/policy-library/blob/main/src/abbey/functions/expire_after.rego)) to say that this policy will revoke access after `5 minutes`. Go ahead and change this to whatever value you like. If you want an Access Request to expire after `60 minutes`, you can change the value in `expire_after` to `"60m"`.

## Using the Policy Bundle in a Grant Kit

You can refer to the Policy Bundle in your Grant Kit like so:

<pre class="language-diff"><code class="lang-diff">resource "abbey_grant_kit" "grant_kit_example" {
  ...

<strong>+  policies = [
</strong>+    { bundle = "github://replace-me-with-organization/replace-me-with-repo/policies" } # CHANGEME
+  ]
}
</code></pre>

Make sure `bundle` points to a URI which points to the top of a bundle directory.


# Inline Policies

## Inline Policies

Inline Policies are snippets of Rego which are defined inline with a grant kit. The Rego code is placed within the `policies` block inside of an Abbey grant kit. When an access request is made, our policy evaluation engine evaluates the access policy and makes sure the policy checks pass before granting requests to resources.&#x20;

The following is an example of using an Inline Policy inside of an Abbey grant kit.

```hcl
resource "abbey_grant_kit" "null_grant" {
  ...
  
  policies = [
    {
      query = <<-EOT
      package main
      
      import abbey.functions

      allow[msg] {
        expire_after("5m") # Expire the access after 5 minutes
        msg := "access allowed for null_grant" # Use any message you like.
      }
      EOT
    }
  ]

  ...
}
```


# Helper Functions

Abbey has created a number of helper functions to help write policies. First you need to write `import data.abbey.functions` to import the helper functions and then you can start using any helper function you'd like.

## in\_group(group\_name)

The `in_group` function tests whether an Abbey user belongs to a certain group. To check whether a user is in a group named `Engineering`, you can write `in_group("Engineering")`.

Look [here](https://github.com/abbeylabs/policy-library/blob/main/src/abbey/functions/in_group.rego) for the source.

## has\_attribute(attribute\_name, attribute\_value)

The `has_attribute` function tests whether an Abbey user has a certain attribute. For example, to check if a user has an Employee Type of `IC`, you can write `has_attribute("employee_type", "IC")`. `attribute_name` can be the name of any attribute on a user from your IDP and `attribute_value` can be any string.

Look [here](https://github.com/abbeylabs/policy-library/blob/main/src/abbey/functions/has_attribute.rego) for the source.

## expire\_at(ts)

The `expire_at` function denies a policy at a certain timestamp `ts`. For example, if you write `expire_at("2023-01-01T02:00:00Z")`, then this will deny the policy at any time after `2023-01-01T02:00:00Z`. Abbey continues to check for whether a policy will be expiring at a later date, allowing you to write time-based expiry policies.

Look [here](https://github.com/abbeylabs/policy-library/blob/main/src/abbey/functions/expire_at.rego) for the source.

## expire\_after(duration)

The `expire_after` function denies a policy after a certain amount of time has passed. For example, to deny a policy after 30 minutes, you can write `expire_after("30m")`. Like `expire_at,` Abbey continues to check whether an `expire_after` policy has expired so that policies will actually deny after their  given time.

The `duration` argument needs an integer concatenated with a unit, so something like `30s`, `60m`, `3h`, or `1d`. The exact `duration` syntax is documented [here](https://pkg.go.dev/time#ParseDuration).

Look [here](https://github.com/abbeylabs/policy-library/blob/main/src/abbey/functions/expire_after.rego) for the source.


# Policy Examples

The following are some examples of policies. These policies can be copied inline into a grant kit or be placed into a Policy Bundle and used with Abbey. The source code for all Abbey Rego functions can be found in our [Policy Library Repository](https://github.com/abbeylabs/policy-library/).

## Table of Contents

[#role-based-access-control](#role-based-access-control "mention")

[#attribute-based-access-control](#attribute-based-access-control "mention")

[#time-based-expiry](#time-based-expiry "mention")

[#confirm-if-user-is-on-call-in-pagerduty-for-access](#confirm-if-user-is-on-call-in-pagerduty-for-access "mention")

## Role-Based Access Control

This example policy evaluates to true when the user has a certain role. We model these roles as groups that the user is part of. This policy checks whether a user is in the group `Engineering`, but you can check if the user is in any group you would like.

```rego
import data.abbey.functions

allow[msg] {
    functions.in_group("Engineering")
    msg := "granting access"
}
```

Information about `in_group` can be found at [Helper Functions](/reference/access-policies/helper-functions#in_group-group_name).

## Attribute-Based Access Control

This example policy evaluates to true when the user has a certain attribute. We want to check whether the Cost Center associated with the given user is `Engineering`. To do this, we check whether the attribute `cost_center_name` is `Engineering`.

```rego
import data.abbey.functions

allow[msg] {
    functions.has_attribute("cost_center_name", "Engineering")
    msg := "is engineering cost center"
}
```

The above example can be modified for other attributes if needed. Information about `has_attribute` can be found at [Helper Functions](/reference/access-policies/helper-functions#has_attribute-attribute_name-attribute_value).

## Time-Based Expiry

This example policy evaluates to false after 60 minutes have passed. Access is revoked at the end of the 60 minute time period. The time can be modified as needed for longer or shorter access durations. Hours can be entered in using syntax like `"1h"` for 1 hour.

```rego
import data.abbey.functions

allow[msg] {
    functions.expire_after("60m")
    msg := "granting access for 60 minutes"
}
```

Information about `expire_after` can be found at [Helper Functions](/reference/access-policies/helper-functions#expire_after-duration).

## Confirm if User is On-Call in PagerDuty for Access

This example policy approves an access request if the user is on-call in PagerDuty.

```rego
allow[msg] {
  data.user.pagerduty.isoncall
  msg := "allowing on-call engineers"
}
```

This does not make use of any Abbey functions.


# Terms of Service

Last Updated: July 27, 2023

BY CLICKING A BOX INDICATING YOUR ACCEPTANCE OF THESE TERMS OF SERVICE OR BY EXECUTING AN ORDER FORM OR COMPLETING AN ONLINE ORDERING FLOW THAT REFERENCES THESE TERMS OF SERVICE (THE “ORDER FORM”, AND TOGETHER WITH THESE TERMS OF SERVICE, THIS “AGREEMENT”), YOU AGREE YOU HAVE READ AND ARE BOUND BY THE TERMS OF THESE TERMS OF SERVICE.  IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH ENTITY TO THIS AGREEMENT, IN WHICH CASE THE TERM “CUSTOMER” WILL REFER TO SUCH ENTITY.  IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT AGREE WITH THIS AGREEMENT, YOU MUST NOT ACCEPT THIS AGREEMENT AND MAY NOT USE THE COMPANY SERVICE (AS DEFINED BELOW). &#x20;

This Agreement, by and between Customer and Abbey Labs Inc. (“Company”), is effective as of the date set forth in the Order Form or the date on which Customer clicks a box accepting this Agreement (the “Effective Date”) and governs Customer’s use of Company’s proprietary software-as-a-service platform (the “Company Platform”) and the Company Software (as defined below, together with the Company Platform, the “Company Service”), which provides access management services to secure granular access to the customer’s cloud infrastructure.  Company reserves the right to change or modify portions of this Agreement at any time.  If Company does so, it will post the changes on this page and will indicate at the top of this page the date this Agreement was last revised. Company will also notify Customer, either through the Company Service user interface, in an email notification or through other reasonable means. Any such changes will become effective no earlier than fourteen (14) days after being posted, except that changes addressing new functions of the Company Service or changes made for legal reasons may become effective immediately; provided, that, if any such changes or modifications materially adversely affect Customer, Customer may terminate this Agreement upon written notice to Company within fourteen (14) days’ of receiving notice of such change or modification. Customer’s continued use of the Company Service thereafter constitutes acceptance of such changes or modifications.  Each of Company and Customer may be referred to herein individually as a “Party” or collectively as “Parties”.

## 1. ACCESS TO COMPANY SERVICE.

1. Access to Platform. Company will use commercially reasonable efforts to make the Company Platform available to Customer. Subject to the terms and conditions of this Agreement, Company hereby grants Customer the limited, non-exclusive, non-transferable, non-sublicensable right to access and use the Company Platform during the Term solely for Customer’s internal business purposes.
2. Access to Company API. Certain software components may be downloaded locally from the Company Platform (the “Company Software”) so that the Company may use the Company Platform. To the extent Customer subscribes to the Company Software via the Order Form, Company will use commercially reasonable efforts to make the Company Software available to Customer. Subject to the terms and conditions of this Agreement, Company hereby grants to Customer the limited, non-exclusive, non-transferable, non-sublicensable right and license to install and use the Company Software during the Term solely to use the Company Platform for Customer’s internal business purposes.
3. License Restrictions and Responsibilities. Customer will not use the Company Service for any purpose other than the purposes expressly set forth herein. Customer may not, directly or indirectly: (a) reverse engineer, decompile, disassemble or otherwise attempt to discover the source code, object code or underlying structure, ideas, know-how or algorithms relevant to the Company Service; (b) modify, translate, or create derivative works based on the Company Service (except to the extent expressly permitted by Company); (c) use the Company Service for timesharing or service bureau purposes or otherwise for the benefit of a third party; or (d) remove any proprietary notices or labels. Customer shall be responsible for obtaining and maintaining any equipment and ancillary services needed to connect to, access or otherwise use the Company Service, including, without limitation, modems, hardware, server, software, operating system, networking, web servers and the like. Customer will be responsible for maintaining the confidentiality of Customer’s usernames, passwords and account details. Customer will be responsible for any actions taken by parties with access to such usernames and passwords, and Customer agrees not to disclose such usernames and passwords to any third parties (other than employees of Customer). Customer will inform Company immediately if it discovers that any such username and/or password has been disclosed or made available to a third party.
4. License to Customer Data. Customer hereby grants to Company a non-exclusive, royalty-free, fully paid up, non-sublicensable (except to contractors and consultants performing services on behalf of Company), non-transferable (subject to Section 10.6) right and license to copy, distribute, display, create derivative works of and otherwise use the data or information submitted, transmitted or uploaded by Customer via the Company Service (the “Customer Data”) to (a) perform its obligations under this Agreement, (b) improve and develop its products and services and (c) create anonymized and/or aggregated data (“Aggregated Data”), which Aggregated Data will not identity of Customer and/or its individual clients. For the avoidance of doubt, Aggregated Data is not Customer Data. Company will comply with its obligations under Company’s Privacy Policy set forth at: <https://docs.abbey.io/reference/privacy-policy>
5. Feedback. Customer may from time to time provide suggestions, comments for enhancements or functionality or other feedback (“Feedback”) to Company with respect to the Company Service or Evaluation Services (as defined below). Company will have full discretion to determine whether or not to proceed with the development of the requested enhancements, new features or functionality. Customer hereby grants to Company a royalty-free, fully paid up, worldwide, transferable, sublicensable, irrevocable, perpetual license to (a) copy, distribute, transmit, display, perform, and create derivative works of the Feedback, and (b) use the Feedback and/or any subject matter thereof, including without limitation, the right to develop, manufacture, have manufactured, market, promote, sell, have sold, offer for sale, have offered for sale, import, have imported, rent, provide and/or lease products or services which practice or embody, or are configured for use in practicing, the Feedback and/or any subject matter of the Feedback.
6. Free Services. Company may offer certain Company Service at no charge, including trial subscriptions, other free services, and pre-release, alpha or beta versions or features (collectively, “Free Services”). Customer’s use of Free Services is subject to any additional terms that Company may specify and limited to the number of free internal use licenses specified on the Order Form.. Except as otherwise set forth in this Section, this Agreement applies to Free Services. Company may modify or terminate Customer’s right to use Free Services at any time. NOTWITHSTANDING ANYTHING TO THE CONTRARY, TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, COMPANY DISCLAIMS ALL OBLIGATIONS, REPRESENTATIONS, WARRANTIES, COVENANTS, AND LIABILITIES WITH RESPECT TO FREE SERVICES, INCLUDING ANY INDEMNITY OBLIGATIONS, AND COMPANY’S MAXIMUM AGGREGATE LIABILITY TO CUSTOMER IN RESPECT OF FREE SERVICES WILL BE U.S. $100. Company may discontinue Free Services at any time in its sole discretion.
7. Third Party Services. The Company Service may enable access to or integration with certain third party services, products, solutions, software or technology which are currently or may be in the future utilized by Customer and with respect to which Customer has a separate contractual relationship with the applicable third party (collectively, the “Third Party Services”). The Third Party Services may also be subject to additional terms and conditions, privacy policies, or other agreements with such third party, and Customer may be required to authenticate to or create separate accounts to use Third Party Services. Some Third Party Services may provide Company with access to certain information that Customer has provided to such Third Party Services. Any data, information or other materials collected via or received by Company from any Third Party Service will be deemed Customer Data and will be treated by Company as Confidential Information. Company has no control over and is not responsible for such Third Party Services, including for the accuracy, availability, reliability or completeness of information shared by or available through Third Party Services, or on the privacy practices of Third Party Services. Company encourages Customer to review the privacy policies of Third Party Services prior to using them. Company will not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use of or reliance on any Third Party Services. Company enables these Third Party Services merely as a convenience and the integration or inclusion of such Third Party Services does not imply an endorsement or recommendation. Any dealings Customer has with third parties while using the Company Service are between Customer and the third party. Company is not liable for any loss caused by or claim that Customer may have against any such third party or that arise under Customer’s agreements with any such third party.

## 2. OWNERSHIP; RESERVATION OF RIGHTS. &#x20;

1. Customer acknowledges and agrees that, as between the Parties, Company retains all right, title and interest in and to the Company Service and all associated intellectual property rights.  Company grants no, and reserves any and all, rights other than the rights expressly granted to Customer under this Agreement with respect to the Company Service.  Customer will acquire no right, title, or interest in and to the Company Service other than the limited licensed rights expressly granted under this Agreement.  Notwithstanding the foregoing, Customer retains all right, title and interest in and to the Customer Data. &#x20;

## 3. FEES; PAYMENT TERMS.

1. Fees; Payment Terms. In exchange for use of the Company Service and the rights granted pursuant to this Agreement, Customer will pay to Company the fees set forth in the Order Form (the “Service Fees”) in accordance with the terms and conditions set forth herein and therein. The Service Fees may include a recurring subscription fee for access to the Company Service (“Subscription Fees”). To the extent the Company Service or any portion thereof is made available for any fee, Customer may be required to select a payment plan and provide information regarding Customer’s credit card or other payment instrument. Customer represent and warrant to Company that such information is true and that Company is authorized to use the payment instrument. Customer will promptly update its account information with Company or the Payment Processor (as defined below), as applicable, of any changes (for example, a change in Customer’s billing address or credit card expiration date) that may occur. Customer agrees to pay Company the amount that is specified in the Order Form in accordance with the terms of such Order Form and these Terms of Service. If Customer’s payment plan includes Subscription Fees, Customer hereby authorizes Company (through the Payment Processor) to bill Customer’s payment instrument in advance on such periodic basis in accordance with the terms of the applicable payment plan until Customer terminates its account, and Customer further agrees to pay any charges so incurred. If Customer disputes any charges, Customer must let Company know within sixty (60) days after the date that Company charges Customer, or within such longer period of time as may be required under applicable law. Company reserve the right to change Company’s prices. If Company does change prices, Company will provide notice of the change through the Company Service user interface, in an email notification or through other reasonable means, at Company’s option, at least thirty (30) days before the change is to take effect. Customer’s continued use of the Company Service after the price change becomes effective constitutes Customer’s agreement to pay the changed amount.
2. Payment Processing. Notwithstanding any amounts owed to Company hereunder, COMPANY DOES NOT PROCESS PAYMENT FOR ANY COMPANY SERVICE. To facilitate payment for the Company Service via bank account, credit card, or debit card, Company uses third-party payment processors (collectively, “Payment Processors”). These payment processing services are provided by the Payment Processors and are subject to the applicable Payment Processor’s terms and conditions, privacy policy, and all other relevant agreements (collectively, the “Payment Processor Agreements”). By agreeing to this Agreement, users that use the payment functions of the Company Service also agree to be bound by the applicable Payment Processor aagreement for the payment function the user is using, as the same may be modified by the applicable Payment Processor from time to time. Customer hereby authorizes the applicable Payment Processor to store and continue billing Customer’s specified payment method even after such payment method has expired, to avoid interruptions in payment for Customer’s use of the Company Service. Please contact the applicable Payment Processor for more information. Company assumes no liability or responsibility for any payments Customer makes through the Company Service.
3. Refunds and Cancellations. Payments made by Customers hereunder are final and non-refundable, unless otherwise determined by Company. Customer may cancel Customer’s subscription online by emailing Company at: \[<hello@abbey.io>].
4. Net of Taxes. All amounts payable by Customer to Company hereunder are exclusive of any sales, use and other taxes or duties, however designated, including without limitation, withholding taxes, royalties, knowhow payments, customs, privilege, excise, sales, use, valueadded and property taxes (collectively “Taxes”). Customer will be solely responsible for payment of any Taxes, except for those taxes based on the income of Company. Customer will not withhold any Taxes from any amounts due Company.

## 4. TERM; TERMINATION.

1. Term; Termination. Subject to earlier termination as set forth in this Agreement, this Agreement will commence on the Effective Date and continue for the initial subscription period set forth in the Order Form (the “Initial Term”). Thereafter, the Agreement shall automatically renew for additional periods of the same duration, unless either Party provides written notice of non-renewal at least sixty (60) days prior to the end of the then-current term (each, a “Renewal Term”, and together with the Initial Term, the “Term”). If Customer does not agree to automatic renewals, Customer may opt-out of automatic renewals by providing written notice to Abbey Labs within fourteen (14) days of the date of the initial Order Form. In addition, a Party may terminate this Agreement immediately if the other Party materially breaches any material provision of this Agreement and does not cure such material breach within thirty (30) days after receiving written notice thereof.
2. Effect of Termination. In the event that this Agreement expires or is terminated for any reason, all rights granted to Customer with respect to the Company Service will immediately terminate, and Customer will (a) cease use of the Company Service; and (b) pay to Company all amounts due and owing under this Agreement (to the extent not previously paid). In addition, upon expiration or termination of this Agreement, each Recipient (as defined below) will return to the Discloser (as defined below) or destroy, at the Discloser’s election, all of the Discloser’s Confidential Information and all copies or other tangible embodiments thereof.
3. Survival. Upon expiration or termination of this Agreement, all obligations in this Agreement will terminate, provided that Sections 1.3 (License Restrictions and Responsibilities), 1.4 (License to Customer Data), 1.5 (Feedback), 2(Ownership; Reservation of Rights), 3 (Fees; Payment Terms), 4 (Term; Termination), 5 (Confidentiality), 6.2 (Disclaimer), 7 (Limitations of Liability), 8 (Indemnification) and 10 (General) will survive.

## 5. CONFIDENTIALITY

1. Definition of Confidential information. “Confidential Information” means, subject to the exceptions set forth in Section 5.2 hereof, any information or data or materials, regardless of whether it is in tangible form, that is disclosed or otherwise made available by a Party (the “Discloser”) to the other Party (the “Recipient”) and that (a) the Discloser has marked as confidential or proprietary, or (b) the Discloser identifies as confidential at the time of disclosure with written confirmation within fifteen (15) days of disclosure to the Recipient; provided, however, that reports and/or information related to or regarding the Discloser’s business plans, business methodologies, strategies, technology, source code, specifications, development plans, customers, prospective customers, partners, suppliers billing records, and products or services will be deemed Confidential Information of the Discloser even if not so marked or identified, unless such information is the subject of any of the exceptions set forth in Section 5.2 hereof. The Company Service is the Confidential Information of Company.
2. Exceptions to Confidential Information. Confidential Information will not include any information which: (a) the Recipient can show by written record was in its possession prior to disclosure by the Discloser hereunder, provided that the Recipient must promptly notify the Discloser of any prior knowledge; (b) becomes generally known by the public other than through the Recipient’s failure to observe any or all terms and conditions hereof; or (c) subsequent to disclosure to the Recipient by the Discloser, is obtained by the Recipient from a third person who is not subject to any confidentiality obligation in favor of Discloser.
3. Use and Disclosure of Confidential Information. The Recipient may only use the Confidential Information for the purpose of performing its obligations and exercising its rights hereunder. The Recipient must keep secret and will never disclose, publish, divulge, furnish or make accessible to anyone any of the Confidential Information of the Discloser, directly or indirectly, other than furnishing such Confidential Information to (a) the Recipient’s employees and contractors who are required to have access to such Confidential Information in connection with the performance of the Recipient’s obligations, or the exercise of the Recipient’s rights, hereunder, and (b) professional advisers (e.g., lawyers and accountants), in each case, during the time that the Recipient is permitted to retain such Confidential Information hereunder; provided that any and all such employees or contractors are bound by written agreements or, in the case of professional advisers, ethical duties, respecting the Confidential Information in the manner set forth in this Agreement. The Recipient will use at least reasonable care and adequate measures to protect the security of the Confidential Information of the Discloser and to ensure that any Confidential Information of the Discloser is not disclosed or otherwise made available to other persons or used in violation of this Agreement.
4. Disclosures Required by Law. In the event that the Recipient is required by law to make any disclosure of any of the Confidential Information of the Discloser, by subpoena, judicial or administrative order or otherwise, the Recipient will first give written notice of such requirement to the Discloser, and will permit the Discloser to intervene in any relevant proceedings to protect its interests in the Confidential Information, and provide full cooperation and assistance to the Discloser in seeking to obtain such protection.

## 6. REPRESENTATIONS AND WARRANTIES; DISCLAIMER.

1. Representations and Warranties. Each Party represents and warrants to the other Party that (a) such Party has the required power and authority to enter into this Agreement and to perform its obligations hereunder, (b) the execution of this Agreement and performance of its obligations thereunder do not and will not violate any other agreement to which it is a party, and (c) this Agreement constitutes a legal, valid and binding obligation when signed by both Parties. In addition, Customer represents, warrants and covenants that (i) it has all rights necessary to permit Company to use the Customer Data as contemplated hereunder and (ii) the Customer Data will be true, accurate and complete.
2. Disclaimer. EXCEPT AS EXPRESSLY SET FORTH HEREIN, THE COMPANY SERVICE IS PROVIDED ON AN “AS-IS” BASIS AND COMPANY DISCLAIMS ANY ADDITIONAL REPRESENTATION OR WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED (EITHER IN FACT OR BY OPERATION OF LAW), OR STATUTORY, AS TO ANY MATTER WHATSOEVER. COMPANY EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUALITY, ACCURACY, TITLE, AND NON-INFRINGEMENT. COMPANY DOES NOT WARRANT THAT THE COMPANY SERVICE IS ERROR-FREE OR THAT OPERATION OF THE COMPANY SERVICE WILL BE SECURE OR UNINTERRUPTED.

## 7. LIMITATIONS OF LIABILITY.

1. Disclaimer of Consequential Damages. EXCEPT FOR LIABILITY ARISING FROM (A) CUSTOMER’S BREACH OF SECTION 1.3 (LICENSE RESTRICTIONS AND RESPONSIBILITIES) ABOVE AND (B) EITHER PARTY’S BREACH OF SECTION 5 (CONFIDENTIALITY) ABOVE, IN NO EVENT WILL EITHER PARTY BE LIABLE TO THE OTHER FOR ANY SPECIAL, INDIRECT, RELIANCE, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, LOST OR DAMAGED DATA, LOST PROFITS OR LOST REVENUE, WHETHER ARISING IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, EVEN IF A PARTY HAS BEEN NOTIFIED OF THE POSSIBILITY THEREOF.
2. General Cap on Liability. EXCEPT FOR LIABILITY ARISING FROM (A) CUSTOMER’S BREACH OF SECTION 1.3 (LICENSE RESTRICTIONS AND RESPONSIBILITIES) ABOVE, (B) EITHER PARTY’S BREACH OF SECTION 5 (CONFIDENTIALITY) ABOVE, AND (C) A PARTY’S INDEMNIFICATION OBLIGATIONS SET FORTH IN SECTIONS 8.1 AND 8.2 BELOW, AS APPLICABLE, UNDER NO CIRCUMSTANCES WILL EITHER PARTY’S LIABILITY FOR ALL CLAIMS ARISING UNDER OR RELATING TO THIS AGREEMENT (INCLUDING BUT NOT LIMITED TO WARRANTY CLAIMS), REGARDLESS OF THE FORUM AND REGARDLESS OF WHETHER ANY ACTION OR CLAIM IS BASED ON CONTRACT, TORT, OR OTHERWISE, EXCEED THE AGGREGATE FEES PAID AND PAYABLE BY CUSTOMER TO COMPANY UNDER THIS AGREEMENT DURING THE TWELVE (12) MONTHS PRECEDING THE CLAIM. THIS LIMITATION OF LIABILITY IS CUMULATIVE AND NOT PER INCIDENT.
3. Independent Allocations of Risk. EACH PROVISION OF THIS AGREEMENT THAT PROVIDES FOR A LIMITATION OF LIABILITY, DISCLAIMER OF WARRANTIES, OR EXCLUSION OF DAMAGES IS TO ALLOCATE THE RISKS OF THIS AGREEMENT BETWEEN THE PARTIES. EACH OF THESE PROVISIONS IS SEVERABLE AND INDEPENDENT OF ALL OTHER PROVISIONS OF THIS AGREEMENT, AND EACH OF THESE PROVISIONS WILL APPLY EVEN IF THEY HAVE FAILED OF THEIR ESSENTIAL PURPOSE.

## 8. INDEMNIFICATION.

1. Indemnification by Company. Company will indemnify, defend and hold Customer and the officers, directors, agents, and employees of Customer (“Customer Indemnified Parties”) harmless from settlement amounts and damages, liabilities, penalties, costs and expenses (“Liabilities”) that are payable to any third party by the Customer Indemnified Parties (including reasonable attorneys’ fees) arising from any claim, demand or allegation by a third party that the Company Service infringes or misappropriates any United States copyright or trade secret (except for claims for which Company is entitled to indemnification under Section 8.2, in which case Company will have no indemnification obligations with respect to such claim). Company will have no liability or obligation under this Section 8.1 with respect to any Liability if such Liability is caused in whole or in part by: (a) modification of the Company Service by any party other than Company; (b) the combination, operation, or use of the Company Service with other product(s), data or services where the Company Service would not by itself be infringing; or (c) unauthorized or improper use of the Company Service. This Section 8.1 states Company’ entire obligation and Customer’s sole remedies in connection with any claim regarding the intellectual property rights of any third party.
2. Indemnification by Customer. Customer will indemnify, defend and hold Company and the officers, directors, agents, and employees of Company (“Company Indemnified Parties”) harmless from Liabilities that are payable to any third party by the Company Indemnified Parties (including reasonable attorneys' fees) arising from, directly or indirectly, any claim, demand or allegation by a third party that arises out of or is in connection with (a) any use by Customer of the Company Service in violation of this Agreement, (b) Company’s use of the Customer Data in accordance with this Agreement, or (c) Customer’s violation of any terms and conditions related to and/or governing use of any Third Party Services.
3. Action in Response to Potential Infringement. If the use of the Company Service or any portion thereof by Customer has become, or in Company’s opinion is likely to become, the subject of any claim of infringement, Company may at its option and expense (a) procure for Customer the right to continue using the Company Service as set forth hereunder; (b) replace or modify the Company Service to make it non-infringing so long as the Company Service has at least equivalent functionality; (c) substitute an equivalent for the Company Service or (d) if options (a)-(c) are not reasonably practicable, terminate this Agreement.
4. Indemnification Procedure. If a Customer Indemnified Party or a Company Indemnified Party (each, an “Indemnified Party”) becomes aware of any matter it believes it should be indemnified under Section 8.1 or Section 8.2, as applicable, involving any claim, action, suit, investigation, arbitration or other proceeding against the Indemnified Party by any third party (each an “Action”), the Indemnified Party will give the other Party (the “Indemnifying Party”) prompt written notice of such Action. The Indemnified Party will cooperate, at the expense of the Indemnifying Party, with the Indemnifying Party and its counsel in the defense and the Indemnified Party will have the right to participate fully, at its own expense, in the defense of such Action with counsel of its own choosing. Any compromise or settlement of an Action will require the prior written consent of both Parties hereunder, such consent not to be unreasonably withheld or delayed.

## 9. GOVERNMENT MATTERS.&#x20;

1. Customer may not remove or export from the United States or allow the export or re-export of the Company Service, or any direct product thereof in violation of any restrictions, laws or regulations of the United States Department of Commerce, the United States Department of Treasury Office of Foreign Assets Control, or any other United States or foreign agency or authority. As defined in FAR section 2.101, the Company Service (including the software, documentation and data related thereto) are “commercial items” and according to DFAR section 252.2277014(a)(1) and (5) are deemed to be “commercial computer software” and “commercial computer software documentation.” Consistent with DFAR section 227.7202 and FAR section 12.212, any use modification, reproduction, release, performance, display, or disclosure of such commercial software or commercial software documentation by the U.S. Government will be governed solely by the terms of this Agreement and will be prohibited except to the extent expressly permitted by the terms of this Agreement.

## 10. GENERAL

1. Force Majeure. No Party hereto will have any liability under this Agreement for such Party’s failure or delay in performing any of the obligations imposed by this Agreement to the extent such failure or delay is the result of any event beyond such Party’s reasonable control, including: (a) any fire, explosion, unusually severe weather, natural disaster or Act of God; (b) epidemic; any nuclear, biological, chemical, or similar attack; any other public health or safety emergency; any act of terrorism; and any action reasonably taken in response to any of the foregoing; (c) any act of declared or undeclared war or of a public enemy, or any riot or insurrection; (d) damage to machinery or equipment; any disruption in transportation, communications, electric power or other utilities, or other vital infrastructure; or any means of disrupting or damaging internet or other computer networks or facilities; (e) any strike, lockout or other labor dispute or action; or (f) any action taken in response to any of the foregoing events by any civil or military authority.
2. Severability. In the event that any provision of this Agreement is found to be unenforceable, such provision will be reformed only to the extent necessary to make it enforceable, and the remainder will continue in effect, to the extent consistent with the intent of the Parties as of the Effective Date. The terms and conditions of this Agreement are severable. If any term or condition of this Agreement is deemed to be illegal or unenforceable under any rule of law, all other terms will remain in force. Further, the term or condition which is held to be illegal or unenforceable will remain in effect as far as possible in accordance with the intention of the Parties as of the Effective Date.
3. Relationship of the Parties. Nothing in this Agreement will be construed to place the Parties in an agency, employment, franchise, joint venture, or partnership relationship. Neither Party will have the authority to obligate or bind the other in any manner, and nothing herein contained will give rise or is intended to give rise to any rights of any kind to any third Parties. Neither Party will represent to the contrary, either expressly, implicitly or otherwise.
4. Remedies. Each Party acknowledges that a breach by it of any of the terms of Section 5 may cause irreparable harm to the Discloser for which Discloser could not be adequately compensated by money damages. Accordingly, Recipient agrees that, in addition to all other remedies available to Discloser in an action at law, in the event of any breach or threatened breach by the Recipient of the terms of this Agreement, the Discloser may seek, from any court of competent jurisdiction and without the necessity of proving actual damages or posting any bond or other security, temporary and permanent injunctive relief, including specific performance of the terms of Section 5.
5. Governing Law; Consent to Jurisdiction. The law, including the statutes of limitation, of the State of Delaware will govern this Agreement, the interpretation and enforcement of its terms and any claim or cause of action (in law or equity), controversy or dispute arising out of or related to it or its negotiation, execution or performance, whether based on contract, tort, statutory or other law, in each case without giving effect to any conflicts-of-law or other principle requiring the application of the law of any other jurisdiction. Each of the Parties hereto hereby irrevocably and unconditionally consents to submit to the sole and exclusive jurisdiction of the courts of the State of Delaware and of the United States of America located in Delaware (the “Delaware Courts”) for any litigation among the Parties hereto arising out of or relating to this Agreement, or the negotiation, validity or performance of this Agreement, waives any objection to the laying of venue of any such litigation in the Delaware Courts and agrees not to plead or claim in any Delaware Court that such litigation brought therein has been brought in any inconvenient forum or that there are indispensable parties to such litigation that are not subject to the jurisdiction of the Delaware Courts.
6. Assignment; Delegation; Binding Effect. Neither Party may assign or transfer this Agreement in whole or in part, by operation of law or otherwise, without the prior written consent of the other Party, except that either Party may assign or transfer this Agreement without the written consent of the other Party to an affiliate or corporation or other business entity succeeding to all or substantially all the assets and business of the assigning Party to which this Agreement relates by merger or purchase. Company may delegate its duties hereunder to any of its affiliates as necessary to perform its obligations hereunder, provided that Company will bear full liability and responsibility for their acts and omissions. Any attempted assignment, delegation or transfer by a Party in violation hereof will be null and void. Subject to the foregoing, this Agreement will be binding on the Parties and their successors and permitted assigns.
7. Notices. All notices under this Agreement will be in writing and will reference this Agreement. Notices will be deemed given: (a) when delivered personally; (b) three (3) days after having been sent by registered or certified mail, return receipt requested, postage prepaid; (c) by email for which receipt is confirmed or (d) one (1) day after deposit with an internationally recognized commercial overnight carrier, with written verification of receipt. All communications will be sent to the applicable address provided on the Order Form, or such other addresses subsequently communicated to the other Party in writing in accordance with this Section 10.7.
8. No Waiver. Failure by either Party to enforce any provision of this Agreement will not be deemed a waiver of future enforcement of that or any other provision.
9. Complete Agreement. This Agreement constitutes the entire agreement between the Parties with respect to the subject matter hereof. It supersedes and replaces all prior or contemporaneous understandings or agreements, written or oral, regarding such subject matter, and prevails over any conflicting terms or conditions contained on printed forms submitted with purchase orders, sales acknowledgments or quotations. To the extent of any conflict or inconsistency between the provisions in the body of this Service Agreement and any applicable Order Form, the terms of this Service Agreement will prevail, unless the Order Form expressly amends a provision in this Service Agreement.


# FAQ

### I am having an issue requesting access to a resource

Please see [Troubleshooting](/reference/faq/troubleshooting) for debugging assistance.

### My initial GitHub Action has failed

When you create a quickstart from a template, it will attempt to run a GitHub Action Workflow. Because you have not configured your quickstart yet, this initial workflow should fail. This is expected and completing the configuration steps in [Broken mention](broken://pages/mLf1JjBfIXwRkhehH0xL) will cause subsequent workflow runs to succeed.

### How can I tell if my request has been approved/denied?

You can see the current status of your request on the Requests page in the sidebar.

&#x20;![](/files/dakkYnBvy3RKGL8vXaKZ)

### How do I add a new repo to my GitHub Connection if I configured it to have permissions to a subset of repos?

1. Go to your GitHub Settings then click on Applications under Integrations.![](/files/RiR8EBvbex5vLYxSiigy)
2. Click Configure on the Abbey Labs application<br>

   <figure><img src="/files/YiVEz6qIBATAWJOmXc4k" alt=""><figcaption></figcaption></figure>
3. Add your new repo to the list of selected repos, then click save<br>

   <figure><img src="/files/4Vcq9Pag00fV5quMpd73" alt=""><figcaption></figcaption></figure>


# Troubleshooting

### Common Issues

#### GitHub Action failing due to Terraform issues

* `Duplicate Resource Name`
  * You may have configured your output with a static name, such that multiple users will result in a resource with the same resource name.

    -> Configure a dynamic resource name using string interpolation. Examples can be seen in [Outputs](/reference/grant-kits/outputs#optionally-interpolate-variables)
  * The resource may be defined in a different terraform file. This commonly happens when people are testing multiple starter kits. You can fix this by renaming one of the resources.
* `Bad Grant Kit Name`
  * Grant kit names must start with a letter or underscore, and may contain only letters, digits, underscores, and dashes.&#x20;
* `Grant Kit Already Exists`
  * Names must be unique across all of your grant kits.&#x20;
* `Abbey Identity Not Found`
  * Your Abbey Identity is the email you used to sign up for Abbey including the domain. Check that the email specified is the same as that value. &#x20;
* `API Error`
  * Please contact us for further support. You can find us on our [Slack](https://join.slack.com/t/abbey-io/shared_invite/zt-1zfhf5mo5-vBQM322YF3v7rsl3Wwl5LQ).
* `Request Denied Due to Unable to add Approver Check`
  * This may happen if you have not granted the Abbey GitHub App the correct permissions. Check that there isn't a permissions request at **Settings** -> **GitHub Apps** -> **Abbey Labs**&#x20;

    <figure><img src="/files/KL6GsOjNpW9fG59zhunu" alt=""><figcaption></figcaption></figure>
* `Request Denied Due to Failing Check`
  * This can happen when the output of your grant kit has issues when trying to run `terraform plan`. Inspect the error log in the GitHub actions run for your PR for details.

#### Other Common errors

* `ABBEY_TOKEN` or another API Token is missing from your GitHub Secrets.

  -> See the [Quickstart](/getting-started/quickstart) for instructions.
* GitHub may not have permissions to write to PRs.

  -> See [Connect a Repo](/build-a-grant-kit/connect-a-repo#grant-workflow-permissions)for instructions.
* You are missing a Connection to GitHub or that connection is missing access permissions to your repo.

  -> See [Connect a Repo](/build-a-grant-kit/connect-a-repo)for instructions.
* `Error refreshing state: HTTP remote state endpoint requires auth`
  * Double check that your Abbey API token is not expired! If it's expired, you'll need to create a new one.

### I've created a Grant Kit but it's not showing up in the web UI

Please make sure that the Materialize GitHub Action has succeeded. To check this, go to your repository containing the grant kit and click on **Actions** -> **Abbey Grant Kit Materialize**. If the Action has failed, inspect the log for further debugging.

<figure><img src="/files/3FnndaUPwBWAjwBO1Qm2" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/NSsWTp2lmKbN3VtPHjoQ" alt="" width="337"><figcaption></figcaption></figure>

Common causes of failure are:

* Your terraform file is misconfigured. Some possible causes and solutions are listed in [#common-issues](#common-issues "mention")

### When I make a request to a Resource it fails

A request may fail for many reasons. Some common reasons are:

* You have misspelled the name of the organization or repo when defining the output location.\
  -> Check that you have correctly specified your repo correctly.
* You are missing a Connection to GitHub for the repo where you want to store `access.tf`.

  -> See [Connect a Repo](/build-a-grant-kit/connect-a-repo) for instructions above for how to create a Connection.

### I've made a successful request to a Resource but I'm not seeing it appear under Approvals

Please make sure that the Generate Policy Input GitHub Action has succeeded. To check this, go to your repository containing the grant kit and click on **Actions** -> **Abbey Grant Kit Generate Policy Input**. If the Action has failed, inspect the log for further debugging. See [#common-issues](#common-issues "mention")for examples of failures and their solutions.

<figure><img src="/files/3FnndaUPwBWAjwBO1Qm2" alt=""><figcaption></figcaption></figure>

![](/files/mEp85Jft2OohHMuxGHIx)

### My Policy is not taking effect

Common reasons to have a failing policy

* The policy must be in the same repo as your output. Check to make sure that this is the case.
* Policy is incorrectly defined. See [Policies](/reference/grant-kits/policies)for how to configure a policy.

### I've made a successful request to a Resource but it immediately gets denied, and I don't have a policy rejecting my request

Please make sure that the Generate Policy Input GitHub Action has succeeded. If this Policy Fails, the request will be denied. To check this, go to your repository containing the grant kit and click on **Actions** -> **Abbey Grant Kit Generate Policy Input**. If the Action has failed, inspect the log for further debugging. See [#common-issues](#common-issues "mention")for examples of failures and their solutions.

<figure><img src="/files/3FnndaUPwBWAjwBO1Qm2" alt=""><figcaption></figcaption></figure>

![](/files/mEp85Jft2OohHMuxGHIx)


# Privacy Policy

Last Updated: July 27th, 2023

Abbey Labs provides a platform for companies to help manage granular access to their cloud infrastructure. This Privacy Policy describes how we handle the personal information we collect from website visitors and prospective and current customers in connection with our website and our related services.

## Personal Information We Collect

We collect the following categories of information:

### Information you provide

* Contact details, including your first and last name and email address. &#x20;
* Profile information, such as your photo if you choose to upload it.&#x20;
* Account information, such as your account credentials and other information used to administer your account, include the services you have purchased or may be interested in.
* Payment and transaction data that our payment service providers collect to process your payments. We do not store payment card numbers on our systems. The information you provide in connection with your purchases is handled by our third-party payment processors, in accordance with their terms of service and privacy policies.
* Communications that we exchange with you, including when you contact us with questions, feedback, or otherwise.
* Marketing information, such as your preferences for receiving communications about our services and publications, and details about how you engage with our communications.

### Information we obtain from other sources

* Social media information. We may maintain pages on social media platforms, such as Twitter and LinkedIn. When you visit or interact with our pages on those platforms, you or the platforms may provide us with information through the platform.&#x20;
* Other sources. We may obtain your personal information from other third parties, such as marketing partners, data providers, and publicly-available sources.

### Automatic data collection

We and our service providers may automatically log information about you, your computer or mobile device, and your interaction over time with our services, such as:

* Device data, such as your computer’s or mobile device’s operating system, manufacturer and model, browser type, IP address, unique identifiers, language settings, mobile device carrier, and general location information such as city, state or geographic area; and
* Usage data, such as pages or screens you viewed, how long you spent on a page, browsing history, and access times.

We may collect this information using cookies and other similar technologies. Cookies are text files that websites store on a visitor‘s device or in the browser for the purpose of helping you navigate between pages efficiently, remembering your preferences, enabling functionality, helping us understand user activity and patterns, and facilitating online advertising. For more information on how you can control cookies, please see the [Your Privacy Choices](https://docs.google.com/document/d/1TSEJhkC6BGqHId-W3g3hv4A2Anu4awLA/edit#bookmark=id.17dp8vu) section below.

## How We Use Personal Information

We use personal information for the following purposes:

To provide our services. This includes:

* Enabling you to subscribe to our newsletters;&#x20;
* Administering, hosting, and operating our services;
* Communicating with you and responding to any inquiries you may have; and
* Analyzing your use of our services to allow us to evaluate and improve the services.

For research, development, benchmarking, and improving our services. We may use personal information to analyze and improve the services, identify trends, and operate and expand our business activities. We may also create aggregated, anonymized, or other de-identified statistics, which we may use for lawful business purposes, including for analytics, forecasting, and strategic planning.&#x20;

For marketing and advertising.&#x20;

* Direct marketing. We may send you direct marketing communications, including, but not limited to, sending newsletters or publications, and notifying you of promotions, offers and events via postal mail, email, telephone, text message, and other means.
* Interest-based advertising. We engage our advertising partners, including third party advertising companies and social media companies, to display ads around the web. These companies may use cookies and similar technologies to collect information about your interaction, including the data described in the [Automatic data collection](https://docs.google.com/document/d/1TSEJhkC6BGqHId-W3g3hv4A2Anu4awLA/edit#bookmark=id.gjdgxs) section above, over time across our services, our communications and other online services, and use that information to serve online ads that they think will interest you. We may also share information about our users with these companies to facilitate interest-based advertising to those or similar users on other online platforms. You can learn more about your choices for limiting interest-based advertising in the [Online tracking opt-out](https://docs.google.com/document/d/1TSEJhkC6BGqHId-W3g3hv4A2Anu4awLA/edit#bookmark=id.3rdcrjn) section below.

For compliance and protection, including to enforce any applicable terms and conditions, comply with legal obligations, defend against legal claims or disputes, protect the security and integrity of our services, and identify and investigate fraudulent, harmful, unauthorized, unethical or illegal activity.

## How We Disclose Personal Information

We may disclose personal information to:&#x20;

Third-party service providers, that provide services on our behalf or help us operate our services or our business (such as hosting, communications, data and cyber security, billing and payment processing, fraud detection, investigation and prevention, web and mobile analytics, email and communication distribution and monitoring, and customer relation management systems).

Professional advisors, such as lawyers, auditors, bankers and insurers, where necessary in the course of the professional services that they render to us.

Advertising partners, including for the [interest-based advertising purposes](https://docs.google.com/document/d/1TSEJhkC6BGqHId-W3g3hv4A2Anu4awLA/edit#bookmark=id.1fob9te) described above.

Law enforcement, government authorities, and private parties, as we believe in good faith to be necessary or appropriate, for the [compliance and protection purposes](https://docs.google.com/document/d/1TSEJhkC6BGqHId-W3g3hv4A2Anu4awLA/edit#bookmark=id.4d34og8) described above.

Acquirers and other relevant participants in business transactions (or negotiations for such transactions) involving a corporate divestiture, merger, consolidation, acquisition, reorganization, sale or other disposition of all or any portion of the business or assets of, or equity interests in, Abbey Labs or our affiliates (including, in connection with a bankruptcy or similar proceedings).

## Your Privacy Choices

Unsubscribe from direct marketing communications. You may opt out of marketing-related communications by following the opt-out or unsubscribe instructions contained in the marketing communication we send you. You may continue to receive service-related and other non-marketing communications.&#x20;

Online tracking opt-out. There are a number of ways to opt out of having your online activity and device data collected through our services, which we have summarized below:

* Blocking cookies in your browser. Most browsers let you remove or reject cookies, including cookies used for interest-based advertising. To do this, follow the instructions in your browser settings. Many browsers accept cookies by default until you change your settings. For more information about cookies, including how to see what cookies have been set on your device and how to manage and delete them, visit [allaboutcookies.org](https://www.allaboutcookies.org/).

Use the following links to learn more about how to control cookies and online tracking through your browser:

* [Firefox](https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop); [Chrome](https://support.google.com/chrome/answer/95647); [Microsoft Edge](https://support.microsoft.com/en-us/microsoft-edge/learn-about-tracking-prevention-in-microsoft-edge-5ac125e8-9b90-8d59-fa2c-7f2e9a44d869); [Safari](https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac)
* Blocking advertising ID use in your mobile settings. Your mobile device settings may provide functionality to limit use of the advertising ID associated with your mobile device for interest-based advertising purposes.
* Using privacy plug-ins or browsers. You can block our services from setting cookies used for interest-based ads by using a browser with privacy features, like Brave, or installing browser plugins like [Privacy Badger](https://www.eff.org/privacybadger), [DuckDuckGo](https://duckduckgo.com/), [Ghostery](https://www.ghostery.com/) or [uBlock Origin](https://ublock.org/), and configuring them to block third party cookies/trackers.
* Google Analytics. We use Google Analytics to help us better understand how people engage with our services by collecting information and creating reports about how users use our services. For more information on Google Analytics, click [here](https://marketingplatform.google.com/about/analytics/). For more information about Google’s privacy practices, click [here](https://www.google.com/policies/privacy/partners/). You can opt out of Google Analytics by downloading and installing the browser plug-in available at: <https://tools.google.com/dlpage/gaoptout>.
* Platform opt-outs. The following advertising partners offer opt-out features that let you opt out of use of your information for interest-based advertising:
  * [Google](https://adssettings.google.com/)&#x20;
  * [Twitter](https://twitter.com/settings/account/personalization?lang=en)
* Advertising industry opt-out tools. You can also use these opt-out options to limit use of your information for interest-based advertising by participating companies:
  * [Digital Advertising Alliance](http://optout.aboutads.info/)&#x20;
  * [Network Advertising Initiative](http://optout.networkadvertising.org/?c=1)&#x20;

Note that because these opt-out mechanisms are specific to the device or browser on which they are exercised, you will need to opt out on every browser and device that you use.

Do Not Track. Some Internet browsers may be configured to send “Do Not Track” signals to the online services that you visit. We currently do not respond to "Do Not Track" or similar signals. To find out more about "Do Not Track," please visit [http://www.allaboutdnt.com](http://www.allaboutdnt.com/).

## Data Security

We employ a number of technical, organizational and physical safeguards designed to protect the personal information we collect. However, no security measures are failsafe and we cannot guarantee the security of your personal information.

## Children

Our services are not intended for use by children under 13 years of age. If we learn that we have collected personal information through our services from a child under 13 without the consent of the child’s parent or guardian as required by law, we will delete it.

## Changes to This Privacy Policy

We reserve the right to modify this Privacy Policy at any time. If we make material changes to this Privacy Policy, we will notify you.

## Contact Us

You can reach us by email at <hello@abbey.io> or at the following mailing address: 2261 Market Street #5351 San Francisco, CA 94114

<br>


# Logo

![](/files/xQK26xKupGUrycDEPiLZ)


