コード例 #1
0
 def test_get_multiple_keys(self):
     env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     mutliple_keys = self.crypto_context.get_multiple_keys(env)
     self.assertEqual([
         fetch_crypto_keys(),
         fetch_crypto_keys(key_id={'secret_id': 'myid'})
     ], mutliple_keys)
コード例 #2
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def _test_override_etag_bad_meta(self, method, bad_crypto_meta):
     env = {
         'REQUEST_METHOD': method,
         CRYPTO_KEY_CALLBACK: fetch_crypto_keys
     }
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(len(body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     # simulate missing crypto meta from encrypted override etag
     hdrs['X-Object-Sysmeta-Container-Update-Override-Etag'] = \
         encrypt_and_append_meta(
             md5hex(body), key, crypto_meta=bad_crypto_meta)
     self.app.register(method,
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn(
         'Error decrypting header '
         'X-Object-Sysmeta-Container-Update-Override-Etag',
         self.decrypter.logger.get_lines_for_level('error')[0])
     return resp
コード例 #3
0
    def test_get_keys(self):
        # ok
        env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(fetch_crypto_keys(), keys)

        # only default required keys are checked
        subset_keys = {'object': fetch_crypto_keys()['object']}
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(subset_keys, keys)

        # only specified required keys are checked
        subset_keys = {'container': fetch_crypto_keys()['container']}
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(env, required=['container'])
        self.assertDictEqual(subset_keys, keys)

        subset_keys = {
            'object': fetch_crypto_keys()['object'],
            'container': fetch_crypto_keys()['container']
        }
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(env,
                                            required=['object', 'container'])
        self.assertDictEqual(subset_keys, keys)
コード例 #4
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def _test_bad_crypto_meta_for_user_metadata(self, method, bad_crypto_meta):
     # use bad iv for metadata headers
     env = {
         'REQUEST_METHOD': method,
         CRYPTO_KEY_CALLBACK: fetch_crypto_keys
     }
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(len(body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     enc_val = base64.b64encode(encrypt('encrypt me', key, FAKE_IV))
     if bad_crypto_meta:
         enc_val += ';swift_meta=' + get_crypto_meta_header(
             crypto_meta=bad_crypto_meta)
     hdrs['x-object-transient-sysmeta-crypto-meta-test'] = enc_val
     self.app.register(method,
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn(
         'Error decrypting header X-Object-Transient-Sysmeta-Crypto-Meta-'
         'Test',
         self.decrypter.logger.get_lines_for_level('error')[0])
     return resp
コード例 #5
0
ファイル: test_crypto_utils.py プロジェクト: mahak/swift
 def test_get_multiple_keys(self):
     env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     mutliple_keys = self.crypto_context.get_multiple_keys(env)
     self.assertEqual(
         [fetch_crypto_keys(),
          fetch_crypto_keys(key_id={'secret_id': 'myid'})],
         mutliple_keys)
コード例 #6
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_cipher_mismatch_for_metadata(self):
     # Cipher does not match
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     bad_crypto_meta = fake_get_crypto_meta()
     bad_crypto_meta['cipher'] = 'unknown_cipher'
     hdrs = self._make_response_headers(len(enc_body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     hdrs.update({
         'x-object-transient-sysmeta-crypto-meta-test':
         base64.b64encode(encrypt('encrypt me', key, FAKE_IV)) +
         ';swift_meta=' +
         get_crypto_meta_header(crypto_meta=bad_crypto_meta)
     })
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Error decrypting header', resp.body)
     self.assertIn(
         'Error decrypting header X-Object-Transient-Sysmeta-Crypto-Meta-'
         'Test',
         self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #7
0
        def do_test(method, plain_etags, expected_plain_etags=None):
            env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
            match_header_value = ', '.join(plain_etags)
            req = Request.blank(
                '/v1/a/c/o',
                environ=env,
                method=method,
                headers={match_header_name: match_header_value})
            app = FakeSwift()
            app.register(method, '/v1/a/c/o', HTTPOk, {})
            resp = req.get_response(encrypter.Encrypter(app, {}))
            self.assertEqual('200 OK', resp.status)

            self.assertEqual(1, len(app.calls), app.calls)
            self.assertEqual(method, app.calls[0][0])
            actual_headers = app.headers[0]

            # verify the alternate etag location has been specified
            if match_header_value and match_header_value != '*':
                self.assertIn('X-Backend-Etag-Is-At', actual_headers)
                self.assertEqual('X-Object-Sysmeta-Crypto-Etag-Mac',
                                 actual_headers['X-Backend-Etag-Is-At'])

            # verify etags have been supplemented with masked values
            self.assertIn(match_header_name, actual_headers)
            actual_etags = set(actual_headers[match_header_name].split(', '))
            # masked values for secret_id None
            key = fetch_crypto_keys()['object']
            masked_etags = [
                '"%s"' % bytes_to_wsgi(
                    base64.b64encode(
                        hmac.new(key, wsgi_to_bytes(etag.strip('"')),
                                 hashlib.sha256).digest()))
                for etag in plain_etags if etag not in ('*', '')
            ]
            # masked values for secret_id myid
            key = fetch_crypto_keys(key_id={'secret_id': 'myid'})['object']
            masked_etags_myid = [
                '"%s"' % bytes_to_wsgi(
                    base64.b64encode(
                        hmac.new(key, wsgi_to_bytes(etag.strip('"')),
                                 hashlib.sha256).digest()))
                for etag in plain_etags if etag not in ('*', '')
            ]
            expected_etags = set((expected_plain_etags or plain_etags) +
                                 masked_etags + masked_etags_myid)
            self.assertEqual(expected_etags, actual_etags)
            # check that the request environ was returned to original state
            self.assertEqual(set(plain_etags),
                             set(req.headers[match_header_name].split(', ')))
コード例 #8
0
    def _test_PUT_with_etag_override_in_headers(self, override_etag):
        # verify handling of another middleware's
        # container-update-override-etag in headers
        plaintext = b'FAKE APP'
        plaintext_etag = md5hex(plaintext)

        env = {'REQUEST_METHOD': 'PUT', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {
            'content-type': 'text/plain',
            'content-length': str(len(plaintext)),
            'Etag': plaintext_etag,
            'X-Object-Sysmeta-Container-Update-Override-Etag': override_etag
        }
        req = Request.blank('/v1/a/c/o',
                            environ=env,
                            body=plaintext,
                            headers=hdrs)
        self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
        resp = req.get_response(self.encrypter)

        self.assertEqual('201 Created', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])

        # verify metadata items
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual(('PUT', '/v1/a/c/o'), self.app.calls[0])
        req_hdrs = self.app.headers[0]

        # verify encrypted etag for container update
        self.assertIn('X-Object-Sysmeta-Container-Update-Override-Etag',
                      req_hdrs)
        parts = req_hdrs[
            'X-Object-Sysmeta-Container-Update-Override-Etag'].rsplit(';', 1)
        self.assertEqual(2, len(parts))
        cont_key = fetch_crypto_keys()['container']

        # extract crypto_meta from end of etag for container update
        param = parts[1].strip()
        crypto_meta_tag = 'swift_meta='
        self.assertTrue(param.startswith(crypto_meta_tag), param)
        actual_meta = json.loads(
            urlparse.unquote_plus(param[len(crypto_meta_tag):]))
        self.assertEqual(Crypto().cipher, actual_meta['cipher'])
        self.assertEqual(fetch_crypto_keys()['id'], actual_meta['key_id'])

        cont_etag_iv = base64.b64decode(actual_meta['iv'])
        self.assertEqual(FAKE_IV, cont_etag_iv)
        exp_etag = encrypt(override_etag.encode('ascii'), cont_key,
                           cont_etag_iv)
        self.assertEqual(exp_etag, base64.b64decode(parts[0]))
コード例 #9
0
ファイル: test_encrypter.py プロジェクト: mahak/swift
    def _test_PUT_with_etag_override_in_headers(self, override_etag):
        # verify handling of another middleware's
        # container-update-override-etag in headers
        plaintext = b'FAKE APP'
        plaintext_etag = md5hex(plaintext)

        env = {'REQUEST_METHOD': 'PUT',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {'content-type': 'text/plain',
                'content-length': str(len(plaintext)),
                'Etag': plaintext_etag,
                'X-Object-Sysmeta-Container-Update-Override-Etag':
                    override_etag}
        req = Request.blank(
            '/v1/a/c/o', environ=env, body=plaintext, headers=hdrs)
        self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
        resp = req.get_response(self.encrypter)

        self.assertEqual('201 Created', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])

        # verify metadata items
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual(('PUT', '/v1/a/c/o'), self.app.calls[0])
        req_hdrs = self.app.headers[0]

        # verify encrypted etag for container update
        self.assertIn(
            'X-Object-Sysmeta-Container-Update-Override-Etag', req_hdrs)
        parts = req_hdrs[
            'X-Object-Sysmeta-Container-Update-Override-Etag'].rsplit(';', 1)
        self.assertEqual(2, len(parts))
        cont_key = fetch_crypto_keys()['container']

        # extract crypto_meta from end of etag for container update
        param = parts[1].strip()
        crypto_meta_tag = 'swift_meta='
        self.assertTrue(param.startswith(crypto_meta_tag), param)
        actual_meta = json.loads(
            urlparse.unquote_plus(param[len(crypto_meta_tag):]))
        self.assertEqual(Crypto().cipher, actual_meta['cipher'])
        self.assertEqual(fetch_crypto_keys()['id'], actual_meta['key_id'])

        cont_etag_iv = base64.b64decode(actual_meta['iv'])
        self.assertEqual(FAKE_IV, cont_etag_iv)
        exp_etag = encrypt(override_etag.encode('ascii'),
                           cont_key, cont_etag_iv)
        self.assertEqual(exp_etag, base64.b64decode(parts[0]))
コード例 #10
0
ファイル: test_encrypter.py プロジェクト: jgmerritt/swift
    def test_encrypt_header_val(self):
        # Prepare key and Crypto instance
        object_key = fetch_crypto_keys()['object']

        # - Normal string can be crypted
        encrypted = encrypter.encrypt_header_val(Crypto(), 'aaa', object_key)
        # sanity: return value is 2 item tuple
        self.assertEqual(2, len(encrypted))
        crypted_val, crypt_info = encrypted
        expected_crypt_val = base64.b64encode(
            encrypt('aaa', object_key, FAKE_IV))
        expected_crypt_info = {
            'cipher': 'AES_CTR_256', 'iv': 'This is an IV123'}
        self.assertEqual(expected_crypt_val, crypted_val)
        self.assertEqual(expected_crypt_info, crypt_info)

        # - Empty string raises a ValueError for safety
        with self.assertRaises(ValueError) as cm:
            encrypter.encrypt_header_val(Crypto(), '', object_key)

        self.assertEqual('empty value is not acceptable',
                         cm.exception.message)

        # - None also raises a ValueError for safety
        with self.assertRaises(ValueError) as cm:
            encrypter.encrypt_header_val(Crypto(), None, object_key)

        self.assertEqual('empty value is not acceptable',
                         cm.exception.message)
コード例 #11
0
ファイル: test_encrypter.py プロジェクト: jgmerritt/swift
    def _test_etag_is_at_not_duplicated(self, method):
        # verify only one occurrence of X-Object-Sysmeta-Crypto-Etag-Mac in
        # X-Backend-Etag-Is-At
        key = fetch_crypto_keys()['object']
        env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank(
            '/v1/a/c/o', environ=env, method=method,
            headers={'If-Match': '"an etag"',
                     'If-None-Match': '"another etag"'})
        self.app.register(method, '/v1/a/c/o', HTTPOk, {})
        resp = req.get_response(self.encrypter)
        self.assertEqual('200 OK', resp.status)

        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual(method, self.app.calls[0][0])
        actual_headers = self.app.headers[0]
        self.assertIn('X-Backend-Etag-Is-At', actual_headers)
        self.assertEqual('X-Object-Sysmeta-Crypto-Etag-Mac',
                         actual_headers['X-Backend-Etag-Is-At'])

        self.assertIn('"%s"' % base64.b64encode(
            hmac.new(key, 'an etag', hashlib.sha256).digest()),
            actual_headers['If-Match'])
        self.assertIn('"another etag"', actual_headers['If-None-Match'])
        self.assertIn('"%s"' % base64.b64encode(
            hmac.new(key, 'another etag', hashlib.sha256).digest()),
            actual_headers['If-None-Match'])
コード例 #12
0
    def test_GET_container_json(self):
        content_type_1 = u'\uF10F\uD20D\uB30B\u9409'
        content_type_2 = 'text/plain; param=foo'
        pt_etag1 = 'c6e8196d7f0fff6444b90861fe8d609d'
        pt_etag2 = 'ac0374ed4d43635f803c82469d0b5a10'
        key = fetch_crypto_keys()['container']

        obj_dict_1 = {"bytes": 16,
                      "last_modified": "2015-04-14T23:33:06.439040",
                      "hash": encrypt_and_append_meta(
                          pt_etag1.encode('utf-8'), key),
                      "name": "testfile",
                      "content_type": content_type_1}

        obj_dict_2 = {"bytes": 24,
                      "last_modified": "2015-04-14T23:33:06.519020",
                      "hash": encrypt_and_append_meta(
                          pt_etag2.encode('utf-8'), key),
                      "name": "testfile2",
                      "content_type": content_type_2}

        listing = [obj_dict_1, obj_dict_2]
        fake_body = json.dumps(listing)

        resp = self._make_cont_get_req(fake_body, 'json')

        self.assertEqual('200 OK', resp.status)
        body = resp.body
        self.assertEqual(len(body), int(resp.headers['Content-Length']))
        body_json = json.loads(body)
        self.assertEqual(2, len(body_json))
        obj_dict_1['hash'] = pt_etag1
        self.assertDictEqual(obj_dict_1, body_json[0])
        obj_dict_2['hash'] = pt_etag2
        self.assertDictEqual(obj_dict_2, body_json[1])
コード例 #13
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def test_cont_get_json_req_with_cipher_mismatch(self):
        bad_crypto_meta = fake_get_crypto_meta()
        bad_crypto_meta['cipher'] = 'unknown_cipher'
        key = fetch_crypto_keys()['container']
        pt_etag = 'c6e8196d7f0fff6444b90861fe8d609d'
        ct_etag = encrypt_and_append_meta(pt_etag,
                                          key,
                                          crypto_meta=bad_crypto_meta)

        obj_dict_1 = {
            "bytes": 16,
            "last_modified": "2015-04-14T23:33:06.439040",
            "hash": ct_etag,
            "name": "testfile",
            "content_type": "image/jpeg"
        }

        listing = [obj_dict_1]
        fake_body = json.dumps(listing)

        resp = self._make_cont_get_req(fake_body, 'json')

        self.assertEqual('500 Internal Error', resp.status)
        self.assertEqual('Error decrypting container listing', resp.body)
        self.assertIn("Cipher must be AES_CTR_256",
                      self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #14
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def test_headers_case(self):
        body = 'fAkE ApP'
        req = Request.blank('/v1/a/c/o', body='FaKe')
        req.environ[CRYPTO_KEY_CALLBACK] = fetch_crypto_keys
        plaintext_etag = md5hex(body)
        body_key = os.urandom(32)
        enc_body = encrypt(body, body_key, FAKE_IV)
        hdrs = self._make_response_headers(len(enc_body), plaintext_etag,
                                           fetch_crypto_keys(), body_key)

        hdrs.update({
            'x-Object-mEta-ignoRes-caSe': 'thIs pArt WilL bE cOol',
        })
        self.app.register('GET',
                          '/v1/a/c/o',
                          HTTPOk,
                          body=enc_body,
                          headers=hdrs)

        status, headers, app_iter = req.call_application(self.decrypter)
        self.assertEqual(status, '200 OK')
        expected = {
            'Etag': '7f7837924188f7b511a9e3881a9f77a8',
            'X-Object-Sysmeta-Container-Update-Override-Etag':
            'encrypt me, too',
            'X-Object-Meta-Test': 'encrypt me',
            'Content-Length': '8',
            'X-Object-Meta-Ignores-Case': 'thIs pArt WilL bE cOol',
            'X-Object-Sysmeta-Test': 'do not encrypt me',
            'Content-Type': 'text/plain',
        }
        self.assertEqual(dict(headers), expected)
        self.assertEqual('fAkE ApP', ''.join(app_iter))
コード例 #15
0
    def test_POST_req(self):
        body = 'FAKE APP'
        env = {
            'REQUEST_METHOD': 'POST',
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys
        }
        hdrs = {
            'x-object-meta-test': 'encrypt me',
            'x-object-meta-test2': '',
            'x-object-sysmeta-test': 'do not encrypt me'
        }
        req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
        key = fetch_crypto_keys()['object']
        self.app.register('POST', '/v1/a/c/o', HTTPAccepted, {})
        resp = req.get_response(self.encrypter)
        self.assertEqual('202 Accepted', resp.status)
        self.assertNotIn('Etag', resp.headers)

        # verify metadata items
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual('POST', self.app.calls[0][0])
        req_hdrs = self.app.headers[0]

        # user meta is encrypted
        self._verify_user_metadata(req_hdrs, 'Test', 'encrypt me', key)
        # unless it had no value
        self.assertEqual('', req_hdrs['X-Object-Meta-Test2'])

        # sysmeta is not encrypted
        self.assertEqual('do not encrypt me',
                         req_hdrs['X-Object-Sysmeta-Test'])
コード例 #16
0
 def test_GET_missing_key_callback(self):
     # Do not provide keys, and do not set override flag
     env = {'REQUEST_METHOD': 'GET'}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
     hdrs = self._make_response_headers(
         len(body), md5hex('not the body'), fetch_crypto_keys(), 'not used')
     self.app.register(
         'GET', '/v1/a/c/o', HTTPOk, body=enc_body, headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Unable to retrieve encryption keys.',
                      resp.body)
     self.assertIn('missing callback',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #17
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def _test_req_metadata_not_encrypted(self, method):
     # check that metadata is not decrypted if it does not have crypto meta;
     # testing for case of an unencrypted POST to an object.
     env = {
         'REQUEST_METHOD': method,
         CRYPTO_KEY_CALLBACK: fetch_crypto_keys
     }
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     plaintext_etag = md5hex(body)
     body_key = os.urandom(32)
     enc_body = encrypt(body, body_key, FAKE_IV)
     hdrs = self._make_response_headers(len(body), plaintext_etag,
                                        fetch_crypto_keys(), body_key)
     hdrs.pop('x-object-transient-sysmeta-crypto-meta-test')
     hdrs['x-object-meta-test'] = 'plaintext not encrypted'
     self.app.register(method,
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('200 OK', resp.status)
     self.assertEqual(plaintext_etag, resp.headers['Etag'])
     self.assertEqual('text/plain', resp.headers['Content-Type'])
     self.assertEqual('plaintext not encrypted',
                      resp.headers['x-object-meta-test'])
コード例 #18
0
    def test_GET_multipart_content_type(self):
        # *just* having multipart content type shouldn't trigger the mime doc
        # code path
        body_key = os.urandom(32)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, body_key, FAKE_IV)

        # register request with fake swift
        hdrs = self._make_response_headers(
            len(ciphertext), plaintext_etag, fetch_crypto_keys(), body_key)
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        self.app.register('GET', '/v1/a/c/o', HTTPOk, body=ciphertext,
                          headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('200 OK', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(len(plaintext), int(resp.headers['Content-Length']))
        self.assertEqual('multipart/byteranges;boundary=multipartboundary',
                         resp.headers['Content-Type'])
        self.assertEqual(plaintext, resp.body)
コード例 #19
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_unencrypted_data(self):
     # testing case of an unencrypted object with encrypted metadata from
     # a later POST
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     obj_key = fetch_crypto_keys()['object']
     hdrs = {
         'Etag':
         md5hex(body),
         'content-type':
         'text/plain',
         'content-length':
         len(body),
         'x-object-transient-sysmeta-crypto-meta-test':
         base64.b64encode(encrypt('encrypt me', obj_key, FAKE_IV)) +
         ';swift_meta=' + get_crypto_meta_header(),
         'x-object-sysmeta-test':
         'do not encrypt me'
     }
     self.app.register('GET', '/v1/a/c/o', HTTPOk, body=body, headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual(body, resp.body)
     self.assertEqual('200 OK', resp.status)
     self.assertEqual(md5hex(body), resp.headers['Etag'])
     self.assertEqual('text/plain', resp.headers['Content-Type'])
     # POSTed user meta was encrypted
     self.assertEqual('encrypt me', resp.headers['x-object-meta-test'])
     # PUT sysmeta was not encrypted
     self.assertEqual('do not encrypt me',
                      resp.headers['x-object-sysmeta-test'])
コード例 #20
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_multiseg_with_range(self):
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     req.headers['Content-Range'] = 'bytes 3-10/17'
     chunks = ['0123', '45678', '9abcdef']
     body = ''.join(chunks)
     plaintext_etag = md5hex(body)
     body_key = os.urandom(32)
     ctxt = Crypto().create_encryption_ctxt(body_key, FAKE_IV)
     enc_body = [encrypt(chunk, ctxt=ctxt) for chunk in chunks]
     enc_body = [enc_body[0][3:], enc_body[1], enc_body[2][:2]]
     hdrs = self._make_response_headers(sum(map(len,
                                                enc_body)), plaintext_etag,
                                        fetch_crypto_keys(), body_key)
     hdrs['content-range'] = req.headers['Content-Range']
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('3456789a', resp.body)
     self.assertEqual('200 OK', resp.status)
     self.assertEqual(plaintext_etag, resp.headers['Etag'])
     self.assertEqual('text/plain', resp.headers['Content-Type'])
コード例 #21
0
 def test_GET_unencrypted_data(self):
     # testing case of an unencrypted object with encrypted metadata from
     # a later POST
     env = {'REQUEST_METHOD': 'GET',
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     obj_key = fetch_crypto_keys()['object']
     hdrs = {'Etag': md5hex(body),
             'content-type': 'text/plain',
             'content-length': len(body),
             'x-object-transient-sysmeta-crypto-meta-test':
                 base64.b64encode(encrypt('encrypt me', obj_key, FAKE_IV)) +
                 ';swift_meta=' + get_crypto_meta_header(),
             'x-object-sysmeta-test': 'do not encrypt me'}
     self.app.register('GET', '/v1/a/c/o', HTTPOk, body=body, headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual(body, resp.body)
     self.assertEqual('200 OK', resp.status)
     self.assertEqual(md5hex(body), resp.headers['Etag'])
     self.assertEqual('text/plain', resp.headers['Content-Type'])
     # POSTed user meta was encrypted
     self.assertEqual('encrypt me', resp.headers['x-object-meta-test'])
     # PUT sysmeta was not encrypted
     self.assertEqual('do not encrypt me',
                      resp.headers['x-object-sysmeta-test'])
コード例 #22
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def test_GET_multipart_content_type(self):
        # *just* having multipart content type shouldn't trigger the mime doc
        # code path
        body_key = os.urandom(32)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, body_key, FAKE_IV)

        # register request with fake swift
        hdrs = self._make_response_headers(len(ciphertext), plaintext_etag,
                                           fetch_crypto_keys(), body_key)
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        self.app.register('GET',
                          '/v1/a/c/o',
                          HTTPOk,
                          body=ciphertext,
                          headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('200 OK', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(len(plaintext), int(resp.headers['Content-Length']))
        self.assertEqual('multipart/byteranges;boundary=multipartboundary',
                         resp.headers['Content-Type'])
        self.assertEqual(plaintext, resp.body)
コード例 #23
0
ファイル: test_encrypter.py プロジェクト: jgmerritt/swift
    def test_POST_req(self):
        body = 'FAKE APP'
        env = {'REQUEST_METHOD': 'POST',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {'x-object-meta-test': 'encrypt me',
                'x-object-meta-test2': '',
                'x-object-sysmeta-test': 'do not encrypt me'}
        req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
        key = fetch_crypto_keys()['object']
        self.app.register('POST', '/v1/a/c/o', HTTPAccepted, {})
        resp = req.get_response(self.encrypter)
        self.assertEqual('202 Accepted', resp.status)
        self.assertNotIn('Etag', resp.headers)

        # verify metadata items
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual('POST', self.app.calls[0][0])
        req_hdrs = self.app.headers[0]

        # user meta is encrypted
        self._verify_user_metadata(req_hdrs, 'Test', 'encrypt me', key)
        # unless it had no value
        self.assertEqual('', req_hdrs['X-Object-Meta-Test2'])

        # sysmeta is not encrypted
        self.assertEqual('do not encrypt me',
                         req_hdrs['X-Object-Sysmeta-Test'])
コード例 #24
0
    def _test_request_success(self, method, body):
        env = {'REQUEST_METHOD': method,
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        plaintext_etag = md5hex(body)
        body_key = os.urandom(32)
        enc_body = encrypt(body, body_key, FAKE_IV)
        hdrs = self._make_response_headers(
            len(enc_body), plaintext_etag, fetch_crypto_keys(), body_key)

        # there shouldn't be any x-object-meta- headers, but if there are
        # then the decrypted header will win where there is a name clash...
        hdrs.update({
            'x-object-meta-test': 'unexpected, overwritten by decrypted value',
            'x-object-meta-distinct': 'unexpected but distinct from encrypted'
        })
        self.app.register(
            method, '/v1/a/c/o', HTTPOk, body=enc_body, headers=hdrs)
        resp = req.get_response(self.decrypter)
        self.assertEqual('200 OK', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual('text/plain', resp.headers['Content-Type'])
        self.assertEqual('encrypt me', resp.headers['x-object-meta-test'])
        self.assertEqual('unexpected but distinct from encrypted',
                         resp.headers['x-object-meta-distinct'])
        self.assertEqual('do not encrypt me',
                         resp.headers['x-object-sysmeta-test'])
        self.assertEqual(
            'encrypt me, too',
            resp.headers['X-Object-Sysmeta-Container-Update-Override-Etag'])
        self.assertNotIn('X-Object-Sysmeta-Crypto-Body-Meta', resp.headers)
        self.assertNotIn('X-Object-Sysmeta-Crypto-Etag', resp.headers)
        return resp
コード例 #25
0
    def _test_etag_is_at_not_duplicated(self, method):
        # verify only one occurrence of X-Object-Sysmeta-Crypto-Etag-Mac in
        # X-Backend-Etag-Is-At
        key = fetch_crypto_keys()['object']
        env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o',
                            environ=env,
                            method=method,
                            headers={
                                'If-Match': '"an etag"',
                                'If-None-Match': '"another etag"'
                            })
        self.app.register(method, '/v1/a/c/o', HTTPOk, {})
        resp = req.get_response(self.encrypter)
        self.assertEqual('200 OK', resp.status)

        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual(method, self.app.calls[0][0])
        actual_headers = self.app.headers[0]
        self.assertIn('X-Backend-Etag-Is-At', actual_headers)
        self.assertEqual('X-Object-Sysmeta-Crypto-Etag-Mac',
                         actual_headers['X-Backend-Etag-Is-At'])

        self.assertIn(
            '"%s"' % base64.b64encode(
                hmac.new(key, 'an etag', hashlib.sha256).digest()),
            actual_headers['If-Match'])
        self.assertIn('"another etag"', actual_headers['If-None-Match'])
        self.assertIn(
            '"%s"' % base64.b64encode(
                hmac.new(key, 'another etag', hashlib.sha256).digest()),
            actual_headers['If-None-Match'])
コード例 #26
0
ファイル: test_encrypter.py プロジェクト: notmyname/swift
        def do_test(method, plain_etags, expected_plain_etags=None):
            env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
            match_header_value = ", ".join(plain_etags)
            req = Request.blank(
                "/v1/a/c/o", environ=env, method=method, headers={match_header_name: match_header_value}
            )
            app = FakeSwift()
            app.register(method, "/v1/a/c/o", HTTPOk, {})
            resp = req.get_response(encrypter.Encrypter(app, {}))
            self.assertEqual("200 OK", resp.status)

            self.assertEqual(1, len(app.calls), app.calls)
            self.assertEqual(method, app.calls[0][0])
            actual_headers = app.headers[0]

            # verify the alternate etag location has been specified
            if match_header_value and match_header_value != "*":
                self.assertIn("X-Backend-Etag-Is-At", actual_headers)
                self.assertEqual("X-Object-Sysmeta-Crypto-Etag-Mac", actual_headers["X-Backend-Etag-Is-At"])

            # verify etags have been supplemented with masked values
            self.assertIn(match_header_name, actual_headers)
            actual_etags = set(actual_headers[match_header_name].split(", "))
            key = fetch_crypto_keys()["object"]
            masked_etags = [
                '"%s"' % base64.b64encode(hmac.new(key, etag.strip('"'), hashlib.sha256).digest())
                for etag in plain_etags
                if etag not in ("*", "")
            ]
            expected_etags = set((expected_plain_etags or plain_etags) + masked_etags)
            self.assertEqual(expected_etags, actual_etags)
            # check that the request environ was returned to original state
            self.assertEqual(set(plain_etags), set(req.headers[match_header_name].split(", ")))
コード例 #27
0
    def test_headers_case(self):
        body = 'fAkE ApP'
        req = Request.blank('/v1/a/c/o', body='FaKe')
        req.environ[CRYPTO_KEY_CALLBACK] = fetch_crypto_keys
        plaintext_etag = md5hex(body)
        body_key = os.urandom(32)
        enc_body = encrypt(body, body_key, FAKE_IV)
        hdrs = self._make_response_headers(
            len(enc_body), plaintext_etag, fetch_crypto_keys(), body_key)

        hdrs.update({
            'x-Object-mEta-ignoRes-caSe': 'thIs pArt WilL bE cOol',
        })
        self.app.register(
            'GET', '/v1/a/c/o', HTTPOk, body=enc_body, headers=hdrs)

        status, headers, app_iter = req.call_application(self.decrypter)
        self.assertEqual(status, '200 OK')
        expected = {
            'Etag': '7f7837924188f7b511a9e3881a9f77a8',
            'X-Object-Sysmeta-Container-Update-Override-Etag':
            'encrypt me, too',
            'X-Object-Meta-Test': 'encrypt me',
            'Content-Length': '8',
            'X-Object-Meta-Ignores-Case': 'thIs pArt WilL bE cOol',
            'X-Object-Sysmeta-Test': 'do not encrypt me',
            'Content-Type': 'text/plain',
        }
        self.assertEqual(dict(headers), expected)
        self.assertEqual('fAkE ApP', ''.join(app_iter))
コード例 #28
0
    def test_encrypt_header_val(self):
        # Prepare key and Crypto instance
        object_key = fetch_crypto_keys()['object']

        # - Normal string can be crypted
        encrypted = encrypter.encrypt_header_val(Crypto(), 'aaa', object_key)
        # sanity: return value is 2 item tuple
        self.assertEqual(2, len(encrypted))
        crypted_val, crypt_info = encrypted
        expected_crypt_val = base64.b64encode(
            encrypt('aaa', object_key, FAKE_IV))
        expected_crypt_info = {
            'cipher': 'AES_CTR_256',
            'iv': 'This is an IV123'
        }
        self.assertEqual(expected_crypt_val, crypted_val)
        self.assertEqual(expected_crypt_info, crypt_info)

        # - Empty string raises a ValueError for safety
        with self.assertRaises(ValueError) as cm:
            encrypter.encrypt_header_val(Crypto(), '', object_key)

        self.assertEqual('empty value is not acceptable', cm.exception.message)

        # - None also raises a ValueError for safety
        with self.assertRaises(ValueError) as cm:
            encrypter.encrypt_header_val(Crypto(), None, object_key)

        self.assertEqual('empty value is not acceptable', cm.exception.message)
コード例 #29
0
ファイル: test_crypto_utils.py プロジェクト: mahak/swift
    def test_get_keys_with_crypto_meta(self):
        # verify that key_id from crypto_meta is passed to fetch_crypto_keys
        keys = fetch_crypto_keys()
        mock_fetch_crypto_keys = mock.MagicMock(return_value=keys)
        env = {CRYPTO_KEY_CALLBACK: mock_fetch_crypto_keys}
        key_id = {'secret_id': '123'}
        keys = self.crypto_context.get_keys(env, key_id=key_id)
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id={'secret_id': '123'})

        # but it's ok for there to be no crypto_meta
        keys = self.crypto_context.get_keys(env, key_id={})
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id={})
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id=None)
コード例 #30
0
    def test_get_keys_with_crypto_meta(self):
        # verify that key_id from crypto_meta is passed to fetch_crypto_keys
        keys = fetch_crypto_keys()
        mock_fetch_crypto_keys = mock.MagicMock(return_value=keys)
        env = {CRYPTO_KEY_CALLBACK: mock_fetch_crypto_keys}
        key_id = {'secret_id': '123'}
        keys = self.crypto_context.get_keys(env, key_id=key_id)
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id={'secret_id': '123'})

        # but it's ok for there to be no crypto_meta
        keys = self.crypto_context.get_keys(env, key_id={})
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id={})
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(fetch_crypto_keys(), keys)
        mock_fetch_crypto_keys.assert_called_with(key_id=None)
コード例 #31
0
    def _test_bad_key(self, method):
        # use bad key
        def bad_fetch_crypto_keys():
            keys = fetch_crypto_keys()
            keys['object'] = 'bad key'
            return keys

        env = {'REQUEST_METHOD': method,
               CRYPTO_KEY_CALLBACK: bad_fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        body = 'FAKE APP'
        key = fetch_crypto_keys()['object']
        enc_body = encrypt(body, key, FAKE_IV)
        hdrs = self._make_response_headers(
            len(body), md5hex(body), fetch_crypto_keys(), 'not used')
        self.app.register(method, '/v1/a/c/o', HTTPOk, body=enc_body,
                          headers=hdrs)
        return req.get_response(self.decrypter)
コード例 #32
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def test_GET_multipart_ciphertext(self):
        # build fake multipart response body
        body_key = os.urandom(32)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, body_key, FAKE_IV)
        parts = ((0, 3, 'text/plain'), (4, 9, 'text/plain; charset=us-ascii'),
                 (24, 32, 'text/plain'))
        length = len(ciphertext)
        body = ''
        for start, end, ctype in parts:
            body += '--multipartboundary\r\n'
            body += 'Content-Type: %s\r\n' % ctype
            body += 'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)
            body += '\r\n\r\n' + ciphertext[start:end] + '\r\n'
        body += '--multipartboundary--'

        # register request with fake swift
        hdrs = self._make_response_headers(len(body), plaintext_etag,
                                           fetch_crypto_keys(), body_key)
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        self.app.register('GET',
                          '/v1/a/c/o',
                          HTTPPartialContent,
                          body=body,
                          headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('206 Partial Content', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(len(body), int(resp.headers['Content-Length']))
        self.assertEqual('multipart/byteranges;boundary=multipartboundary',
                         resp.headers['Content-Type'])

        # the multipart headers could be re-ordered, so parse response body to
        # verify expected content
        resp_lines = resp.body.split('\r\n')
        resp_lines.reverse()
        for start, end, ctype in parts:
            self.assertEqual('--multipartboundary', resp_lines.pop())
            expected_header_lines = {
                'Content-Type: %s' % ctype,
                'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)
            }
            resp_header_lines = {resp_lines.pop(), resp_lines.pop()}
            self.assertEqual(expected_header_lines, resp_header_lines)
            self.assertEqual('', resp_lines.pop())
            self.assertEqual(plaintext[start:end], resp_lines.pop())
        self.assertEqual('--multipartboundary--', resp_lines.pop())

        # we should have consumed the whole response body
        self.assertFalse(resp_lines)
コード例 #33
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_missing_key_callback(self):
     # Do not provide keys, and do not set override flag
     env = {'REQUEST_METHOD': 'GET'}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
     hdrs = self._make_response_headers(len(body), md5hex('not the body'),
                                        fetch_crypto_keys(), 'not used')
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Unable to retrieve encryption keys.', resp.body)
     self.assertIn('missing callback',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #34
0
ファイル: test_encrypter.py プロジェクト: mahak/swift
        def do_test(method, plain_etags, expected_plain_etags=None):
            env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
            match_header_value = ', '.join(plain_etags)
            req = Request.blank(
                '/v1/a/c/o', environ=env, method=method,
                headers={match_header_name: match_header_value})
            app = FakeSwift()
            app.register(method, '/v1/a/c/o', HTTPOk, {})
            resp = req.get_response(encrypter.Encrypter(app, {}))
            self.assertEqual('200 OK', resp.status)

            self.assertEqual(1, len(app.calls), app.calls)
            self.assertEqual(method, app.calls[0][0])
            actual_headers = app.headers[0]

            # verify the alternate etag location has been specified
            if match_header_value and match_header_value != '*':
                self.assertIn('X-Backend-Etag-Is-At', actual_headers)
                self.assertEqual('X-Object-Sysmeta-Crypto-Etag-Mac',
                                 actual_headers['X-Backend-Etag-Is-At'])

            # verify etags have been supplemented with masked values
            self.assertIn(match_header_name, actual_headers)
            actual_etags = set(actual_headers[match_header_name].split(', '))
            # masked values for secret_id None
            key = fetch_crypto_keys()['object']
            masked_etags = [
                '"%s"' % bytes_to_wsgi(base64.b64encode(hmac.new(
                    key, wsgi_to_bytes(etag.strip('"')),
                    hashlib.sha256).digest()))
                for etag in plain_etags if etag not in ('*', '')]
            # masked values for secret_id myid
            key = fetch_crypto_keys(key_id={'secret_id': 'myid'})['object']
            masked_etags_myid = [
                '"%s"' % bytes_to_wsgi(base64.b64encode(hmac.new(
                    key, wsgi_to_bytes(etag.strip('"')),
                    hashlib.sha256).digest()))
                for etag in plain_etags if etag not in ('*', '')]
            expected_etags = set((expected_plain_etags or plain_etags) +
                                 masked_etags + masked_etags_myid)
            self.assertEqual(expected_etags, actual_etags)
            # check that the request environ was returned to original state
            self.assertEqual(set(plain_etags),
                             set(req.headers[match_header_name].split(', ')))
コード例 #35
0
 def test_GET_missing_etag_crypto_meta(self):
     env = {'REQUEST_METHOD': 'GET',
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(
         len(body), md5hex(body), fetch_crypto_keys(), 'not used')
     # simulate missing crypto meta from encrypted etag
     hdrs['X-Object-Sysmeta-Crypto-Etag'] = \
         base64.b64encode(encrypt(md5hex(body), key, FAKE_IV))
     self.app.register('GET', '/v1/a/c/o', HTTPOk, body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn('Error decrypting header', resp.body)
     self.assertIn('Error decrypting header X-Object-Sysmeta-Crypto-Etag',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #36
0
 def test_get_keys_missing_key_for_default_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys.pop('object')
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda: bad_keys})
     self.assertIn('500 Internal Error', cm.exception.message)
     self.assertIn("Missing key for 'object'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn('Unable to retrieve encryption keys.', cm.exception.body)
コード例 #37
0
 def _test_GET_with_bad_crypto_meta_for_object_body(self, bad_crypto_meta):
     # use bad iv for object body
     env = {'REQUEST_METHOD': 'GET',
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(
         len(body), md5hex(body), fetch_crypto_keys(), 'not used')
     hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
         get_crypto_meta_header(crypto_meta=bad_crypto_meta)
     self.app.register('GET', '/v1/a/c/o', HTTPOk, body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Error decrypting object', resp.body)
     self.assertIn('Error decrypting object',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #38
0
    def test_GET_error_in_key_callback(self):
        def raise_exc():
            raise Exception('Testing')

        env = {'REQUEST_METHOD': 'GET',
               CRYPTO_KEY_CALLBACK: raise_exc}
        req = Request.blank('/v1/a/c/o', environ=env)
        body = 'FAKE APP'
        enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
        hdrs = self._make_response_headers(
            len(body), md5hex(body), fetch_crypto_keys(), 'not used')
        self.app.register(
            'GET', '/v1/a/c/o', HTTPOk, body=enc_body, headers=hdrs)
        resp = req.get_response(self.decrypter)
        self.assertEqual('500 Internal Error', resp.status)
        self.assertEqual('Unable to retrieve encryption keys.',
                         resp.body)
        self.assertIn('from callback: Testing',
                      self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #39
0
 def test_get_keys_missing_key_for_default_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys.pop('object')
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda: bad_keys})
     self.assertIn('500 Internal Error', cm.exception.message)
     self.assertIn("Missing key for 'object'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn('Unable to retrieve encryption keys.', cm.exception.body)
コード例 #40
0
ファイル: test_crypto_utils.py プロジェクト: jgmerritt/swift
 def test_bad_object_key_for_default_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys['object'] = 'the minor key'
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: bad_keys})
     self.assertIn('500 Internal Error', cm.exception.message)
     self.assertIn("Bad key for 'object'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn('Unable to retrieve encryption keys.', cm.exception.body)
コード例 #41
0
    def test_GET_multipart_ciphertext(self):
        # build fake multipart response body
        body_key = os.urandom(32)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, body_key, FAKE_IV)
        parts = ((0, 3, 'text/plain'),
                 (4, 9, 'text/plain; charset=us-ascii'),
                 (24, 32, 'text/plain'))
        length = len(ciphertext)
        body = ''
        for start, end, ctype in parts:
            body += '--multipartboundary\r\n'
            body += 'Content-Type: %s\r\n' % ctype
            body += 'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)
            body += '\r\n\r\n' + ciphertext[start:end] + '\r\n'
        body += '--multipartboundary--'

        # register request with fake swift
        hdrs = self._make_response_headers(
            len(body), plaintext_etag, fetch_crypto_keys(), body_key)
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        self.app.register('GET', '/v1/a/c/o', HTTPPartialContent, body=body,
                          headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('206 Partial Content', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(len(body), int(resp.headers['Content-Length']))
        self.assertEqual('multipart/byteranges;boundary=multipartboundary',
                         resp.headers['Content-Type'])

        # the multipart headers could be re-ordered, so parse response body to
        # verify expected content
        resp_lines = resp.body.split('\r\n')
        resp_lines.reverse()
        for start, end, ctype in parts:
            self.assertEqual('--multipartboundary', resp_lines.pop())
            expected_header_lines = {
                'Content-Type: %s' % ctype,
                'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)}
            resp_header_lines = {resp_lines.pop(), resp_lines.pop()}
            self.assertEqual(expected_header_lines, resp_header_lines)
            self.assertEqual('', resp_lines.pop())
            self.assertEqual(plaintext[start:end], resp_lines.pop())
        self.assertEqual('--multipartboundary--', resp_lines.pop())

        # we should have consumed the whole response body
        self.assertFalse(resp_lines)
コード例 #42
0
ファイル: test_encrypter.py プロジェクト: notmyname/swift
    def test_PUT_with_etag_override_in_headers(self):
        # verify handling of another middleware's
        # container-update-override-etag in headers
        plaintext = "FAKE APP"
        plaintext_etag = md5hex(plaintext)

        env = {"REQUEST_METHOD": "PUT", CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {
            "content-type": "text/plain",
            "content-length": str(len(plaintext)),
            "Etag": plaintext_etag,
            "X-Object-Sysmeta-Container-Update-Override-Etag": "final etag",
        }
        req = Request.blank("/v1/a/c/o", environ=env, body=plaintext, headers=hdrs)
        self.app.register("PUT", "/v1/a/c/o", HTTPCreated, {})
        resp = req.get_response(self.encrypter)

        self.assertEqual("201 Created", resp.status)
        self.assertEqual(plaintext_etag, resp.headers["Etag"])

        # verify metadata items
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual(("PUT", "/v1/a/c/o"), self.app.calls[0])
        req_hdrs = self.app.headers[0]

        # verify encrypted etag for container update
        self.assertIn("X-Object-Sysmeta-Container-Update-Override-Etag", req_hdrs)
        parts = req_hdrs["X-Object-Sysmeta-Container-Update-Override-Etag"].rsplit(";", 1)
        self.assertEqual(2, len(parts))
        cont_key = fetch_crypto_keys()["container"]

        # extract crypto_meta from end of etag for container update
        param = parts[1].strip()
        crypto_meta_tag = "swift_meta="
        self.assertTrue(param.startswith(crypto_meta_tag), param)
        actual_meta = json.loads(urllib.unquote_plus(param[len(crypto_meta_tag) :]))
        self.assertEqual(Crypto().cipher, actual_meta["cipher"])
        self.assertEqual(fetch_crypto_keys()["id"], actual_meta["key_id"])

        cont_etag_iv = base64.b64decode(actual_meta["iv"])
        self.assertEqual(FAKE_IV, cont_etag_iv)
        self.assertEqual(encrypt("final etag", cont_key, cont_etag_iv), base64.b64decode(parts[0]))
コード例 #43
0
 def test_bad_object_key_for_default_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys['object'] = b'the minor key'
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: bad_keys})
     self.assertIn('500 Internal Error', cm.exception.status)
     self.assertIn("Bad key for 'object'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn(b'Unable to retrieve encryption keys.',
                   cm.exception.body)
コード例 #44
0
 def test_bad_container_key_for_default_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys['container'] = 'the major key'
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda: bad_keys},
             required=['object', 'container'])
     self.assertIn('500 Internal Error', cm.exception.message)
     self.assertIn("Bad key for 'container'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn('Unable to retrieve encryption keys.', cm.exception.body)
コード例 #45
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def test_GET_error_in_key_callback(self):
        def raise_exc():
            raise Exception('Testing')

        env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: raise_exc}
        req = Request.blank('/v1/a/c/o', environ=env)
        body = 'FAKE APP'
        enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
        hdrs = self._make_response_headers(len(body), md5hex(body),
                                           fetch_crypto_keys(), 'not used')
        self.app.register('GET',
                          '/v1/a/c/o',
                          HTTPOk,
                          body=enc_body,
                          headers=hdrs)
        resp = req.get_response(self.decrypter)
        self.assertEqual('500 Internal Error', resp.status)
        self.assertEqual('Unable to retrieve encryption keys.', resp.body)
        self.assertIn('from callback: Testing',
                      self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #46
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_missing_etag_crypto_meta(self):
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(len(body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     # simulate missing crypto meta from encrypted etag
     hdrs['X-Object-Sysmeta-Crypto-Etag'] = \
         base64.b64encode(encrypt(md5hex(body), key, FAKE_IV))
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn('Error decrypting header', resp.body)
     self.assertIn('Error decrypting header X-Object-Sysmeta-Crypto-Etag',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #47
0
 def test_get_keys_missing_container_key_for_specified_required_list(self):
     bad_keys = dict(fetch_crypto_keys())
     bad_keys.pop('container')
     with self.assertRaises(HTTPException) as cm:
         self.crypto_context.get_keys(
             {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: bad_keys},
             required=['object', 'container'])
     self.assertIn('500 Internal Error', cm.exception.status)
     self.assertIn("Missing key for 'container'",
                   self.fake_logger.get_lines_for_level('error')[0])
     self.assertIn(b'Unable to retrieve encryption keys.',
                   cm.exception.body)
コード例 #48
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def _test_GET_with_bad_crypto_meta_for_object_body(self, bad_crypto_meta):
     # use bad iv for object body
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(len(body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
         get_crypto_meta_header(crypto_meta=bad_crypto_meta)
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Error decrypting object', resp.body)
     self.assertIn('Error decrypting object',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #49
0
 def _test_override_etag_bad_meta(self, method, bad_crypto_meta):
     env = {'REQUEST_METHOD': method,
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(
         len(body), md5hex(body), fetch_crypto_keys(), 'not used')
     # simulate missing crypto meta from encrypted override etag
     hdrs['X-Object-Sysmeta-Container-Update-Override-Etag'] = \
         encrypt_and_append_meta(
             md5hex(body), key, crypto_meta=bad_crypto_meta)
     self.app.register(method, '/v1/a/c/o', HTTPOk, body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn('Error decrypting header '
                   'X-Object-Sysmeta-Container-Update-Override-Etag',
                   self.decrypter.logger.get_lines_for_level('error')[0])
     return resp
コード例 #50
0
 def test_GET_cipher_mismatch_for_body(self):
     # Cipher does not match
     env = {'REQUEST_METHOD': 'GET',
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
     bad_crypto_meta = fake_get_crypto_meta()
     bad_crypto_meta['cipher'] = 'unknown_cipher'
     hdrs = self._make_response_headers(
         len(enc_body), md5hex(body), fetch_crypto_keys(), 'not used')
     hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
         get_crypto_meta_header(crypto_meta=bad_crypto_meta)
     self.app.register(
         'GET', '/v1/a/c/o', HTTPOk, body=enc_body, headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Error decrypting object', resp.body)
     self.assertIn('Error decrypting object',
                   self.decrypter.logger.get_lines_for_level('error')[0])
     self.assertIn('Bad crypto meta: Cipher',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #51
0
    def _test_GET_multipart_bad_body_crypto_meta(self, bad_crypto_meta):
        # build fake multipart response body
        key = fetch_crypto_keys()['object']
        ctxt = Crypto().create_encryption_ctxt(key, FAKE_IV)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, ctxt=ctxt)
        parts = ((0, 3, 'text/plain'),
                 (4, 9, 'text/plain; charset=us-ascii'),
                 (24, 32, 'text/plain'))
        length = len(ciphertext)
        body = ''
        for start, end, ctype in parts:
            body += '--multipartboundary\r\n'
            body += 'Content-Type: %s\r\n' % ctype
            body += 'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)
            body += '\r\n\r\n' + ciphertext[start:end] + '\r\n'
        body += '--multipartboundary--'

        # register request with fake swift
        hdrs = self._make_response_headers(
            len(body), plaintext_etag, fetch_crypto_keys(), 'not used')
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
            get_crypto_meta_header(bad_crypto_meta)
        self.app.register('GET', '/v1/a/c/o', HTTPOk, body=body, headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('500 Internal Error', resp.status)
        self.assertEqual('Error decrypting object', resp.body)
        self.assertIn('Error decrypting object',
                      self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #52
0
    def test_PUT_zero_size_object(self):
        # object body encryption should be skipped for zero sized object body
        object_key = fetch_crypto_keys()['object']
        plaintext_etag = EMPTY_ETAG

        env = {'REQUEST_METHOD': 'PUT', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {
            'etag': EMPTY_ETAG,
            'content-type': 'text/plain',
            'content-length': '0',
            'x-object-meta-etag': 'not to be confused with the Etag!',
            'x-object-meta-test': 'encrypt me',
            'x-object-sysmeta-test': 'do not encrypt me'
        }
        req = Request.blank('/v1/a/c/o', environ=env, body='', headers=hdrs)
        self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})

        resp = req.get_response(self.encrypter)

        self.assertEqual('201 Created', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual('PUT', self.app.calls[0][0])
        req_hdrs = self.app.headers[0]

        # verify that there is no body crypto meta
        self.assertNotIn('X-Object-Sysmeta-Crypto-Meta', req_hdrs)
        # verify etag is md5 of plaintext
        self.assertEqual(EMPTY_ETAG, req_hdrs['Etag'])
        # verify there is no etag crypto meta
        self.assertNotIn('X-Object-Sysmeta-Crypto-Etag', req_hdrs)
        # verify there is no container update override for etag
        self.assertNotIn('X-Object-Sysmeta-Container-Update-Override-Etag',
                         req_hdrs)

        # user meta is still encrypted
        self._verify_user_metadata(req_hdrs, 'Test', 'encrypt me', object_key)
        self._verify_user_metadata(req_hdrs, 'Etag',
                                   'not to be confused with the Etag!',
                                   object_key)

        # sysmeta is not encrypted
        self.assertEqual('do not encrypt me',
                         req_hdrs['X-Object-Sysmeta-Test'])

        # verify object is empty by getting direct from the app
        get_req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'})
        resp = get_req.get_response(self.app)
        self.assertEqual('', resp.body)
        self.assertEqual(EMPTY_ETAG, resp.headers['Etag'])
コード例 #53
0
 def _test_bad_crypto_meta_for_user_metadata(self, method, bad_crypto_meta):
     # use bad iv for metadata headers
     env = {'REQUEST_METHOD': method,
            CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     key = fetch_crypto_keys()['object']
     enc_body = encrypt(body, key, FAKE_IV)
     hdrs = self._make_response_headers(
         len(body), md5hex(body), fetch_crypto_keys(), 'not used')
     enc_val = base64.b64encode(encrypt('encrypt me', key, FAKE_IV))
     if bad_crypto_meta:
         enc_val += ';swift_meta=' + get_crypto_meta_header(
             crypto_meta=bad_crypto_meta)
     hdrs['x-object-transient-sysmeta-crypto-meta-test'] = enc_val
     self.app.register(method, '/v1/a/c/o', HTTPOk, body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertIn(
         'Error decrypting header X-Object-Transient-Sysmeta-Crypto-Meta-'
         'Test', self.decrypter.logger.get_lines_for_level('error')[0])
     return resp
コード例 #54
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def _test_bad_key(self, method):
        # use bad key
        def bad_fetch_crypto_keys():
            keys = fetch_crypto_keys()
            keys['object'] = 'bad key'
            return keys

        env = {
            'REQUEST_METHOD': method,
            CRYPTO_KEY_CALLBACK: bad_fetch_crypto_keys
        }
        req = Request.blank('/v1/a/c/o', environ=env)
        body = 'FAKE APP'
        key = fetch_crypto_keys()['object']
        enc_body = encrypt(body, key, FAKE_IV)
        hdrs = self._make_response_headers(len(body), md5hex(body),
                                           fetch_crypto_keys(), 'not used')
        self.app.register(method,
                          '/v1/a/c/o',
                          HTTPOk,
                          body=enc_body,
                          headers=hdrs)
        return req.get_response(self.decrypter)
コード例 #55
0
ファイル: test_encrypter.py プロジェクト: jgmerritt/swift
    def test_PUT_zero_size_object(self):
        # object body encryption should be skipped for zero sized object body
        object_key = fetch_crypto_keys()['object']
        plaintext_etag = EMPTY_ETAG

        env = {'REQUEST_METHOD': 'PUT',
               CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        hdrs = {'etag': EMPTY_ETAG,
                'content-type': 'text/plain',
                'content-length': '0',
                'x-object-meta-etag': 'not to be confused with the Etag!',
                'x-object-meta-test': 'encrypt me',
                'x-object-sysmeta-test': 'do not encrypt me'}
        req = Request.blank(
            '/v1/a/c/o', environ=env, body='', headers=hdrs)
        self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})

        resp = req.get_response(self.encrypter)

        self.assertEqual('201 Created', resp.status)
        self.assertEqual(plaintext_etag, resp.headers['Etag'])
        self.assertEqual(1, len(self.app.calls), self.app.calls)
        self.assertEqual('PUT', self.app.calls[0][0])
        req_hdrs = self.app.headers[0]

        # verify that there is no body crypto meta
        self.assertNotIn('X-Object-Sysmeta-Crypto-Meta', req_hdrs)
        # verify etag is md5 of plaintext
        self.assertEqual(EMPTY_ETAG, req_hdrs['Etag'])
        # verify there is no etag crypto meta
        self.assertNotIn('X-Object-Sysmeta-Crypto-Etag', req_hdrs)
        # verify there is no container update override for etag
        self.assertNotIn(
            'X-Object-Sysmeta-Container-Update-Override-Etag', req_hdrs)

        # user meta is still encrypted
        self._verify_user_metadata(req_hdrs, 'Test', 'encrypt me', object_key)
        self._verify_user_metadata(
            req_hdrs, 'Etag', 'not to be confused with the Etag!', object_key)

        # sysmeta is not encrypted
        self.assertEqual('do not encrypt me',
                         req_hdrs['X-Object-Sysmeta-Test'])

        # verify object is empty by getting direct from the app
        get_req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'})
        resp = get_req.get_response(self.app)
        self.assertEqual('', resp.body)
        self.assertEqual(EMPTY_ETAG, resp.headers['Etag'])
コード例 #56
0
    def test_GET_container_xml(self):
        content_type_1 = u'\uF10F\uD20D\uB30B\u9409'
        content_type_2 = 'text/plain; param=foo'
        pt_etag1 = 'c6e8196d7f0fff6444b90861fe8d609d'
        pt_etag2 = 'ac0374ed4d43635f803c82469d0b5a10'
        key = fetch_crypto_keys()['container']

        fake_body = '''<?xml version="1.0" encoding="UTF-8"?>
<container name="testc">\
<object><hash>\
''' + encrypt_and_append_meta(pt_etag1.encode('utf8'), key) + '''\
</hash><content_type>\
''' + content_type_1 + '''\
</content_type><name>testfile</name><bytes>16</bytes>\
<last_modified>2015-04-19T02:37:39.601660</last_modified></object>\
<object><hash>\
''' + encrypt_and_append_meta(pt_etag2.encode('utf8'), key) + '''\
</hash><content_type>\
''' + content_type_2 + '''\
</content_type><name>testfile2</name><bytes>24</bytes>\
<last_modified>2015-04-19T02:37:39.684740</last_modified></object>\
</container>'''

        resp = self._make_cont_get_req(fake_body, 'xml')
        self.assertEqual('200 OK', resp.status)
        body = resp.body
        self.assertEqual(len(body), int(resp.headers['Content-Length']))

        tree = minidom.parseString(body)
        containers = tree.getElementsByTagName('container')
        self.assertEqual(1, len(containers))
        self.assertEqual('testc',
                         containers[0].attributes.getNamedItem("name").value)

        objs = tree.getElementsByTagName('object')
        self.assertEqual(2, len(objs))

        obj_dict_1 = {"bytes": "16",
                      "last_modified": "2015-04-19T02:37:39.601660",
                      "hash": pt_etag1,
                      "name": "testfile",
                      "content_type": content_type_1}
        self._assert_element_contains_dict(obj_dict_1, objs[0])
        obj_dict_2 = {"bytes": "24",
                      "last_modified": "2015-04-19T02:37:39.684740",
                      "hash": pt_etag2,
                      "name": "testfile2",
                      "content_type": content_type_2}
        self._assert_element_contains_dict(obj_dict_2, objs[1])
コード例 #57
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
 def test_GET_cipher_mismatch_for_body(self):
     # Cipher does not match
     env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
     req = Request.blank('/v1/a/c/o', environ=env)
     body = 'FAKE APP'
     enc_body = encrypt(body, fetch_crypto_keys()['object'], FAKE_IV)
     bad_crypto_meta = fake_get_crypto_meta()
     bad_crypto_meta['cipher'] = 'unknown_cipher'
     hdrs = self._make_response_headers(len(enc_body), md5hex(body),
                                        fetch_crypto_keys(), 'not used')
     hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
         get_crypto_meta_header(crypto_meta=bad_crypto_meta)
     self.app.register('GET',
                       '/v1/a/c/o',
                       HTTPOk,
                       body=enc_body,
                       headers=hdrs)
     resp = req.get_response(self.decrypter)
     self.assertEqual('500 Internal Error', resp.status)
     self.assertEqual('Error decrypting object', resp.body)
     self.assertIn('Error decrypting object',
                   self.decrypter.logger.get_lines_for_level('error')[0])
     self.assertIn('Bad crypto meta: Cipher',
                   self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #58
0
ファイル: test_decrypter.py プロジェクト: yinyalan/swift
    def _test_GET_multipart_bad_body_crypto_meta(self, bad_crypto_meta):
        # build fake multipart response body
        key = fetch_crypto_keys()['object']
        ctxt = Crypto().create_encryption_ctxt(key, FAKE_IV)
        plaintext = 'Cwm fjord veg balks nth pyx quiz'
        plaintext_etag = md5hex(plaintext)
        ciphertext = encrypt(plaintext, ctxt=ctxt)
        parts = ((0, 3, 'text/plain'), (4, 9, 'text/plain; charset=us-ascii'),
                 (24, 32, 'text/plain'))
        length = len(ciphertext)
        body = ''
        for start, end, ctype in parts:
            body += '--multipartboundary\r\n'
            body += 'Content-Type: %s\r\n' % ctype
            body += 'Content-Range: bytes %s-%s/%s' % (start, end - 1, length)
            body += '\r\n\r\n' + ciphertext[start:end] + '\r\n'
        body += '--multipartboundary--'

        # register request with fake swift
        hdrs = self._make_response_headers(len(body), plaintext_etag,
                                           fetch_crypto_keys(), 'not used')
        hdrs['content-type'] = \
            'multipart/byteranges;boundary=multipartboundary'
        hdrs['X-Object-Sysmeta-Crypto-Body-Meta'] = \
            get_crypto_meta_header(bad_crypto_meta)
        self.app.register('GET', '/v1/a/c/o', HTTPOk, body=body, headers=hdrs)

        # issue request
        env = {'REQUEST_METHOD': 'GET', CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        req = Request.blank('/v1/a/c/o', environ=env)
        resp = req.get_response(self.decrypter)

        self.assertEqual('500 Internal Error', resp.status)
        self.assertEqual('Error decrypting object', resp.body)
        self.assertIn('Error decrypting object',
                      self.decrypter.logger.get_lines_for_level('error')[0])
コード例 #59
0
ファイル: test_crypto_utils.py プロジェクト: mahak/swift
    def test_get_keys(self):
        # ok
        env = {CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(fetch_crypto_keys(), keys)

        # only default required keys are checked
        subset_keys = {'object': fetch_crypto_keys()['object']}
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(env)
        self.assertDictEqual(subset_keys, keys)

        # only specified required keys are checked
        subset_keys = {'container': fetch_crypto_keys()['container']}
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(env, required=['container'])
        self.assertDictEqual(subset_keys, keys)

        subset_keys = {'object': fetch_crypto_keys()['object'],
                       'container': fetch_crypto_keys()['container']}
        env = {CRYPTO_KEY_CALLBACK: lambda *args, **kwargs: subset_keys}
        keys = self.crypto_context.get_keys(
            env, required=['object', 'container'])
        self.assertDictEqual(subset_keys, keys)