Exemple #1
0
    def test_keys_cached(self):
        secrets = {None: os.urandom(32),
                   '22': os.urandom(33),
                   'my_secret_id': os.urandom(50)}
        conf = {}
        for secret_id, secret in secrets.items():
            opt = ('encryption_root_secret%s' %
                   (('_%s' % secret_id) if secret_id else ''))
            conf[opt] = base64.b64encode(secret)
        conf['active_root_secret_id'] = '22'
        self.app = keymaster.KeyMaster(self.swift, conf)
        orig_create_key = self.app.create_key
        calls = []

        def mock_create_key(path, secret_id=None):
            calls.append((path, secret_id))
            return orig_create_key(path, secret_id)

        context = keymaster.KeyMasterContext(self.app, 'a', 'c', 'o')
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys()
        expected_keys = {
            'container': hmac.new(secrets['22'], b'/a/c',
                                  digestmod=hashlib.sha256).digest(),
            'object': hmac.new(secrets['22'], b'/a/c/o',
                               digestmod=hashlib.sha256).digest(),
            'id': {'path': '/a/c/o', 'secret_id': '22', 'v': '1'},
            'all_ids': [
                {'path': '/a/c/o', 'v': '1'},
                {'path': '/a/c/o', 'secret_id': '22', 'v': '1'},
                {'path': '/a/c/o', 'secret_id': 'my_secret_id', 'v': '1'}]}
        self.assertEqual(expected_keys, keys)
        self.assertEqual([('/a/c', '22'), ('/a/c/o', '22')], calls)
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys()
        # no more calls to create_key
        self.assertEqual([('/a/c', '22'), ('/a/c/o', '22')], calls)
        self.assertEqual(expected_keys, keys)
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys(key_id={'secret_id': None})
        expected_keys = {
            'container': hmac.new(secrets[None], b'/a/c',
                                  digestmod=hashlib.sha256).digest(),
            'object': hmac.new(secrets[None], b'/a/c/o',
                               digestmod=hashlib.sha256).digest(),
            'id': {'path': '/a/c/o', 'v': '1'},
            'all_ids': [
                {'path': '/a/c/o', 'v': '1'},
                {'path': '/a/c/o', 'secret_id': '22', 'v': '1'},
                {'path': '/a/c/o', 'secret_id': 'my_secret_id', 'v': '1'}]}
        self.assertEqual(expected_keys, keys)
        self.assertEqual([('/a/c', '22'), ('/a/c/o', '22'),
                          ('/a/c', None), ('/a/c/o', None)],
                         calls)
Exemple #2
0
    def test_v1_keys_with_weird_paths(self):
        secrets = {None: os.urandom(32), '22': os.urandom(33)}
        conf = {}
        for secret_id, secret in secrets.items():
            opt = ('encryption_root_secret%s' %
                   (('_%s' % secret_id) if secret_id else ''))
            conf[opt] = base64.b64encode(secret)
        conf['active_root_secret_id'] = '22'
        self.app = keymaster.KeyMaster(self.swift, conf)
        orig_create_key = self.app.create_key
        calls = []

        def mock_create_key(path, secret_id=None):
            calls.append((path, secret_id))
            return orig_create_key(path, secret_id)

        # request path doesn't match stored path -- this could happen if you
        # misconfigured your proxy to have copy right of encryption
        context = keymaster.KeyMasterContext(self.app, 'a', 'not-c', 'not-o')
        for version in ('1', '2'):
            with mock.patch.object(self.app, 'create_key', mock_create_key):
                keys = context.fetch_crypto_keys(key_id={
                    'v': version,
                    'path': '/a/c/o'
                })
            expected_keys = {
                'container':
                hmac.new(secrets[None], b'/a/c',
                         digestmod=hashlib.sha256).digest(),
                'object':
                hmac.new(secrets[None], b'/a/c/o',
                         digestmod=hashlib.sha256).digest(),
                'id': {
                    'path': '/a/c/o',
                    'v': version
                },
                'all_ids': [{
                    'path': '/a/c/o',
                    'v': version
                }, {
                    'path': '/a/c/o',
                    'secret_id': '22',
                    'v': version
                }]
            }
            self.assertEqual(expected_keys, keys)
            self.assertEqual([('/a/c', None), ('/a/c/o', None)], calls)
            del calls[:]

        context = keymaster.KeyMasterContext(self.app, 'not-a', 'not-c',
                                             '/not-o')
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys(key_id={'v': '1', 'path': '/o'})
        expected_keys = {
            'container':
            hmac.new(secrets[None], b'/not-a/not-c',
                     digestmod=hashlib.sha256).digest(),
            'object':
            hmac.new(secrets[None], b'/o', digestmod=hashlib.sha256).digest(),
            'id': {
                'path': '/o',
                'v': '1'
            },
            'all_ids': [{
                'path': '/o',
                'v': '1'
            }, {
                'path': '/o',
                'secret_id': '22',
                'v': '1'
            }]
        }
        self.assertEqual(expected_keys, keys)
        self.assertEqual([('/not-a/not-c', None), ('/o', None)], calls)
        del calls[:]

        context = keymaster.KeyMasterContext(self.app, 'not-a', 'not-c',
                                             '/not-o')
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys(key_id={
                'v': '2',
                'path': '/a/c//o'
            })
        expected_keys = {
            'container':
            hmac.new(secrets[None], b'/a/c',
                     digestmod=hashlib.sha256).digest(),
            'object':
            hmac.new(secrets[None], b'/a/c//o',
                     digestmod=hashlib.sha256).digest(),
            'id': {
                'path': '/a/c//o',
                'v': '2'
            },
            'all_ids': [{
                'path': '/a/c//o',
                'v': '2'
            }, {
                'path': '/a/c//o',
                'secret_id': '22',
                'v': '2'
            }]
        }
        self.assertEqual(expected_keys, keys)
        self.assertEqual([('/a/c', None), ('/a/c//o', None)], calls)
Exemple #3
0
    def test_v2_keys(self):
        secrets = {None: os.urandom(32), '22': os.urandom(33)}
        conf = {}
        for secret_id, secret in secrets.items():
            opt = ('encryption_root_secret%s' %
                   (('_%s' % secret_id) if secret_id else ''))
            conf[opt] = base64.b64encode(secret)
        conf['active_root_secret_id'] = '22'
        self.app = keymaster.KeyMaster(self.swift, conf)
        orig_create_key = self.app.create_key
        calls = []

        def mock_create_key(path, secret_id=None):
            calls.append((path, secret_id))
            return orig_create_key(path, secret_id)

        container = u'\N{SNOWMAN}'
        obj = u'\N{SNOWFLAKE}'
        if six.PY2:
            container = container.encode('utf-8')
            obj = obj.encode('utf-8')
        good_con_path = '/a/%s' % container
        good_path = '/a/%s/%s' % (container, obj)

        if six.PY2:
            mangled_con_path = ('/a/%s' %
                                container).decode('latin-1').encode('utf-8')
            mangled_path = ('/a/%s/%s' %
                            (container, obj)).decode('latin-1').encode('utf-8')
        else:
            mangled_con_path = ('/a/%s' %
                                container).encode('utf-8').decode('latin-1')
            mangled_path = ('/a/%s/%s' %
                            (container, obj)).encode('utf-8').decode('latin-1')

        context = keymaster.KeyMasterContext(self.app, 'a', container, obj)
        for version in ('1', '2', '3'):
            with mock.patch.object(self.app, 'create_key', mock_create_key):
                keys = context.fetch_crypto_keys(key_id={
                    'v': version,
                    'path': good_path
                })
            key_id_path = (good_path
                           if version == '3' or six.PY2 else mangled_path)
            expected_keys = {
                'container':
                hmac.new(secrets[None],
                         b'/a/\xe2\x98\x83',
                         digestmod=hashlib.sha256).digest(),
                'object':
                hmac.new(secrets[None],
                         b'/a/\xe2\x98\x83/\xe2\x9d\x84',
                         digestmod=hashlib.sha256).digest(),
                'id': {
                    'path': key_id_path,
                    'v': version
                },
                'all_ids': [{
                    'path': key_id_path,
                    'v': version
                }, {
                    'path': key_id_path,
                    'secret_id': '22',
                    'v': version
                }]
            }
            self.assertEqual(expected_keys, keys)
            self.assertEqual([(good_con_path, None), (good_path, None)], calls)
            del calls[:]

        context = keymaster.KeyMasterContext(self.app, 'a', container, obj)
        for version in ('1', '2'):
            with mock.patch.object(self.app, 'create_key', mock_create_key):
                keys = context.fetch_crypto_keys(key_id={
                    'v': version,
                    'path': mangled_path
                })
            key_id_path = (good_path if six.PY2 else mangled_path)
            expected_keys = {
                'container':
                hmac.new(secrets[None],
                         b'/a/\xe2\x98\x83',
                         digestmod=hashlib.sha256).digest(),
                'object':
                hmac.new(secrets[None],
                         b'/a/\xe2\x98\x83/\xe2\x9d\x84',
                         digestmod=hashlib.sha256).digest(),
                'id': {
                    'path': key_id_path,
                    'v': version
                },
                'all_ids': [{
                    'path': key_id_path,
                    'v': version
                }, {
                    'path': key_id_path,
                    'secret_id': '22',
                    'v': version
                }]
            }
            self.assertEqual(expected_keys, keys)
            self.assertEqual([(good_con_path, None), (good_path, None)], calls)
            del calls[:]

        # If v3, we know to trust the meta -- presumably, data was PUT with
        # the mojibake path then COPYed to the right path (but with bad
        # pipeline placement for copy)
        with mock.patch.object(self.app, 'create_key', mock_create_key):
            keys = context.fetch_crypto_keys(key_id={
                'v': '3',
                'path': mangled_path
            })
        expected_keys = {
            'container':
            hmac.new(secrets[None],
                     b'/a/\xc3\xa2\xc2\x98\xc2\x83',
                     digestmod=hashlib.sha256).digest(),
            'object':
            hmac.new(secrets[None],
                     b'/a/\xc3\xa2\xc2\x98\xc2\x83/\xc3\xa2\xc2\x9d\xc2\x84',
                     digestmod=hashlib.sha256).digest(),
            'id': {
                'path': mangled_path,
                'v': '3'
            },
            'all_ids': [{
                'path': mangled_path,
                'v': '3'
            }, {
                'path': mangled_path,
                'secret_id': '22',
                'v': '3'
            }]
        }
        self.assertEqual(expected_keys, keys)
        self.assertEqual([(mangled_con_path, None), (mangled_path, None)],
                         calls)
        del calls[:]