# Deploying tbot on Jenkins

Jenkins is an open source automation server that is frequently used to build Continuous Integration and Continuous Delivery (CI/CD) pipelines.

In this guide, we will demonstrate how to migrate existing Jenkins pipelines to utilize Machine & Workload Identity to connect to infrastructure protected by Teleport.

## Prerequisites

You will need the following tools to use Teleport with Jenkins.

- A running Teleport cluster. 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/ver/19.x/get-started/deploy-community.md).

- The `tctl` and `tsh` clients.

  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:

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.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/ver/19.x/installation.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
     ```

* `ssh` OpenSSH tool
* Jenkins
* To check that you can connect to your Teleport cluster, sign in with `tsh login`, then verify that you can run `tctl` commands using your current credentials. For example, run the following command, assigning teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username:
  ```
  $ tsh login --proxy=teleport.example.com --user=email@example.com
  $ tctl status
  Cluster  teleport.example.com
  Version  19.0.0-dev
  CA pin   sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
  ```
  If you can connect to the cluster and run the `tctl status` command, you can use your current credentials to run subsequent `tctl` commands from your workstation. If you host your own Teleport cluster, you can also run `tctl` commands on the computer that hosts the Teleport Auth Service for full permissions.

## Architecture

Before we begin, it should be noted that Jenkins is a tool that is notoriously difficult to secure. Machine & Workload Identity is one part of securing your infrastructure, but it alone is not sufficient. Below we will provide some basic guidance which can help improve the security posture of your Jenkins installation.

### Single-host deployments

The simplest Jenkins deployments have the controller (process that stores configuration, plugins, UI) and agents (process that executes tasks) run on the same host. This deployment model is simple to get started with, however any compromise of the `jenkins` user within a single pipeline can lead to the compromise of your entire CI/CD infrastructure.

### Multihost deployments

A slightly more complex, but more secure deployment is running your Jenkins controllers and agents on different hosts and pinning workloads to specific agents. This is an improvement over the simple deployment because you can limit the blast radius of the compromise of a single pipeline to a subset of your CI/CD infrastructure instead of all of your infrastructure.

### Best practices

We strongly encourage the use of the second deployment model whenever possible, with ephemeral hosts and IAM joining when possible. When using Machine & Workload Identity with this model, create and run separate bots per-host and pin particular pipelines to a worker. This will allow you to give each pipeline the minimal scope for server access, reduce the blast radius if one pipeline is compromised, and allow you to remotely audit and lock pipelines if you detect malicious behavior.

![Jenkins Deployments](/docs/assets/images/jenkins-c8fc6b68ea333a60b95819263a7a0535.png)

## Step 1/2 Configure and start `tbot`

First, determine if you would like to create a new role or use an existing role for your Jenkins workflow. You can run `tctl get roles` to examine your existing roles.

In the example below, create a file called `api-workers.yaml` with the content below to create a new role called `api-workers` that will allow you to log in to Nodes with the label `group: api` and Linux user `jenkins`.

```
kind: "role"
version: "v3"
metadata:
  name: "api-workers"
spec:
  allow:
    logins: ["jenkins"]
    node_labels:
      "group": "api"

```

**Teleport Enterprise Cloud**

On your client machine, log in to Teleport using `tsh` before using `tctl`.

```
$ tctl create -f api-workers.yaml
$ tctl bots add jenkins --roles=api-workers
```

**Self-Hosted**

Connect to the Teleport Auth Service and use `tctl` to examine what roles exist on your system.

```
$ tctl create -f api-workers.yaml
$ tctl bots add jenkins --roles=api-workers
```

The Machine & Workload Identity agent, `tbot`, allows you to use Linux Access Control Lists (ACLs) to control access to certificates on disk. You will use this to limit the access Jenkins has to the short-lived certificates `tbot` issues.

In the example that follows, you will create a Linux user called `teleport` to run `tbot` but short-lived certificates will be written to disk as the Linux user `jenkins`.

```
$ sudo adduser \
    --disabled-password \
    --no-create-home \
    --shell=/bin/false \
    --gecos "" \
    teleport
```

Create and initialize the directories you will need using the `tbot init` command.

```
$ sudo tbot init \
    --destination-dir=/opt/machine-id \
    --bot-user=teleport \
    --owner=teleport:teleport \
    --reader-user=jenkins
```

Create the bot data directory and grant permissions to access it to the Linux user (in our example, `teleport`) which `tbot` will run as.

```
Make the bot directory and assign ownership to teleport user
$ sudo mkdir -p /var/lib/teleport/bot
$ sudo chown teleport:teleport /var/lib/teleport/bot
Allow teleport user to open directory
$ sudo chmod +x /var/lib/teleport /var/lib/teleport/bot
```

Next, you need to start `tbot` in the background of each Jenkins worker.

First create a configuration file for `tbot` at `/etc/tbot.yaml`.

```
version: v2
# Replace "example.teleport.sh:443" with the address of your Teleport Proxy or
# Teleport Cloud tenant.
proxy_server: "example.teleport.sh:443"
onboarding:
  join_method: "token"
  # Replace the token field with the name of the token that was output when you
  # ran `tctl bots add`.
  token: "00000000000000000000000000000000"
storage:
  type: directory
  path: /var/lib/teleport/bot
services:
  - type: identity
    destination:
      type: directory
      path: /opt/machine-id

```

### Create a `tbot` systemd unit file

By default, `tbot` will run in daemon mode. However, this must then be configured as a service within the service manager on the Linux host. The service manager will start `tbot` on boot and ensure it is restarted if it fails.

**If tbot was installed using the Teleport install script or `teleport-update` command, the `tbot` systemd service is automatically created for you.**

After `tbot.yaml` is created, enable and start the service:

```
$ sudo systemctl enable tbot --now
```

Check the service has started successfully:

```
$ sudo systemctl status tbot
```

Service properties like `User` and `Group` may be configured using `systemctl edit tbot`.

**If tbot was installed manually, service configuration will need to be performed manually as well.**

For this guide, systemd will be demonstrated but `tbot` should be compatible with all common alternatives.

Use `tbot install systemd` to generate a systemd service file:

```
$ sudo tbot install systemd \
   --write \
   --config /etc/tbot.yaml \
   --user teleport \
   --group teleport \
   --pid-file /run/tbot.pid \
   --anonymous-telemetry
```

Ensure that you replace:

- `teleport` with the name of Linux user you wish to run `tbot` as.
- `/etc/tbot.yaml` with the path to the configuration file you have created.
- `/run/tbot.pid` with a path that the user configured for `tbot` has write access to. By default, `tbot` writes its PID file to `/run/tbot.pid`.

You can omit `--write` to print the systemd service file to the console instead of writing it to disk.

`--anonymous-telemetry` enables the submission of anonymous usage telemetry. This helps us shape the future development of `tbot`. You can disable this by omitting this.

Next, enable the service so that it will start on boot and then start the service:

```
$ sudo systemctl daemon-reload
$ sudo systemctl enable tbot --now
```

Check the service has started successfully:

```
$ sudo systemctl status tbot
```

## Step 2/2. Update and run Jenkins pipelines

Using the credentials produced by `tbot` within a Jenkins pipeline is now a one-line change. For example, if you want to run the `hostname` command on a remote host, add the following to your Jenkins pipeline.

```
steps {
  sh "ssh -F /opt/machine-id/ssh_config root@node-name.example.com hostname"
}

```

You are all set. You have provided Jenkins with short-lived certificates tied to a machine identity that can be rotated, audited, and controlled with access controls.

## Next steps

[More information about `TELEPORT_ANONYMOUS_TELEMETRY`.](https://goteleport.com/docs/ver/19.x/reference/machine-workload-identity/telemetry.md)
