Using AWS SSM Parameter Store to Retrieve Secrets Encrypted by KMS Using Python
Today we will use Amazon Web Services SSM Service to store secrets in their Parameter Store which we will encyrpt using KMS.
Then we will read the data from SSM and decrypt using our KMS key. We will then end it off by writing a Python Script that reads the AWS credentials, authenticates with SSM and then read the secret values that we stored.
The Do List:
We will break up this post in the following topics:
Create a KMS Key which will use to Encrypt/Decrypt the Parameter in SSM
Create the IAM Policy which will be used to authorize the Encrypt/Decrypt by the KMS ID
Create the KMS Alias
Create the Parameter using PutParameter as a SecureString to use Encryption with KMS
Describe the Parameters
Read the Parameter with and without Decryption to determine the difference using GetParameter
Read the Parameters using GetParameters
Environment Variable Example
Create the KMS Key:
As the administrator, or root account, create the KMS Key:
1234567891011121314
>>>importboto3>>>session=boto3.Session(region_name='eu-west-1',profile_name='personal')>>>iam=session.client('iam')>>>kms=session.client('kms')>>>response=kms.create_key(Description='Ruan Test Key',KeyUsage='ENCRYPT_DECRYPT',Origin='AWS_KMS',BypassPolicyLockoutSafetyCheck=False,Tags=[{'TagKey':'Name','TagValue':'RuanTestKey'}])>>>print(response['KeyMetadata']['KeyId'])foobar-2162-4363-ba02-a953729e5ce6
Create the IAM Policy:
123456789101112131415161718
>>>response=iam.create_policy(PolicyName='ruan-kms-test-policy',PolicyDocument='{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1517212478199","Action":["kms:Decrypt","kms:Encrypt"],"Effect":"Allow","Resource":"arn:aws:kms:eu-west-1:0123456789012:key/foobar-2162-4363-ba02-a953729e5ce6"}]}', Description='Ruan KMS Test Policy')>>>print(response['Policy']['Arn'])arn:aws:iam::0123456789012:policy/ruan-kms-test-policy
As the administrator, write the secret values to the parameter store in SSM. We will publish a secret with the Parameter: /test/ruan/mysql/db01/mysql_hostname and the Value: db01.eu-west-1.mycompany.com:
123456789101112131415
>>>fromgetpassimportgetpass>>>secretvalue=getpass()Password:>>>print(secretvalue)db01.eu-west-1.mycompany.com>>>response=ssm.put_parameter(Name='/test/ruan/mysql/db01/mysql_hostname',Description='RuanTest MySQL Hostname',Value=secretvalue,Type='SecureString',KeyId='foobar-2162-4363-ba02-a953729e5ce6',Overwrite=False)
Now we will create a policy that can only decrypt and read values from SSM that matches the path: /test/ruan/mysql/db01/mysql_*. This policy will be associated to a instance profile role, which will be used by EC2, where our application will read the values from.