summaryrefslogtreecommitdiffstats
path: root/doc/radosgw/vault.rst
blob: 0f3cb8fd12105ff7883e3493f973a310ccb015c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
===========================
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 necesary 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 settinsg 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
ceritificate 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 enviroments.

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 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 verisons. 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