Skip to content

devops-rob/vault-plugin-boundary-secrets-engine

Repository files navigation

Boundary Secrets Engine for HashiCorp Vault

The Boundary secrets engine creates Boundary Workers, and additionally, generates user and account credentials dynamically based on configured permissions and scopes. This means that services that need to access a Boundary scope no longer need to hardcode credentials and Boundary workers can be ephemeral.

With every service accessing Boundary with unique credentials, auditing is much easier in threat modelled scenarios.

Vault makes use both of its own internal revocation system to delete Boundary users and accounts when generating Boundary credentials to ensure that users and accounts become invalid within a reasonable time of the lease expiring.

Additionally, Vault can remove workers that it has created, thereby removing the controller led auth token

Setup for User credentials

Most secrets engines must be configured in advance before they can perform their functions. These steps are usually completed by an operator or configuration management tool.

  1. Enable secrets engine:
vault secrets enable boundary

By default, the secrets engine will mount at the name of the engine. To enable the secrets engine at a different path, use the -path argument.

  1. Configure the credentials that Vault uses to communicate with Boundary to generate credentials:
vault write boundary/config \
  addr=http://localhost:9200 \
  login_name=admin \
  password=password \
  auth_method_id=ampw_1234567890

It is important that the Vault user have the permissions to manage users and accounts at all scope levels.

  1. Configure a role that maps a name in Vault to a Boundary scope and roles:
vault write boundary/role/my-role \
  ttl=180 \
  max_ttl=360 \
  auth_method_id=ampw_1234567890 \
  boundary_roles=r_cwRmglckUr \
  role_type=user \
  scope_id=global
  

By writing to the roles/my-role path we are defining the my-role role. This role will be created by evaluating the given auth_method_id, boundary_roles, scope_id, ttl and max_ttl statements. Credentials generated against this role will be created at the specified scope, using the specified auth method, and will have the specified boundary roles assigned for the duration of the ttl specified. You can read more about Boundary's Identity and Access Management domain.

Usage

After the secrets engine is configured and a user/machine has a Vault token with the proper permission, it can generate credentials.

  1. Generate a new credential by reading from the /creds endpoint with the name of the role:
vault read boundary/creds/my-role

Worker auth tokens

Configuring a worker role is slightly different to a user role. The example below shows a worker role being configured:

vault write boundary/role/worker \
  ttl=180 \
  max_ttl=360 \
  role_type=worker \
  scope_id=global

A worker can then be generated using the following command:

vault read boundary/creds/worker worker_name="local worker"

An optional description can be added to the worker using the description parameter.

vault read boundary/creds/worker worker_name="local worker" description="Local worker for testing purposes"

API

Setup

  1. Enable secrets engine

Sample request

curl \
    -X POST \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/sys/mounts

Sample payload

{
    "type": "boundary"
}
  1. Configure the credentials that Vault uses to communicate with Boundary to generate credentials:

Sample request

curl \
    -X POST \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/boundary/config

Sample payload

{
  "addr": "http://localhost:9200",
  "login_name": "vault-admin",
  "password": "...",
  "auth_method_id": "ampw_1234567890"
}
  1. Configure a role that maps a name in Vault to a Boundary scope and roles:

Sample request

curl \
    -X POST \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/boundary/role/my-role

Sample payload

{
    "ttl": 180,
    "max_ttl": 360,
    "auth_method_id": "ampw_1234567890",
    "credential_type": "userpass",
    "boundary_roles": "r_cbvEFZbN1S,r_r8mxdp7zOp",
    "role_type": "user",
    "scope_id": "global"
}

Usage

  1. Generate a new credential by reading from the /creds endpoint with the name of the role:

Sample request

curl \
    -X GET \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/boundary/creds/my-role

Sample response

{
    "request_id": "ed281bc6-182d-a15e-d700-8c2e64897010",
    "lease_id": "boundary/creds/my-role/pH9CfQcAmE9va6CwQKOEPBsx",
    "renewable": true,
    "lease_duration": 180,
    "data": {
        "account_id": "acctpw_Haufl3nWxH",
        "auth_method_id": "ampw_1234567890",
        "boundary_roles": "r_CSuslu0w1X,r_S0OqRsecY6",
        "login_name": "vault-role-my-role-fudjntgy",
        "password": "2QW7U03mXr614895",
        "user_id": "u_sKom7Pxa1v"
    },
    "wrap_info": null,
    "warnings": null,
    "auth": null
}

Terraform

Setup

  1. Enable secrets engine:
resource "vault_mount" "boundary" {
  path        = "boundary"
  type        = "boundary"
  description = "This is the boundary secrets engine"
}
  1. Configure the credentials that Vault uses to communicate with Boundary to generate credentials:
resource "vault_generic_endpoint" "boundary_config" {
  depends_on           = [
    vault_mount.boundary
  ]
  
  path                 = "boundary/config"
  ignore_absent_fields = true

  data_json = <<EOT
{
  "addr": "http://localhost:9200",
  "login_name": "vault-admin",
  "password": "...",
  "auth_method_id": "ampw_1234567890"
}
EOT
}
  1. Configure a role that maps a name in Vault to a Boundary scope and roles:
resource "vault_generic_endpoint" "boundary_role" {
  depends_on           = [
    vault_mount.boundary
  ]
  
  path                 = "boundary/role/my-role"
  ignore_absent_fields = true

  data_json = <<EOT
{
    "ttl": 180,
    "max_ttl": 360,
    "auth_method_id": "ampw_1234567890",
    "credential_type": "userpass",
    "boundary_roles": "r_cbvEFZbN1S,r_r8mxdp7zOp",
    "role_type": "user"
    "scope_id": "global"
}
EOT
}

Usage

  1. Generate a new credential by reading from the /creds endpoint with the name of the role:
data "vault_generic_secret" "boundary_creds" {
  path = "boundary/creds/my-role"
}

output "creds" {
  value     = data.vault_generic_secret.boundary_creds.data
  sensitive = true
}
  1. Read the output from Terraform's state file:
terraform output creds

Example response:

tomap({
  "account_id" = "acctpw_nNaPX7PYzl"
  "auth_method_id" = "ampw_1234567890"
  "boundary_roles" = "r_U2t8YBalKE,r_5hKAwk9Rs9"
  "login_name" = "vault-role-my-role-tewohlyv"
  "password" = "4Le8z639725g0f1G"
  "user_id" = "u_TxJs1IabfY"
})

License

Licensed under the Apache License, Version 2.0 (the "License").

You may obtain a copy of the License at apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, without WARRANTIES or conditions of any kind, either express or implied.

See the License for the specific language governing permissions and limitations under the License.

About

A Vault secrets engine that generates dynamic Boundary accounts

Resources

License

Stars

Watchers

Forks

Packages

No packages published