Enable session recording with AWS and Vault
Boundary supports session recording with the HCP Boundary Standard tier and Boundary Enterprise editions. Session recording provides insight into user actions over remote SSH and RDP sessions to meet regulatory requirements for organizations and prevent malicious behavior. Administrators can enable session recording on SSH and RDP targets in their Boundary environment and replay recordings back within the Boundary admin UI.
You can watch the following video to learn more about session recording.
This tutorial demonstrates enabling SSH and RDP session recording using Amazon S3 as the storage backend and HashiCorp Vault for credential management. You will deploy the required AWS resources using Terraform.
Tutorial overview
- Prerequisites
- Background
- Get setup
- Deploy Vault, targets, and workers
- Configure Vault
- Set up Boundary
- Enable session recording
- Verify and play back recordings
Prerequisites
This tutorial recommends completing the HCP Boundary administration tutorials first. The learner should have a working Boundary cluster and org running on HCP.
A Boundary binary 1.0.0 or later in your
PATHA Vault binary 2.0.0 or later in your
PATHis recommended. Any version of Vault 1.7 or later should work with this tutorial.Terraform 1.11 or greater is recommended. The binary must be available in your
PATH.The
jqutility installed and in yourPATHThe
makeutility is recommended to simplify workflow management for this tutorial, and should be installed and in yourPATH.The tutorial can be completed without usingmake.Installing the Boundary Desktop Client provides an optional workflow at the end of this tutorial. The 2.7 version or above is required for RDP support.
Installing an RDP client enables you to connect to the RDP targets in this tutorial. You could use the Windows App on Windows on macOS systems, or any other RDP client you prefer.
This tutorial assumes basic knowledge of using Vault, including managing policies, roles, and tokens. If you are new to using Vault, complete the Getting Started with Vault quick start tutorials before you integrate Vault with Boundary.
Session recording background
In highly regulated environments, a common requirement and challenge is having a system of record that archives actions taken on the network so that organizations can improve their security posture and enhance compliance.
Session recording allows administrators to get insight into user actions over remote SSH and RDP sessions to meet various regulatory requirements for organizations and prevent malicious behavior. Administrators can enable session recording on SSH and RDP targets in their Boundary environment, store signed recordings in their Amazon S3 storage bucket, and replay recordings back within the Boundary admin UI.
Boundary converts recorded sessions into a Boundary session recording (BSR) file, a binary file format and specification created to define the structure of Boundary recording files.
The BSR format is designed to:
- Support the recording of both multiplexed and non-multiplexed protocols.
- Allow recordings of independent byte streams in a session to be written in parallel.
- Support an optimal user experience during playback.
- Be extensible to support more protocols in the future.
The BSR file contains all of the data transmitted between a user and a target during a session and is available within your storage bucket. These files are signed to ensure they are tamper-proof.
SSH and RDP session recording is available in both the HCP Boundary Standard tier and Boundary Enterprise.
Configure the lab environment
You need the following prerequisites for the lab environment for this tutorial:
- HCP Boundary Standard cluster or Boundary Enterprise cluster
- Amazon S3 storage bucket
- SSH and/or RDP hosts for testing session recording
- Vault server with policies allowing connections from Boundary and credentials for the SSH or RDP targets
- Boundary AWS host catalog, Vault credential store, and SSH or RDP targets
Deploy Boundary
Session recording and credential injection are features available in HCP Boundary Standard tier and Boundary Enterprise.
You can try the tutorial using an HCP account, or within a test environment in a Boundary Enterprise cluster.
Select an edition of Boundary in the upper-right section of this tutorial labeled Deployment.
First, deploy an HCP Boundary cluster with the Standard tier selected.
Launch the HCP Portal and login.
Select your organization and project. From within that project, select Boundary from the Services menu in the left navigation.
Click Deploy Boundary.

In the Instance Name text box, provide a name for your Boundary instance.
Under Choose a tier, select the Standard option to enable session recording.
Under the Create an administrator account section, enter the Username and Password for the initial Boundary administrator account.
Click Deploy. Wait for the instance to initialize before proceeding.

The following values will be used as environment variables later on. Copy the Boundary Cluster URL from the HCP Boundary portal.
- Boundary address: the
BOUNDARY_ADDRvariable - Boundary Cluster ID: the
BOUNDARY_CLUSTER_IDvariable - Boundary admin username: the
BOUNDARY_USERNAMEvariable - Boundary admin password: the
BOUNDARY_PASSWORDvariable
Store these values in a safe location.
Next, click Open Admin UI.
Log in to Boundary using your admin credentials used to launch the cluster.
Navigate to the Auth Methods page using the left navigation panel. Locate the password auth method, and copy its ID (such as ampw_AQSr776Hnm).
You will use this value later on:
- Boundary auth method ID: the
BOUNDARY_AUTH_METHOD_IDvariable
Review Terraform configuration
Open a terminal and navigate to a working directory, such as the home directory. Clone the sample repository containing the lab environment config files.
$ git clone https://github.com/hashicorp-education/learn-boundary-session-rec-aws-vault
Navigate into the learn-boundary-session-rec-aws-vault directory and list its contents.
$ ls -R1
boundary-example.tf
boundary-example.tfvars
Makefile
README.md
infra
scripts
vault
./infra:
ec2.tf
iam.tf
key_pair.tf
kms.tf
main.tf
outputs.tf
s3.tf
security_groups.tf
variables.tf
vpc.tf
./scripts:
boundary-worker
worker_init.sh
setup.sh
vault
vault_init.sh
./vault:
boundary-controller-policy.hcl
kv-policy.hcl
The repository contains the following files and folders:
Makefile: Definitions of scripts for easy lab deployment and cleanup.infra/: Terraform resources for configuring Vault, EC2 hosts, Amazon S3 storage buckets, and Boundary workers.scripts/: Setup script for Make, and service scripts needed by Vault and Boundary workers.vault/: Vault policies for Boundary and the KV secrets engine.boundary-example.tf/: Optional example Terraform config for deploying Boundary resources.boundary-example.tfvars/: Optional example tfvars config.
Because this lab environment utilizes Vault for credential management, make is
used to reduce complexity when deploying Terraform, configuring Vault, and
setting up the Boundary workers.
The tutorial content can be completed without using make.
These components are explained at a high level in this tutorial, but review the content at your own pace before proceeding. While the Terraform code is extensive, a deep knowledge of Terraform is not necessary to deploy the lab environment and continue learning about session recording.
Deploy Vault, targets, and workers
The infra/ folder contains several Terraform config files that specify the
resources used in this lab:
$ ls -R1 infra/
ec2.tf
iam.tf
key_pair.tf
kms.tf
main.tf
outputs.tf
s3.tf
security_groups.tf
variables.tf
vpc.tf
By default, the following resources are deployed:
- 1 HashiCorp Vault instance (including Boundary worker service)
- 3 Amazon Linux EC2 target instances (including Boundary worker service)
- 1 key pair for EC2 instance access (for Vault and targets)
- 1 Amazon S3 storage bucket
- 2 IAM users (1 for the host catalog, 1 for the S3 storage bucket)
The required IAM roles and policies are also deployed and associated with the storage bucket, instances, and IAM users. VPCs, subnets, and gateways are also assigned as required to allow the Boundary worker services to communicate with Boundary.
A Boundary worker deployed on the same network as Vault is required for integrating private Vault clusters with HCP Boundary. Additionally, a worker is also needed to route traffic to targets on private networks, like the AWS target hosts in this tutorial. To learn more about setting up workers, refer to the Worker Registration with HCP Boundary tutorial.
This tutorial automatically deploys the latest available worker binary for the Boundary control plane. To use a different version of the worker binary, modify the scripts/worker_init file. The binary version should match the version of the control plane you are deploying to. Check the version of the control plane in the Boundary portal.
Set required environment variables
You must set the following environment variables to deploy the lab environment:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_REGIONBOUNDARY_ADDRBOUNDARY_USERNAMEBOUNDARY_PASSWORDBOUNDARY_AUTH_METHOD_IDBOUNDARY_CLUSTER_ID
First, set the AWS variables.
$ export AWS_ACCESS_KEY_ID="<YOUR_ACCESS_KEY_ID>"; \
export AWS_SECRET_ACCESS_KEY="<YOUR_SECRET_ACCESS_KEY>"; \
export AWS_REGION="us-east-1"
Next, set the required Boundary variables.
$ export BOUNDARY_ADDR="<YOUR_BOUNDARY_ADDR>"; \
export BOUNDARY_USERNAME="<YOUR_ADMIN_USERNAME>"; \
export BOUNDARY_PASSWORD="<YOUR_ADMIN_PASSWORD>"; \
export BOUNDARY_AUTH_METHOD_ID="<YOUR_AUTH_METHOD_ID>"; \
export BOUNDARY_CLUSTER_ID="<YOUR_CLUSTER_ID>"
Verify all the environment variables have been set:
$ echo $AWS_ACCESS_KEY_ID; \
echo $AWS_SECRET_ACCESS_KEY; \
echo $AWS_REGION; \
echo $BOUNDARY_ADDR; \
echo $BOUNDARY_USERNAME; \
echo $BOUNDARY_PASSWORD; \
echo $BOUNDARY_AUTH_METHOD_ID; \
echo $BOUNDARY_CLUSTER_ID
Apply Terraform
You can use the make utility to manage the Terraform deployment.
The following make commands allow you to interact with Terraform from the learn-boundary-session-rec-aws-vault/ directory:
apply: Deploys a set of AWS resources defined in the infra folder. Supporting the ability to test a self managed Boundary worker & any version of Vault. Required env variables:BOUNDARY_CLUSTER_ID. Optional env variables:INSTANCE_COUNT(determine number of aws_instances to create for testing dynamic host catalog[1,5]). Created resource names will be prefixed with the Terraform workspace value, which will be derived from the whoami output.force-apply: Taints the aws_instance resource to recreate and refresh Vault.destroy: Destroys the AWS resources defined in the infra folder.
Remember that you must run make from the root of this repository.
Next, apply Terraform using make apply. The deployment usually completes within five minutes.
$ make apply
bash -c "source ./scripts/setup.sh && apply"
~/learn-boundary-session-rec-aws-vault/infra ~/learn-boundary-session-rec-aws-vault
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching ">= 6.47.0"...
- Finding latest version of hashicorp/random...
- Finding latest version of hashicorp/tls...
- Finding latest version of hashicorp/http...
- Installing hashicorp/random v3.9.0...
- Installed hashicorp/random v3.9.0 (signed by HashiCorp)
- Installing hashicorp/tls v4.3.0...
- Installed hashicorp/tls v4.3.0 (signed by HashiCorp)
- Installing hashicorp/http v3.6.0...
- Installed hashicorp/http v3.6.0 (signed by HashiCorp)
- Installing hashicorp/aws v6.47.0...
- Installed hashicorp/aws v6.47.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Workspace "username" doesn't exist.
You can create this workspace with the "new" subcommand
or include the "-or-create" flag with the "select" subcommand.
Created and switched to workspace "username"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
data.http.myip: Reading...
data.http.myip: Read complete after 1s [id=http://ipv4.icanhazip.com]
data.aws_caller_identity.current: Reading...
data.aws_availability_zones.vault: Reading...
data.aws_iam_policy_document.assume_role_ec2: Reading...
data.aws_availability_zones.aws: Reading...
data.aws_ami.ubuntu: Reading...
data.aws_ami.windows: Reading...
data.aws_region.current: Reading...
data.aws_ssm_parameter.amazon_linux: Reading...
data.aws_iam_policy_document.assume_role_ec2: Read complete after 0s [id=285111xxxx]
data.aws_region.current: Read complete after 0s [id=us-east-1]
data.aws_caller_identity.current: Read complete after 0s [id=80707xxxxxxx]
data.aws_iam_policy_document.host_catalog_plugin: Reading...
data.aws_iam_policy_document.host_catalog_plugin: Read complete after 0s [id=213486xxxx]
data.aws_ssm_parameter.amazon_linux: Read complete after 0s [id=/aws/service/ami-amazon-linux-latest/al2026-ami-kernel-default-x86_64]
data.aws_availability_zones.vault: Read complete after 0s [id=us-east-1]
data.aws_availability_zones.aws: Read complete after 0s [id=us-east-1]
data.aws_ami.ubuntu: Read complete after 1s [id=ami-052355af2a014bd2c]
data.aws_ami.windows: Read complete after 1s [id=ami-0ed0165f19a049904]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:
# data.aws_iam_policy_document.vault will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "vault" {
+ id = (known after apply)
+ json = (known after apply)
+ minified_json = (known after apply)
+ statement {
+ actions = [
+ "ec2:DescribeInstances",
]
+ effect = "Allow"
+ resources = [
+ "*",
]
}
+ statement {
+ actions = [
+ "ec2:DescribeInstances",
+ "iam:GetInstanceProfile",
+ "iam:GetRole",
+ "iam:GetUser",
]
+ effect = "Allow"
+ resources = [
+ "*",
]
+ sid = "VaultAWSAuthMethod"
}
+ statement {
+ actions = [
+ "kms:Decrypt",
+ "kms:DescribeKey",
+ "kms:Encrypt",
]
+ effect = "Allow"
+ resources = [
+ (known after apply),
]
+ sid = "VaultKMSUnseal"
}
}
...
... Truncated output ...
...
Apply complete! Resources: 73 added, 0 changed, 0 destroyed.
Outputs:
host_catalog_access_key_id = <sensitive>
host_catalog_secret_access_key = <sensitive>
host_key_pair_name = "boundary-recording-user-host-key"
rdp_target_instance_ids = [
"i-0940d027155aad01c",
]
rdp_target_instance_private_ips = [
"10.0.234.111",
]
rdp_target_instance_public_dns = [
"ec2-98-92-151-xxx.compute-1.amazonaws.com",
]
rdp_target_instance_public_ips = [
"98.92.151.xxx",
]
rdp_target_instance_tags = {
"i-0940d027155aad01c" = tomap({
"Name" = "rdp-host-user@test.com"
"User" = "user@test.com"
"env" = "dev"
"platform" = "windows"
"protocol" = "rdp"
"workspace" = "test"
})
}
rdp_target_password = <sensitive>
rdp_target_username = "Administrator"
recording_bucket_name = "demobucket832340674"
recording_iam_access_key_ids = <sensitive>
recording_iam_secret_access_keys = <sensitive>
recording_iam_user_arns = [
"arn:aws:iam::807078899029:user/demo-user@test.com-boundary-iam-user3052637430",
"arn:aws:iam::807078899029:user/demo-user@test.com-boundary-iam-user3563863154",
]
recording_iam_user_names = [
"demo-user@test.com-boundary-iam-user3052637430",
"demo-user@test.com-boundary-iam-user3563863154",
]
recording_storage_user_access_key_id = <sensitive>
recording_storage_user_secret_access_key = <sensitive>
target_instance_ids = [
"i-03d7e0370f00e005b",
]
target_instance_ids_map = {
"i-03d7e0370f00e005b" = "32.197.42.216"
}
target_instance_private_ips = [
"10.0.200.201",
]
target_instance_public_dns = [
"ec2-32-197-42-xxx.compute-1.amazonaws.com",
]
target_instance_public_ips = [
"32.197.42.xxx",
]
target_instance_tags = {
"i-03d7e0370f00e005b" = tomap({
"Name" = "ssh-host-user@test.com"
"User" = "user@test.com"
"protocol" = "rdp"
"platform" = "linux"
"protocol" = "ssh"
"workspace" = "test"
})
}
target_worker_private_ip = "10.0.153.98"
target_worker_public_dns = "ec2-18-207-101-xxx.compute-1.amazonaws.com"
target_worker_public_ip = "18.207.101.xxx"
vault_private_ip = "10.0.6.127"
vault_private_key = <sensitive>
vault_public_dns = "ec2-35-172-236-xxx.compute-1.amazonaws.com"
vault_public_ip = "35.172.236.xxx"
vault_public_key = <<EOT
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDN63N0e2oqHiW2/0Trpyp+arK4xdOH9TY4nYpFVbcX4G/C9LAqFMUU7M6/cEkCd5XS0teMGqUooDZ56Q/WdRU0oPa/5Wm0+V4LLLERYedLNVlwWc/J3XdYGFJ1Cfd+xgunG3igMJ4U05Ts6igJoqol2SrQCpJ8NBdONl1mpyr4UIYoGceURPSxrAHDXuFB5HS1F04hsQXUvw7VHoOzfJRPsuTVy87yuwcZDSsKGLOpO033MNBlRxKhB61O7NRBHI9ITc4JtZy3LP4KSs49Gt/d5zJh1/psGEU5hipyTQrLmcYIE/5hUstQJiDyA5fa0WXJOvxt4CEqGtyx+cXRQSZfEwd6dEAylwmzP8muZpprX8qdTFjSt18xcBuZj/wd4rE2IGH3vwlEr15a179SVeui3Yl4HgAwNoPS0jxxxx+EvfGK3mgIF7pPECVEPg909zBDZlT+2/MmOnMVS5Giomc9fJL8PiKSKE5Jx46O4PeU5HfaNXVh58NPOaAzrYWUK/GAL7k/DN/AUhIxf289xt0iq0oN2C5mNdGYMQ2YreQqzzLRlyAIuEidfWkqgrUThNzEv6ag6gd+u1R1V4kRtWXzmHVXTXheDkdUA6CjAHgl0xju0iZy3LbVFF0aiYoyEX/fov1jb2kyVYmvzvR9kUtKOL5VzV8VBBO3FlMnxxxxxxx==
EOT
vault_worker_private_ip = "10.0.166.xxx"
vault_worker_public_dns = "ec2-13-223-175-xxx.compute-1.amazonaws.com"
vault_worker_public_ip = "13.223.175.xxx"
worker_private_key = <sensitive>
Your output will include container resources prefixed by your Terraform workspace name,
which is derrived from the output of whoami. For example, the
host_key_pair_name value is prefixed by username-, which will match the
whoami output of the user that deployed Terraform.
You can query these outputs any time by executing make terraform_output:
$ make terraform_output
The lab infrastructure is now deployed.
Next, configure Vault and register the Boundary workers.
Configure Vault
Setting up Vault to inject credentials for the targets requires the following steps:
- Obtain the Vault root token to enable login
- Write the
boundary-controllerandkv-readpolicies to Vault - Enable the kv-v2 secrets engine
- Create a target secret, including a username and private key
- Register a Boundary worker to provide network access to Vault from HCP Boundary
These steps are simplified using two make calls:
make vault_root_token: Copies the root token to your local machine from the Vault host. The command also prints theVAULT_TOKENandVAULT_ADDRvalues, which should be exported as environment variables.make vault_init: Logs into Vault, writes theboundary-controllerandkv-readpolicies to Vault, and generates a client token for Boundary. This token will be used to set up the Vault credential store, and should be exported as theVAULT_CRED_STORE_TOKENvariable.
Obtain the root token
Use make vault_root_token to print the Vault root token and Vault address.
Enter yes when prompted to continue connecting to the Vault EC2 host.
$ make vault_root_token
bash -c "source ./scripts/setup.sh && vault_root_token"
~/learn-boundary-session-rec-aws-vault/infra ~/learn-boundary-session-rec-aws-vault
Warning: Permanently added 'ec2-35-172-236-xxx.compute-1.amazonaws.com' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
credentials 100% 897 8.1KB/s 00:00
----------------------------------------------------------------------------
export VAULT_TOKEN="hvs.eayBna9zZ9sdxxxxxvxxxxxx"
export VAULT_ADDR="http://ec2-35-172-236-xxx.compute-1.amazonaws.com:8200"
----------------------------------------------------------------------------
Examine the output, and execute the suggested commands to export the
VAULT_TOKEN and VAULT_ADDR environment variables.
$ export VAULT_TOKEN="<YOUR_VAULT_ROOT_TOKEN>" ; \
export VAULT_ADDR="<YOUR_VAULT_ADDR>"
Next, you will log in to Vault and write the necessary policies for Boundary, and generate a client token for the Boundary credential store.
Write policies and create a client token
The make vault_init command performs the following actions:
- Write the
boundary-controllerandkv-readpolicies to Vault - Create a kv secret at
secret/ssh_hostwith the target credentials - Generate a client token for Boundary
The target instances (and Vault) all utilize the same keypair to reduce
complexity for this example. The username for all instances is ec2-user, and
the keypair is stored on your local machine at ~/.ssh/username-host-key. This
means a single secret will be used when injecting the credentials later on with
Boundary.
To learn more about credential injection with Vault, refer to the HCP credential injection with private Vault tutorial.
Execute make vault_init.
$ make vault_init
bash -c "source ./scripts/setup.sh && vault_init"
~/learn-boundary-session-rec-aws-vault/infra ~/learn-boundary-session-rec-aws-vault
~/learn-boundary-session-rec-aws-vault
~/learn-boundary-session-rec-aws-vault/vault ~/learn-boundary-session-rec-aws-vault
WARNING! The VAULT_TOKEN environment variable is set! The value of this
variable will take precedence; if this is unwanted please unset VAULT_TOKEN or
update its value accordingly.
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.eayBna9zZ9sdWPd9xxxxxxxx
token_accessor JIlwOxaBoCJZtPqUxEFc9HTz
token_duration ā
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
Success! Uploaded policy: boundary-controller
Success! Uploaded policy: kv-read
Success! Disabled the secrets engine (if it existed) at: secret/
Success! Enabled the kv-v2 secrets engine at: secret/
Success! Data deleted (if it existed) at: secret/data/ssh_host
Success! Data deleted (if it existed) at: secret/data/rdp_host
Success! Data deleted (if it existed) at: secret/data/vault_host
==== Secret Path ====
secret/data/ssh_host
======= Metadata =======
Key Value
--- -----
created_time 2026-07-21T22:34:59.809060896Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
==== Secret Path ====
secret/data/rdp_host
======= Metadata =======
Key Value
--- -----
created_time 2026-07-21T22:35:00.075278744Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
===== Secret Path =====
secret/data/vault_host
======= Metadata =======
Key Value
--- -----
created_time 2026-07-21T22:35:00.33123557Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
----------------------------------------------------------------------------
export VAULT_CRED_STORE_TOKEN="hvs.CAESIPbWU_zPdmAqORkb8-GzpM9XrqNH6U-LeQRnkGKDdfu3Gh4KHGh2cy5YMUlzRUo3VkhWQnVySDQyeE5xxxxxxxx"
----------------------------------------------------------------------------
~/learn-boundary-session-rec-aws-vault
Examine the output, and execute the suggested command to export the
VAULT_CRED_STORE_TOKEN environment variable.
$ export VAULT_CRED_STORE_TOKEN="<YOUR_VAULT_CRED_STORE_TOKEN>"
Register the Vault worker
A Boundary worker is required to provide private network access to HCP Boundary and connect users to targets. This means both Vault and the target instances require a Boundary worker deployed in their respective networks. The worker instances were deployed as part of the Terraform apply.
Refer to the scripts/worker_init.sh file to learn more about how the worker services were deployed.
When the worker service was started, a token was produced to register the worker with HCP Boundary. You can register Boundary workers using the Boundary CLI or Admin Console Web UI.
The make register_workers command first logs into the Vault worker and obtains
the worker auth token. Next, it authenticates to your HCP Boundary instance
using the BOUNDARY_ADDR, BOUNDARY_USERNAME and BOUNDARY_PASSWORD
environment variables you set earlier. Finally, it registers the worker using
the boundary workers create command. The same process happens for the target worker.
Execute make register_workers.
$ make register_workers
bash -c "source ./scripts/setup.sh && vault_root_token && host_worker_token"
~/learn-boundary-session-rec-aws-vault/infra ~/learn-boundary-session-rec-aws-vault
Warning: Permanently added 'ec2-35-172-236-xxx.compute-1.amazonaws.com' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
credentials 100% 897 8.8KB/s 00:00
----------------------------------------------------------------------------
export VAULT_TOKEN="hvs.eayBna9zZ9sdWPd9xxxxxxxx"
export VAULT_ADDR="http://ec2-35-172-236-xxx.compute-1.amazonaws.com:8200"
----------------------------------------------------------------------------
~/learn-boundary-session-rec-aws-vault
Authentication information:
Account ID: acctpw_lyEFrDsYTp
Auth Method ID: ampw_URSTMBpTLX
Expiration Time: Tue, 28 Jul 2026 16:37:12 MDT
User ID: u_48bCbR47cU
The token name "default" was successfully stored in the chosen keyring and is not displayed here.
~/learn-boundary-session-rec-aws-vault/infra ~/learn-boundary-session-rec-aws-vault
Warning: Permanently added 'ec2-13-223-175-xxx.compute-1.amazonaws.com' (ED25519) to the list of known hosts.
worker_auth_token 100% 299 2.9KB/s 00:00
----------------------------------------------------------------------------
export BOUNDARY_WORKER_TOKEN="GzusqckarbczHoLGQ4UA25uSRcGQXdvMvtgYF31NeeGXgWTHUYEXXcnSJvt8BQjpuuhtU8MUH5w5VN79HNAFCaF5svgxa2uMm8YibhpUdQegHvsVQmzbdctFUzDp2sCpBeTseiVAM5onSPpfXTcLm9AS4NAKj4obyuMdVBYgx6VpJWZgWeuNmwTcFNzT6Jb9V2a6vcAPjc7Thhejz8s6DrLaQUMuRVnTrUiPw7qRhuthWty224xNCddEbwRVrEaMSYPJ5TqTMqSr6PGyzkFmU2o594vPRansAftsxxxxxx"
----------------------------------------------------------------------------
Worker information:
Active Connection Count: 0
Created Time: Tue, 21 Jul 2026 16:37:17 MDT
ID: w_Gk2hrXUAo7
Local Storage State: unknown
Name: aws-vault-worker
Type: pki
Updated Time: Tue, 21 Jul 2026 16:37:17 MDT
Version: 1
Scope:
ID: global
Name: global
Type: global
Authorized Actions:
delete
add-worker-tags
set-worker-tags
remove-worker-tags
no-op
read
update
Warning: Permanently added 'ec2-18-207-101-xxx.compute-1.amazonaws.com' (ED25519) to the list of known hosts.
worker_auth_token 100% 296 2.6KB/s 00:00
----------------------------------------------------------------------------
export BOUNDARY_WORKER_TOKEN="pdZ5SAAebKa9DmnokkNu5EuBKcBgrdFCfhW5yS4xwumaeeXQLDZueWrPYfNqJwEZHsqTC9EmzP4SKTo4or6D55j5czMF7qsGhbatWyGWjWd4isXTtsGyfcDKqeXtXuaTEYGBrTEv1rGudxYJdi3taFjjq6cPmTN8espf1QJWb7Rj9dF8SNUjAsohXSdrqJYkjnKqCfPq2L83MUCdMnjQ9UXsSowZwT5ZHaAQLgBUGWEAvzdfx8UwM1LrZQterFjMYTKgVcMFMfhSXkjPRWTBLqA6HypUT5rafxxxxxxx"
----------------------------------------------------------------------------
Worker information:
Active Connection Count: 0
Created Time: Tue, 21 Jul 2026 16:37:21 MDT
ID: w_UrFjvEIrZq
Local Storage State: unknown
Name: aws-target-worker
Type: pki
Updated Time: Tue, 21 Jul 2026 16:37:21 MDT
Version: 1
Scope:
ID: global
Name: global
Type: global
Authorized Actions:
add-worker-tags
set-worker-tags
remove-worker-tags
no-op
read
update
delete
~/learn-boundary-session-rec-aws-vault
Next, verify the workers were registered.
Start by logging in to Boundary using your admin credentials.
$ boundary authenticate
Please enter the login name (it will be hidden):
Please enter the password (it will be hidden):
Authentication information:
Account ID: acctpw_byMkJ6gu9n
Auth Method ID: ampw_AQSr776Hnm
Expiration Time: Sun, 24 Sep 2023 14:47:35 MDT
User ID: u_IwFxiyB0I8
The token was successfully stored in the chosen keyring and is not displayed here.
List the workers.
$ boundary workers list
Worker information:
ID: w_Gk2hrXUAo7
Version: 1
Name: aws-vault-worker
Address: 13.223.175.xxx:9202
ReleaseVersion: Boundary v1.0.1+ent
Last Status Time: Tue, 21 Jul 2026 22:43:49 UTC
Authorized Actions:
no-op
read
update
delete
add-worker-tags
set-worker-tags
remove-worker-tags
ID: w_UrFjvEIrZq
Version: 1
Name: aws-target-worker
Address: 18.207.101.xxx:9202
ReleaseVersion: Boundary v1.0.1+ent
Last Status Time: Tue, 21 Jul 2026 22:43:53 UTC
Authorized Actions:
remove-worker-tags
no-op
read
update
delete
add-worker-tags
set-worker-tags
You should see both the aws-vault-worker and aws-target-worker are registered.
You may also notice two hcp-managed-workers if you are using HCP Boundary. These are part of the HCP Boundary control plane.
Read the aws-vault-worker worker details by copying its ID.
$ boundary workers read -id w_UrFjvEIrZq
Worker information:
Active Connection Count: 0
Address: 13.223.175.xxx:9202
Created Time: Tue, 21 Jul 2026 16:37:17 MDT
ID: w_Gk2hrXUAo7
Last Status Time: 2026-07-21 22:49:08.3627 +0000 UTC
Local Storage State: available
Name: aws-vault-worker
Release Version: Boundary v1.0.1+ent
Type: pki
Updated Time: Tue, 21 Jul 2026 16:49:08 MDT
Version: 1
Scope:
ID: global
Name: global
Type: global
Tags:
Configuration:
env: ["prod"]
platform: ["ubuntu"]
protocol: ["ssh"]
type: ["worker" "vault" "s3"]
Canonical:
env: ["prod"]
platform: ["ubuntu"]
protocol: ["ssh"]
type: ["worker" "vault" "s3"]
Authorized Actions:
add-worker-tags
set-worker-tags
remove-worker-tags
no-op
read
update
delete
Notice the tags defined for this worker:
Tags:
Configuration:
env: ["prod"]
platform: ["ubuntu"]
protocol: ["ssh"]
type: ["worker" "vault" "s3"]
Canonical:
env: ["prod"]
platform: ["ubuntu"]
protocol: ["ssh"]
type: ["worker" "vault" "s3"]
This worker is tagged with "type":["worker" "vault" "s3"]. These are defined in the vault worker configuration file in scripts/worker_init, which references tags set in `infra/variables.tf. You will use these tags later on when setting up Boundary's Vault credential store.
Just like Vault, a Boundary worker is required to provide private network access
to the targets. The aws-target-worker provides access to the target network for both the SSH and RDP targets.
Next, read the aws-target-worker details and examine its tags.
$ boundary workers read -id w_Gk2hrXUAo7
Worker information:
Active Connection Count: 0
Address: 18.207.101.168:9202
Created Time: Tue, 21 Jul 2026 16:37:21 MDT
ID: w_UrFjvEIrZq
Last Status Time: 2026-07-21 22:47:16.021366 +0000 UTC
Local Storage State: available
Name: aws-target-worker
Release Version: Boundary v1.0.1+ent
Type: pki
Updated Time: Tue, 21 Jul 2026 16:47:16 MDT
Version: 1
Scope:
ID: global
Name: global
Type: global
Tags:
Configuration:
env: ["dev"]
platform: ["ubuntu"]
protocol: ["rdp" "ssh"]
type: ["worker" "s3" "rdp" "ssh"]
Canonical:
env: ["dev"]
platform: ["ubuntu"]
protocol: ["rdp" "ssh"]
type: ["worker" "s3" "rdp" "ssh"]
Authorized Actions:
add-worker-tags
set-worker-tags
remove-worker-tags
no-op
read
update
delete
Notice the tags defined for the aws-target-worker:
Tags:
Configuration:
env: ["dev"]
platform: ["ubuntu"]
protocol: ["rdp" "ssh"]
type: ["worker" "s3" "rdp" "ssh"]
Canonical:
env: ["dev"]
platform: ["ubuntu"]
protocol: ["rdp" "ssh"]
type: ["worker" "s3" "rdp" "ssh"]
This worker is tagged with "type":["worker" "s3" "rdp" "ssh"], as defined in the worker configuration file in scripts/worker_init. These tags will be used later on when setting up Boundary's AWS host sets, which include the SSH and RDP targets.
Set up Boundary
The following are required to set up session recording for an SSH or RDP target in Boundary:
- A credential store
- A credential library
- A Boundary storage bucket
- An SSH or RDP target type with credential injection enabled
These resources can be configured via the Admin Console UI, the CLI, or Terraform. Select a workflow below to continue setting up Boundary.
Start by logging in to HCP Boundary within the terminal.
Log in to the HCP portal.
From the HCP Portal's Boundary page, click Open Admin UI - a new page will open.
Enter the admin username and password you created when you deployed the new instance and click Authenticate.
Next, set up a new testing org and project scope.
Navigate to the Orgs page and click New Org.
Fill out the new org form with a Name of
recording-organd Description ofSession recording test org. Click Save.From within the new org, click New Project.
Fill out the new project form with a Name of
recording-projectand Description ofSSH and RDP recording testing. Click Save.
Create a host catalog
You can use a dynamic host catalog to import the hosts created by Terraform into Boundary. These hosts will be used later on when configuring an SSH target.
Select Host Catalogs from the left navigation panel.
Choose New.
Enter
aws-recording-catalogin the Name field, and enter a description ofaws session recording host catalog.

Select the Dynamic type. Select the AWS provider, and enter the following details:
- AWS Region:
<YOUR_AWS_REGION> - Access Key ID:
<YOUR_host_catalog_access_key_id> - Secret Access Key:
<YOUR_host_catalog_secret_access_key>
The
host_catalog_access_key_idandhost_catalog_secret_access_keyare sensitive Terraform outputs. This means you will have to manually extract their contents from the terraform.tfstate file.Open the shell session where Terraform was deployed, and execute the following:
$ export HOST_CATALOG_ACCESS_KEY_ID=$(jq -r ".outputs.host_catalog_access_key_id.value" "./infra/terraform.tfstate.d/boundary-recording-$(whoami)/terraform.tfstate"); \ echo "HOST_CATALOG_ACCESS_KEY_ID=$HOST_CATALOG_ACCESS_KEY_ID" ; \ export HOST_CATALOG_SECRET_ACCESS_KEY=$(jq -r ".outputs.host_catalog_secret_access_key.value" "./infra/terraform.tfstate.d/boundary-recording-$(whoami)/terraform.tfstate"); \ echo "HOST_CATALOG_SECRET_ACCESS_KEY=$HOST_CATALOG_SECRET_ACCESS_KEY"Copy these values into their fields.
Lastly, check the box beside Disable credential rotation.
- AWS Region:
Click Save.
Create the SSH host set
A host set can be used to sort hosts by environment, target type, or any other catalog you want to implement.
Start by creating a host set for the SSH host.
Select the Host Sets tab, and then select New.
Enter
ssh_host_setin the Name field.Next, define the instance that should belong to the ssh host set. This can be done by examining the instance tags, which are printed in the Terraform output:
$ make terraform_output ... ... ... ssh_target_instance_tags = { "i-03d7e0370f00e005b" = tomap({ "Name" = "ssh-host-user@test.com" "User" = "user@test.com" "env" = "prod" "platform" = "linux" "protocol" = "ssh" "workspace" = "test" }) } ... ... ...Notice the instance tagged as
"protocol" = "ssh".To select it for the host set, enter the following in the Filter field:
tag:protocol=sshClick Save.
Click the Hosts tab, and verify that the
ssh-hosthost appears as expected. If it's missing, wait a few moments and refresh the page.
Create the RDP host set
Next, create a host set for the RDP host.
Navigate back to the
aws-recording-cataloghost catalog. Click Manage, and select New Host Set.Enter
rdp_host_setin the Name field.Define the instances that should belong to the RDP host set by selecting the instance tagged as
"protocol" = "rdp".To select it for the host set, enter the following in the Filter field,
tag:protocol=rdpClick Save.
Click the Hosts tab, and verify that the
ssh-hosthost appears as expected. If it's missing, wait a few moments and refresh the page.
Create a credential store
Next, create a Vault credential store within Boundary using the
VAULT_CRED_STORE_TOKEN value, defined when you set up Vault.
The vault credential store type is used for Vault integration, but you can also use static
credential stores with credential injection.
When you set up a worker, it's important to create a filter for the credential store. A worker filter will identify workers that should be used as proxies for the new credential store, and ensure these credentials are brokered from the private Vault.
Navigate to the global scope within the UI, and select the Workers page.
Select aws-vault-worker, and notice its Worker Tags:
"type" = ["s3", "vault", "worker"]
With the tags and VAULT_CRED_STORE_TOKEN value, set up a new credential store.
Navigate back to the
recording-org, and select therecording-project.Select the Credential Stores page, and click New.
Enter the Name
Vault AWS Host Credentials.Select the type Vault, and enter the following details:
- Address:
<YOUR_VAULT_ADDR> - Worker Filter:
"vault" in "/tags/type" - Token:
<YOUR_VAULT_CRED_STORE_TOKEN>
The
VAULT_ADDRandVAULT_CRED_STORE_TOKENvalues were exported as environment variables when executingmake vault_initin the Write policies and create a client token section. Check their values in the terminal session used to apply Terraform:$ echo $VAULT_ADDR; echo $VAULT_CRED_STORE_TOKENCopy these values into their fields.
- Address:
Click Save.
Create the credential libraries
A credential library is used to determine what credentials should be accessed from Vault, and the path to query for them.
Create the SSH 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 secret/data/ssh_host.
Navigate back to the
recording-org, and select therecording-project.Select the Credential Stores page, and click on the Vault AWS Host Credentials credential store.
Click the Credential Libraries tab, then click New Credential Library.
Enter the Name
Vault SSH Host Cred Library, and enter the following details:- Type:
Generic Secrets - Vault Path:
secret/data/ssh_host - Credential Type:
SSH Private Key - HTTP Method:
Get
The
Vault Pathis defined in thescripts/setup.shfile when you executedmake vault_init. The Vault policy for these paths is defined in thevault/kv-read.hclfile, which allows for read access to the secret path.- Type:
Click Save.
Navigate back to the Credential Stores page.
From the Vault AWS Host Credentials host catalog, click the Credential
Libraries tab. Verify that the Vault SSH Host Cred Library was created successfully, and click on its name to verify its details.
Create the RDP credential library
Create a new credential library of type Username and Password within Boundary using the credential store ID and passing the vault-path of secret/data/rdp_host.
Navigate back to the
recording-org, and select therecording-project.Select the Credential Stores page, and click on the Vault AWS Host Credentials credential store.
Click the Credential Libraries tab, then click the Manage dropdown. Select New Credential Library.
Enter the Name
Vault RDP Host Cred Library, and enter the following details:- Type:
Generic Secrets - Vault Path:
secret/data/rdp_host - Credential Type:
Username and Password - HTTP Method:
Get
- Type:
Click Save.
Navigate back to the Credential Stores page.
From the Vault AWS Host Credentials host catalog, click the Credential
Libraries tab. Verify that the Vault RDP Host Cred Library was created successfully, and click on its name to verify its details.
Enable session recordings
Two tasks are left to finish setting up session recordings:
- Set up a Boundary storage bucket
- Create an SSH target
The SSH target requires the injected application credentials (supplied from the Vault credential library), and the Boundary storage bucket it should associate recordings with.
Create a storage bucket
Within Boundary, a storage bucket resource is used to store the recorded sessions. A storage bucket represents a bucket in an external store, in this case, Amazon S3. You must create a Boundary storage bucket associated with an external store before enabling session recording.
Navigate to the
globalscope, and then the Storage Buckets page.Click New Storage Bucket. Fill out the following details:
- Name: boundary-test-bucket
- Scope:
recording-org - Bucket name:
YOUR_S3_BUCKET_NAME - Region:
YOUR_AWS_REGION - Access key ID:
YOUR_recording_storage_user_access_key_id - Secret access key:
YOUR_recording_storage_user_secret_access_key - Worker filter:
"s3" in "/tags/type"
The
recording_storage_user_access_key_idandrecording_storage_user_secret_access_keyvalues are sensitive Terraform outputs. This means you will have to manually extract their contents from the terraform.tfstate file.Additionally, the name of the Amazon S3 bucket is required from the Terraform outputs.
Open the shell session where Terraform was deployed, and execute the following:
$ export recording_bucket_name=$(jq -r ".outputs.recording_bucket_name.value" "./infra/terraform.tfstate.d/boundary-recording-$(whoami)/terraform.tfstate"); \ echo "recording_bucket_name=$recording_bucket_name"; \ echo "AWS_REGION=$AWS_REGION"; \ export recording_storage_user_access_key_id=$(jq -r ".outputs.recording_storage_user_access_key_id.value" "./infra/terraform.tfstate.d/boundary-recording-$(whoami)/terraform.tfstate"); \ echo "recording_storage_user_access_key_id=$recording_storage_user_access_key_id"; \ export recording_storage_user_secret_access_key=$(jq -r ".outputs.recording_storage_user_secret_access_key.value" "./infra/terraform.tfstate.d/boundary-recording-$(whoami)/terraform.tfstate"); \ echo "recording_storage_user_secret_access_key=$recording_storage_user_secret_access_key"Copy these values into their fields.
For the Worker Filter, a worker with access to the S3 storage bucket is needed. A public S3 bucket is used for this tutorial, meaning any worker will have access. In the case of a private S3 bucket, a worker with appropriate network access should be deployed and registered with Boundary, then entered here.
Select the worker tagged with
"type" = ["s3", "vault", "worker"], which also provides access to Vault. The following filter will select this worker:"s3" in "/tags/type"Lastly, check the box next to Disable credential rotation.
Click Save.
Create a storage policy
A storage policy defines how long session recordings should be retained before they can be deleted. By default, recordings cannot be deleted until a storage policy allowing for it is attached to the org scope.
To delete session recordings, you must define a storage policy that allows for zero retention. In a real-world scenario, you would likely retain your recordings for an amount of time defined by your organization.
Create a storage policy that allows for immediate deletion:
Navigate back to the
Globalscope, and click on Storage Policies.Click New Storage Policy.
Enter the following details:
- Name:
Delete Policy - Retention Policy:
Do not protect, allow deletion any time - Deletion Policy:
Custom- Delete after:
1days
- Delete after:
- Name:
Click Save.
Attach the storage policy to your org:
Navigate back
Globaland click on Orgs. Select therecording-org.Click on Org Settings in the left sidebar. From the Details view, click on Add Storage Policy.
Select the
Delete Policy, and click Save.
Create an SSH target
To finish setting up recordings, create an SSH target for the ssh-host host.
Navigate to the Targets page within
recording-projectand click New.Fill out the New Target form. Select a Type of SSH.
- Name:
ssh-target - Type:
SSH - Default Port:
22 - Maximum Connections:
-1
- Name:
Click Save.
Click the Workers tab for the new target.
Next to Egress workers, click Edit worker filter.
An egress worker filter specifies which worker has access to the target, such as a worker deployed in the same network as the target. An ingress worker specifies how to route a Boundary client to the target network, and is not used in this example.
Recall the tags associated with the
aws-target-worker, which provides access to thessh-hosthost:Tags: Configuration: env: ["dev"] platform: ["ubuntu"] protocol: ["rdp" "ssh"] type: ["worker" "s3" "rdp" "ssh"] Canonical: env: ["dev"] platform: ["ubuntu"] protocol: ["rdp" "ssh"] type: ["ssh" "worker" "s3" "rdp"]The tags for this worker include:
type: ["worker" "s3" "rdp" "ssh"]An appropriate filter to select this worker is:
"ssh" in "/tags/type"- Egress worker filter:
"ssh" in "/tags/type"
Paste the filter expression in and click Save.
- Egress worker filter:
Now associate ssh-target with ssh-host-set.
Select the Host Sources tab for
ssh-target.Click Add Host Sources.
Check the box next to the host set named ssh_host_set, then click Add Host Sources.
Now associate the SSH target with the Vault credential library.
Select the Injected Application Credentials tab for
ssh-target.Click +Add Injected Application Credentials.
Check the box next to the credential library named vault-cred-library, then click Add Injected Application Credentials.
Enable session recording
Finally, enable session recording for the ssh-target.
Navigate back to the
ssh-targetDetails page.Under Session Recording, click Enable recording.
On the Enable Session Recording for Target page, toggle the switch next to Record sessions for this target.
For the AWS storage buckets, select the
boundary-test-bucket.Click Save.
Under the ssh-target Details page, the boundary-test-bucket should
now be listed under Session Recording.
Record a session
Now you are ready to test session recording using the SSH target or RDP target.
To log into Boundary using the Boundary Desktop Client, you must gather the BOUNDARY_ADDR values from the HCP Boundary Admin Console.
Check the value of BOUNDARY_ADDR in the terminal session where Terraform was applied.
$ echo $BOUNDARY_ADDR
https://d2a6e010-ba05-431a-b7f2-5cbc4e1e9f06.boundary.hashicorp.cloud
Open the Boundary Desktop Client.
Enter the Boundary cluster URL (for example,
https://d2a6e010-ba05-431a-b7f2-5cbc4e1e9f06.boundary.hashicorp.cloud) and
click Submit.
Authenticate using your HCP Boundary admin credentials.

Connect to the SSH target
On the Targets page, notice the target details for ssh-target.

Click Connect to initiate a session.
The Successfully Connected page displays the target ID (Target Connection details) and Proxy URL.
To start a session, open your terminal or SSH client. You can start a session using SSH and the Proxy URL from the Boundary Desktop app.
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 '3.239.211.190 (3.239.211.190)' can't be established.
ED25519 key fingerprint is SHA256:Bo4D8kPtsRVR6zu+kz2bgaSoCP3C/Zwhst/J+twVFyw.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:73: ec2-3-239-211-190.compute-1.amazonaws.com
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '3.239.211.190' (ED25519) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
[ec2-user@ip-10-0-51-203 ~]$
When you are finished, you can close the connection to the server by entering
exit, or you can cancel the session directly from the Boundary Desktop Client
under the Sessions view.
Connect to the RDP target
On the Targets page, notice the target details for rdp-target.
Click Open to initiate a session.
Your RDP client should automatically launch. You will be prompted to accept a certificate. After accepting your connection is automatically routed through Boundary to the RDP target.
The Sessions page in the Boundary Desktop Client will also open. If your RDP client did not automatically launch the proxy address and port are displayed on this page, such as 127.0.0.1 and 61978. You can use these details to set up a new connection in your RDP client manually, and the session will still be proxied through Boundary. Leave the credentials for the PC empty when you set up the connection.

When you are finished, you can close the connection to the server by closing your RDP client, or you can cancel the session directly using the End session button directly from the Boundary Desktop Client under the Sessions view. Note that even if you close your RDP client, the Boundary session does not close until you click End session in the Boundary Desktop Client.
View the recordings
You can view a list of all recorded sessions, or if you know the ID of a specific recorded session, you can find any channels associated with that recording.
To play back a session, open the Admin Console Web UI, and re-authenticate as the admin user if necessary.
From the global scope, navigate to the Session Recordings page.
Note that the following details are listed for each recording:
- Time
- Status
- User
- Target
- Duration
Click View next to the recording.
Within the Session Playback page, click Play for Channel 1.
After the recording loads, hover your mouse on the video player and click the play button to start playback.
Note the Channel details on the right, which display the duration and bytes up / bytes down.
Validate the recording
A session recording represents a directory structure of files in an external object store that together are the recording of a single session between a user and a target.
Verify that the recording exists within Boundary.
$ boundary session-recordings list -scope-id $ORG_ID
Session Recording information:
ID: sr_6bZnEudkf0
Session ID: s_tquYdkeHeZ
Storage Bucket ID: sb_pp1aMfHtGE
Created Time: Tue, 21 Jul 2026 20:50:29 MDT
Updated Time: Tue, 21 Jul 2026 20:51:21 MDT
Start Time: Tue, 21 Jul 2026 20:50:29 MDT
End Time: Tue, 21 Jul 2026 20:51:21 MDT
Type: ssh
State: available
Availability: available
Storage State: synced
Delete After: Wed, 22 Jul 2026 20:51:21 MDT
Authorized Actions:
export:cancel
no-op
read
download
delete
reapply-storage-policy
export
ID: sr_HpOP1OtqBl
Session ID: s_q2WsrUUYq6
Storage Bucket ID: sb_pp1aMfHtGE
Created Time: Tue, 21 Jul 2026 20:37:23 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Start Time: Tue, 21 Jul 2026 20:37:23 MDT
End Time: Tue, 21 Jul 2026 20:48:35 MDT
Type: rdp
State: available
Availability: available
Storage State: synced
Delete After: Wed, 22 Jul 2026 20:48:35 MDT
Authorized Actions:
reapply-storage-policy
export
export:cancel
no-op
read
download
delete
Pick a session recording by ID and read its details.
$ boundary session-recordings read -id sr_HpOP1OtqBl
Session Recording information:
Availability: available
Bytes Down: 414047
Bytes Up: 11993
Created Time: Tue, 21 Jul 2026 20:37:23 MDT
Delete After: Wed, 22 Jul 2026 20:48:35 MDT
Duration (Seconds): 672.107504
Endpoint: rdp://10.0.234.111:3389
ID: sr_HpOP1OtqBl
Scope ID: o_KnaemDMtAM
Session ID: s_q2WsrUUYq6
Start Time: Tue, 21 Jul 2026 20:37:23 MDT
State: available
Storage Bucket ID: sb_pp1aMfHtGE
Type: rdp
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Scope:
ID: o_KnaemDMtAM
Name: recording-org
Parent Scope ID: global
Type: org
Authorized Actions:
download
delete
reapply-storage-policy
export
export:cancel
no-op
read
User Info:
Description: Global admin user
ID: u_48bCbR47cU
Name: admin
Scope:
ID: global
Name:
Type: global
Target Info:
Default Port: 3389
Description: RDP target
Egress Worker Filter: "rdp" in "/tags/type"
ID: trdp_utJBQ4E7Bg
Name: rdp-target
Session Connection Limit: -1
Session Max Seconds: 28800
Target Type: rdp
Scope:
ID: p_IMAIF9F6ES
Name: recording-project
Parent Scope ID: o_KnaemDMtAM
Type: project
Host Info:
External ID: i-0940d027155aad01c
ID: hplg_9FMBDiPqI8
Type: plugin
HostCatalog:
ID: hcplg_KKMEnRm2nE
Scope:
ID: p_IMAIF9F6ES
Name: recording-project
Parent Scope ID: o_KnaemDMtAM
Type: project
Credential Libraries:
Http Method: GET
ID: clvlt_tO9veV0B3E
Name: Vault RDP Host Cred Library
Purpose: injected_application
Type: vault-generic
Vault Path: secret/data/rdp_host
Credential Store:
ID: csvlt_2qHMETuwV7
Name: Vault AWS Host Credentials
Scope ID: p_IMAIF9F6ES
Type: vault
Vault Address: http://ec2-35-172-236-xxx.compute-1.amazonaws.com:8200
Connection Recordings:
Bytes Down: 414047
Bytes Up: 11993
Created Time: Tue, 21 Jul 2026 20:38:25 MDT
Duration (Seconds): 609.825324
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: cr_2blIbch1VX
Start Time: Tue, 21 Jul 2026 20:38:25 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Channel Recordings:
Bytes Down: 391477
Bytes Up: 6223
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.116027
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_an5EKM2EQu
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Bytes Down: 106
Bytes Up: 82
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.182824
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_U50hiENyly
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.241402
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_MeO8yApc6g
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Bytes Down: 4242
Bytes Up: 1117
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.303076
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_Sa8wKGkj6S
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Bytes Down: 4290
Bytes Up: 2112
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.364682
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_kzLXUTpmff
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Bytes Down: 1460
Bytes Up: 996
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.418545
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_nSVn0LRbo8
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Created Time: Tue, 21 Jul 2026 20:48:35 MDT
Duration (Seconds): 609.472713
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: chr_dhWwa2CEdq
Start Time: Tue, 21 Jul 2026 20:38:26 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Created Time: Tue, 21 Jul 2026 20:37:27 MDT
Duration (Seconds): 668.189869
End Time: Tue, 21 Jul 2026 20:48:35 MDT
ID: cr_6pZAbuckJ7
Start Time: Tue, 21 Jul 2026 20:37:27 MDT
Updated Time: Tue, 21 Jul 2026 20:48:35 MDT
Recording State:
Storage State: synced
Note the Channel Recording (ID chr_an5EKM2EQu in this example). Downloading this recording would produces a .cast file, which can be played back locally using asciinema.
If you want to download this file, execute the following command:
$ boundary session-recordings download -id chr_an5EKM2EQu
BSR files
The Boundary Session Recording (BSR) file defines a hierarchical directory structure of files and a binary file format. It contains all the data transmitted between a user and a target during a single session.
Boundary stores the recordings within the Amazon S3 storage bucket as BSR files.
A BSR connections directory contains a summary of connections, as well as inbound and outbound requests. If you use a multiplexed protocol, there are subdirectories for the channels.
The asciicast format is well suited for the playback of interactive shell activity.
However, some aspects of the recording cannot be translated into asciicast.
For example, if an SSH session uses the RemoteCommand option, or is used to exec a command, the command is not displayed in the asciicast.
The output of the command may be displayed, though.
If you use SSH for something other than an interactive shell, such as for file transfer, X11 forwarding, or port forwarding, Boundary does not attempt to create an asciicast.
In all cases, the SSH session is still recorded in the BSR file and you can view the BSR file in the external storage bucket.
Cleanup and teardown
Destroy the Boundary resources. This step must be completed before tearing down the AWS environment.
From the Admin Console Web UI, destroy the following resources in the following order:
- Session recordings
- Targets
- Org scope (This deletes host catalogs and cred stores)
- Storage bucket
- Storage Policy
- Workers
You must delete all session recordings from the org before the storage bucket and org can be cleaned up.
Destroy the AWS resources.
Execute
make destroyto destroy the Terraform resources in AWS.$ make destroyUnset the environment variables used in any active terminal windows for this tutorial.
$ unset BOUNDARY_ADDR; \
unset BOUNDARY_AUTH_METHOD_ID; \
unset BOUNDARY_USERNAME; \
unset BOUNDARY_PASSWORD; \
unset HOST_CATALOG_ACCESS_KEY_ID; \
unset HOST_CATALOG_SECRET_ACCESS_KEY; \
unset AWS_REGION; \
unset AWS_ACCESS_KEY_ID; \
unset AWS_SECRET_ACCESS_KEY; \
unset VAULT_ADDR; \
unset VAULT_TOKEN; \
unset VAULT_CRED_STORE_TOKEN; \
unset recording_bucket_name; \
unset recording_storage_user_access_key_id; \
unset recording_storage_user_secret_access_key