Fork me on GitHub

Teleport

Machine ID with Databases

  • Available for:
  • OpenSource
  • Team
  • Cloud
  • Enterprise

This version of the guide uses the v2 tbot configuration. This version is only supported by Teleport 14 and beyond. Change the selected version of the documentation to view the guide for previous Teleport versions.

In this guide, we will demonstrate how to use Machine ID to access a database protected by Teleport from a custom application.

With Machine ID, Teleport issues short-lived certificates, tied to a machine identity, that can be rotated, audited, and managed with the same access controls that Teleport provides for human users.

Machine ID and Database Access Deployment
Machine ID and Database Access Deployment

Prerequisites

  • A running Teleport cluster. For details on how to set this up, see the Getting Started guide.

  • The tctl admin tool and tsh client tool version >= 14.0.1.

    See Installation for details.

  • A Teleport Team account. If you don't have an account, sign up to begin your free trial.

  • The Enterprise tctl admin tool and tsh client tool, version >= 13.3.9.

    You can download these tools from the Cloud Downloads page.

  • A running Teleport Enterprise cluster. For details on how to set this up, see the Enterprise Getting Started guide.

  • The Enterprise tctl admin tool and tsh client tool version >= 14.0.1.

    You can download these tools by visiting your Teleport account workspace.

Cloud is not available for Teleport v.
Please use the latest version of Teleport Enterprise documentation.

To check version information, run the tctl version and tsh version commands. For example:

tctl version

Teleport Enterprise v13.3.9 git:api/14.0.0-gd1e081e go1.21


tsh version

Teleport v13.3.9 go1.21

Proxy version: 13.3.9Proxy: teleport.example.com
  • If you have not already put your database behind the Teleport Database Service, follow the database access getting started guide. The Teleport Database Service supports databases like PostgreSQL, MongoDB, Redis, and much more. See our database access guides for a complete list.
  • If you have not already set up Machine ID, follow the Machine ID getting started guide to familiarize yourself with Machine ID. You'll need tctl access to initially configure the bot.
  • To check that you can connect to your Teleport cluster, sign in with tsh login, then verify that you can run tctl commands on your administrative workstation using your current credentials. For example:
    tsh login --proxy=teleport.example.com --user=[email protected]
    tctl status

    Cluster teleport.example.com

    Version 14.0.1

    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.
  • Ensure both the tbot and tsh executables are available on your application host. See Installation for details.

Step 1/3. Create a Machine ID bot and assign permissions

In the example below, you will create a bot user named app and assign this bot user the machine-id-db role.

First, create a role that Machine ID can use to access your database:

kind: role
version: v5
metadata:
  name: machine-id-db
spec:
  allow:
    db_labels:
      '*': '*'
    db_names: [example]
    db_users: [alice]
    rules:
      - resources: [db_server, db]
        verbs: [read, list]

This role allows Machine ID bots to do two things:

  • Access the database example on any database server (due to the '*': '*' label selector) as the user alice. You may restrict access to the bot using a more specific label selector; see the Database Access RBAC guide for more info.
  • Discover information about databases in Teleport.

Write this to role.yaml and run the following to create the role in Teleport:

tctl create -f role.yaml

With the role created, create a new bot and allow it to assume the new role.

Cloud is not available for Teleport v.
Please use the latest version of Teleport Enterprise documentation.

Connect to the Teleport Auth Server and use tctl to create the bot:

tctl bots add app --roles=machine-id-db

Step 2/3. Configure and start Machine ID

Next, we'll run Machine ID alongside our database client app to begin fetching credentials.

Start by creating a configuration file for Machine ID at /etc/tbot.yaml:

version: v2
auth_server: "example.teleport.sh:443"
onboarding:
  join_method: "token"
  token: "00000000000000000000000000000000"
  ca_pins:
  - "sha256:1111111111111111111111111111111111111111111111111111111111111111"
storage:
  type: directory
  path: /var/lib/teleport/bot
outputs:
  - type: database
    destination:
      type: directory
      path: /opt/machine-id
    # Specify the details of the database you wish to connect to.
    service: example-server
    username: alice
    database: example
    # Specify a format to use for the output credentials. For most databases,
    # this configuration field can be omitted. See the table below for the
    # databases that require a value to be specified here.
    # format: mongo

The outputs field controls the what certificates tbot will produce when it runs and where these certificates should be written.

The format field in the database output controls the format of the generated credentials. This setting allows the credentials to work with database clients that require a specific format. When this field is not specified, a sensible default option is used that is compatible with most clients. The full list of supported format options is below:

ClientformatDescription
DefaultUnspecifiedProvides a certificate in tlscert, a private key in key and the CA in teleport-database-ca.crt. This is compatible with most clients.
MongoDBmongoProvides mongo.crt and mongo.cas.
CockroachDBcockroachProvides cockroach/node.key, cockroach/node.crt, and cockroach/ca.crt.
Generic TLStlsProvides tls.key, tls.crt, and tls.cas for generic clients that require specific file extensions.

Be sure to configure the token and ca_pins fields to match the output from tctl bots add ....

Machine ID also allows you to use Linux ACLs to control access to certificates on disk. You will use this to ensure only your application has access to the short-lived certificates Machine ID uses.

We'll work with the assumption you will be running Machine ID as the Linux user teleport and your application as the Linux user app. Create and initialize the output destination by running this tbot init command either as root or as the teleport user:

tbot init \ -c /etc/tbot.yaml \ --init-dir=/opt/machine-id \ --bot-user=teleport \ --owner=teleport:teleport \ --reader-user=app

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

Be sure to re-run tbot init ... as shown here if config templates are added or removed from tbot.yaml. You may run into permissions errors if tbot init is not run for new files.

Next, you will use systemd to run Machine ID in the background on your application node. Create a systemd.unit file at /etc/systemd/system/machine-id.service:

[Unit]
Description=Teleport Machine ID Service
After=network.target

[Service]
Type=simple
User=teleport
Group=teleport
Restart=on-failure
Environment="TELEPORT_ANONYMOUS_TELEMETRY=1"
ExecStart=/usr/local/bin/tbot start -c /etc/tbot.yaml
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/run/machine-id.pid
LimitNOFILE=524288

[Install]
WantedBy=multi-user.target

TELEPORT_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.

Additionally, we'll need to create a secondary service to manage the database proxy. Create another unit file at /etc/systemd/system/machine-id-proxy.service:

[Unit]
Description=Teleport Machine ID Proxy Service
After=network.target
Requires=machine-id.service

[Service]
Type=simple
User=teleport
Group=teleport
Restart=on-failure
ExecStart=/usr/local/bin/tbot -c /etc/tbot.yaml proxy --proxy=proxy.example.com:3080 --destination-dir=/opt/machine-id db --port=12345 example-server
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/run/machine-id-proxy.pid
LimitNOFILE=8192

[Install]
WantedBy=multi-user.target

This will start a local proxy on port 12345 applications can use to connect to the example-server database server. Be sure to customize the tbot parameters as necessary for your local setup.

Finally, run the following commands to start Machine ID:

sudo systemctl enable machine-id machine-id-proxy
sudo systemctl start machine-id machine-id-proxy
sudo systemctl status machine-id machine-id-proxy

Step 3/3. Update and run your application

In the default proxy mode, database clients must also be configured to use tbot's generated TLS certificates. This ensures no other users of the system can access the database via the local proxy, and ensures the connection between your database client and server is never unencrypted, even over localhost.

TLS Configuration Note

If desired, you can add the --tunnel flag to the tbot proxy db ... command in the machine-id-proxy.service systemd unit file to authenticate automatically at the proxy level, however this will decrease security as all users of the system will be able to connect to the database without any additional authentication.

Once the necessary credentials for your database are ready to use, refer to these sample Go programs to test connectivity to your database.

// This example program demonstrates how to connect to a Postgres database
// using certificates issued by Teleport Machine ID.

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/jackc/pgx/v4/stdlib"
)

func main() {
	// Open connection to database.
	db, err := sql.Open("pgx", fmt.Sprint(
		"host=localhost ",
		"port=1234 ",
		"dbname=example ",
		"user=alice ",
		"sslmode=verify-full ",
		"sslrootcert=/opt/machine-id/teleport-host-ca.crt ",
		"sslkey=/opt/machine-id/key ",
		"sslcert=/opt/machine-id/tlscert ",
	))
	if err != nil {
		log.Fatalf("Failed to open database: %v.", err)
	}

	defer db.Close()

	// Call "Ping" to test connectivity.
	err = db.Ping()
	if err != nil {
		log.Fatalf("Failed to Ping database: %v.", err)
	}

	log.Printf("Successfully connected to PostgreSQL.")
}

// This example program demonstrates how to connect to a MongoDB database
// using certificates issued by Teleport Machine ID.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// Create client and connect to MongoDB. Make sure to modify the host,
	// port, and certificate paths.
	uri := fmt.Sprintf(
		"mongodb://localhost:1234/?tlsCAFile=%s&tlsCertificateKeyFile=%s",
		"/opt/machine-id/mongo.cas",
		"/opt/machine-id/mongo.crt",
	)
	client, err := mongo.NewClient(options.Client().ApplyURI(uri))
	if err != nil {
		log.Fatalf("Failed to create database client: %v.", err)
	}
	err = client.Connect(ctx)
	if err != nil {
		log.Fatalf("Failed to connect to database: %v.", err)
	}

	defer client.Disconnect(ctx)

	log.Printf("Successfully connected to MongoDB.")

	// List databases to test connectivity.
	databases, err := client.ListDatabaseNames(ctx, bson.M{})
	if err != nil {
		log.Fatalf("Failed to list databases: %v.", err)
	}
	log.Println(databases)

}

You are all set. You have provided your application with short-lived certificates tied to a machine identity that can access your database, be rotated, and audited, all while being controlled with all the familiar Teleport access controls.

Next steps

More information about TELEPORT_ANONYMOUS_TELEMETRY.