mirror of https://github.com/ceph/ceph
483 lines
16 KiB
ReStructuredText
483 lines
16 KiB
ReStructuredText
===========================
|
|
HashiCorp Vault Integration
|
|
===========================
|
|
|
|
HashiCorp `Vault`_ can be used as a secure key management service for
|
|
`Server-Side Encryption`_ (SSE-KMS).
|
|
|
|
.. ditaa::
|
|
|
|
+---------+ +---------+ +-------+ +-------+
|
|
| Client | | RadosGW | | Vault | | OSD |
|
|
+---------+ +---------+ +-------+ +-------+
|
|
| create secret | | |
|
|
| key for key ID | | |
|
|
|-----------------+---------------->| |
|
|
| | | |
|
|
| upload object | | |
|
|
| with key ID | | |
|
|
|---------------->| request secret | |
|
|
| | key for key ID | |
|
|
| |---------------->| |
|
|
| |<----------------| |
|
|
| | return secret | |
|
|
| | key | |
|
|
| | | |
|
|
| | encrypt object | |
|
|
| | with secret key | |
|
|
| |--------------+ | |
|
|
| | | | |
|
|
| |<-------------+ | |
|
|
| | | |
|
|
| | store encrypted | |
|
|
| | object | |
|
|
| |------------------------------>|
|
|
|
|
#. `Vault secrets engines`_
|
|
#. `Vault authentication`_
|
|
#. `Vault namespaces`_
|
|
#. `Create a key in Vault`_
|
|
#. `Configure the Ceph Object Gateway`_
|
|
#. `Upload object`_
|
|
|
|
Some examples below use the Vault command line utility to interact with
|
|
Vault. You may need to set the following environment variable with the correct
|
|
address of your Vault server to use this utility::
|
|
|
|
export VAULT_ADDR='https://vault-server-fqdn:8200'
|
|
|
|
Vault secrets engines
|
|
=====================
|
|
|
|
Vault provides several secrets engines, which can store, generate, and encrypt
|
|
data. Currently, the Object Gateway supports:
|
|
|
|
- `KV secrets engine`_ version 2
|
|
- `Transit engine`_
|
|
|
|
KV secrets engine
|
|
-----------------
|
|
|
|
The KV secrets engine is used to store arbitrary key/value secrets in Vault. To
|
|
enable the KV engine version 2 in Vault, use the following command::
|
|
|
|
vault secrets enable -path secret kv-v2
|
|
|
|
The Object Gateway can be configured to use the KV engine version 2 with the
|
|
following setting::
|
|
|
|
rgw crypt vault secret engine = kv
|
|
|
|
Transit secrets engine
|
|
----------------------
|
|
|
|
The transit engine handles cryptographic functions on data in-transit. To enable
|
|
it in Vault, use the following command::
|
|
|
|
vault secrets enable transit
|
|
|
|
The Object Gateway can be configured to use the transit engine with the
|
|
following setting::
|
|
|
|
rgw crypt vault secret engine = transit
|
|
|
|
Vault authentication
|
|
====================
|
|
|
|
Vault supports several authentication mechanisms. Currently, the Object
|
|
Gateway can be configured to authenticate to Vault using the
|
|
`Token authentication method`_ or a `Vault agent`_.
|
|
|
|
Most tokens in Vault have limited lifetimes and powers. The only
|
|
sort of Vault token that does not have a lifetime are root tokens.
|
|
For all other tokens, it is necessary to periodically refresh them,
|
|
either by performing initial authentication, or by renewing the token.
|
|
Ceph does not have any logic to perform either operation.
|
|
The simplest best way to use Vault tokens with ceph is to
|
|
also run the Vault agent and have it refresh the token file.
|
|
When the Vault agent is used in this mode, file system permissions
|
|
can be used to restrict who has the use of tokens.
|
|
|
|
Instead of having Vault agent refresh a token file, it can be told
|
|
to act as a proxy server. In this mode, Vault will add a token when
|
|
necessary and add it to requests passed to it before forwarding them on
|
|
to the real server. Vault agent will still handle token renewal just
|
|
as it would when storing a token in the filesystem. In this mode, it
|
|
is necessary to properly secure the network path rgw uses to reach the
|
|
Vault agent, such as having the Vault agent listen only to localhost.
|
|
|
|
Token policies for the object gateway
|
|
-------------------------------------
|
|
|
|
All Vault tokens have powers as specified by the polices attached
|
|
to that token. Multiple policies may be associated with one
|
|
token. You should only use the policy necessary for your
|
|
configuration.
|
|
|
|
When using the kv secret engine with the object gateway::
|
|
|
|
vault policy write rgw-kv-policy -<<EOF
|
|
path "secret/data/*" {
|
|
capabilities = ["read"]
|
|
}
|
|
EOF
|
|
|
|
When using the transit secret engine with the object gateway::
|
|
|
|
vault policy write rgw-transit-policy -<<EOF
|
|
path "transit/keys/*" {
|
|
capabilities = [ "create", "update" ]
|
|
denied_parameters = {"exportable" = [], "allow_plaintext_backup" = [] }
|
|
}
|
|
|
|
path "transit/keys/*" {
|
|
capabilities = ["read", "delete"]
|
|
}
|
|
|
|
path "transit/keys/" {
|
|
capabilities = ["list"]
|
|
}
|
|
|
|
path "transit/keys/+/rotate" {
|
|
capabilities = [ "update" ]
|
|
}
|
|
|
|
path "transit/*" {
|
|
capabilities = [ "update" ]
|
|
}
|
|
EOF
|
|
|
|
If you had previously used an older version of ceph with the
|
|
transit secret engine, you might need the following policy::
|
|
|
|
vault policy write old-rgw-transit-policy -<<EOF
|
|
path "transit/export/encryption-key/*" {
|
|
capabilities = ["read"]
|
|
}
|
|
EOF
|
|
|
|
|
|
Token authentication
|
|
--------------------
|
|
|
|
.. note: Never use root tokens with ceph in production environments.
|
|
|
|
The token authentication method expects a Vault token to be present in a
|
|
plaintext file. The Object Gateway can be configured to use token authentication
|
|
with the following settings::
|
|
|
|
rgw crypt vault auth = token
|
|
rgw crypt vault token file = /run/.rgw-vault-token
|
|
rgw crypt vault addr = https://vault-server-fqdn:8200
|
|
|
|
Adjust these settings to match your configuration.
|
|
For security reasons, the token file must be readable by the Object Gateway
|
|
only.
|
|
|
|
You might set up vault agent as follows::
|
|
|
|
vault write auth/approle/role/rgw-ap \
|
|
token_policies=rgw-transit-policy,default \
|
|
token_max_ttl=60m
|
|
|
|
Change the policy here to match your configuration.
|
|
|
|
Get the role-id::
|
|
|
|
vault read auth/approle/role/rgw-ap/role-id -format=json | \
|
|
jq -r .data.role_id
|
|
|
|
Store the output in some file, such as /usr/local/etc/vault/.rgw-ap-role-id
|
|
|
|
Get the secret-id::
|
|
|
|
vault read auth/approle/role/rgw-ap/role-id -format=json | \
|
|
jq -r .data.role_id
|
|
|
|
Store the output in some file, such as /usr/local/etc/vault/.rgw-ap-secret-id
|
|
|
|
Create configuration for the Vault agent, such as::
|
|
|
|
pid_file = "/run/rgw-vault-agent-pid"
|
|
auto_auth {
|
|
method "AppRole" {
|
|
mount_path = "auth/approle"
|
|
config = {
|
|
role_id_file_path ="/usr/local/etc/vault/.rgw-ap-role-id"
|
|
secret_id_file_path ="/usr/local/etc/vault/.rgw-ap-secret-id"
|
|
remove_secret_id_file_after_reading ="false"
|
|
}
|
|
}
|
|
sink "file" {
|
|
config = {
|
|
path = "/run/.rgw-vault-token"
|
|
}
|
|
}
|
|
}
|
|
vault {
|
|
address = "https://vault-server-fqdn:8200"
|
|
}
|
|
|
|
Then use systemctl or another method of your choice to run
|
|
a persistent daemon with the following arguments::
|
|
|
|
/usr/local/bin/vault agent -config=/usr/local/etc/vault/rgw-agent.hcl
|
|
|
|
Once the vault agent is running, the token file should be populated
|
|
with a valid token.
|
|
|
|
Vault agent
|
|
-----------
|
|
|
|
The Vault agent is a client daemon that provides authentication to Vault and
|
|
manages token renewal and caching. It typically runs on the same host as the
|
|
Object Gateway. With a Vault agent, it is possible to use other Vault
|
|
authentication mechanism such as AppRole, AWS, Certs, JWT, and Azure.
|
|
|
|
The Object Gateway can be configured to use a Vault agent with the following
|
|
settings::
|
|
|
|
rgw crypt vault auth = agent
|
|
rgw crypt vault addr = http://127.0.0.1:8100
|
|
|
|
You might set up vault agent as follows::
|
|
|
|
vault write auth/approle/role/rgw-ap \
|
|
token_policies=rgw-transit-policy,default \
|
|
token_max_ttl=60m
|
|
|
|
Change the policy here to match your configuration.
|
|
|
|
Get the role-id:
|
|
vault read auth/approle/role/rgw-ap/role-id -format=json | \
|
|
jq -r .data.role_id
|
|
|
|
Store the output in some file, such as /usr/local/etc/vault/.rgw-ap-role-id
|
|
|
|
Get the secret-id:
|
|
vault read auth/approle/role/rgw-ap/role-id -format=json | \
|
|
jq -r .data.role_id
|
|
|
|
Store the output in some file, such as /usr/local/etc/vault/.rgw-ap-secret-id
|
|
|
|
Create configuration for the Vault agent, such as::
|
|
|
|
pid_file = "/run/rgw-vault-agent-pid"
|
|
auto_auth {
|
|
method "AppRole" {
|
|
mount_path = "auth/approle"
|
|
config = {
|
|
role_id_file_path ="/usr/local/etc/vault/.rgw-ap-role-id"
|
|
secret_id_file_path ="/usr/local/etc/vault/.rgw-ap-secret-id"
|
|
remove_secret_id_file_after_reading ="false"
|
|
}
|
|
}
|
|
}
|
|
cache {
|
|
use_auto_auth_token = true
|
|
}
|
|
listener "tcp" {
|
|
address = "127.0.0.1:8100"
|
|
tls_disable = true
|
|
}
|
|
vault {
|
|
address = "https://vault-server-fqdn:8200"
|
|
}
|
|
|
|
Then use systemctl or another method of your choice to run
|
|
a persistent daemon with the following arguments::
|
|
|
|
/usr/local/bin/vault agent -config=/usr/local/etc/vault/rgw-agent.hcl
|
|
|
|
Once the vault agent is running, you should find it listening
|
|
to port 8100 on localhost, and you should be able to interact
|
|
with it using the vault command.
|
|
|
|
Vault namespaces
|
|
================
|
|
|
|
In the Enterprise version, Vault supports the concept of `namespaces`_, which
|
|
allows centralized management for teams within an organization while ensuring
|
|
that those teams operate within isolated environments known as tenants.
|
|
|
|
The Object Gateway can be configured to access Vault within a particular
|
|
namespace using the following configuration setting::
|
|
|
|
rgw crypt vault namespace = tenant1
|
|
|
|
Create a key in Vault
|
|
=====================
|
|
|
|
.. note:: Keys for server-side encryption must be 256-bit long and base-64
|
|
encoded.
|
|
|
|
Using the KV engine
|
|
-------------------
|
|
|
|
A key for server-side encryption can be created in the KV version 2 engine using
|
|
the command line utility, as in the following example::
|
|
|
|
vault kv put secret/myproject/mybucketkey key=$(openssl rand -base64 32)
|
|
|
|
Sample output::
|
|
|
|
====== Metadata ======
|
|
Key Value
|
|
--- -----
|
|
created_time 2019-08-29T17:01:09.095824999Z
|
|
deletion_time n/a
|
|
destroyed false
|
|
version 1
|
|
|
|
Note that in the KV secrets engine, secrets are stored as key-value pairs, and
|
|
the Gateway expects the key name to be ``key``, i.e. the secret must be in the
|
|
form ``key=<secret key>``.
|
|
|
|
Using the Transit engine
|
|
------------------------
|
|
|
|
Keys created for use with the Transit engine should no longer be marked
|
|
exportable. They can be created with::
|
|
|
|
vault write -f transit/keys/mybucketkey
|
|
|
|
The command above creates a keyring, which contains a key of type
|
|
``aes256-gcm96`` by default. To verify that the key was correctly created, use
|
|
the following command::
|
|
|
|
vault read transit/mybucketkey
|
|
|
|
Sample output::
|
|
|
|
Key Value
|
|
--- -----
|
|
derived false
|
|
exportable false
|
|
name mybucketkey
|
|
type aes256-gcm96
|
|
|
|
Configure the Ceph Object Gateway
|
|
=================================
|
|
|
|
Edit the Ceph configuration file to enable Vault as a KMS backend for
|
|
server-side encryption::
|
|
|
|
rgw crypt s3 kms backend = vault
|
|
|
|
Choose the Vault authentication method, e.g.::
|
|
|
|
rgw crypt vault auth = token
|
|
rgw crypt vault token file = /run/.rgw-vault-token
|
|
rgw crypt vault addr = https://vault-server-fqdn:8200
|
|
|
|
Or::
|
|
|
|
rgw crypt vault auth = agent
|
|
rgw crypt vault addr = http://localhost:8100
|
|
|
|
Choose the secrets engine::
|
|
|
|
rgw crypt vault secret engine = kv
|
|
|
|
Or::
|
|
|
|
rgw crypt vault secret engine = transit
|
|
|
|
Optionally, set the Vault namespace where encryption keys will be fetched from::
|
|
|
|
rgw crypt vault namespace = tenant1
|
|
|
|
Finally, the URLs where the Gateway will retrieve encryption keys from Vault can
|
|
be restricted by setting a path prefix. For instance, the Gateway can be
|
|
restricted to fetch KV keys as follows::
|
|
|
|
rgw crypt vault prefix = /v1/secret/data
|
|
|
|
Or, when using the transit secret engine::
|
|
|
|
rgw crypt vault prefix = /v1/transit
|
|
|
|
In the example above, the Gateway would only fetch transit encryption keys under
|
|
``https://vault-server:8200/v1/transit``.
|
|
|
|
You can use custom ssl certs to authenticate with vault with help of
|
|
following options::
|
|
|
|
rgw crypt vault verify ssl = true
|
|
rgw crypt vault ssl cacert = /etc/ceph/vault.ca
|
|
rgw crypt vault ssl clientcert = /etc/ceph/vault.crt
|
|
rgw crypt vault ssl clientkey = /etc/ceph/vault.key
|
|
|
|
where vault.ca is CA certificate and vault.key/vault.crt are private key and ssl
|
|
certificate generated for RGW to access the vault server. It highly recommended to
|
|
set this option true, setting false is very dangerous and need to avoid since this
|
|
runs in very secured environments.
|
|
|
|
Transit engine compatibility support
|
|
------------------------------------
|
|
The transit engine has compatibility support for previous
|
|
versions of ceph, which used the transit engine as a simple key store.
|
|
|
|
There is a "compat" option which can be given to the transit
|
|
engine to configure the compatibility support,
|
|
|
|
To entirely disable backwards support, use::
|
|
|
|
rgw crypt vault secret engine = transit compat=0
|
|
|
|
This will be the default in future versions. and is safe to use
|
|
for new installs using the current version.
|
|
|
|
This is the normal default with the current version::
|
|
|
|
rgw crypt vault secret engine = transit compat=1
|
|
|
|
This enables the new engine for newly created objects,
|
|
but still allows the old engine to be used for old objects.
|
|
In order to access old and new objects, the vault token given
|
|
to ceph must have both the old and new transit policies.
|
|
|
|
To force use of only the old engine, use::
|
|
|
|
rgw crypt vault secret engine = transit compat=2
|
|
|
|
This mode is automatically selected if the vault prefix
|
|
ends in export/encryption-key, which was the previously
|
|
documented setting.
|
|
|
|
Upload object
|
|
=============
|
|
|
|
When uploading an object to the Gateway, provide the SSE key ID in the request.
|
|
As an example, for the kv engine, using the AWS command-line client::
|
|
|
|
aws --endpoint=http://radosgw:8000 s3 cp plaintext.txt s3://mybucket/encrypted.txt --sse=aws:kms --sse-kms-key-id myproject/mybucketkey
|
|
|
|
As an example, for the transit engine (new flavor), using the AWS command-line client::
|
|
|
|
aws --endpoint=http://radosgw:8000 s3 cp plaintext.txt s3://mybucket/encrypted.txt --sse=aws:kms --sse-kms-key-id mybucketkey
|
|
|
|
The Object Gateway will fetch the key from Vault, encrypt the object and store
|
|
it in the bucket. Any request to download the object will make the Gateway
|
|
automatically retrieve the correspondent key from Vault and decrypt the object.
|
|
|
|
Note that the secret will be fetched from Vault using a URL constructed by
|
|
concatenating the base address (``rgw crypt vault addr``), the (optional)
|
|
URL prefix (``rgw crypt vault prefix``), and finally the key ID.
|
|
|
|
In the kv engine example above, the Gateway would fetch the secret from::
|
|
|
|
http://vaultserver:8200/v1/secret/data/myproject/mybucketkey
|
|
|
|
In the transit engine example above, the Gateway would encrypt the secret using this key::
|
|
|
|
http://vaultserver:8200/v1/transit/mybucketkey
|
|
|
|
.. _Server-Side Encryption: ../encryption
|
|
.. _Vault: https://www.vaultproject.io/docs/
|
|
.. _Token authentication method: https://www.vaultproject.io/docs/auth/token.html
|
|
.. _Vault agent: https://www.vaultproject.io/docs/agent/index.html
|
|
.. _KV Secrets engine: https://www.vaultproject.io/docs/secrets/kv/
|
|
.. _Transit engine: https://www.vaultproject.io/docs/secrets/transit
|
|
.. _namespaces: https://www.vaultproject.io/docs/enterprise/namespaces/index.html
|