Fork me on GitHub

Teleport

Access Requests with PagerDuty

Improve

With Teleport's PagerDuty integration, engineers can access the infrastructure they need to resolve incidents quickly—without longstanding admin permissions that can become a vector for attacks.

Teleport's PagerDuty integration allows you to treat Teleport Role Access Requests as PagerDuty incidents, notify the appropriate on-call team, and approve or deny the requests via PagerDuty. You can also configure the plugin to approve Role Access Requests automatically if the user making the request is on the on-call team for a service affected by an incident.

This guide will explain how to set up Teleport's Access Request plugin for PagerDuty.

Prerequisites

  • A running Teleport cluster, including the Auth Service and Proxy Service. For details on how to set this up, see our Enterprise Getting Started guide.

  • The tctl admin tool and tsh client tool version >= 10.3.1, which you can download by visiting the customer portal.

    tctl version

    Teleport v10.3.1 go1.18

    tsh version

    Teleport v10.3.1 go1.18

  • A Teleport Cloud account, which includes a running Auth Service and Proxy Service. If you do not have a Teleport Cloud account, visit the sign up page to begin your free trial.

  • The tctl admin tool and tsh client tool version >= 10.2.2. To download these tools, visit the Downloads page.

    tctl version

    Teleport v10.2.2 go1.18

    tsh version

    Teleport v10.2.2 go1.18

  • A PagerDuty account with the "Admin", "Global Admin", or "Account Owner" roles. These roles are necessary for generating an API token that can list and look up user profiles.

    You can see your role by visiting your user page in PagerDuty, navigating to the "Permissions & Teams" tab, and checking the value of the "Base Role" field.

  • Either a Linux host or Kubernetes cluster where you will run the PagerDuty plugin.

We recommend installing Teleport plugins on the same host as the Teleport Proxy Service. This is an ideal location as plugins have a low memory footprint, and will require both public internet access and Teleport Auth Service access.

To connect to Teleport, log in to your cluster using tsh, then use tctl remotely:

tsh login --proxy=teleport.example.com [email protected]
tctl status

Cluster teleport.example.com

Version 10.3.1

CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

You can run subsequent tctl commands in this guide on your local machine.

For full privileges, you can also run tctl commands on your Auth Service host.

To connect to Teleport, log in to your cluster using tsh, then use tctl remotely:

tsh login --proxy=myinstance.teleport.sh [email protected]
tctl status

Cluster myinstance.teleport.sh

Version 10.2.2

CA pin sha256:sha-hash-here

You must run subsequent tctl commands in this guide on your local machine.

Step 1/8. Create services

To demonstrate the PagerDuty plugin, create two services in PagerDuty. For each service, fill in only the "Name" field and skip all other configuration screens, leaving options as the defaults:

  • Teleport Access Request Notifications
  • My Critical Service

We will configure the PagerDuty plugin to create an incident in the Teleport Access Request Notifications service when certain users create an Access Request.

For users on the on-call team for My Critical Service (in this case, your PagerDuty user), we will configure the PagerDuy plugin to approve Access Requests automatically, letting them investigate incidents on the service quickly.

Step 2/8. Define RBAC resources

The Teleport PagerDuty plugin works by receiving Access Request events from the Teleport Auth Service and, based on these events, interacting with the PagerDuty API.

In this section, we will show you how to configure the PagerDuty plugin by defining the following RBAC resources:

  • A role called editor-requester, which can request the built-in editor role. We will configure this role to open a PagerDuty incident whenever a user requests it, notifying the on-call team for the Teleport Access Request Notifications service.
  • A role called demo-role-requester, which can request a role called demo-role. We will configure the PagerDuty plugin to auto-approve this request whenever the user making it is on the on-call team for My Critical Service.
  • A user and role called access-plugin that the PagerDuty plugin will assume in order to authenticate to the Teleport Auth Service. This role will have permissions to approve Access Requests from users on the on-call team for My Critical Service automatically.
  • A role called access-plugin-impersonator that allows you to generate signed credentials that the PagerDuty plugin can use to authenticate with your Teleport cluster.

editor-requester

Create a file called editor-request-rbac.yaml with the following content, which defines a role called editor-reviewer that can review requests for the editor role, plus an editor-requester role that can request this role.

kind: role
version: v5
metadata:
  name: editor-reviewer
spec:
  allow:
    review_requests:
      roles: ['editor']
---
kind: role
version: v5
metadata:
  name: editor-requester
spec:
  allow:
    request:
      roles: ['editor']
      thresholds:
        - approve: 1
          deny: 1
      annotations:
        pagerduty_notify_service: ["Teleport Access Request Notifications"]

The Teleport Auth Service annotates Access Request events with metadata based on the roles of the Teleport user submitting the Access Request. The PagerDuty plugin reads these annotations to determine how to respond to a new Access Request event.

Whenever a user with the editor-requester role requests the editor role, the PagerDuty plugin will read the pagerduty_notify_service annotation and notify PagerDuty to open an incident in the specified service, Teleport Access Request Notifications, until someone with the editor-reviewer role approves or denies the request.

Create the roles you defined:

tctl create -f editor-request-rbac.yaml

role 'editor-reviewer' has been created

role 'editor-requester' has been created

demo-role-requester

Create a file called demo-role-requester.yaml with the following content:

kind: role
version: v5
metadata:
  name: demo-role
---
kind: role
version: v5
metadata:
  name: demo-role-requester
spec:
  allow:
    request:
      roles: ['demo-role']
      thresholds:
        - approve: 1
          deny: 1
      annotations:
        pagerduty_services: ["My Critical Service"]

Users with the demo-role-requester role can request the demo-role role. When such a user makes this request, the PagerDuty plugin will read the pagerduty_services annotation. If the user making the request is on the on-call team for a service listed as a value for the annotation, the plugin will approve the Access Request automatically.

In this case, the PagerDuty plugin will approve any requests from users on the on-call team for My Critical Service.

Create the resources:

tctl create -f demo-role-requester.yaml;
Warning

For auto-approval to work, the user creating an Access Request must have a Teleport username that is also the email address associated with a PagerDuty account. In this guide, we will add the demo-role-requester role to your own Teleport account—which we assume is also your email address for PagerDuty—so you can request the demo-role role.

access-plugin

Teleport's Access Request plugins authenticate to your Teleport cluster as a user with permissions to list, read, and update Access Requests. This way, plugins can retrieve Access Requests from the Teleport Auth Service, present them to reviewers, and modify them after a review.

Define a user and role called access-plugin by adding the following content to a file called access-plugin.yaml:

kind: role
version: v5
metadata:
  name: access-plugin
spec:
  allow:
    rules:
      - resources: ['access_request']
        verbs: ['list', 'read', 'update']
      - resources: ['access_plugin_data']
        verbs: ['update']
    review_requests:
      roles: ['demo-role']
      where: 'contains(request.system_annotations["pagerduty_services"], "My Critical Service")'
---
kind: user
metadata:
  name: access-plugin
spec:
  roles: ['access-plugin']
version: v2

Notice that the access-plugin role includes an allow.review_requests.roles field with demo-role as a value. This allows the plugin to review requests for the demo-role role.

We are also restricting the access-plugin role to reviewing only Access Requests associated with My Critical Service. To do so, we have defined a predicate expression in the review_requests.where field. This expression indicates that the plugin cannot review requests for demo-role unless the request contains an annotation with the key pagerduty_services and the value My Critical Service.

The where field includes a predicate expression that determines whether a reviewer is allowed to review a specific request. You can include two functions in a predicate expression:

FunctionDescriptionExample
equalsA field is equivalent to a value.equals(request.reason, "resolve an incident")
containsA list of strings includes a value.contains(reviewer.traits["team"], "devops")

When you use the where field, you can include the following fields in your predicate expression:

FieldTypeDescription
reviewer.roles[]stringA list of the reviewer's Teleport role names
reviewer.traitsmap[string][]stringA map of the reviewer's Teleport traits by the name of the trait
request.roles[]stringA list of the Teleport roles a user is requesting
request.reasonstringThe reason attached to the request
request.system_annotationsmap[string][]stringA map of annotations for the request by annotation key, e.g., pagerduty_services

You can combine functions using the following operators:

OperatorFormatDescription
&&function && functionEvaluates to true if both functions evaluate to true
||function || functionEvalutes to true if either one or both functions evaluate to true
!!functionEvaluates to true if the function evaluates to false

An example of a function is equals(request.reason, "resolve an incident"). To configure an allow condition to match any Access Request that does not include the reason, "resolve an incident", you could use the function, !equals(request.reason, "resolve an incident").

Create the user and role:

tctl create -f access-plugin.yaml

access-plugin-impersonator

As with all Teleport users, the Teleport Auth Service authenticates the access-plugin user by issuing short-lived TLS credentials. In this case, we will need to request the credentials manually by impersonating the access-plugin role and user.

If you are using tctl from the Auth Service host, you will already have impersonation privileges.

To grant your user impersonation privileges for access-plugin, define a role called access-plugin-impersonator by pasting the following YAML document into a file called access-plugin-impersonator.yaml:

kind: role
version: v5
metadata:
  name: access-plugin-impersonator
spec:
  allow:
    impersonate:
      roles:
      - access-plugin
      users:
      - access-plugin

Create the access-plugin-impersonator role:

tctl create -f access-plugin-impersonator.yaml

Add roles to your user

Later in this guide, your Teleport user will take three actions that require additional permissions:

  • Generate signed credentials that the PagerDuty plugin will use to connect to your Teleport Cluster
  • Manually review an Access Request for the editor role
  • Create an Access Request for the demo-role role

To grant these permissions to your user, give your user the editor-reviewer, access-plugin-impersonator, and demo-role-requester roles we defined earlier.

Retrieve your user definition:

TELEPORT_USER=$(tsh status --format=json | jq -r .active.username)
tctl get users/${TELEPORT_USER?} > myuser.yaml

Edit myuser.yaml to include the roles you just created:

  roles:
   - access
   - auditor
   - editor
+  - editor-reviewer
+  - access-plugin-impersonator
+  - demo-role-requester

Apply your changes:

tctl create -f myuser.yaml

Log out of your Teleport cluster and log in again. You will now be able to review requests for the editor role, request the demo-role role, and generate signed certificates for the access-plugin role and user.

Create a user who will request access

Create a user called myuser who has the editor-requester role. Later in this guide, you will create an Access Request as this user to test the PagerDuty plugin:

tctl users add myuser --roles=editor-requester

tctl will print an invitation URL to your terminal. Visit the URL and log in as myuser for the first time, registering credentials as configured for your Teleport cluster.

Step 3/8. Install the Teleport PagerDuty plugin

We currently only provide linux-amd64 binaries. You can also compile these plugins from source. You can run the plugin from a remote host or your local development machine.

curl -L -O https://get.gravitational.com/teleport-access-pagerduty-v10.3.1-linux-amd64-bin.tar.gz
tar -xzf teleport-access-pagerduty-v10.3.1-linux-amd64-bin.tar.gz
cd teleport-access-pagerduty
sudo ./install

Teleport PagerDuty Plugin binaries have been copied to /usr/local/bin

You can run teleport-pagerduty configure > /etc/teleport-pagerduty.toml to

bootstrap your config file.

To install from source you need git and go installed. If you do not have Go installed, visit the Go downloads page.

Checkout teleport-plugins

git clone https://github.com/gravitational/teleport-plugins.git
cd teleport-plugins/access/pagerduty
make

Run ./install from teleport-pagerduty.

docker pull public.ecr.aws/gravitational/teleport-plugin-pagerduty:10.3.1
helm repo add teleport https://charts.releases.teleport.dev/
helm repo update

Step 4/8. Export the access plugin identity

Like all Teleport users, access-plugin needs signed credentials in order to connect to your Teleport cluster. You will use the tctl auth sign command to request these credentials for your plugin.

The format of the credentials depends on whether you have set up your network to give the plugin direct access to the Teleport Auth Service, or if all Teleport clients and services connect to the Teleport Proxy Service instead.

Environment type

The following tctl auth sign command impersonates the access-plugin user, generates signed credentials, and writes an identity file to the local directory:

tctl auth sign --user=access-plugin --out=auth.pem

Teleport's Access Request plugins listen for new and updated Access Requests by connecting to the Teleport Auth Service's gRPC endpoint over TLS.

The identity file, auth.pem, includes both TLS and SSH credentials. Your Access Request plugin uses the SSH credentials to connect to the Proxy Service, which establishes a reverse tunnel connection to the Auth Service. The plugin uses this reverse tunnel, along with your TLS credentials, to connect to the Auth Service's gRPC endpoint.

You will refer to this file later when configuring the plugin.

If your network allows your plugin to access the Auth Service directly, e.g., you are running the plugin on the Auth Service host, the plugin uses TLS credentials to connect to the Auth Service's gRPC endpoint and listen for new and updated Access Requests.

You can generate TLS credentials with the following command:

tctl auth sign --format=tls --user=access-plugin --out=auth

This command should result in three PEM-encoded files: auth.crt, auth.key, and auth.cas (certificate, private key, and CA certs respectively). Later, you will configure the plugin to use these credentials to connect to the Auth Service directly.

The following tctl auth sign command impersonates the access-plugin user, generates signed credentials, and writes an identity file to the local directory:

tctl auth sign --user=access-plugin --out=auth

Then create a Kubernetes secret:

kubectl create secret generic teleport-mattermost-identity --from-file=auth_id=auth.pem

Teleport's Access Request plugins listen for new and updated Access Requests by connecting to the Teleport Auth Service's gRPC endpoint over TLS.

The identity file, auth.pem, includes both TLS and SSH credentials. Your Access Request plugin uses the SSH credentials to connect to the Proxy Service, which establishes a reverse tunnel connection to the Auth Service. The plugin uses this reverse tunnel, along with your TLS credentials, to connect to the Auth Service's gRPC endpoint.

The Helm chart only supports the file format.

You will refer to this file later when configuring the plugin.

The following tctl auth sign command impersonates the access-plugin user, generates signed credentials, and writes an identity file to the local directory:

tctl auth sign --user=access-plugin --out=auth

Then create a Kubernetes secret:

kubectl create secret generic teleport-mattermost-identity --from-file=auth_id=auth.pem

Teleport's Access Request plugins listen for new and updated Access Requests by connecting to the Teleport Auth Service's gRPC endpoint over TLS.

The identity file, auth.pem, includes both TLS and SSH credentials. Your Access Request plugin uses the SSH credentials to connect to the Proxy Service, which establishes a reverse tunnel connection to the Auth Service. The plugin uses this reverse tunnel, along with your TLS credentials, to connect to the Auth Service's gRPC endpoint.

The Helm chart only supports the file format.

You will refer to this file later when configuring the plugin.

Certificate Lifetime

By default, tctl auth sign produces certificates with a relatively short lifetime. For production deployments, you can use the --ttl flag to ensure a more practical certificate lifetime, e.g., --ttl=8760h to export a one-year certificate.

Step 5/8. Set up a PagerDuty API key

Generate an API key that the PagerDuty plugin will use to create and modify incidents as well as list users, services, and on-call policies.

In your PagerDuty dashboard, go to Integrations → API Access Keys and click Create New API Key. Add a key description, e.g., "Teleport integration". Leave "Read-only API Key" unchecked. Copy the key to a file on your local machine. We'll use the key in the plugin config file later.

Create an API
key

Step 6/8. Configure the PagerDuty plugin

At this point, you have generated credentials that the PagerDuty plugin will use to connect to Teleport and the PagerDuty API. You will now configure the PagerDuty plugin to use these credentials, plus adjust any settings required for your environment.

Teleport's PagerDuty plugin has its own configuration file in TOML format. On the host where you will run the PagerDuty plugin, generate a boilerplate config by running the following commands:

teleport-pagerduty configure > teleport-pagerduty.toml
sudo mv teleport-pagerduty.toml /etc

The Mattermost Helm Chart uses a YAML values file to configure the plugin. On the host where you have Helm installed, create a file called teleport-pagerduty-values.yaml based on the following example:

teleport:
  address: ""                 # Teleport Auth Server GRPC API address
  identitySecretName: ""      # Identity file path

pagerduty:
  apiKey: ""                  # PagerDuty API Key
  userEmail: ""               # PagerDuty bot user email (Could be admin email)

The PagerDuty plugin expects the configuration to be in /etc/teleport-pagerduty.toml, but you can override this with the --config flag when you run the plugin binary later in this guide.

Edit the configuration file in /etc/teleport-pagerduty.toml as explained below:

[teleport]

The PagerDuty plugin uses this section to connect to your Teleport cluster:

The address and credentials you configure depend on whether your plugin can access the Auth Service directly:

Environment type

Set addr to your Proxy Service address with port 443.

Set identity to the identity file generated earlier:

[teleport]
addr = "teleport.example.com:443"
identity = "/var/lib/teleport/plugins/pagerduty/auth.pem"

Set addr to the address and port of your Auth Service. This address must be reachable from the Teleport PagerDuty plugin.

Set client_key, client_crt, and root_cas to the identity files generated earlier:

[teleport]
addr = "localhost:3025"
client_key = "/var/lib/teleport/plugins/pagerduty/auth.key" # Teleport GRPC client secret key
client_crt = "/var/lib/teleport/plugins/pagerduty/auth.crt" # Teleport GRPC client certificate
root_cas = "/var/lib/teleport/plugins/pagerduty/auth.cas"   # Teleport cluster CA certs

address: Include the hostname and HTTPS port of your Teleport Cloud tenant (e.g., teleport.example.com:443).

identitySecretName: Fill in the identitySecretName field with the name of the Kubernetes secret you created earlier.

teleport:
  address: "teleport.example.com:443"
  identitySecretName: teleport-plugin-pagerduty-identity

[pagerduty]

Assign api_key to the PagerDuty API key you generated earlier.

Assign user_email to the email address of a PagerDuty user on the account associated with your API key. When the PagerDuty plugin creates a new incident, PagerDuty will display this incident as created by that user.

This guide has assumed that the Teleport PagerDuty plugin uses pagerduty_notify_service annotation to determine which services to notify of new Access Request events and the pagerduty_services annotation to configure auto-approval.

If you would like to use a different name for these annotations in your Teleport roles, you can assign the pagerduty.notify_service and pagerduty.services fields.

The final configuration should resemble the following:

Environment type

# example teleport-pagerduty configuration TOML file
[teleport]
auth_server = "myinstance.teleport.sh:443"                  # Teleport Cloud proxy HTTPS address
identity = "/var/lib/teleport/plugins/pagerduty/auth.pem"   # Identity file path

[pagerduty]
api_key = "key"               # PagerDuty API Key
user_email = "[email protected]" # PagerDuty bot user email (Could be admin email)

[log]
output = "stderr" # Logger output. Could be "stdout", "stderr" or "/var/lib/teleport/pagerduty.log"
severity = "INFO" # Logger severity. Could be "INFO", "ERROR", "DEBUG" or "WARN".

# example teleport-pagerduty configuration TOML file
[teleport]
auth_server = "example.com:3025"                            # Teleport Auth Server GRPC API address
client_key = "/var/lib/teleport/plugins/pagerduty/auth.key" # Teleport GRPC client secret key
client_crt = "/var/lib/teleport/plugins/pagerduty/auth.crt" # Teleport GRPC client certificate
root_cas = "/var/lib/teleport/plugins/pagerduty/auth.cas"   # Teleport cluster CA certs

[pagerduty]
api_key = "key"               # PagerDuty API Key
user_email = "[email protected]" # PagerDuty bot user email (Could be admin email)

[log]
output = "stderr" # Logger output. Could be "stdout", "stderr" or "/var/lib/teleport/pagerduty.log"
severity = "INFO" # Logger severity. Could be "INFO", "ERROR", "DEBUG" or "WARN".

teleport:
  address: "teleportauth:3025"                            # Teleport Auth Server GRPC API address
  identitySecretName: teleport-plugin-pagerduty-identity  # Identity file path

pagerduty:
  apiKey: "key"                # PagerDuty API Key
  userEmail: "[email protected]"  # PagerDuty bot user email (Could be admin email)

log:
  output: "stderr"  # Logger output. Could be "stdout", "stderr" or "/var/lib/teleport/pagerduty.log"
  severity: "INFO"  # Logger severity. Could be "INFO", "ERROR", "DEBUG" or "WARN".

Step 7/8. Test the PagerDuty plugin

After you configure the PagerDuty plugin, run the following command to start it. The -d flag will provide debug information to ensure that the plugin can connect to PagerDuty and your Teleport cluster:

teleport-pagerduty start -d

DEBU DEBUG logging enabled logrus/exported.go:117

INFO Starting Teleport Access PagerDuty extension 0.1.0-dev.1: pagerduty/main.go:124

DEBU Checking Teleport server version pagerduty/main.go:226

DEBU Starting a request watcher... pagerduty/main.go:288

DEBU Starting PagerDuty API health check... pagerduty/main.go:170

DEBU Starting secure HTTPS server on :8081 utils/http.go:146

DEBU Watcher connected pagerduty/main.go:252

DEBU PagerDuty API health check finished ok pagerduty/main.go:176

DEBU Setting up the webhook extensions pagerduty/main.go:178

After modifying your configuration, run the bot with the following command:

helm upgrade --install teleport-plugin-pagerduty teleport/teleport-plugin-pagerduty --values teleport-pagerduty-values.yaml

To inspect the plugin's logs, use the following command:

kubectl logs deploy/teleport-plugin-pagerduty

Debug logs can be enabled by setting log.severity to DEBUG in teleport-pagerduty-helm.yaml and executing the helm upgrade ... command above again. Then you can restart the plugin with the following command:

kubectl rollout restart deployment teleport-plugin-pagerduty

Create an Access Request

As the Teleport user myuser, create an Access Request for the editor role:

A Teleport admin can create an Access Request for another user with tctl:

tctl request create myuser --roles=editor

Users can use tsh to create an Access Request and log in with approved roles:

tsh request new --roles=editor

Seeking request approval... (id: 8f77d2d1-2bbf-4031-a300-58926237a807)

Users can request access using the Web UI by visiting the "Access Requests" tab and clicking "New Request":

Creating an Access Request using the Web UI

You should see a log resembling the following on your PagerDuty plugin host:

INFO   Successfully created PagerDuty incident pd_incident_id:00000000000000
pd_service_name:Teleport Access Request Notifications
request_id:00000000-0000-0000-0000-000000000000 request_op:put
request_state:PENDING pagerduty/app.go:366

In PagerDuty, you will see a new incident containing information about the Access Request:

PagerDuty dashboard showing an Access
Request

Resolve the request

Once you receive an Access Request message, click the link to visit Teleport and approve or deny the request:

Reviewing a request

You can also review an Access Request from the command line:

Replace REQUEST_ID with the id of the request

tctl request approve REQUEST_ID
tctl request deny REQUEST_ID

Replace REQUEST_ID with the id of the request

tsh request review --approve REQUEST_ID
tsh request review --deny REQUEST_ID
Auditing Access Requests

When the PagerDuty plugin sends a notification, anyone who receives the notification can follow the enclosed link to an Access Reqeust URL. While users must be authorized via their Teleport roles to review Access Request, you should still check the Teleport audit log to ensure that the right users are reviewing the right requests.

When auditing Access Request reviews, check for events with the type Access Request Reviewed in the Teleport Web UI and access_request.review if reviewing the audit log on the Auth Service host.

Trigger an auto-approval

As your Teleport user, create an Access Request for the demo-role role.

You will see a log similar to the following on your PagerDuty plugin host:

INFO   Successfully submitted a request approval
pd_user_email:[email protected] pd_user_name:My User
request_id:00000000-0000-0000-0000-000000000000 request_op:put
request_state:PENDING pagerduty/app.go:511

Your Access Request will appear as APPROVED:

tsh requests ls

ID User Roles Created (UTC) Status

------------------------------------ ------------------ --------- ------------------- --------

00000000-0000-0000-0000-000000000000 [email protected] demo-role 12 Aug 22 18:30 UTC APPROVED

Step 8/8. Set up systemd

In production, we recommend starting the Teleport plugin daemon via an init system like systemd. Here's the recommended Teleport plugin service unit file for systemd:

[Unit]
Description=Teleport Pagerduty Plugin
After=network.target

[Service]
Type=simple
Restart=on-failure
ExecStart=/usr/local/bin/teleport-pagerduty start --config=/etc/teleport-pagerduty.toml
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/run/teleport-pagerduty.pid

[Install]
WantedBy=multi-user.target

Save this as teleport-pagerduty.service in either /usr/lib/systemd/system/ or another unit file load path supported by systemd.

Enable and start the plugin:

sudo systemctl enable teleport-pagerduty
sudo systemctl start teleport-pagerduty

Feedback

If you have any issues with this plugin please create a GitHub issue.