{"token_count": 5020}

# Creating an Access List for Just-in-Time Access

Identity Governance is available only with Teleport Enterprise.

The **Just-in-Time Access Guide** creates an Access List whose members are required to request access to a defined set of resources, rather than being granted that access automatically. The list's members submit an [Access Request](https://goteleport.com/docs/identity-governance/access-requests.md); the list's owners review and approve or deny it. Once approved, the member receives temporary access bounded by the request's TTL, capped by the member's remaining Teleport session.

In this guide, you will:

- Decide when a Just-in-Time Access List is the right fit
- Create one with the Teleport Web UI, `tctl`, or Terraform
- Verify the request-and-approval experience as a member

## When to use this flow

Use a Just-in-Time Access List when:

- The resources are sensitive enough that members should justify each access event.
- You want a clear audit trail of *who requested what, when, and who approved it*.
- You want a single list to govern who can request the access, with periodic reviews so the membership is reaffirmed rather than left to drift.
- You'd rather have Teleport generate the supporting roles than write role specs by hand.

If members instead need access immediately on login for the duration of their session, use the [Standing Access Guide](https://goteleport.com/docs/identity-governance/access-lists/standing-access-list.md) instead.

## Prerequisites

- A running Teleport Enterprise (v18.8.0 or higher) cluster accessible at a hostname with a valid TLS certificate. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

- The `tctl` and `tsh` clients, required only if creating the list with `tctl` or Terraform.

  Installing `tctl` and `tsh` clients

  1. Determine the version of your Teleport cluster. The `tctl` and `tsh` clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at `/v1/webapi/find` and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

     **Mac/Linux**

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
     ```

     **Windows - Powershell**

     ```
     $ $TELEPORT_DOMAIN = "teleport.example.com:443"
     $ $TELEPORT_VERSION = (Invoke-RestMethod -Uri "https://${TELEPORT_DOMAIN}/v1/webapi/find").server_version
     ```

  2. Follow the instructions for your platform to install `tctl` and `tsh` clients:

     **Mac**

     Download the signed macOS .pkg installer for Teleport, which includes the `tctl` and `tsh` clients:

     ```
     $ curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg
     ```

     In Finder double-click the `pkg` file to begin installation.

     ---

     DANGER

     Using Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v$TELEPORT_VERSION-windows-amd64-bin.zip
     Unzip the archive and move the `tctl` and `tsh` clients to your %PATH%
     NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
     Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation/single-machine.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

  Connecting with TLS routing disabled

  This guide's commands assume your Teleport cluster uses TLS routing (`proxy_listener_mode: multiplex`), where the `tctl` and `tsh` clients reach every Teleport service through the Proxy Service's web address on port `443`. If you're not sure whether this applies to your cluster, check with whoever manages it.

  If your cluster uses separate listener ports instead, adjust ports as follows:

  - **`tsh` commands** (e.g., `tsh login --proxy=...`): continue using the Proxy Service web address on port `3080` (or `443` if behind a load balancer). Do not change these to port `3025`.

  - **Direct `tctl` or Auth Service API commands**: use port `3025` for the Auth Service gRPC listener:

    ```
    $ tctl status --auth-server=teleport.example.com:3025
    ```

* At least one user who will be a member of the list, preferably a user with no access to resources to verify the access flow later.

* At least one resource enrolled in the cluster for the Access List to grant access to.

- Permissions to create Access Lists, users, and roles. These are included in the preset [`editor`](https://goteleport.com/docs/reference/access-controls/roles.md#preset-roles) role, or you can copy and paste the following into your own role:
  ```
  allow:
    rules:
    - resources:
      - access_list
      - user
      - role
      verbs:
      - read
      - list
      - create
      - update
      - delete

  ```

## Step 1/2. Create the Access List

Choose how to create the list.

**Web UI**

In the Teleport Web UI, hover over **Add New** from the sidebar menu then click **Access List**.

Enter a name and optional description for the list.

Click **Just-in-Time Access Guide** and click **Start Guide**.

The guide steps you through:

1. **Define Access to Resources** — for each resource type, specify the matching criteria. Most resource types are matched by [labels](https://goteleport.com/docs/zero-trust-access/rbac-get-started/labels.md); others may ask you to select the resource itself. Members can request access to anything that matches.

   ---

   PREVIEWING RESOURCES

   After defining access for a resource type, the UI shows a preview of matching resources. The preview is limited by your own role permissions — members may be granted access to additional resources that aren't visible to you.

   ---

2. **Define Resource Identities or Principals** — for resource types that need them (e.g. SSH logins, database users, Kubernetes users/groups, etc.), specify which principals members can use to connect once their request is approved.

3. **Basic Information** — confirm the name and description of the Access List, and select the next review date. Periodic reviews are how list owners reaffirm that the right members are still on the list.

4. **Define Membership** — add the users who should be eligible to request access through this list.

5. **Define Ownership** — add the users responsible for managing the list, reviewing membership, and reviewing Access Requests submitted through this list.

At the final **Deployment** step, click **Create Access List Now**. The list is created directly via the Teleport API and is immediately active.

**tctl**

`tctl acl create` was introduced in `tctl` v18.10.3. On earlier versions of `tctl`, use the Web UI.

The following command creates a list where `bob` must submit an Access Request to reach SSH servers labeled `env: test`, and `alice` reviews it. Once `alice` approves, `bob` can connect to those servers as the `ubuntu` OS user for the lifetime of the request. Substitute the usernames, roles, labels, and logins with ones that suit your cluster:

```
$ tctl acl create \
    --access-type access-request \
    --title "On-call access for support engineers" \
    --description "Request temporary access to test servers." \
    --audit-frequency 6 \
    --audit-day 1 \
    --owners alice \
    --owner-required-roles manager \
    --members bob \
    --member-required-roles engineer \
    --node-labels env=test \
    --logins ubuntu
```

See [`tctl acl create`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-acl-create) for the full list of flags.

Every list-valued flag takes a comma-separated string, for example `--members bob,carol`. Members can also be added after the fact with [`tctl acl users add`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-acl-users-add).

**Terraform**

`tctl acl create` accepts `--output terraform` as of `tctl` v19.0.0. On earlier versions of `tctl`, use the Web UI instead: the guided flow mirrors your input as a Terraform module, which you can copy at the final **Deployment** step.

### Generate the configuration

The `tctl acl create --output terraform` command will not create anything, but instead prints a Terraform module describing the Access List the other flags define, which you can write straight to a file.

The following command generates a module for a list where `bob` must submit an Access Request to reach SSH servers labeled `env: test`, and `alice` reviews it. Once `alice` approves, `bob` can connect to those servers as the `ubuntu` OS user for the lifetime of the request. Substitute the usernames, roles, labels, and logins with ones that suit your cluster:

```
$ tctl acl create \
    --access-type access-request \
    --title "On-call access for support engineers" \
    --description "Request temporary access to test servers." \
    --owners alice \
    --owner-required-roles manager \
    --members bob \
    --member-required-roles engineer \
    --node-labels env=test \
    --logins ubuntu \
    --output terraform > access-list.tf
```

See [`tctl acl create`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-acl-create) for the full list of flags.

The dry-run is a complete module: a provider block, the three role definitions a Just-in-Time list needs, the Access List itself, and one member resource per user you passed to `--members`. The provider's `addr` is filled in from the cluster `tctl` is talking to, so your output will be similar to the following:

```
# Terraform config for creating an Access List with just-in-time (JIT) access.
# Members must submit an access request for temporary access to Teleport resources,
# subject to approval by the owners.

terraform {
  required_providers {
    teleport = {
      source  = "terraform.releases.teleport.dev/gravitational/teleport"
      version = "~> 19.0"
    }
  }
}

provider "teleport" {
  addr = "teleport.example.com:443"
}

resource "teleport_role" "access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789" {
  version = "v8"

  metadata = {
    name = "access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    labels = {
      "teleport.dev/iac-tool"                = "terraform"
      "teleport.internal/access-list-preset" = "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    }
  }

  spec = {
    options = {
      max_session_ttl    = "30h0m0s"
      cert_format        = "standard"
      enhanced_recording = ["command", "network"]
      record_session = {
        desktop = true
        default = "best_effort"
      }
      desktop_clipboard         = true
      desktop_directory_sharing = true
      ssh_file_copy             = true
    }
    allow = {
      logins = ["ubuntu"]
      node_labels = {
        env = ["test"]
      }
    }
  }
}

# A role that requires requesting access to resources (assigned to members).
resource "teleport_role" "requester-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789" {
  version = "v8"

  metadata = {
    name = "requester-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    labels = {
      "teleport.dev/iac-tool"                = "terraform"
      "teleport.internal/access-list-preset" = "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    }
  }

  spec = {
    options = {
      max_session_ttl    = "30h0m0s"
      cert_format        = "standard"
      enhanced_recording = ["command", "network"]
      record_session = {
        desktop = true
        default = "best_effort"
      }
      desktop_clipboard         = true
      desktop_directory_sharing = true
      ssh_file_copy             = true
    }
    allow = {
      request = {
        search_as_roles = ["access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"]
      }
    }
  }
}

# A role that allows reviewing access requests (assigned to owners).
resource "teleport_role" "reviewer-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789" {
  version = "v8"

  metadata = {
    name = "reviewer-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    labels = {
      "teleport.dev/iac-tool"                = "terraform"
      "teleport.internal/access-list-preset" = "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    }
  }

  spec = {
    options = {
      max_session_ttl    = "30h0m0s"
      cert_format        = "standard"
      enhanced_recording = ["command", "network"]
      record_session = {
        desktop = true
        default = "best_effort"
      }
      desktop_clipboard         = true
      desktop_directory_sharing = true
      ssh_file_copy             = true
    }
    allow = {
      review_requests = {
        roles            = ["access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"]
        preview_as_roles = ["access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"]
      }
    }
  }
}

resource "teleport_access_list" "acl-0a1b2c3d-4e5f-6789-abcd-ef0123456789" {
  header = {
    kind    = "access_list"
    version = "v1"
    metadata = {
      name = "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
      labels = {
        "teleport.dev/iac-tool"                      = "terraform"
        "teleport.internal/access-list-preset"       = "short-term"
        "teleport.internal/access-list-preset-roles" = "reviewer-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789,requester-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789,access-standard-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"
      }
    }
  }

  spec = {
    description = "Request temporary access to test servers."
    owners = [{
      membership_kind = "1"
      name            = "alice"
    }]
    membership_requires = {
      roles = ["engineer"]
    }
    ownership_requires = {
      roles = ["manager"]
    }
    grants = {
      roles = ["requester-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"]
    }
    title = "On-call access for support engineers"
    owner_grants = {
      roles = ["reviewer-acl-preset-0a1b2c3d-4e5f-6789-abcd-ef0123456789"]
    }
    type = "static"
  }
}

resource "teleport_access_list_member" "acl-member-bob_86c6a0d4" {
  depends_on = [teleport_access_list.acl-0a1b2c3d-4e5f-6789-abcd-ef0123456789]

  header = {
    kind    = "access_list_member"
    version = "v1"
    metadata = {
      name = "bob"
    }
  }

  spec = {
    access_list     = "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
    name            = "bob"
    membership_kind = "1"
  }
}

```

Note the `type = "static"` field. Access Lists managed with Terraform must be static so that Terraform can own their membership, and static lists do not support periodic auditing. To learn the differences, see [Static versus default Access Lists](https://goteleport.com/docs/configuration/resource-guides/access-list.md#static-versus-default-access-lists).

### Apply the configuration

Log in to your cluster, assigning teleport.example.com:443 to your Teleport proxy address and email\@example.com to your Teleport username:

```
$ tsh login --proxy=teleport.example.com:443 --user=email@example.com
```

Generate temporary credentials for the Terraform provider:

```
$ eval "$(tctl terraform env)"
```

Initialize Terraform, preview the changes, and apply them:

```
$ terraform init
$ terraform plan
$ terraform apply
```

The Access List is created once `terraform apply` completes.

---

NOTE

The steps above use `tctl terraform env` to issue short-lived credentials, which is convenient for trying things out locally. For remote environments such as CI/CD pipelines or cloud VMs, see the [Terraform provider documentation](https://goteleport.com/docs/configuration/terraform-provider.md) for guidance on setting up the provider.

---

To write the configuration by hand instead of generating it, or for the full set of fields on the `teleport_access_list` and `teleport_access_list_member` resources, see [Creating Access Lists with IaC](https://goteleport.com/docs/configuration/resource-guides/access-list.md).

---

EDITING THE SUPPORTING ROLES

However you created the list, keep the supporting roles' names and their `teleport.internal/access-list-preset*` labels unchanged. Both the Web UI Access List editor and `tctl acl update` rely on them to recognize which roles belong to this Access List.

To change what the list grants:

- **Web UI** — from the sidebar menu, click **Identity Governance** > **Access Lists**, click the target Access List, open the **Access Definition** tab, then click **Edit Access**.
- **`tctl`** — rerun [`tctl acl update`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-acl-update) with the resource flags you want. It updates the supporting roles for you.
- **Terraform** — rerun [`tctl acl update`](https://goteleport.com/docs/reference/cli/tctl.md#tctl-acl-update) with the resource flags you want and `--output terraform` to regenerate the configuration, then apply it.

Both tools support only a limited subset of role fields. If the roles end up outside that subset, neither can change the list's grants — the Web UI editor can no longer parse them, and `tctl acl update` rejects them rather than silently dropping the fields you added. From that point on you must manage the roles directly for the rest of the Access List's life.

---

## Step 2/2. Verify the request flow

Log in as one of the **members** you added. The resources the list covers should appear in the resource list with a **Request Access** button rather than a direct connect button.

1. Submit a request for one of the resources, optionally providing a reason.
2. Log in as one of the **owners** and approve the request. (The JIT preset grants owners a `reviewer` role automatically, which is what lets them approve.)
3. Back as the member, assume the approved request. You now have temporary access to the resource; once the request expires or your session ends, the access is gone.

## Next steps

- Create an Access List whose members get access on login with the [Standing Access Guide](https://goteleport.com/docs/identity-governance/access-lists/standing-access-list.md).
- Create an Access List by assigning existing roles directly with the [Custom Form](https://goteleport.com/docs/identity-governance/access-lists/custom-access-list.md).
- Learn more about how members request and reviewers approve access in [Access Requests](https://goteleport.com/docs/identity-governance/access-requests.md).
- Auto-approve low-risk requests with [automatic reviews](https://goteleport.com/docs/identity-governance/access-requests/automatic-reviews.md).
- Route request notifications with [notification routing rules](https://goteleport.com/docs/identity-governance/access-requests/notification-routing-rules.md).
- Group members by inheriting access from other lists with [nested Access Lists](https://goteleport.com/docs/identity-governance/access-lists/nested-access-lists.md).
- Learn more about managing Access Lists as code with the [Terraform provider and Kubernetes operator](https://goteleport.com/docs/configuration/resource-guides/access-list.md).
