• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Boundary
  • Install
  • Tutorials
  • Documentation
  • API
  • Try Cloud(opens in new tab)
  • Sign up
HCP Administration

Skip to main content
8 tutorials
  • Introduction to HCP Boundary
  • Manage Scopes with HCP Boundary
  • Manage Targets with HCP Boundary
  • Manage Users and Groups with HCP Boundary
  • Manage Roles and Permissions with HCP Boundary
  • Manage Sessions with HCP Boundary
  • Self-Managed Worker Registration with HCP Boundary
  • SSH Credential Injection with HCP Boundary

  • Resources

  • Tutorial Library
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  1. Developer
  2. Boundary
  3. Tutorials
  4. HCP Administration
  5. SSH Credential Injection with HCP Boundary

SSH Credential Injection with HCP Boundary

  • 20min

  • HCPHCP
  • VaultVault
  • BoundaryBoundary

Boundary 0.10 adds support for credential management of SSH keys, starting with credential brokering. HCP Boundary introduces credential injection: the ability to inject SSH credentials into sessions, particularly via Vault. Currently users must bring their own Vault deployment to HCP Boundary using a public endpoint.

This tutorial will demonstrate SSH credential injection into an SSH server configured using Docker. Learners may also bring their own target to use for this tutorial.

Tutorial overview

  1. Prerequisites
  2. Background
  3. Set up an SSH target
  4. Set up Vault
  5. Set up Boundary
  6. Inject credentials into sessions

Prerequisites

  • This tutorial assumes the learner has completed the HCP Boundary Getting Started tutorials. The learner should have a working Boundary cluster and org running on HCP.

  • Docker is installed (Note: Learners may also bring their own target, instead of using Docker)

  • A Boundary binary greater than 0.10.0 in your PATH

  • A Vault binary greater than 1.7.0 in your PATH

  • Installing the Boundary Desktop App provides an optional workflow at the end of this tutorial. The 1.2.0 version or above is required for Vault support.

This tutorial assumes basic knowledge of using Vault, including running a development server and managing policies, roles, and tokens. If you are new to using Vault, complete the Getting Started with Vault quick start tutorials before integrating Vault with Boundary.

This tutorial also extends the workflow for credential brokering via Vault. If new to this process, we recommend completing the Vault Credential Brokering Quickstart tutorial before moving forward.

Credential injection background

Boundary is a distributed system for managing identity-based access to computing resources. Core to Boundary are controllers and workers which, from a resource point of view, are referred to as servers. Controllers are responsible for authenticating and authorizing users, as well as serving user API requests for processes like session initiation. They also assign jobs to workers, such as session handling, session recording, and parsing. Workers are responsible for session proxying, as well as other jobs that involve storage.

SSH, also known as Secure Shell, is arguably the de facto tool for remote administration, enabling end users and administrators with a simple, powerful and secure access method. SSH offers a variety of benefits and configurations, such as:

  • Encryption
  • Support for multiple keys types and sizes
  • Built in key exchange
  • Ability to create a tunnel and spawn multiple channels

Boundary seamlessly provides authenticated users access to remote machines via their SSH client, regardless of the authentication mechanisms implemented by their administrators.

Previously Boundary supported credential brokering, where Boundary controllers check out credentials from Vault and return them back to users and clients. In this workflow, Boundary acts as a broker of the credential.

Brokering lacks the ability to hide credentials from clients. For credential injection, controllers instead return credentials to Boundary workers and create a session to a target where the user/client never has access to the credential. This workflow is called credential injection because the credential is injected into a worker’s session, instead of being passed back to the client.

Set up an SSH target

This tutorial assumes the reader has installed Boundary 0.10.0 or above, and a Vault binary greater than 1.7.0. Vault can be run in development mode locally, as demonstrated in this tutorial, or by supplying a Vault public address to HCP Boundary.

First, you are going to set up a target which will be used to test the credential injection using Vault.

Note: Alternatively, you can bring your own target to test the credential injection. Credential injection is currently supported for user/pass and sshpass credentials. If bringing your own target, skip to the Set up Vault section.

Docker is used to deploy an openssh-server target for testing credential injection.

For the purposes of this tutorial, create an ssh keypair that will be used to log in to the openssh container.

First, open a terminal session and create a new directory to store the keypair in. This tutorial creates the openssh directory at /, but you can place this directory elsewhere if desired.

$ mkdir /openssh/

Next, create a new ssh keypair.

$ ssh-keygen -t ecdsa -b 521 -f /openssh/openssh-key

Press enter twice when prompted for a passphrase, or supply one if desired.

The above command will create the keypair in the /openssh/ directory at /openssh/openssh-key and /openssh/openssh-key.pub. Update this path if you wish to store the key elsewhere. Note the path to the keypair for later.

Ensure Docker is running, and then deploy the openssh container. Supply the path to the /openssh/ directory created earlier after the --volume= option. This will mount the folder within the docker container, making the public key file available at /keys/.

$ docker run -d \
  --name=openssh-server \
  --hostname=openssh-server \
  -e SUDO_ACCESS=false \
  -e USER_NAME=admin \
  -e PUBLIC_KEY_FILE=/keys/openssh-key.pub \
  -p 2222:2222 \
  --restart unless-stopped \
  -v /path/to/openssh/:/keys \
  lscr.io/linuxserver/openssh-server:latest

Note that the username for the openssh server is admin, and the target is available on your localhost at port 2222 (127.0.0.1:2222).

Leave this container running for the duration of the tutorial.

Set up Vault

Note: This tutorial recommends running a Vault dev server to test credential injection. Vault environments on a public subnet can also be used with HCP Boundary. If bringing your own Vault instance, ensure that public connections are configured (refer to the Create a Vault Cluster on HCP tutorial), and then skip the running Vault in dev mode section of this tutorial.

Credential injection with Vault can be set up with a Vault dev server or using HCP Vault.

Open a new terminal session and run Vault in development mode.

$ vault server -dev -dev-root-token-id=groot
==> Vault server configuration:

             Api Address: http://127.0.0.1:8200
                     Cgo: disabled
         Cluster Address: https://127.0.0.1:8201
              Go Version: go1.16.7
              Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
               Log Level: info
                   Mlock: supported: false, enabled: false
           Recovery Mode: false
                 Storage: inmem
                 Version: Vault v1.8.2
             Version Sha: aca76f63357041a43b49f3e8c11d67358496959f

==> Vault server started! Log data will stream in below:

2022-05-05T14:01:31.647-0500 [INFO]  proxy environment: http_proxy="" https_proxy="" no_proxy=""
2022-05-05T14:01:31.648-0500 [WARN]  no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set
2022-05-05T14:01:31.649-0500 [INFO]  core: security barrier not initialized
2022-05-05T14:01:31.650-0500 [INFO]  core: security barrier initialized: stored=1 shares=1 threshold=1
2022-05-05T14:01:31.650-0500 [INFO]  core: post-unseal setup starting
2022-05-05T14:01:31.657-0500 [INFO]  core: loaded wrapping token key
2022-05-05T14:01:31.657-0500 [INFO]  core: successfully setup plugin catalog: plugin-directory=""
2022-05-05T14:01:31.657-0500 [INFO]  core: no mounts; adding default mount table
2022-05-05T14:01:31.658-0500 [INFO]  core: successfully mounted backend: type=cubbyhole path=cubbyhole/
2022-05-05T14:01:31.659-0500 [INFO]  core: successfully mounted backend: type=system path=sys/
2022-05-05T14:01:31.659-0500 [INFO]  core: successfully mounted backend: type=identity path=identity/
2022-05-05T14:01:31.663-0500 [INFO]  core: successfully enabled credential backend: type=token path=token/
2022-05-05T14:01:31.663-0500 [INFO]  rollback: starting rollback manager
2022-05-05T14:01:31.663-0500 [INFO]  core: restoring leases
2022-05-05T14:01:31.664-0500 [INFO]  identity: entities restored
2022-05-05T14:01:31.664-0500 [INFO]  identity: groups restored
2022-05-05T14:01:31.666-0500 [INFO]  core: post-unseal setup complete
2022-05-05T14:01:31.667-0500 [INFO]  expiration: lease restore complete
2022-05-05T14:01:31.667-0500 [INFO]  core: root token generated
2022-05-05T14:01:31.667-0500 [INFO]  core: pre-seal teardown starting
2022-05-05T14:01:31.667-0500 [INFO]  rollback: stopping rollback manager
2022-05-05T14:01:31.667-0500 [INFO]  core: pre-seal teardown complete
2022-05-05T14:01:31.668-0500 [INFO]  core.cluster-listener.tcp: starting listener: listener_address=127.0.0.1:8201
2022-05-05T14:01:31.668-0500 [INFO]  core.cluster-listener: serving cluster requests: cluster_listen_address=127.0.0.1:8201
2022-05-05T14:01:31.668-0500 [INFO]  core: post-unseal setup starting
2022-05-05T14:01:31.668-0500 [INFO]  core: loaded wrapping token key
2022-05-05T14:01:31.668-0500 [INFO]  core: successfully setup plugin catalog: plugin-directory=""
2022-05-05T14:01:31.668-0500 [INFO]  core: successfully mounted backend: type=system path=sys/
2022-05-05T14:01:31.668-0500 [INFO]  core: successfully mounted backend: type=identity path=identity/
2022-05-05T14:01:31.668-0500 [INFO]  core: successfully mounted backend: type=cubbyhole path=cubbyhole/
2022-05-05T14:01:31.669-0500 [INFO]  core: successfully enabled credential backend: type=token path=token/
2022-05-05T14:01:31.669-0500 [INFO]  rollback: starting rollback manager
2022-05-05T14:01:31.669-0500 [INFO]  core: restoring leases
2022-05-05T14:01:31.670-0500 [INFO]  identity: entities restored
2022-05-05T14:01:31.670-0500 [INFO]  identity: groups restored
2022-05-05T14:01:31.670-0500 [INFO]  expiration: lease restore complete
2022-05-05T14:01:31.670-0500 [INFO]  core: post-unseal setup complete
2022-05-05T14:01:31.670-0500 [INFO]  core: vault is unsealed
2022-05-05T14:01:31.672-0500 [INFO]  expiration: revoked lease: lease_id=auth/token/root/h49a4c4a4eef16a18370b98f2883fff349e0917dd5913d74c02bd97d04d8edcbb
2022-05-05T14:01:31.675-0500 [INFO]  core: successful mount: namespace="" path=secret/ type=kv
2022-05-05T14:01:31.686-0500 [INFO]  secrets.kv.kv_c1ca00f3: collecting keys to upgrade
2022-05-05T14:01:31.686-0500 [INFO]  secrets.kv.kv_c1ca00f3: done collecting keys: num_keys=1
2022-05-05T14:01:31.686-0500 [INFO]  secrets.kv.kv_c1ca00f3: upgrading keys finished
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.

You may need to set the following environment variable:

    $ export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: Yc27V3wm7l9axQaYQTxeZUlsn4AVOtqOPPUvvQuVOng=
Root Token: groot

Development mode should NOT be used in production installations!

Leave Vault running in dev mode and open a new terminal window.

Lastly, export the required Vault environment variables for the address and token.

$ export VAULT_ADDR="http://127.0.0.1:8200"; export VAULT_TOKEN="groot"

If using HCP vault, gather the public Vault address and generate an Admin token.

HCP URL and Token

Next, export the required Vault environment variables for the address and token.

$ export VAULT_ADDR="https://vault-cluster-boundary.vault.11eb3a47-8920-4714-ba99-0242ac11000e.aws.hashicorp.cloud:8200"; export VAULT_TOKEN="s.mStyhzHOwNsxuLTd5ANWMZ2H.AwVNv"

HCP Vault also requires an exported VAULT_NAMESPACE variable. This tutorial demonstrates using the admin namespace.

Export the VAULT_NAMESPACE variable.

$ export VAULT_NAMESPACE=admin

Lastly, enable the key/value v2 secrets engine at secret/.

$ vault secrets enable -path=secret kv-v2

Success! Enabled the kv-v2 secrets engine at: secret/

Define the controller policy

As described in the OSS Vault Credential Brokering Quickstart tutorial, the following Vault policy must be defined for the Boundary controller to support credential brokering.

Create a new file named boundary-controller-policy.hcl and copy the following policy into it.

path "auth/token/lookup-self" {
  capabilities = ["read"]
}

path "auth/token/renew-self" {
  capabilities = ["update"]
}

path "auth/token/revoke-self" {
  capabilities = ["update"]
}

path "sys/leases/renew" {
  capabilities = ["update"]
}

path "sys/leases/revoke" {
  capabilities = ["update"]
}

path "sys/capabilities-self" {
  capabilities = ["update"]
}

Save this file, and write the controller policy to Vault.

$ vault policy write boundary-controller boundary-controller-policy.hcl

Success! Uploaded policy: boundary-controller

Define the KV policy

A policy must also be defined for the key-value secrets that will be brokered via Vault.

Create a new file named kv-policy.hcl and copy the following policy into it.

path "secret/data/my-secret" {
  capabilities = ["read"]
}

path "secret/data/my-app-secret" {
  capabilities = ["read"]
}

Save this file, and write the policy to Vault.

$ vault policy write kv-read kv-policy.hcl

Success! Uploaded policy: kv-read

Lastly, create a new Vault KV credential at the secret/my-secret path and provide the username and private key for the openssh-server target machine you are connecting to. Ensure the path to the private key is entered after the @ symbol.

Note: If you brought your own target to test credential brokering against, enter the target’s username after username and path to the private key after the @.

$ vault kv put secret/my-secret username=admin private_key=@/openssh/openssh-key

Key              Value
---              -----
created_time     2022-07-28T20:02:26.513783Z
deletion_time    n/a
destroyed        false
version          1

Additionally, brokered credentials can also be attached to SSH targets. These credentials will be brokered to the end user after injection. This is useful in the case that a user needs access to application credentials on the target after the SSH credentials are successfully injected.

Create a second KV credential at the secret/my-app-secret path for brokering. This example will user a simple username and password that will be passed back to the authenticated user.

$ vault kv put secret/my-app-secret username=application-user password=application-password

Key              Value
---              -----
created_time     2022-05-09T17:26:34.228467Z
deletion_time    n/a
destroyed        false
version          1

Create a Vault token

Now create a Vault token.

$ vault token create \
  -no-default-policy=true \
  -policy="boundary-controller" \
  -policy="kv-read" \
  -orphan=true \
  -period=20m \
  -renewable=true \
  -format=json

Example:

$ vault token create \
  -no-default-policy=true \
  -policy="boundary-controller" \
  -policy="kv-read" \
  -orphan=true \
  -period=20m \
  -renewable=true \
  -format=json

{
  "request_id": "5935f26b-00ee-c7d2-0d68-cfc9d029d7a1",
  "lease_id": "",
  "lease_duration": 0,
  "renewable": false,
  "data": null,
  "warnings": null,
  "auth": {
    "client_token": "s.2jCq202rvXuSdjfVrpomUKq7",
    "accessor": "J2qWHGHICmsXtdQgLjkDWjUV",
    "policies": [
      "boundary-controller",
      "kv-read"
    ],
    "token_policies": [
      "boundary-controller",
      "kv-read"
    ],
    "identity_policies": null,
    "metadata": null,
    "orphan": true,
    "entity_id": "",
    "lease_duration": 1200,
    "renewable": true
  }
}

Copy the .auth.client_token value and export it as the $CRED_STORE_TOKEN variable.

Note: If you plan on using the Admin Console UI to connect, save this value for creating a credential store later on.

$ export CRED_STORE_TOKEN=s.2jCq202rvXuSdjfVrpomUKq7

Tip: If you have the jq utility installed, this can be performed in a single step with this command:

$ export CRED_STORE_TOKEN=`vault token create -no-default-policy=true -policy="boundary-controller" -policy="kv-read" -orphan=true -period=20m -renewable=true -format=json | jq -r '.auth.client_token'`

Set up Boundary

Start by logging in to HCP Boundary within the terminal.

Export the BOUNDARY_ADDR and BOUNDARY_AUTH_METHOD_ID environment variables. These values are gathered from the HCP Boundary Admin Console, as demonstrated in the Get Started with HCP Boundary tutorials.

$ export BOUNDARY_AUTH_METHOD_ID=copied-value-from-boundary-ui; export BOUNDARY_ADDR=copied-value-from-hcp-portal

Log in to the CLI as an admin user, or a user with privileges to manage resources in the global scope. Enter your admin username for login-name.

Enter password at the Please enter the password (it will be hidden): prompt.

$ boundary authenticate password \
  -auth-method-id=$BOUNDARY_AUTH_METHOD_ID \
  -login-name=awesome-admin

You will also need an ORG_ID to create the SSH test project within. You may create a new global scope for this, or utilize an existing scope used for testing.

If creating a new org for testing, execute the following:

$ boundary scopes create -scope-id=global -name=testing-org -description="SSH testing org"

Scope information:
  Created Time:        Mon, 09 May 2022 12:33:12 CDT
  Description:         SSH testing org
  ID:                  o_YcngFcjRcP
  Name:                testing-org
  Updated Time:        Mon, 09 May 2022 12:33:12 CDT
  Version:             1

  Scope (parent):
    ID:                global
    Name:              global
    Type:              global

  Authorized Actions:
    no-op
    read
    update
    delete

Whether you create a new org or not, be sure to export the org ID.

$ export ORG_ID=global-testing-org-id

Set up a new project

Create a new project scope within Boundary. You will need an org ID to create the new project within. To view your existing orgs, execute boundary scopes list -recursive.

Note: You may use an existing org scope, or create a new org scope for the ssh-project. Refer to the Manage Scopes tutorial to learn more about creating and managing scopes.

$ boundary scopes create -scope-id=$ORG_ID -name=ssh-project -description="SSH test machines"

Scope information:
  Created Time:        Fri, 06 May 2022 14:13:39 CDT
  Description:         SSH test machines
  ID:                  p_TRfAEMzkAP
  Name:                ssh-project
  Updated Time:        Fri, 06 May 2022 14:13:39 CDT
  Version:             1

  Scope (parent):
    ID:                o_26VOj9vJjN
    Name:              ssh-org
    Parent Scope ID:   global
    Type:              org

  Authorized Actions:
    no-op
    read
    update
    delete

Copy the ID from the output and export it as the $PROJECT_ID variable.

$ export PROJECT_ID=p_TRfAEMzkAP

Create a credential store

Next, create a new credential store within Boundary using the new token. The vault credential store type is used to integrate with Vault, but static credential stores can also be used with credential injection. Note: If using HCP Vault, provide the vault namespace while creating the credential store.

$ boundary credential-stores create vault \
  -scope-id $PROJECT_ID \
  -vault-address $VAULT_ADDR \
  -vault-token $CRED_STORE_TOKEN

If using HCP Vault,

$ boundary credential-stores create vault \
  -scope-id $PROJECT_ID \
  -vault-address $VAULT_ADDR \
  -vault-token $CRED_STORE_TOKEN \
  -vault-namespace $VAULT_NAMESPACE

Example output:

$ boundary credential-stores create vault \
  -scope-id $PROJECT_ID \
  -vault-address $VAULT_ADDR \
  -vault-token $CRED_STORE_TOKEN

Credential Store information:
  Created Time:        Thu, 28 Jul 2022 15:08:12 MDT
  ID:                  csvlt_dcpUDG2INd
  Type:                vault
  Updated Time:        Thu, 28 Jul 2022 15:08:12 MDT
  Version:             1

  Scope:
    ID:                p_jd7lspegXk
    Name:              ssh-project
    Parent Scope ID:   o_SN2K0DAGpi
    Type:              project

  Authorized Actions:
    no-op
    read
    update
    delete

  Authorized Actions on Credential Store's Collections:
    credential-libraries:
      create
      list

  Attributes:
    Address:           http://127.0.0.1:8200
    Token HMAC:        NZJWT74Jyq09gLQfP4RiK5eDWfY7NWXYHoKL4nKQFDY

Copy the ID from the output and export it as the $CRED_STORE_ID variable.

$ export CRED_STORE_ID=csvlt_dcpUDG2INd

Tip: If you have the jq utility installed, this can be performed in a single step with this command:

$ export CRED_STORE_ID=`boundary credential-stores create vault -scope-id $PROJECT_ID -vault-address $VAULT_ADDR -vault-token $CRED_STORE_TOKEN -format json | jq -r '.item.id'`

Create credential library

Create a new credential library of type ssh_private_key within Boundary using the credential store ID and passing the vault-path of my-secret.

$ boundary credential-libraries create vault \
  -credential-store-id $CRED_STORE_ID \
  -vault-path "secret/data/my-secret" \
  -name "vault-cred-library" \
  -credential-type ssh_private_key

Example output:

$ boundary credential-libraries create vault \
  -credential-store-id $CRED_STORE_ID \
  -vault-path "secret/data/my-secret" \
  -name "vault-cred-library" \
  -credential-type ssh_private_key

Credential Library information:
  Created Time:          Thu, 28 Jul 2022 15:09:59 MDT
  Credential Store ID:   csvlt_dcpUDG2INd
  ID:                    clvlt_yUr2VCd3lJ
  Name:                  vault-cred-library
  Type:                  vault
  Updated Time:          Thu, 28 Jul 2022 15:09:59 MDT
  Version:               1

  Scope:
    ID:                  p_jd7lspegXk
    Name:                ssh-project
    Parent Scope ID:     o_SN2K0DAGpi
    Type:                project

  Authorized Actions:
    no-op
    read
    update
    delete

  Attributes:
    HTTP Method:         GET
    Path:                secret/data/my-secret

  Credential Type:
    ssh_private_key

Copy the ID from the output and export it as the $CRED_LIB_SSH_ID variable.

$ export CRED_LIB_SSH_ID=clvlt_yUr2VCd3lJ

Tip: If you have the jq utility installed, this can be performed in a single step with this command:

$ export CRED_LIB_SSH_ID=`boundary credential-libraries create vault -credential-store-id $CRED_STORE_ID -vault-path "secret/data/my-secret" -name "vault-cred-library" -credential-type ssh_private_key -format json | jq -r '.item.id'`

Additionally, create another credential library of type username_password for the my-app-secret credential.

$ boundary credential-libraries create vault \
  -credential-store-id $CRED_STORE_ID \
  -vault-path "secret/data/my-app-secret" \
  -name "vault-app-library" \
  -credential-type username_password

Example output:

$ boundary credential-libraries create vault \
  -credential-store-id $CRED_STORE_ID \
  -vault-path "secret/data/my-app-secret" \
  -name "vault-app-library" \
  -credential-type username_password

Credential Library information:
  Created Time:          Thu, 28 Jul 2022 15:14:45 MDT
  Credential Store ID:   csvlt_dcpUDG2INd
  ID:                    clvlt_1yY6bOjF8A
  Name:                  vault-app-library
  Type:                  vault
  Updated Time:          Thu, 28 Jul 2022 15:14:45 MDT
  Version:               1

  Scope:
    ID:                  p_jd7lspegXk
    Name:                ssh-project
    Parent Scope ID:     o_SN2K0DAGpi
    Type:                project

  Authorized Actions:
    no-op
    read
    update
    delete

  Attributes:
    HTTP Method:         GET
    Path:                secret/data/my-app-secret

  Credential Type:
    username_password

Copy the ID from the output and export it as the $CRED_LIB_APP_ID variable.

$ export CRED_LIB_APP_ID=clvlt_1yY6bOjF8A

Tip: If you have the jq utility installed, this can be performed in a single step with this command:

$ export CRED_LIB_APP_ID=`boundary credential-libraries create vault -credential-store-id $CRED_STORE_ID -vault-path "secret/data/my-app-secret" -name "vault-app-library" -credential-type username_password -format json | jq -r '.item.id'`

Create an SSH target

First, create a new static host catalog.

$ boundary host-catalogs create static \
  -scope-id=$PROJECT_ID \
  -name=ssh-catalog \
  -description="For static SSH targets"

Example output:

$ boundary host-catalogs create static \
  -scope-id=$PROJECT_ID \
  -name=ssh-catalog \
  -description="For static SSH targets"

Host Catalog information:
  Created Time:        Thu, 28 Jul 2022 15:20:08 MDT
  Description:         For static SSH targets
  ID:                  hcst_FsS2LaNSy3
  Name:                ssh-catalog
  Type:                static
  Updated Time:        Thu, 28 Jul 2022 15:20:08 MDT
  Version:             1

  Scope:
    ID:                p_jd7lspegXk
    Name:              ssh-project
    Parent Scope ID:   o_SN2K0DAGpi
    Type:              project

  Authorized Actions:
    no-op
    read
    update
    delete

  Authorized Actions on Host Catalog's Collections:
    host-sets:
      create
      list
    hosts:
      create
      list

Export the new host catalog ID as the HOST_CATALOG_ID environment variable

$ export HOST_CATALOG_ID=hcst_FsS2LaNSy3

Now create a new static host.

Note: Learners may also bring their own target to test credential injection. If bringing your own target, enter the connection address for the -address option. The connection port is supplied when creating a target later on.

$ boundary hosts create static -name=openssh \
  -description="openssh test host" \
  -address="127.0.0.1" \
  -host-catalog-id=$HOST_CATALOG_ID

Example output:

$ boundary hosts create static -name=openssh \
  -description="openssh test host" \
  -address="127.0.0.1" \
  -host-catalog-id=$HOST_CATALOG_ID

Host information:
  Created Time:        Thu, 28 Jul 2022 15:20:41 MDT
  Description:         openssh test host
  Host Catalog ID:     hcst_FsS2LaNSy3
  ID:                  hst_zNheyZ8wSg
  Name:                openssh
  Type:                static
  Updated Time:        Thu, 28 Jul 2022 15:20:41 MDT
  Version:             1

  Scope:
    ID:                p_jd7lspegXk
    Name:              ssh-project
    Parent Scope ID:   o_SN2K0DAGpi
    Type:              project

  Authorized Actions:
    no-op
    read
    update
    delete

  Attributes:
    address:           127.0.0.1

Export the openssh host ID as the HOST_ID environment variable.

$ export HOST_ID=hst_zNheyZ8wSg

Then create a static host set.

$ boundary host-sets create static -name="ssh-machines" \
  -description="SSH host set" \
  -host-catalog-id=$HOST_CATALOG_ID

Example output:

$ boundary host-sets create static -name="ssh-machines" \
  -description="SSH host set" \
  -host-catalog-id=$HOST_CATALOG_ID

Host Set information:
  Created Time:        Thu, 28 Jul 2022 15:21:44 MDT
  Description:         SSH host set
  Host Catalog ID:     hcst_FsS2LaNSy3
  ID:                  hsst_IXcLAq4HCJ
  Name:                ssh-machines
  Type:                static
  Updated Time:        Thu, 28 Jul 2022 15:21:44 MDT
  Version:             1

  Scope:
    ID:                p_jd7lspegXk
    Name:              ssh-project
    Parent Scope ID:   o_SN2K0DAGpi
    Type:              project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-hosts
    set-hosts
    remove-hosts

Export the host set ID as the HOST_SET_ID environment variable.

$ export HOST_SET_ID=hsst_IXcLAq4HCJ

Add the new host to the host set.

$ boundary host-sets add-hosts -id=$HOST_SET_ID -host=$HOST_ID

Host Set information:
  Created Time:        Thu, 28 Jul 2022 15:21:44 MDT
  Description:         SSH host set
  Host Catalog ID:     hcst_FsS2LaNSy3
  ID:                  hsst_IXcLAq4HCJ
  Name:                ssh-machines
  Type:                static
  Updated Time:        Thu, 28 Jul 2022 15:22:58 MDT
  Version:             2

  Scope:
    ID:                p_jd7lspegXk
    Name:              ssh-project
    Parent Scope ID:   o_SN2K0DAGpi
    Type:              project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-hosts
    set-hosts
    remove-hosts

  Host IDs:
    hst_zNheyZ8wSg

With the host set up, create a new target of type ssh and set its default port to 2222.

Note: Learners may also bring their own target to test credential injection. If bringing your own target, enter the SSH connection port (likely 22 for SSH) for the -default-port option.

$ boundary targets create ssh -scope-id $PROJECT_ID \
  -name="openssh target" \
  -session-connection-limit=-1 \
  -default-port 2222

Example output:

$ boundary targets create ssh -scope-id $PROJECT_ID \
  -name="openssh target" \
  -session-connection-limit=-1 \
  -default-port 2222

Target information:
  Created Time:               Thu, 28 Jul 2022 15:23:42 MDT
  ID:                         tssh_Lp3M0ERnoK
  Name:                       openssh target
  Session Connection Limit:   -1
  Session Max Seconds:        28800
  Type:                       ssh
  Updated Time:               Thu, 28 Jul 2022 15:23:42 MDT
  Version:                    1

  Scope:
    ID:                       p_jd7lspegXk
    Name:                     ssh-project
    Parent Scope ID:          o_SN2K0DAGpi
    Type:                     project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-host-sources
    set-host-sources
    remove-host-sources
    add-credential-sources
    set-credential-sources
    remove-credential-sources
    authorize-session

  Attributes:
    Default Port:             2222

Copy the ID from the output and export it as the $TARGET_ID variable.

$ export TARGET_ID=tssh_Lp3M0ERnoK

Tip: If you have the jq utility installed, this can be performed in a single step with this command:

$ export TARGET_ID=`boundary targets create ssh -scope-id $PROJECT_ID -session-connection-limit=-1 -default-port 2222 -name="openssh target" -format json | jq -r '.item.id'`

Add the target to the host set.

$ boundary targets add-host-sources -host-source=$HOST_SET_ID -id=$TARGET_ID

Target information:
  Created Time:               Thu, 28 Jul 2022 15:23:42 MDT
  ID:                         tssh_Lp3M0ERnoK
  Name:                       openssh target
  Session Connection Limit:   -1
  Session Max Seconds:        28800
  Type:                       ssh
  Updated Time:               Thu, 28 Jul 2022 15:24:56 MDT
  Version:                    2

  Scope:
    ID:                       p_jd7lspegXk
    Name:                     ssh-project
    Parent Scope ID:          o_SN2K0DAGpi
    Type:                     project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-host-sources
    set-host-sources
    remove-host-sources
    add-credential-sources
    set-credential-sources
    remove-credential-sources
    authorize-session

  Host Sources:
    Host Catalog ID:          hcst_FsS2LaNSy3
    ID:                       hsst_IXcLAq4HCJ

  Attributes:
    Default Port:             2222

Associate the SSH target with the SSH credential library for credential injection.

$ boundary targets add-credential-sources -id $TARGET_ID -injected-application-credential-source $CRED_LIB_SSH_ID

Target information:
  Created Time:               Thu, 28 Jul 2022 15:23:42 MDT
  ID:                         tssh_Lp3M0ERnoK
  Name:                       openssh target
  Session Connection Limit:   -1
  Session Max Seconds:        28800
  Type:                       ssh
  Updated Time:               Thu, 28 Jul 2022 15:27:10 MDT
  Version:                    3

  Scope:
    ID:                       p_jd7lspegXk
    Name:                     ssh-project
    Parent Scope ID:          o_SN2K0DAGpi
    Type:                     project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-host-sources
    set-host-sources
    remove-host-sources
    add-credential-sources
    set-credential-sources
    remove-credential-sources
    authorize-session

  Host Sources:
    Host Catalog ID:          hcst_FsS2LaNSy3
    ID:                       hsst_IXcLAq4HCJ

  Injected Application Credential Sources:
    Credential Store ID:      csvlt_dcpUDG2INd
    ID:                       clvlt_yUr2VCd3lJ

  Attributes:
    Default Port:             2222

Inject credentials into sessions

Now you are ready to inject credentials directly into the shell session. You can accomplish this using the boundary connect command, which has a helper called ssh.

Enter yes when prompted to establish the connection.

$ boundary connect ssh -target-id $TARGET_ID

The authenticity of host 'hst_c0ytm16ggf ([127.0.0.1]:49174)' can't be established.
ECDSA key fingerprint is SHA256:+IfWTTBnnsSUSr3ueHjPU8q6jufc9GBDJQVKOIiZzQ4.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'hst_c0ytm16ggf' (ECDSA) to the list of known hosts.
Welcome to OpenSSH Server

openssh-server:~$

When finished, the user can close the connection to the server using exit, or the session can be canceled directly from Boundary in a new terminal window:

$ boundary sessions list -recursive

Session information:
  ID:                    s_EOsEgwF3JN
    Scope ID:            p_ZbpoZDE03L
    Status:              active
    Created Time:        Mon, 09 May 2022 12:39:02 CDT
    Expiration Time:     Mon, 09 May 2022 20:39:01 CDT
    Updated Time:        Mon, 09 May 2022 12:39:02 CDT
    User ID:             u_1234567890
    Target ID:           tssh_zIUXGVzB5L
    Authorized Actions:
      no-op
      read
      read:self
      cancel
      cancel:self

Copy the session ID and cancel the session:

$ boundary sessions cancel -id s_EOsEgwF3JN

Session information:
  Auth Token ID:       at_wXd9EASFp6
  Created Time:        Mon, 09 May 2022 12:39:02 CDT
  Endpoint:            ssh://127.0.0.1:2222
  Expiration Time:     Mon, 09 May 2022 20:39:01 CDT
  Host ID:             hst_C0YtM16ggf
  Host Set ID:         hsst_DyUCqhHuiP
  ID:                  s_EOsEgwF3JN
  Status:              canceling
  Target ID:           tssh_zIUXGVzB5L
  Type:                ssh
  Updated Time:        Mon, 09 May 2022 12:43:28 CDT
  User ID:             u_1234567890
  Version:             3

  Scope:
    ID:                p_ZbpoZDE03L
    Name:              ssh-project
    Parent Scope ID:   o_YcngFcjRcP
    Type:              project

  Authorized Actions:
    no-op
    read
    read:self
    cancel
    cancel:self

  States:
    Start Time:        Mon, 09 May 2022 12:43:28 CDT
    Status:            canceling

    End Time:          Mon, 09 May 2022 12:43:28 CDT
    Start Time:        Mon, 09 May 2022 12:39:02 CDT
    Status:            active

    End Time:          Mon, 09 May 2022 12:39:02 CDT
    Start Time:        Mon, 09 May 2022 12:39:02 CDT
    Status:            pending

You can verify the session was canceled by listing the sessions again and noticing the terminated Status:

$ boundary sessions list -recursive

Session information:
  ID:                    s_EOsEgwF3JN
    Scope ID:            p_ZbpoZDE03L
    Status:              terminated
    Created Time:        Mon, 09 May 2022 12:39:02 CDT
    Expiration Time:     Mon, 09 May 2022 20:39:01 CDT
    Updated Time:        Mon, 09 May 2022 12:43:29 CDT
    User ID:             u_1234567890
    Target ID:           tssh_zIUXGVzB5L
    Authorized Actions:
      no-op
      read
      read:self
      cancel
      cancel:self

In addition to injecting SSH credentials, brokered credentials can also be passed to the user if they are attached to the target. This can be useful when the user needs access to application credentials once they are connected to the target.

Attach the username_password application credentials to the target by supplying the $CRED_LIB_APP_ID to the -brokered-credential-source option.

$ boundary targets add-credential-sources -id $TARGET_ID -brokered-credential-source $CRED_LIB_APP_ID

Target information:
  Created Time:               Thu, 28 Jul 2022 15:23:42 MDT
  ID:                         tssh_Lp3M0ERnoK
  Name:                       openssh target
  Session Connection Limit:   -1
  Session Max Seconds:        28800
  Type:                       ssh
  Updated Time:               Thu, 28 Jul 2022 16:18:57 MDT
  Version:                    14

  Scope:
    ID:                       p_jd7lspegXk
    Name:                     ssh-project
    Parent Scope ID:          o_SN2K0DAGpi
    Type:                     project

  Authorized Actions:
    no-op
    read
    update
    delete
    add-host-sources
    set-host-sources
    remove-host-sources
    add-credential-sources
    set-credential-sources
    remove-credential-sources
    authorize-session

  Host Sources:
    Host Catalog ID:          hcst_FsS2LaNSy3
    ID:                       hsst_IXcLAq4HCJ

  Brokered Credential Sources:
    Credential Store ID:      csvlt_dcpUDG2INd
    ID:                       clvlt_1yY6bOjF8A

  Injected Application Credential Sources:
    Credential Store ID:      csvlt_dcpUDG2INd
    ID:                       clvlt_yUr2VCd3lJ

  Attributes:
    Default Port:             2222

Notice that the target now has both injected and brokered credential sources.

Connect to the open-ssh target again.

$ boundary connect ssh -target-id $TARGET_ID
Credentials:
  Credential Source ID:   clvlt_1yY6bOjF8A
  Credential Source Name: vault-app-library
  Credential Store ID:    csvlt_dcpUDG2INd
  Credential Store Type:  vault
  Credential Type:        username_password
  Secret:
        password:   application-password
        username:   application-user

Welcome to OpenSSH Server

openssh-server:~$

After credential injection is complete, the brokered credentials are also passed on the CLI, enabling the user to utilize the credentials within their session.

Note: There are cases in which targets might have multiple SSH keys or username_password credentials attached as injected application credential sources. SSH supports multiple credential sources, and Boundary will try them until it finds a usable credential when attempting a connection. This scenario is useful when rotating private keys. Both the old key and the new key can be attached to a target simultaneously, and Boundary will try both of them, stopping if one is successful. This facilitates key rotation without downtime.

Inject credentials with the Desktop App

To log into Boundary using the Desktop App, the BOUNDARY_ADDR (Boundary cluster address) and BOUNDARY_AUTH_METHOD_ID (user Auth Method ID) values must be gathered from the HCP Boundary Admin Console, as demonstrated in the HCP Boundary Getting Started tutorial.

Open the Boundary desktop app.

Enter the Boundary cluster URL (for example, https://ffee961b-5fd8-4e68-ba1d-2bbb487b576e.boundary.hashicorp.cloud) and click Submit.

Authenticate using your HCP Boundary user credentials.

Boundary Desktop Login

Under the Targets page, notice the target details for ssh-target.

Boundary Desktop Target Details

Click Connect to initiate a session.

Boundary Desktop Target Connect

The Successfully Connected page will display the target ID (Target Connection details) and Proxy URL.

Open the raw API output.

Boundary Desktop Connect Raw API

Scrolling through the raw API output, you will find the username_password brokered application credentials. The user should note these credentials when using the Desktop app to establish connections.

To start a session, open your terminal or SSH client. A session can be started using SSH and the Proxy URL from the Boundary desktop app.

For the openssh docker target, connect on 127.0.0.1 and provide the proxy port using the -p option. Enter yes when prompted to establish a connection.

$ ssh 127.0.0.1 -p 51968

The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
ECDSA key fingerprint is SHA256:SzGEXZDM/6u0/9lcO8EDADHXzDsemSFaL6Q36KBrlhQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts.
Welcome to OpenSSH Server

openssh-server:~$

When using the Desktop app to connect, the brokered credential are displayed in the raw API output, not upon connection.

When finished, the user can close the connection to the server by entering exit, or the session can be canceled directly from the Boundary desktop app under the Sessions view.

Cleanup and teardown

Locate the terminal session used to execute the vault dev server command, and execute ctrl+c to stop Vault.

Unset the environment variables used in any active terminal windows for this tutorial.

$ unset VAULT_ADDR; unset VAULT_TOKEN

Destroy the openssh-server container created for the tutorial.

$ docker rm -f openssh-server

Check your work by executing docker ps and ensure there are no more containers from the tutorial leftover. If unexpected containers still exist, execute docker rm -f <CONTAINER_ID> against each to remove them.

Help and reference

  • HCP Boundary Documentation
  • HCP Boundary Getting Started
  • Boundary command documentation
  • Vault Documentation
 Previous
 Next Collection

On this page

  1. SSH Credential Injection with HCP Boundary
  2. Tutorial overview
  3. Prerequisites
  4. Credential injection background
  5. Set up an SSH target
  6. Set up Vault
  7. Set up Boundary
  8. Inject credentials into sessions
  9. Cleanup and teardown
  10. Help and reference
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)