인터페이스는 현지화되어 있으며, Skill 소개와 설명 문서는 선택한 언어로 AI가 자동 번역합니다. 코드·명령어·경로·전문 용어는 원문을 유지하며 원작자 문서가 우선합니다.
Skills 둘러보기
생산성 및 협업 · SKILL.md

implementing-zero-trust-with-hashicorp-boundary

implementing-zero-trust-with-hashicorp-boundary

使用 HashiCorp Boundary 实现具备动态凭据代理、会话录制和 Vault 集成的身份感知零信任基础设施访问管理。

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill 문서

GitHub

name: implementing-zero-trust-with-hashicorp-boundary description: 使用 HashiCorp Boundary 实现具备动态凭据代理、会话录制和 Vault 集成的身份感知零信任基础设施访问管理。 domain: cybersecurity subdomain: zero-trust-architecture tags: [zero-trust, hashicorp, boundary, privileged-access, vault, identity-aware-proxy, session-recording, just-in-time-access] version: "1.0" author: mahipal license: Apache-2.0

使用 HashiCorp Boundary 实施零信任

概述

HashiCorp Boundary 是一款身份感知代理(Identity-Aware Proxy),无需传统 VPN 或直接网络访问即可提供对基础设施资源的安全零信任访问。Boundary 采用默认拒绝模型——用户初始没有任何访问权限,必须为特定资源显式授予权限。与 HashiCorp Vault 集成后,Boundary 可以动态代理凭据,确保用户无需查看或管理底层机密。这消除了凭据扩散问题,并支持即时访问(Just-in-Time Access)及会话结束时自动撤销凭据。Boundary 支持会话录制用于审计合规,支持 OIDC/LDAP 认证,并通过组织和项目的分层作用域模型管理访问权限。

前置条件

  • HashiCorp Boundary 服务器(自托管或 HCP Boundary)
  • HashiCorp Vault(用于凭据代理)
  • 支持 OIDC 的身份提供商(Okta、Azure AD、Auth0)
  • 作为 Boundary 后端的 PostgreSQL 数据库
  • 用于安全通信的 TLS 证书
  • 了解 PKI 和 X.509 证书管理

架构

                    身份提供商(OIDC)
                           |
                        认证
                           |
                  +--------+--------+
                  |   Boundary      |
                  |   控制器        |
                  |  (控制平面)   |
                  +--------+--------+
                           |
              +------------+------------+
              |                         |
     +--------+--------+      +--------+--------+
     | Boundary Worker |      | Boundary Worker |
     |   (数据平面)  |      |   (数据平面)  |
     +--------+--------+      +--------+--------+
              |                         |
     +--------+--------+      +--------+--------+
     |   目标主机      |      |   目标主机      |
     |  (SSH、RDP、   |      |  (数据库、     |
     |   K8s、HTTP)   |      |   API)         |
     +-----------------+      +-----------------+

     Vault(凭据代理)
     - 动态数据库凭据
     - SSH 证书签名
     - 凭据库

安装与配置

Boundary 服务器安装

# 安装 Boundary
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install boundary

# 初始化数据库
boundary database init \
  -config=/etc/boundary/controller.hcl

# 启动控制器
boundary server -config=/etc/boundary/controller.hcl

控制器配置

# /etc/boundary/controller.hcl
controller {
  name = "boundary-controller-1"
  description = "Primary Boundary Controller"
  database {
    url = "postgresql://boundary:password@localhost:5432/boundary?sslmode=require"
  }
  public_cluster_addr = "boundary.example.com"
}

listener "tcp" {
  address = "0.0.0.0:9200"
  purpose = "api"
  tls_cert_file = "/etc/boundary/tls/cert.pem"
  tls_key_file  = "/etc/boundary/tls/key.pem"
}

listener "tcp" {
  address = "0.0.0.0:9201"
  purpose = "cluster"
  tls_cert_file = "/etc/boundary/tls/cert.pem"
  tls_key_file  = "/etc/boundary/tls/key.pem"
}

kms "aead" {
  purpose = "root"
  aead_type = "aes-gcm"
  key = "sP1fnF5Xz85RrXM..."  # 生产环境使用 Vault Transit
  key_id = "global_root"
}

kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEG..."
  key_id = "global_worker-auth"
}

kms "aead" {
  purpose = "recovery"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEG..."
  key_id = "global_recovery"
}

Worker 配置

# /etc/boundary/worker.hcl
worker {
  name = "boundary-worker-1"
  description = "Worker in production VPC"
  public_addr = "worker1.example.com"

  controllers = [
    "boundary.example.com:9201"
  ]

  tags {
    type = ["production"]
    region = ["us-east-1"]
  }
}

listener "tcp" {
  address = "0.0.0.0:9202"
  purpose = "proxy"
}

kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEG..."
  key_id = "global_worker-auth"
}

Terraform 配置

作用域和认证配置

# main.tf - 通过 Terraform 管理 Boundary 资源
terraform {
  required_providers {
    boundary = {
      source  = "hashicorp/boundary"
      version = "~> 1.1"
    }
  }
}

provider "boundary" {
  addr             = "https://boundary.example.com:9200"
  recovery_kms_hcl = file("recovery_kms.hcl")
}

# 组织作用域
resource "boundary_scope" "org" {
  scope_id                 = "global"
  name                     = "production-org"
  description              = "生产组织作用域"
  auto_create_admin_role   = true
  auto_create_default_role = true
}

# 项目作用域
resource "boundary_scope" "production" {
  name                     = "production"
  description              = "生产基础设施项目"
  scope_id                 = boundary_scope.org.id
  auto_create_admin_role   = true
  auto_create_default_role = true
}

# OIDC 认证方法(Okta 示例)
resource "boundary_auth_method_oidc" "okta" {
  scope_id               = boundary_scope.org.id
  name                   = "okta"
  description            = "Okta OIDC 认证"
  issuer                 = "https://company.okta.com/oauth2/default"
  client_id              = var.okta_client_id
  client_secret          = var.okta_client_secret
  signing_algorithms     = ["RS256"]
  api_url_prefix         = "https://boundary.example.com:9200"
  claims_scopes          = ["groups"]
  account_claim_maps     = ["oid=sub"]
  is_primary_for_scope   = true
}

# 用于自动分配的托管组
resource "boundary_managed_group" "sre_team" {
  auth_method_id = boundary_auth_method_oidc.okta.id
  name           = "sre-team"
  description    = "来自 Okta 的 SRE 团队成员"
  filter         = "\"sre-team\" in \"/token/groups\""
}

resource "boundary_managed_group" "dev_team" {
  auth_method_id = boundary_auth_method_oidc.okta.id
  name           = "dev-team"
  description    = "来自 Okta 的开发团队"
  filter         = "\"dev-team\" in \"/token/groups\""
}

主机目录和访问目标

# 已知基础设施的静态主机目录
resource "boundary_host_catalog_static" "production_servers" {
  name     = "production-servers"
  scope_id = boundary_scope.production.id
}

resource "boundary_host_static" "web_server" {
  name            = "web-server-1"
  host_catalog_id = boundary_host_catalog_static.production_servers.id
  address         = "10.0.1.10"
}

resource "boundary_host_static" "db_server" {
  name            = "db-server-1"
  host_catalog_id = boundary_host_catalog_static.production_servers.id
  address         = "10.0.2.20"
}

# 主机集分组
resource "boundary_host_set_static" "web_servers" {
  name            = "web-servers"
  host_catalog_id = boundary_host_catalog_static.production_servers.id
  host_ids        = [boundary_host_static.web_server.id]
}

resource "boundary_host_set_static" "db_servers" {
  name            = "database-servers"
  host_catalog_id = boundary_host_catalog_static.production_servers.id
  host_ids        = [boundary_host_static.db_server.id]
}

# SSH 访问目标
resource "boundary_target" "ssh_production" {
  name         = "ssh-production-servers"
  description  = "生产服务器 SSH 访问"
  type         = "ssh"
  scope_id     = boundary_scope.production.id
  default_port = 22

  host_source_ids = [
    boundary_host_set_static.web_servers.id
  ]

  session_max_seconds          = 3600  # 最大会话时长 1 小时
  session_connection_limit     = 1
  enable_session_recording     = true
  storage_bucket_id            = boundary_storage_bucket.sessions.id

  injected_application_credential_source_ids = [
    boundary_credential_library_vault_ssh_certificate.ssh_cert.id
  ]
}

# 使用 Vault 凭据代理的数据库访问目标
resource "boundary_target" "postgres_production" {
  name         = "postgres-production"
  description  = "PostgreSQL 生产数据库"
  type         = "tcp"
  scope_id     = boundary_scope.production.id
  default_port = 5432

  host_source_ids = [
    boundary_host_set_static.db_servers.id
  ]

  session_max_seconds      = 1800  # 最大 30 分钟
  session_connection_limit = 5

  brokered_credential_source_ids = [
    boundary_credential_library_vault.postgres_creds.id
  ]
}

Vault 集成凭据代理

# Vault 凭据存储
resource "boundary_credential_store_vault" "vault" {
  name        = "vault-store"
  scope_id    = boundary_scope.production.id
  address     = "https://vault.example.com:8200"
  token       = var.vault_token
  namespace   = "production"
}

# 来自 Vault 的动态数据库凭据
resource "boundary_credential_library_vault" "postgres_creds" {
  name                = "postgres-dynamic-creds"
  credential_store_id = boundary_credential_store_vault.vault.id
  path                = "database/creds/readonly"
  http_method         = "GET"
  credential_type     = "username_password"
}

# 通过 Vault 签发 SSH 证书
resource "boundary_credential_library_vault_ssh_certificate" "ssh_cert" {
  name                = "ssh-certificate"
  credential_store_id = boundary_credential_store_vault.vault.id
  path                = "ssh-client-signer/sign/production"
  username            = "admin"
  key_type            = "ed25519"
  key_bits            = 256
  extensions = {
    "permit-pty" = ""
  }
}

# 会话录制存储
resource "boundary_storage_bucket" "sessions" {
  name        = "session-recordings"
  scope_id    = "global"
  plugin_name = "aws"
  bucket_name = "boundary-session-recordings"
  attributes_json = jsonencode({
    "region"                      = "us-east-1"
    "disable_credential_rotation" = true
  })
  secrets_json = jsonencode({
    "access_key_id"     = var.aws_access_key
    "secret_access_key" = var.aws_secret_key
  })
}

基于角色的访问控制

# SRE 团队角色 - 完整生产访问权限
resource "boundary_role" "sre_production" {
  name          = "sre-production-access"
  scope_id      = boundary_scope.production.id
  grant_strings = [
    "ids=*;type=target;actions=list,read,authorize-session",
    "ids=*;type=session;actions=list,read,cancel",
    "ids=*;type=host;actions=list,read",
  ]
  principal_ids = [
    boundary_managed_group.sre_team.id
  ]
}

# 开发团队角色 - 受限访问
resource "boundary_role" "dev_staging" {
  name          = "dev-staging-access"
  scope_id      = boundary_scope.production.id
  grant_strings = [
    "ids=${boundary_target.ssh_production.id};type=target;actions=read,authorize-session",
  ]
  principal_ids = [
    boundary_managed_group.dev_team.id
  ]
}

连接到访问目标

# 通过 OIDC 认证
boundary authenticate oidc \
  -auth-method-id amoidc_xxxxx

# 列出可用访问目标
boundary targets list -scope-id p_xxxxx

# 连接到 SSH 目标(Vault 注入凭据)
boundary connect ssh \
  -target-id ttcp_xxxxx

# 连接到数据库(Vault 代理凭据)
boundary connect postgres \
  -target-id ttcp_xxxxx \
  -dbname production

# 使用 Boundary Desktop 客户端进行 GUI 访问
# 下载地址:https://developer.hashicorp.com/boundary/install

会话录制与审计

# 列出会话录制
boundary session-recordings list \
  -scope-id p_xxxxx

# 下载会话录制用于审查
boundary session-recordings download \
  -id sr_xxxxx \
  -output recording.cast

# 使用 asciinema 回放
asciinema play recording.cast

动态主机目录

# AWS 动态主机目录 - 自动发现 EC2 实例
resource "boundary_host_catalog_plugin" "aws_catalog" {
  scope_id    = boundary_scope.production.id
  name        = "aws-production"
  plugin_name = "aws"

  attributes_json = jsonencode({
    "region"                      = "us-east-1"
    "disable_credential_rotation" = true
  })

  secrets_json = jsonencode({
    "access_key_id"     = var.aws_access_key
    "secret_access_key" = var.aws_secret_key
  })
}

resource "boundary_host_set_plugin" "web_tier" {
  host_catalog_id = boundary_host_catalog_plugin.aws_catalog.id
  name            = "web-tier"
  attributes_json = jsonencode({
    "filters" = [
      "tag:Environment=production",
      "tag:Tier=web"
    ]
  })
}

安全最佳实践

  1. 使用 Vault KMS 进行密钥管理:生产环境避免使用静态 AEAD 密钥
  2. 为所有特权访问目标启用会话录制
  3. 根据资源敏感程度设置会话时间限制
  4. 使用 OIDC 托管组:实现从 IdP 自动分配角色
  5. 部署多跳 Worker:用于跨网络边界访问资源
  6. 定期轮换凭据存储使用的 Vault 令牌
  7. 在控制器和 Worker 上启用审计日志
  8. 优先使用凭据注入(SSH 证书)而非凭据代理
  9. 实施最小权限授权:避免使用通配符权限
  10. 定期审查会话录制:用于合规和事件响应

参考资料

저장한 Skills