From e8ff0464d4ee2c418a119c03df3d313f3769ffdb Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Mon, 25 Jan 2021 20:49:16 -0500 Subject: [PATCH] rgw/kms/vault - s3tests for both old and new test logic. Test both "old" and "new" transit logic with s3tests. Does not test migration - that will need to be done separately. I've added a "flavor" parameter so the test logic can tell the difference between the "old" engine and the "new" engine. The vault keys creation logic now has options to determine whether the keys created are exportable (needed for the old transit engine), or not (should be the case going forward with the new transit engine.) Fixes: http://tracker.ceph.com/issues/48746 Signed-off-by: Marcus Watts --- qa/suites/rgw/crypt/2-kms/vault_old.yaml | 24 ++++++++++++++ qa/suites/rgw/crypt/2-kms/vault_transit.yaml | 2 +- qa/suites/rgw/crypt/4-tests/s3tests.yaml | 5 ++- qa/tasks/rgw.py | 1 + qa/tasks/s3tests.py | 15 +++++++-- qa/tasks/vault.py | 34 ++++++++++++++++---- 6 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 qa/suites/rgw/crypt/2-kms/vault_old.yaml diff --git a/qa/suites/rgw/crypt/2-kms/vault_old.yaml b/qa/suites/rgw/crypt/2-kms/vault_old.yaml new file mode 100644 index 00000000000..4befc1ecf8a --- /dev/null +++ b/qa/suites/rgw/crypt/2-kms/vault_old.yaml @@ -0,0 +1,24 @@ +overrides: + ceph: + conf: + client: + rgw crypt s3 kms backend: vault + rgw crypt vault auth: token + rgw crypt vault secret engine: transit + rgw crypt vault prefix: /v1/transit/export/encryption-key/ + rgw: + client.0: + use-vault-role: client.0 + +tasks: +- vault: + client.0: + install_url: https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_linux_amd64.zip + install_sha256: 7725b35d9ca8be3668abe63481f0731ca4730509419b4eb29fa0b0baa4798458 + root_token: test_root_token + engine: transit + flavor: old + prefix: /v1/transit/keys/ + secrets: + - path: my-key-1 + - path: my-key-2 diff --git a/qa/suites/rgw/crypt/2-kms/vault_transit.yaml b/qa/suites/rgw/crypt/2-kms/vault_transit.yaml index 775f546dee2..fe8c8409dbe 100644 --- a/qa/suites/rgw/crypt/2-kms/vault_transit.yaml +++ b/qa/suites/rgw/crypt/2-kms/vault_transit.yaml @@ -5,7 +5,7 @@ overrides: rgw crypt s3 kms backend: vault rgw crypt vault auth: token rgw crypt vault secret engine: transit - rgw crypt vault prefix: /v1/transit/export/encryption-key/ + rgw crypt vault prefix: /v1/transit/ rgw: client.0: use-vault-role: client.0 diff --git a/qa/suites/rgw/crypt/4-tests/s3tests.yaml b/qa/suites/rgw/crypt/4-tests/s3tests.yaml index 9f52fee08e0..791528508a0 100644 --- a/qa/suites/rgw/crypt/4-tests/s3tests.yaml +++ b/qa/suites/rgw/crypt/4-tests/s3tests.yaml @@ -8,6 +8,9 @@ tasks: vault_kv: key_path: my-key-1 key_path2: my-key-2 - vault_transit: + vault_old: key_path: my-key-1/1 key_path2: my-key-2/1 + vault_transit: + key_path: my-key-1 + key_path2: my-key-2 diff --git a/qa/tasks/rgw.py b/qa/tasks/rgw.py index dc87631f919..49b99819e24 100644 --- a/qa/tasks/rgw.py +++ b/qa/tasks/rgw.py @@ -133,6 +133,7 @@ def start_rgw(ctx, config, clients): if not ctx.vault.root_token: raise ConfigError('vault: no "root_token" specified') # create token on file + ctx.rgw.vault_role = vault_role ctx.cluster.only(client).run(args=['echo', '-n', ctx.vault.root_token, run.Raw('>'), token_path]) log.info("Token file content") ctx.cluster.only(client).run(args=['cat', token_path]) diff --git a/qa/tasks/s3tests.py b/qa/tasks/s3tests.py index f80e9954ee6..302ead5e2ad 100644 --- a/qa/tasks/s3tests.py +++ b/qa/tasks/s3tests.py @@ -324,9 +324,18 @@ def configure(ctx, config): s3tests_conf['DEFAULT']['kms_keyid2'] = key['id'] elif hasattr(ctx, 'vault'): - properties = properties['vault_%s' % ctx.vault.engine] - s3tests_conf['DEFAULT']['kms_keyid'] = properties['key_path'] - s3tests_conf['DEFAULT']['kms_keyid2'] = properties['key_path2'] + engine_or_flavor = vars(ctx.vault).get('flavor',ctx.vault.engine) + keys=[] + for name in (x['Path'] for x in vars(ctx.vault).get('keys', {}).get(ctx.rgw.vault_role)): + keys.append(name) + + keys.extend(['testkey-1','testkey-2']) + if engine_or_flavor == "old": + keys=[keys[i] + "/1" for i in range(len(keys))] + + properties = properties.get('vault_%s' % engine_or_flavor, {}) + s3tests_conf['DEFAULT']['kms_keyid'] = properties.get('key_path', keys[0]) + s3tests_conf['DEFAULT']['kms_keyid2'] = properties.get('key_path2', keys[1]) elif hasattr(ctx.rgw, 'pykmip_role'): keys=[] for name in (x['Name'] for x in ctx.pykmip.keys[ctx.rgw.pykmip_role]): diff --git a/qa/tasks/vault.py b/qa/tasks/vault.py index c204cf8f462..2ff008c4dbe 100644 --- a/qa/tasks/vault.py +++ b/qa/tasks/vault.py @@ -185,14 +185,17 @@ def create_secrets(ctx, config): engine = cconfig.get('engine') prefix = cconfig.get('prefix') secrets = cconfig.get('secrets') + flavor = cconfig.get('flavor') if secrets is None: raise ConfigError("No secrets specified, please specify some.") + ctx.vault.keys[cclient] = [] for secret in secrets: try: path = secret['path'] except KeyError: raise ConfigError('Missing "path" field in secret') + exportable = secret.get("exportable", flavor == "old") if engine == 'kv': try: @@ -204,12 +207,14 @@ def create_secrets(ctx, config): except KeyError: raise ConfigError('Missing "secret" field in secret') elif engine == 'transit': - data = {"exportable": "true"} + data = {"exportable": "true" if exportable else "false"} else: raise Exception("Unknown or missing secrets engine") send_req(ctx, cconfig, cclient, urljoin(prefix, path), json.dumps(data)) + ctx.vault.keys[cclient].append({ 'Path': path }); + log.info("secrets created") yield @@ -224,15 +229,28 @@ def task(ctx, config): tasks: - vault: client.0: - version: 1.2.2 + install_url: http://my.special.place/vault.zip + install_sha256: zipfiles-sha256-sum-much-larger-than-this root_token: test_root_token - engine: kv - prefix: /v1/kv/data/ + engine: transit + flavor: old + prefix: /v1/transit/keys secrets: - path: kv/teuthology/key_a - secret: YmluCmJvb3N0CmJvb3N0LWJ1aWxkCmNlcGguY29uZgo= + secret: base64_only_if_using_kv_aWxkCmNlcGguY29uZgo= + exportable: true - path: kv/teuthology/key_b - secret: aWIKTWFrZWZpbGUKbWFuCm91dApzcmMKVGVzdGluZwo= + secret: base64_only_if_using_kv_dApzcmMKVGVzdGluZwo= + + engine can be 'kv' or 'transit' + prefix should be /v1/kv/data/ for kv, /v1/transit/keys/ for transit + flavor should be 'old' only if testing the original transit logic + otherwise omit. + for kv only: 256-bit key value should be specified via secret, + otherwise should omit. + for transit: exportable may be used to make individual keys exportable. + flavor may be set to 'old' to make all keys exportable by default, + which is required by the original transit logic. """ all_clients = ['client.{id}'.format(id=id_) for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')] @@ -255,6 +273,10 @@ def task(ctx, config): ctx.vault.root_token = None ctx.vault.prefix = config[client].get('prefix') ctx.vault.engine = config[client].get('engine') + ctx.vault.keys = {} + q=config[client].get('flavor') + if q: + ctx.vault.flavor = q with contextutil.nested( lambda: download(ctx=ctx, config=config), -- 2.39.5