Teleport Workload Identity with SPIFFE: Achieving Zero Trust in Modern Infrastructure
May 23
Virtual
Register Today
Teleport logoTry For Free
Fork me on GitHub

Teleport

Registering Agentless OpenSSH Servers with IaC

In this guide, you will see how to register in Teleport your OpenSSH nodes through infrastructure as code (IaC). Teleport supports three ways to dynamically create resources from code:

  • The Teleport Kubernetes Operator, which allows you to manage Teleport resources from Kubernetes
  • The Teleport Terraform Provider, which allows you to manage Teleport resources via Terraform
  • The tctl CLI, which allows you to manage Teleport resources from your local computer or your CI environment

Prerequisites

To follow this guide, you must have:

  • A running Teleport cluster version 15.2.4 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool.

    On Teleport Enterprise, you must use the Enterprise version of tctl, which you can download from your Teleport account workspace. Otherwise, visit Installation for instructions on downloading tctl and tsh for Teleport Community Edition.

A running operator by following either:

You must also set the namespace in which you deployed the operator as this is the namespace where you will deploy the CustomResources:

for operators deployed with the `teleport-cluster` Helm chart

export OPERATOR_NAMESPACE="teleport-cluster"

for standalone operators

export OPERATOR_NAMESPACE="teleport-iac"

A functional Teleport Terraform provider by following the Terraform provider guide.

  • a server running OpenSSH you will add to the Teleport cluster. This server must be reachable from the proxy (public IP address and firewall allowing traffic on port 22).
Tip

If you want to add a private SSH server (e.g. behind a NAT, in a private network, protected by a firewall blocking inbound traffic, ...) you can install a Teleport agent. The Teleport agent opens a tunnel to the Teleport Proxy Service, allowing any user to connect to it by going through the Proxy Service.

Step 1/4 - Gather the required information

To register an OpenSSH server in Teleport you will need the following information:

  • The server hostname: ssh-server-hostname
  • The public server IP address with SSH port: 198.51.100.1:22

You must also choose a set of labels for the server. Those labels can be used to describe the server and control which users can access the server. They can be dynamically changed later, without having to reconfigure openSSH.

See the Access Controls for Servers page for more details about labels and how to control access to your servers.

In the rest of this guide, the labels will be:

env: test
team: engineering

Step 2/4 - Write the server manifest

In this step, we'll write text files describing the OpenSSH server resource we want to register in Teleport. Those files are called manifests and their syntax will vary based on the IaC tooling you'll use.

Those manifests are typically versioned in a shared revision system like git. This allows you to keep track of all changes, follow standard code review procedures before changing resources in Teleport, and quickly redeploy your Teleport instance if needed.

You must pick a server ID, or Teleport will pick one for you. This ID is used for two things:

  • if you want to update the server information (e.g. change the labels) later, you will need to specify its ID in the manifest. Else Teleport will create a new server resource instead of editing the existing one.
  • if you have multiple servers with identical hostnames, the unique ID allows you to pick a specific server.

To generate a new UUID:

Use uuidgen. This executable is installed by default on most machines. If it's not installed, it is available via the uuid-runtime package for DEB-based distros, and util-linux for RPM-based distros.

uuidgen

a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Use uuidgen and tr packages that are installed by default:

uuidgen | tr '[:upper:]' '[:lower:]'

a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Use the NewGuid powershell cmdlet:

New-guid
Guid----a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Create the following openssh-node-resource.yaml file:

kind: node
version: v2
sub_kind: openssh
metadata:
  name: a100fdd0-52db-4eca-a7ab-c3afa7a1564a  # this is the UUID previously generated
  labels:
    env: test
    team: engineering
spec:
  addr: 198.51.100.1:22
  hostname: ssh-server-hostname

To generate a new UUID:

Use uuidgen. This executable is installed by default on most machines. If it's not installed, it is available via the uuid-runtime package for DEB-based distros, and util-linux for RPM-based distros.

uuidgen

a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Use uuidgen and tr packages that are installed by default:

uuidgen | tr '[:upper:]' '[:lower:]'

a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Use the NewGuid powershell cmdlet:

New-guid
Guid----a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Create the following openssh-node-resource.yaml file:

apiVersion: resources.teleport.dev/v1
kind: TeleportOpenSSHServerV2
metadata:
  name: a100fdd0-52db-4eca-a7ab-c3afa7a1564a  # this is the UUID previously generated
  # kubernetes CR labels are propagated to the Teleport resource
  labels:
    env: test
    team: engineering
spec:
  addr: 198.51.100.1:22
  hostname: ssh-server-hostname

Create the following openssh-node-resource.tf file:

resource "teleport_server" "openssh_agentless" {
  version = "v2"
  sub_kind = "openssh"
  // Name is not required for servers, this is a special case.
  // When a name is not set, an UUID will be generated by Teleport and
  // imported back into Terraform.
  spec = {
    addr = "198.51.100.1:22"
    hostname = "ssh-server-hostname"
  }
}

output "openssh_node_id" {
  value = teleport_server.openssh_agentless.metadata.name
}

Step 3/4. Apply all manifests

Declare the server with the following command:

tctl create -f openssh-node-resource.yaml
node "a100fdd0-52db-4eca-a7ab-c3afa7a1564a" has been created

Apply the Kubernetes manifest with the following command:

kubectl apply -n "$OPERATOR_NAMESPACE" -f openssh-node-resource.yaml
teleportopensshserverv2.resources.teleport.dev/a100fdd0-52db-4eca-a7ab-c3afa7a1564a created

Then list the TeleportOpenSSHServerV2 Kubernetes custom resources:

kubectl get teleportopensshserverv2 -n "$OPERATOR_NAMESPACE"

NAME AGE

a100fdd0-52db-4eca-a7ab-c3afa7a1564a 10m

Test the Terraform connectivity and review the changes:

terraform plan
Terraform will perform the following actions:
# teleport_server.openssh_agentless will be created + resource "teleport_server" "openssh_agentless" { + id = (known after apply) + kind = (known after apply) + metadata = (known after apply) + spec = { + addr = "198.51.100.1:22" + hostname = "ssh-server-hostname" } + sub_kind = "openssh" + version = "v2" }
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs: + openssh_node_id = (known after apply)

Apply the plan and recover the node UUID:

terraform apply

[...]

Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve.
Enter a value: yes
teleport_server.openssh_agentless: Creating...teleport_server.openssh_agentless: Creation complete after 3s [id=a100fdd0-52db-4eca-a7ab-c3afa7a1564a]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
openssh_node_id = "a100fdd0-52db-4eca-a7ab-c3afa7a1564a"

Step 3/4. Validate the server created in Teleport

Now that the IaC tooling has run, we'll validate that Teleport is now aware of the OpenSSH server:

List nodes with a given hostname or IP address

tsh ls --search="ssh-server-hostname"
Node Name Address Labels--------------------- ------------ --------------- --------------------------ssh-server-hostname 198.51.100.1:22 env=test,team=engineering

Get the node details by hostname

tctl get "node/ssh-server-hostname"

Get the node details by ID

tctl get node/a100fdd0-52db-4eca-a7ab-c3afa7a1564a

Step 4/4. Trust the Teleport CA and issue host certificates

At this point, Teleport is aware that there's an OpenSSH server and knows how to contact it and which user should have access. However, neither Teleport nor the server trust each other.

You need to configure the server to trust connections coming from Teleport (trust the Teleport SSH Certificate Authority), and you need to give the server an SSH Host certificate issued by Teleport.

Those steps can be automated, but the automation will depend on your custom infrastructure and tooling (you can configure the SSH CA in the VM image, use custom startup scripts, provision servers with Ansible, ...).

A step-by-step manual setup is described in the OpenSSH manual installation guide starting with the Step 2.

Next steps

  • Setup RBAC to control which user can SSH on which server.