| # Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved |
| # |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the |
| # "Software"), to deal in the Software without restriction, including |
| # without limitation the rights to use, copy, modify, merge, publish, dis- |
| # tribute, sublicense, and/or sell copies of the Software, and to permit |
| # persons to whom the Software is furnished to do so, subject to the fol- |
| # lowing conditions: |
| # |
| # The above copyright notice and this permission notice shall be included |
| # in all copies or substantial portions of the Software. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| # IN THE SOFTWARE. |
| # |
| |
| import boto |
| from boto.compat import json |
| from boto.connection import AWSQueryConnection |
| from boto.regioninfo import RegionInfo |
| from boto.exception import JSONResponseError |
| from boto.kms import exceptions |
| from boto.compat import six |
| import base64 |
| |
| |
| class KMSConnection(AWSQueryConnection): |
| """ |
| AWS Key Management Service |
| AWS Key Management Service (KMS) is an encryption and key |
| management web service. This guide describes the KMS actions that |
| you can call programmatically. For general information about KMS, |
| see (need an address here). For the KMS developer guide, see (need |
| address here). |
| |
| AWS provides SDKs that consist of libraries and sample code for |
| various programming languages and platforms (Java, Ruby, .Net, |
| iOS, Android, etc.). The SDKs provide a convenient way to create |
| programmatic access to KMS and AWS. For example, the SDKs take |
| care of tasks such as signing requests (see below), managing |
| errors, and retrying requests automatically. For more information |
| about the AWS SDKs, including how to download and install them, |
| see `Tools for Amazon Web Services`_. |
| |
| We recommend that you use the AWS SDKs to make programmatic API |
| calls to KMS. However, you can also use the KMS Query API to make |
| to make direct calls to the KMS web service. |
| |
| **Signing Requests** |
| |
| Requests must be signed by using an access key ID and a secret |
| access key. We strongly recommend that you do not use your AWS |
| account access key ID and secret key for everyday work with KMS. |
| Instead, use the access key ID and secret access key for an IAM |
| user, or you can use the AWS Security Token Service to generate |
| temporary security credentials that you can use to sign requests. |
| |
| All KMS operations require `Signature Version 4`_. |
| |
| **Recording API Requests** |
| |
| KMS supports AWS CloudTrail, a service that records AWS API calls |
| and related events for your AWS account and delivers them to an |
| Amazon S3 bucket that you specify. By using the information |
| collected by CloudTrail, you can determine what requests were made |
| to KMS, who made the request, when it was made, and so on. To |
| learn more about CloudTrail, including how to turn it on and find |
| your log files, see the `AWS CloudTrail User Guide`_ |
| |
| **Additional Resources** |
| |
| For more information about credentials and request signing, see |
| the following: |
| |
| |
| + `AWS Security Credentials`_. This topic provides general |
| information about the types of credentials used for accessing AWS. |
| + `AWS Security Token Service`_. This guide describes how to |
| create and use temporary security credentials. |
| + `Signing AWS API Requests`_. This set of topics walks you |
| through the process of signing a request using an access key ID |
| and a secret access key. |
| """ |
| APIVersion = "2014-11-01" |
| DefaultRegionName = "us-east-1" |
| DefaultRegionEndpoint = "kms.us-east-1.amazonaws.com" |
| ServiceName = "KMS" |
| TargetPrefix = "TrentService" |
| ResponseError = JSONResponseError |
| |
| _faults = { |
| "InvalidGrantTokenException": exceptions.InvalidGrantTokenException, |
| "DisabledException": exceptions.DisabledException, |
| "LimitExceededException": exceptions.LimitExceededException, |
| "DependencyTimeoutException": exceptions.DependencyTimeoutException, |
| "InvalidMarkerException": exceptions.InvalidMarkerException, |
| "AlreadyExistsException": exceptions.AlreadyExistsException, |
| "InvalidCiphertextException": exceptions.InvalidCiphertextException, |
| "KeyUnavailableException": exceptions.KeyUnavailableException, |
| "InvalidAliasNameException": exceptions.InvalidAliasNameException, |
| "UnsupportedOperationException": exceptions.UnsupportedOperationException, |
| "InvalidArnException": exceptions.InvalidArnException, |
| "KMSInternalException": exceptions.KMSInternalException, |
| "InvalidKeyUsageException": exceptions.InvalidKeyUsageException, |
| "MalformedPolicyDocumentException": exceptions.MalformedPolicyDocumentException, |
| "NotFoundException": exceptions.NotFoundException, |
| } |
| |
| |
| def __init__(self, **kwargs): |
| region = kwargs.pop('region', None) |
| if not region: |
| region = RegionInfo(self, self.DefaultRegionName, |
| self.DefaultRegionEndpoint) |
| |
| if 'host' not in kwargs or kwargs['host'] is None: |
| kwargs['host'] = region.endpoint |
| |
| super(KMSConnection, self).__init__(**kwargs) |
| self.region = region |
| |
| def _required_auth_capability(self): |
| return ['hmac-v4'] |
| |
| def create_alias(self, alias_name, target_key_id): |
| """ |
| Creates a display name for a customer master key. An alias can |
| be used to identify a key and should be unique. The console |
| enforces a one-to-one mapping between the alias and a key. An |
| alias name can contain only alphanumeric characters, forward |
| slashes (/), underscores (_), and dashes (-). An alias must |
| start with the word "alias" followed by a forward slash |
| (alias/). An alias that begins with "aws" after the forward |
| slash (alias/aws...) is reserved by Amazon Web Services (AWS). |
| |
| :type alias_name: string |
| :param alias_name: String that contains the display name. Aliases that |
| begin with AWS are reserved. |
| |
| :type target_key_id: string |
| :param target_key_id: An identifier of the key for which you are |
| creating the alias. This value cannot be another alias. |
| |
| """ |
| params = { |
| 'AliasName': alias_name, |
| 'TargetKeyId': target_key_id, |
| } |
| return self.make_request(action='CreateAlias', |
| body=json.dumps(params)) |
| |
| def create_grant(self, key_id, grantee_principal, |
| retiring_principal=None, operations=None, |
| constraints=None, grant_tokens=None): |
| """ |
| Adds a grant to a key to specify who can access the key and |
| under what conditions. Grants are alternate permission |
| mechanisms to key policies. If absent, access to the key is |
| evaluated based on IAM policies attached to the user. By |
| default, grants do not expire. Grants can be listed, retired, |
| or revoked as indicated by the following APIs. Typically, when |
| you are finished using a grant, you retire it. When you want |
| to end a grant immediately, revoke it. For more information |
| about grants, see `Grants`_. |
| |
| #. ListGrants |
| #. RetireGrant |
| #. RevokeGrant |
| |
| :type key_id: string |
| :param key_id: A unique key identifier for a customer master key. This |
| value can be a globally unique identifier, an ARN, or an alias. |
| |
| :type grantee_principal: string |
| :param grantee_principal: Principal given permission by the grant to |
| use the key identified by the `keyId` parameter. |
| |
| :type retiring_principal: string |
| :param retiring_principal: Principal given permission to retire the |
| grant. For more information, see RetireGrant. |
| |
| :type operations: list |
| :param operations: List of operations permitted by the grant. This can |
| be any combination of one or more of the following values: |
| |
| #. Decrypt |
| #. Encrypt |
| #. GenerateDataKey |
| #. GenerateDataKeyWithoutPlaintext |
| #. ReEncryptFrom |
| #. ReEncryptTo |
| #. CreateGrant |
| |
| :type constraints: dict |
| :param constraints: Specifies the conditions under which the actions |
| specified by the `Operations` parameter are allowed. |
| |
| :type grant_tokens: list |
| :param grant_tokens: List of grant tokens. |
| |
| """ |
| params = { |
| 'KeyId': key_id, |
| 'GranteePrincipal': grantee_principal, |
| } |
| if retiring_principal is not None: |
| params['RetiringPrincipal'] = retiring_principal |
| if operations is not None: |
| params['Operations'] = operations |
| if constraints is not None: |
| params['Constraints'] = constraints |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| return self.make_request(action='CreateGrant', |
| body=json.dumps(params)) |
| |
| def create_key(self, policy=None, description=None, key_usage=None): |
| """ |
| Creates a customer master key. Customer master keys can be |
| used to encrypt small amounts of data (less than 4K) directly, |
| but they are most commonly used to encrypt or envelope data |
| keys that are then used to encrypt customer data. For more |
| information about data keys, see GenerateDataKey and |
| GenerateDataKeyWithoutPlaintext. |
| |
| :type policy: string |
| :param policy: Policy to be attached to the key. This is required and |
| delegates back to the account. The key is the root of trust. |
| |
| :type description: string |
| :param description: Description of the key. We recommend that you |
| choose a description that helps your customer decide whether the |
| key is appropriate for a task. |
| |
| :type key_usage: string |
| :param key_usage: Specifies the intended use of the key. Currently this |
| defaults to ENCRYPT/DECRYPT, and only symmetric encryption and |
| decryption are supported. |
| |
| """ |
| params = {} |
| if policy is not None: |
| params['Policy'] = policy |
| if description is not None: |
| params['Description'] = description |
| if key_usage is not None: |
| params['KeyUsage'] = key_usage |
| return self.make_request(action='CreateKey', |
| body=json.dumps(params)) |
| |
| def decrypt(self, ciphertext_blob, encryption_context=None, |
| grant_tokens=None): |
| """ |
| Decrypts ciphertext. Ciphertext is plaintext that has been |
| previously encrypted by using the Encrypt function. |
| |
| :type ciphertext_blob: blob |
| :param ciphertext_blob: Ciphertext including metadata. |
| |
| :type encryption_context: map |
| :param encryption_context: The encryption context. If this was |
| specified in the Encrypt function, it must be specified here or the |
| decryption operation will fail. For more information, see |
| `Encryption Context`_. |
| |
| :type grant_tokens: list |
| :param grant_tokens: A list of grant tokens that represent grants which |
| can be used to provide long term permissions to perform decryption. |
| |
| """ |
| if not isinstance(ciphertext_blob, six.binary_type): |
| raise TypeError( |
| "Value of argument ``ciphertext_blob`` " |
| "must be of type %s." % six.binary_type) |
| ciphertext_blob = base64.b64encode(ciphertext_blob) |
| params = {'CiphertextBlob': ciphertext_blob, } |
| if encryption_context is not None: |
| params['EncryptionContext'] = encryption_context |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| response = self.make_request(action='Decrypt', |
| body=json.dumps(params)) |
| if response.get('Plaintext') is not None: |
| response['Plaintext'] = base64.b64decode( |
| response['Plaintext'].encode('utf-8')) |
| return response |
| |
| def delete_alias(self, alias_name): |
| """ |
| Deletes the specified alias. |
| |
| :type alias_name: string |
| :param alias_name: The alias to be deleted. |
| |
| """ |
| params = {'AliasName': alias_name, } |
| return self.make_request(action='DeleteAlias', |
| body=json.dumps(params)) |
| |
| def describe_key(self, key_id): |
| """ |
| Provides detailed information about the specified customer |
| master key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master key to be |
| described. This can be an ARN, an alias, or a globally unique |
| identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='DescribeKey', |
| body=json.dumps(params)) |
| |
| def disable_key(self, key_id): |
| """ |
| Marks a key as disabled, thereby preventing its use. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master key to be |
| disabled. This can be an ARN, an alias, or a globally unique |
| identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='DisableKey', |
| body=json.dumps(params)) |
| |
| def disable_key_rotation(self, key_id): |
| """ |
| Disables rotation of the specified key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master key for which |
| rotation is to be disabled. This can be an ARN, an alias, or a |
| globally unique identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='DisableKeyRotation', |
| body=json.dumps(params)) |
| |
| def enable_key(self, key_id): |
| """ |
| Marks a key as enabled, thereby permitting its use. You can |
| have up to 25 enabled keys at one time. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master key to be |
| enabled. This can be an ARN, an alias, or a globally unique |
| identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='EnableKey', |
| body=json.dumps(params)) |
| |
| def enable_key_rotation(self, key_id): |
| """ |
| Enables rotation of the specified customer master key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master key for which |
| rotation is to be enabled. This can be an ARN, an alias, or a |
| globally unique identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='EnableKeyRotation', |
| body=json.dumps(params)) |
| |
| def encrypt(self, key_id, plaintext, encryption_context=None, |
| grant_tokens=None): |
| """ |
| Encrypts plaintext into ciphertext by using a customer master |
| key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the customer master. This can be an |
| ARN, an alias, or the Key ID. |
| |
| :type plaintext: blob |
| :param plaintext: Data to be encrypted. |
| |
| :type encryption_context: map |
| :param encryption_context: Name:value pair that specifies the |
| encryption context to be used for authenticated encryption. For |
| more information, see `Authenticated Encryption`_. |
| |
| :type grant_tokens: list |
| :param grant_tokens: A list of grant tokens that represent grants which |
| can be used to provide long term permissions to perform encryption. |
| |
| """ |
| if not isinstance(plaintext, six.binary_type): |
| raise TypeError( |
| "Value of argument ``plaintext`` " |
| "must be of type %s." % six.binary_type) |
| plaintext = base64.b64encode(plaintext) |
| params = {'KeyId': key_id, 'Plaintext': plaintext, } |
| if encryption_context is not None: |
| params['EncryptionContext'] = encryption_context |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| response = self.make_request(action='Encrypt', |
| body=json.dumps(params)) |
| if response.get('CiphertextBlob') is not None: |
| response['CiphertextBlob'] = base64.b64decode( |
| response['CiphertextBlob'].encode('utf-8')) |
| return response |
| |
| def generate_data_key(self, key_id, encryption_context=None, |
| number_of_bytes=None, key_spec=None, |
| grant_tokens=None): |
| """ |
| Generates a secure data key. Data keys are used to encrypt and |
| decrypt data. They are wrapped by customer master keys. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type encryption_context: map |
| :param encryption_context: Name/value pair that contains additional |
| data to be authenticated during the encryption and decryption |
| processes that use the key. This value is logged by AWS CloudTrail |
| to provide context around the data encrypted by the key. |
| |
| :type number_of_bytes: integer |
| :param number_of_bytes: Integer that contains the number of bytes to |
| generate. Common values are 128, 256, 512, 1024 and so on. 1024 is |
| the current limit. |
| |
| :type key_spec: string |
| :param key_spec: Value that identifies the encryption algorithm and key |
| size to generate a data key for. Currently this can be AES_128 or |
| AES_256. |
| |
| :type grant_tokens: list |
| :param grant_tokens: A list of grant tokens that represent grants which |
| can be used to provide long term permissions to generate a key. |
| |
| """ |
| params = {'KeyId': key_id, } |
| if encryption_context is not None: |
| params['EncryptionContext'] = encryption_context |
| if number_of_bytes is not None: |
| params['NumberOfBytes'] = number_of_bytes |
| if key_spec is not None: |
| params['KeySpec'] = key_spec |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| response = self.make_request(action='GenerateDataKey', |
| body=json.dumps(params)) |
| if response.get('CiphertextBlob') is not None: |
| response['CiphertextBlob'] = base64.b64decode( |
| response['CiphertextBlob'].encode('utf-8')) |
| if response.get('Plaintext') is not None: |
| response['Plaintext'] = base64.b64decode( |
| response['Plaintext'].encode('utf-8')) |
| return response |
| |
| def generate_data_key_without_plaintext(self, key_id, |
| encryption_context=None, |
| key_spec=None, |
| number_of_bytes=None, |
| grant_tokens=None): |
| """ |
| Returns a key wrapped by a customer master key without the |
| plaintext copy of that key. To retrieve the plaintext, see |
| GenerateDataKey. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type encryption_context: map |
| :param encryption_context: Name:value pair that contains additional |
| data to be authenticated during the encryption and decryption |
| processes. |
| |
| :type key_spec: string |
| :param key_spec: Value that identifies the encryption algorithm and key |
| size. Currently this can be AES_128 or AES_256. |
| |
| :type number_of_bytes: integer |
| :param number_of_bytes: Integer that contains the number of bytes to |
| generate. Common values are 128, 256, 512, 1024 and so on. |
| |
| :type grant_tokens: list |
| :param grant_tokens: A list of grant tokens that represent grants which |
| can be used to provide long term permissions to generate a key. |
| |
| """ |
| params = {'KeyId': key_id, } |
| if encryption_context is not None: |
| params['EncryptionContext'] = encryption_context |
| if key_spec is not None: |
| params['KeySpec'] = key_spec |
| if number_of_bytes is not None: |
| params['NumberOfBytes'] = number_of_bytes |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| response = self.make_request(action='GenerateDataKeyWithoutPlaintext', |
| body=json.dumps(params)) |
| if response.get('CiphertextBlob') is not None: |
| response['CiphertextBlob'] = base64.b64decode( |
| response['CiphertextBlob'].encode('utf-8')) |
| return response |
| |
| def generate_random(self, number_of_bytes=None): |
| """ |
| Generates an unpredictable byte string. |
| |
| :type number_of_bytes: integer |
| :param number_of_bytes: Integer that contains the number of bytes to |
| generate. Common values are 128, 256, 512, 1024 and so on. The |
| current limit is 1024 bytes. |
| |
| """ |
| params = {} |
| if number_of_bytes is not None: |
| params['NumberOfBytes'] = number_of_bytes |
| response = self.make_request(action='GenerateRandom', |
| body=json.dumps(params)) |
| if response.get('Plaintext') is not None: |
| response['Plaintext'] = base64.b64decode( |
| response['Plaintext'].encode('utf-8')) |
| return response |
| |
| def get_key_policy(self, key_id, policy_name): |
| """ |
| Retrieves a policy attached to the specified key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type policy_name: string |
| :param policy_name: String that contains the name of the policy. |
| Currently, this must be "default". Policy names can be discovered |
| by calling ListKeyPolicies. |
| |
| """ |
| params = {'KeyId': key_id, 'PolicyName': policy_name, } |
| return self.make_request(action='GetKeyPolicy', |
| body=json.dumps(params)) |
| |
| def get_key_rotation_status(self, key_id): |
| """ |
| Retrieves a Boolean value that indicates whether key rotation |
| is enabled for the specified key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| """ |
| params = {'KeyId': key_id, } |
| return self.make_request(action='GetKeyRotationStatus', |
| body=json.dumps(params)) |
| |
| def list_aliases(self, limit=None, marker=None): |
| """ |
| Lists all of the key aliases in the account. |
| |
| :type limit: integer |
| :param limit: Specify this parameter when paginating results to |
| indicate the maximum number of aliases you want in each response. |
| If there are additional aliases beyond the maximum you specify, the |
| `Truncated` response element will be set to `true.` |
| |
| :type marker: string |
| :param marker: Use this parameter when paginating results, and only in |
| a subsequent request after you've received a response where the |
| results are truncated. Set it to the value of the `NextMarker` |
| element in the response you just received. |
| |
| """ |
| params = {} |
| if limit is not None: |
| params['Limit'] = limit |
| if marker is not None: |
| params['Marker'] = marker |
| return self.make_request(action='ListAliases', |
| body=json.dumps(params)) |
| |
| def list_grants(self, key_id, limit=None, marker=None): |
| """ |
| List the grants for a specified key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type limit: integer |
| :param limit: Specify this parameter only when paginating results to |
| indicate the maximum number of grants you want listed in the |
| response. If there are additional grants beyond the maximum you |
| specify, the `Truncated` response element will be set to `true.` |
| |
| :type marker: string |
| :param marker: Use this parameter only when paginating results, and |
| only in a subsequent request after you've received a response where |
| the results are truncated. Set it to the value of the `NextMarker` |
| in the response you just received. |
| |
| """ |
| params = {'KeyId': key_id, } |
| if limit is not None: |
| params['Limit'] = limit |
| if marker is not None: |
| params['Marker'] = marker |
| return self.make_request(action='ListGrants', |
| body=json.dumps(params)) |
| |
| def list_key_policies(self, key_id, limit=None, marker=None): |
| """ |
| Retrieves a list of policies attached to a key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type limit: integer |
| :param limit: Specify this parameter only when paginating results to |
| indicate the maximum number of policies you want listed in the |
| response. If there are additional policies beyond the maximum you |
| specify, the `Truncated` response element will be set to `true.` |
| |
| :type marker: string |
| :param marker: Use this parameter only when paginating results, and |
| only in a subsequent request after you've received a response where |
| the results are truncated. Set it to the value of the `NextMarker` |
| in the response you just received. |
| |
| """ |
| params = {'KeyId': key_id, } |
| if limit is not None: |
| params['Limit'] = limit |
| if marker is not None: |
| params['Marker'] = marker |
| return self.make_request(action='ListKeyPolicies', |
| body=json.dumps(params)) |
| |
| def list_keys(self, limit=None, marker=None): |
| """ |
| Lists the customer master keys. |
| |
| :type limit: integer |
| :param limit: Specify this parameter only when paginating results to |
| indicate the maximum number of keys you want listed in the |
| response. If there are additional keys beyond the maximum you |
| specify, the `Truncated` response element will be set to `true.` |
| |
| :type marker: string |
| :param marker: Use this parameter only when paginating results, and |
| only in a subsequent request after you've received a response where |
| the results are truncated. Set it to the value of the `NextMarker` |
| in the response you just received. |
| |
| """ |
| params = {} |
| if limit is not None: |
| params['Limit'] = limit |
| if marker is not None: |
| params['Marker'] = marker |
| return self.make_request(action='ListKeys', |
| body=json.dumps(params)) |
| |
| def put_key_policy(self, key_id, policy_name, policy): |
| """ |
| Attaches a policy to the specified key. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key. This can be an ARN, an |
| alias, or a globally unique identifier. |
| |
| :type policy_name: string |
| :param policy_name: Name of the policy to be attached. Currently, the |
| only supported name is "default". |
| |
| :type policy: string |
| :param policy: The policy, in JSON format, to be attached to the key. |
| |
| """ |
| params = { |
| 'KeyId': key_id, |
| 'PolicyName': policy_name, |
| 'Policy': policy, |
| } |
| return self.make_request(action='PutKeyPolicy', |
| body=json.dumps(params)) |
| |
| def re_encrypt(self, ciphertext_blob, destination_key_id, |
| source_encryption_context=None, |
| destination_encryption_context=None, grant_tokens=None): |
| """ |
| Encrypts data on the server side with a new customer master |
| key without exposing the plaintext of the data on the client |
| side. The data is first decrypted and then encrypted. This |
| operation can also be used to change the encryption context of |
| a ciphertext. |
| |
| :type ciphertext_blob: blob |
| :param ciphertext_blob: Ciphertext of the data to re-encrypt. |
| |
| :type source_encryption_context: map |
| :param source_encryption_context: Encryption context used to encrypt |
| and decrypt the data specified in the `CiphertextBlob` parameter. |
| |
| :type destination_key_id: string |
| :param destination_key_id: Key identifier of the key used to re-encrypt |
| the data. |
| |
| :type destination_encryption_context: map |
| :param destination_encryption_context: Encryption context to be used |
| when the data is re-encrypted. |
| |
| :type grant_tokens: list |
| :param grant_tokens: Grant tokens that identify the grants that have |
| permissions for the encryption and decryption process. |
| |
| """ |
| if not isinstance(ciphertext_blob, six.binary_type): |
| raise TypeError( |
| "Value of argument ``ciphertext_blob`` " |
| "must be of type %s." % six.binary_type) |
| ciphertext_blob = base64.b64encode(ciphertext_blob) |
| params = { |
| 'CiphertextBlob': ciphertext_blob, |
| 'DestinationKeyId': destination_key_id, |
| } |
| if source_encryption_context is not None: |
| params['SourceEncryptionContext'] = source_encryption_context |
| if destination_encryption_context is not None: |
| params['DestinationEncryptionContext'] = destination_encryption_context |
| if grant_tokens is not None: |
| params['GrantTokens'] = grant_tokens |
| response = self.make_request(action='ReEncrypt', |
| body=json.dumps(params)) |
| if response.get('CiphertextBlob') is not None: |
| response['CiphertextBlob'] = base64.b64decode( |
| response['CiphertextBlob'].encode('utf-8')) |
| return response |
| |
| def retire_grant(self, grant_token): |
| """ |
| Retires a grant. You can retire a grant when you're done using |
| it to clean up. You should revoke a grant when you intend to |
| actively deny operations that depend on it. |
| |
| :type grant_token: string |
| :param grant_token: Token that identifies the grant to be retired. |
| |
| """ |
| params = {'GrantToken': grant_token, } |
| return self.make_request(action='RetireGrant', |
| body=json.dumps(params)) |
| |
| def revoke_grant(self, key_id, grant_id): |
| """ |
| Revokes a grant. You can revoke a grant to actively deny |
| operations that depend on it. |
| |
| :type key_id: string |
| :param key_id: Unique identifier of the key associated with the grant. |
| |
| :type grant_id: string |
| :param grant_id: Identifier of the grant to be revoked. |
| |
| """ |
| params = {'KeyId': key_id, 'GrantId': grant_id, } |
| return self.make_request(action='RevokeGrant', |
| body=json.dumps(params)) |
| |
| def update_key_description(self, key_id, description): |
| """ |
| |
| |
| :type key_id: string |
| :param key_id: |
| |
| :type description: string |
| :param description: |
| |
| """ |
| params = {'KeyId': key_id, 'Description': description, } |
| return self.make_request(action='UpdateKeyDescription', |
| body=json.dumps(params)) |
| |
| def make_request(self, action, body): |
| headers = { |
| 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), |
| 'Host': self.region.endpoint, |
| 'Content-Type': 'application/x-amz-json-1.1', |
| 'Content-Length': str(len(body)), |
| } |
| http_request = self.build_base_http_request( |
| method='POST', path='/', auth_path='/', params={}, |
| headers=headers, data=body) |
| response = self._mexe(http_request, sender=None, |
| override_num_retries=10) |
| response_body = response.read().decode('utf-8') |
| boto.log.debug(response_body) |
| if response.status == 200: |
| if response_body: |
| return json.loads(response_body) |
| else: |
| json_body = json.loads(response_body) |
| fault_name = json_body.get('__type', None) |
| exception_class = self._faults.get(fault_name, self.ResponseError) |
| raise exception_class(response.status, response.reason, |
| body=json_body) |
| |