Barbican – OpenStack密钥管理服务

云柯 873 0
对于那些不知道的人,Barbican是一个OpenStack服务,它提供REST API,用于安全存储,配置和管理密码,加密密钥和X.509证书等秘密。Barbican可以与其他OpenStack服务一起使用以提供安全功能,例如,Octavia使用Barbian来存储和检索用于创建启用TLS终止的侦听器的证书,Cinder使用Barbican进行卷加密,Magnum使用Barbican来存储Kubernetes CA证书等。在生产中部署Barbican最重要的事情是决定Barbican应使用哪种秘密商店解决方案。

秘密商店后端在巴比肯

  1. 加密插件加密插件将密钥存储为Barbican数据库中的加密blob。有两个可用的插件在管理密钥加密密钥(KEK)方面有所不同:
    • 简单的加密插件(测试目的),主加密密钥作为纯文本存储在配置文件中,用户的秘密作为加密的blob存储在barbican数据库中。它依赖于配置文件(或配置管理系统)的保护来保护秘密。
    • PKCS#11加密插件(维护得不好),用户的秘密由项目特定的密钥加密密钥(KEK)加密,密钥加密密钥(KEK)位于硬件安全模块(HSM)中。此选项可以提供额外的安全性,但由于需要HSM设备,因此价格昂贵。您还可以选择软件安全模块,例如SoftHSM,它是可通过PKCS#11接口访问的加密存储的软件实现。然而,目前SoftHSM中缺少一个关键的包装机制,目前它无法与Barbican一起使用。
  2. 秘密商店插件Secret store插件与安全存储系统接口,以存储这些系统中的秘密。秘密存储插件有三种类型:
    • KMIP插件此插件用于与支持KMIP的设备通信,例如硬件安全模块(HSM)。秘密直接安全地存储在KMIP设备中。需要KMIP设备。
    • Dogtag插件Dogtag是与红帽证书系统相对应的上游项目,红帽证书系统是一个强大的全功能PKI解决方案,包含证书管理器(CA)和密钥恢复机构(KRA),用于安全存储机密。KRA将秘密作为加密blob存储在其内部数据库中,主加密密钥存储在基于软件的网络安全服务(NSS)安全数据库或硬件安全模块(HSM)中。基于软件的NSS数据库配置为那些不希望使用或无法负担HSM的部署提供了安全选项。安装Dogtag需要Fedora / Centos系统。
    • Vault插件此插件用于与Harshicorp Vault进行通信,Harshicorp Vault是一个用于安全存储/访问机密的开源软件,但也提供了许多高级功能,如插件机制(auth后端,存储后端),审计功能,细粒度ACL规则,响应尽管Harshicorp提供企业级Vault,但开源版本功能丰富且可用于生产。

PKCS#11与KMIP的关系

PKCS#11是用于控制硬件安全模块的API。PKCS#11提供加密和解密的加密操作,以及简单密钥管理的操作。PKCS#11 API和KMIP协议之间存在相当大的重叠。

这两个标准最初是独立开发的。PKCS#11由RSA Security创建,但该标准现在也由OASIS技术委员会管理。PKCS#11和KMIP委员会的既定目标是在可行的情况下协调标准。例如,PKCS#11敏感和可提取属性将添加到KMIP 1.4版。许多同样的人都在KMIP和PKCS#11的技术委员会中。

巴比肯和卡斯特兰之间的关系

Castellan是一个奥斯陆图书馆,为不同的密钥管理系统(包括Barbican)提供不同的驱动程序,可用于各种OpenStack服务。总之,Castellan是一个图书馆,Barbican是一个云服务。

Barbican和Vault之间的关系

Actually, Vault can be definitely used in standalone mode, it provides CLI and HTTP API interface. However, as an OpenStack based cloud provider, Barbican is the first citizen in OpenStack world considering its integration with other OpenStack services and the consistent openstack CLI experience to interact with the service. Vault can be used as a secret store backend for Barbican.

Integrate Barbican with Vault

Install DevStack

user=ubuntu
group=ubuntu
git clone https://git.openstack.org/openstack-dev/devstack
sudo mkdir -p /opt/stack && sudo chown -R $group.$user /opt/stack && cd devstack
cat <<"EOF" > local.conf
[[local|localrc]]
RECLONE=False
MULTI_HOST=True
HOST_IP=

enable_plugin barbican https://git.openstack.org/openstack/barbican
LIBS_FROM_GIT+=python-barbicanclient
DATABASE_PASSWORD=password
ADMIN_PASSWORD=password
SERVICE_PASSWORD=password
SERVICE_TOKEN=password
RABBIT_PASSWORD=password
LOGFILE=$DEST/logs/stack.sh.log
VERBOSE=True
LOG_COLOR=False
LOGDAYS=1

ENABLED_SERVICES=rabbit,mysql,key

# Swift
ENABLED_SERVICES+=,swift
SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2000f5
SWIFT_REPLICAS=1
EOF
nic=$(sudo ip -4 route list 0/0 | awk '{ print $5; exit }'); echo $nic
nic_ip=$(sudo ip addr | awk "/inet / && /$nic/{print \$2; exit }" | awk -F '/' '{ print $1; exit }'); echo $nic_ip
sed -i "/HOST_IP=/c HOST_IP=$nic_ip"  ~/devstack/local.conf && cat ~/devstack/local.conf
./stack.sh

Now you have a DevStack environment with Barbican and Swift enabled, the Barbican service is running with the default configuration, we will change that later on.

Install vault

Vault is delivered as a go binary, in our test, we use Swift as the Vault storage backend.

sudo -s
cd ~; curl -SLO https://releases.hashicorp.com/vault/0.10.3/vault_0.10.3_linux_amd64.zip
unzip vault_0.10.3_linux_amd64.zip; mv vault /usr/local/bin/vault

nic=$(sudo ip -4 route list 0/0 | awk '{ print $5; exit }')
nic_ip=$(sudo ip addr | awk "/inet / && /$nic/{print \$2; exit }" | awk -F '/' '{ print $1; exit }')
mkdir -p /etc/vault && touch /etc/vault/config.hcl
cat<<EOF > /etc/vault/config.hcl
storage "swift" {
  auth_url          = "http://$node_ip/identity/v3"
  username          = "demo"
  password          = "password"
  project           = "demo"
  container         = "vault-storage"
  domain            = "default"
  project-domain    = "default"
  region            = "RegionOne"
}

listener "tcp" {
 address     = "$node_ip:8200"
 tls_disable = 1
}
EOF

We run the vault service in a linux screen so we don’t need to open another shell session for the following steps.

screen -dmS vault && screen -S vault -p bash -X stuff "vault server -config=/etc/vault/config.hcl\n"

Unseal vault

保管库服务运行后,它处于sealed状态且无法处理任何请求,需要初始化以准备保险库以接收数据。在初始化期间,Vault会生成内存中的主密钥,并应用Shamir的秘密共享算法将该主密钥反汇编为密钥共享的配置数,以便这些密钥共享的可配置子集必须聚集在一起以重新生成主密钥。这些密钥在Vault的文档中通常称为“unseal密钥”。

出于安全原因,我们不希望打印明文解封密钥。Vault支持使用GPG密钥文件,以便生成的密封密钥将按照参数中指定的顺序进行加密和base64编码-pgp-keys,只有具有私有GPG密钥的用户才能访问密封密钥。我们不在这里加密根令牌,因为根令牌应该在不再需要之后立即被撤销(例如在初始化过程之后)。可以根据需要使用unseal密钥重新生成根令牌。

export VAULT_ADDR="http://$node_ip:8200"
vault operator init -key-shares=3 -key-threshold=2 -pgp-keys=$HOME/user1_public.key,$HOME/user2_public.key,$HOME/user3_public.key > $HOME/unseal_info
root_token=$(cat $HOME/unseal_info | grep "Initial Root" | awk -F: '{print $2}')

现在,启封保管库应该是手动过程,具有正确GPG私钥的用户可以在可以连接到保管库服务器的任何主机上执行解封操作。至少应由-key-threshold少数用户运行以下步骤。

echo $key_b64 | base64 -d | gpg --decrypt
vault operator unseal $key

在最后一个用户运行unseal命令后,Vault服务器将处于unseal状态并可以接收请求。

为Barbican生成令牌

Barbican与Vault交互时需要一个令牌,显然,令牌不应该是具有在Vault中执行所有操作的权限的根令牌。我们需要将令牌权限限制为Barbican所做的操作范围,我们还需要保证在Barbican配置文件被泄露的情况下可以轻松撤销和重新生成令牌。此外,令牌应仅用于运行Barbican服务的主机上。

为了解决这里的所有问题,我们使用approle来生成临时令牌。

vault login $root_token
vault auth enable approle
cat <<EOF > /etc/vault/policy_secret.hcl
path "secret/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
EOF
vault policy write policy_secret /etc/vault/policy_secret.hcl
vault write auth/approle/role/barbican \
    local_secret_ids=true \
    period=10080m \
    policies=policy_secret \
    secret_id_bound_cidrs="$node_ip/32" \
    secret_id_num_uses=5 \
    secret_id_ttl=30m \
    token_bound_cidrs="$node_ip/32"
role_id=$(vault read -format=yaml auth/approle/role/barbican/role-id | grep role_id | awk '{print $2}')
secret_id=$(vault write -format=yaml auth/approle/role/barbican/secret-id -force=true | grep 'secret_id:' | awk '{print $2}')
token=$(vault write -format=yaml auth/approle/login role_id=$role_id secret_id=$secret_id | grep 'token:' | awk '{print $2}')

配置巴比肯

在Vault服务器初始化和配置完成后,我们需要更改Barbican的秘密存储后端并配置Vault服务器连接信息。

cat <<EOF >> /etc/barbican/barbican.conf
[secretstore]
namespace=barbican.secretstore.plugin
enable_multiple_secret_stores=false
enabled_secretstore_plugins=vault_plugin

[vault_plugin]
root_token_id = $token
vault_url = http://$node_ip:8200
use_ssl = False
EOF
systemctl restart devstack@barbican-svc.service

验证

在Barbican中创建一个秘密,检查它是否存储在Vault中。

$ openstack secret store --name test --payload "my secret"
+---------------+------------------------------------------------------------------------------+
| Field         | Value                                                                        |
+---------------+------------------------------------------------------------------------------+
| Secret href   | http://10.0.0.12/key-manager/v1/secrets/a0941786-d3c6-4955-b8b7-ef755afd908f |
| Name          | test                                                                         |
| Created       | None                                                                         |
| Status        | None                                                                         |
| Content types | None                                                                         |
| Algorithm     | aes                                                                          |
| Bit length    | 256                                                                          |
| Secret type   | opaque                                                                       |
| Mode          | cbc                                                                          |
| Expiration    | None                                                                         |
+---------------+------------------------------------------------------------------------------+

从Barbican secret到Vault secret的映射信息存储在Barbican数据库中。

mysql> select * from secret_store_metadata where secret_id='a0941786-d3c6-4955-b8b7-ef755afd908f';
+--------------------------------------+---------------------+---------------------+------------+---------+---------+--------------------------------------+--------------+-----------------------------------------------------+
| id                                   | created_at          | updated_at          | deleted_at | deleted | status  | secret_id                            | key          | value                                               |
+--------------------------------------+---------------------+---------------------+------------+---------+---------+--------------------------------------+--------------+-----------------------------------------------------+
| 66e0bf82-101a-4019-857d-5e914e6db8bc | 2018-07-15 12:33:01 | 2018-07-15 12:33:01 | NULL       |       0 | PENDING | a0941786-d3c6-4955-b8b7-ef755afd908f | key_id       | 4df3293c0e57479fafd5c71204ff2abd                    |
+--------------------------------------+---------------------+---------------------+------------+---------+---------+--------------------------------------+--------------+-----------------------------------------------------+

价值key_id4df3293c0e57479fafd5c71204ff2abd。检查密钥是否存储在Vault中:

$ vault login $token
$ vault read secret/4df3293c0e57479fafd5c71204ff2abd
Key                 Value
---                 -----
refresh_interval    768h
algorithm           <nil>
bit_length          <nil>
created             <nil>
name                <nil>
type                opaque
value               62586b676332566a636d5630
$ python
>>> import binascii
>>> binascii.unhexlify("62586b676332566a636d5630")
'bXkgc2VjcmV0'
$ echo "bXkgc2VjcmV0" | base64 -d
my secret

您还可以查看Swift中存储对象的方式。

打赏
发表评论 取消回复
表情 图片 链接 代码

分享
微信
微博
QQ