Coder Social home page Coder Social logo

binxio / cfn-secret-provider Goto Github PK

View Code? Open in Web Editor NEW
141.0 7.0 72.0 392 KB

A CloudFormation custom resource provider for deploying secrets and keys

License: Apache License 2.0

Makefile 5.51% Python 92.80% Shell 1.69%
aws-cloudformation aws-ssm credentials deployment rsa-key keypair aws

cfn-secret-provider's Introduction

cfn-secret-provider

A CloudFormation custom resource provider for managing secrets, private keys and EC2 key pairs.

One of the biggest problems I encounter in creating immutable infrastructures, is dealing with secrets. Secrets must always be different per environment and therefore parameterized. As we automated all the things passwords often end up in parameter files and have to pass them around to people and applications: This is not a good thing. With this Custom CloudFormation Resource we put an end to that. Secrets are generated, stored in the EC2 parameter store and access to the secrets can be controlled through security policies.

How do I generate a secret?

It is quite easy: you specify a CloudFormation resource of the Custom::Secret, as follows:

  DBPassword:
    Type: Custom::Secret
    Properties:
      Name: /demo/PGPASSWORD
      KeyAlias: alias/aws/ssm
      Alphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      Length: 30
      ReturnSecret: true
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

After the deployment, a 30 character random string can be found in the EC Parameter Store with the name /demo/PGPASSWORD.

If you need to access the secret in your cloudformation module, you need to specify ReturnSecret and reference it as the attribute Secret.

  Database:
    Type: AWS::RDS::DBInstance
    Properties:
      MasterUserPassword: !GetAtt 'DBPassword.Secret'

How do I add a private key?

In the same manner you can specify a RSA private key as a CloudFormation resource of the Custom::RSAKey:

  PrivateKey:
    Type: Custom::RSAKey
    Properties:
      Name: /demo/private-key
      KeyAlias: alias/aws/ssm
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

After the deployment, a the newly generated private key can be found in the EC2 Parameter Store under the name /demo/private-key:

$ aws ssm get-parameter --name /demo/private-key --with-decryption --query Parameter.Value --output text

If you need to access the public key of the newly generated private key, you can reference it as the attribute PublicKey. Most likely, you would use this in the Custom::KeyPair resource, to create a EC2 key pair:

       KeyPair:
         Type: Custom::KeyPair
         DependsOn: CustomPrivateKey
         Properties:
           Name: CustomKeyPair
           PublicKeyMaterial: !GetAtt 'PrivateKey.PublicKey'
           ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

This will create the ec2 key pair for you named CustomKeyPair, based on the generated private key. Now private key is securely stored in the EC2 Parameter Store and the public key can be used to gain access to specific EC2 instances. See Amazon EC2 Key Pairs for more information.

Installation

To install these custom resources, type:

aws cloudformation create-stack \
       --capabilities CAPABILITY_IAM \
       --stack-name cfn-secret-provider \
       --template-body file://cloudformation/cfn-resource-provider.yaml

aws cloudformation wait stack-create-complete  --stack-name cfn-secret-provider 

This CloudFormation template will use our pre-packaged provider from s3://binxio-public-${AWS_REGION}/lambdas/cfn-secret-provider-2.0.1.zip.

or use

Demo

To install the simple sample of the Custom Resource, type:

aws cloudformation create-stack \
    --capabilities CAPABILITY_NAMED_IAM \
    --stack-name cfn-secret-provider-demo \
    --template-body file://cloudformation/demo-stack.yaml
aws cloudformation wait stack-create-complete  --stack-name cfn-secret-provider-demo

to validate the result, type:

aws ssm get-parameter --name /cfn-secret-provider-demo/demo/PGPASSWORD --with-decryption
aws ssm get-parameter --name /cfn-secret-provider-demo/demo/private-key  --with-decryption
aws ec2 --output text describe-key-pairs --key-names cfn-secret-provider-demo-custom-key-pair

Conclusion

With this solution:

  • secrets are generated per environment
  • always stored encrypted in the parameter store
  • where access to the secrets is audited and controlled!

cfn-secret-provider's People

Contributors

anwbtom avatar chiefbiiko avatar darkibot avatar dependabot[bot] avatar ingcsmoreno avatar mvanholsteijn avatar rogerchi avatar rubendg avatar xiaket avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfn-secret-provider's Issues

Installation Demo seems out of date

aws cloudformation create-stack \
	--capabilities CAPABILITY_IAM \
	--stack-name cfn-secret-provider \
	--template-body file://cloudformation/cfn-resource-provider.json

fails with:

An error occurred (ValidationError) when calling the CreateStack operation: Template format error: unsupported structure.

I checked the folder and found it is a Yaml file, so made that change and it worked:

aws cloudformation create-stack \
	--capabilities CAPABILITY_IAM \
	--stack-name cfn-secret-provider \
	--template-body file://cloudformation/cfn-resource-provider.yaml

Set NoEcho on response to keep return Secret hidden

Thanks for this and the cfn-resource-provider. It goes a long way to make my job easier!

If the ReturnSecret option is used, it appears that the value will still show up in CloudFormation.

According to these AWS Docs, we should be able to set the NoEcho parameter to keep the secret a secret.

This will be important for me, as the only interface my service engineers have with AWS is CloudFormation. So they will be using the CloudFormation console and seeing templates.

I may have missed something, but I couldn't find a reference to "NoEcho" anywhere in this repo.

I would be happy to open up a PR if it would be welcome.

stack update fails with current FunctionName

Thanks for awesome work.

The current function naming fails with stack updates, suggest instead the following FunctionName which works with stack updates/change sets:

...
        S3Key: !Ref 'CFNCustomProviderZipFileName'
      FunctionName: !Join [ '-', [ 'binxio-cfn-secret-provider', !Select [ 2, !Split [ '/', !Ref 'AWS::StackId' ]]]]
      Handler: secrets.handler
...

Error: The key pair 'arn:aws:ec2:<region>:<account_id>:keypair/CustomKeyPair' does not exist

I've added these resources to a cloudformation template and the keypair is successfully created. The same keypair is a dependency of the instance I'm trying to create and is referenced by it like so:

  KeyPair:
    Type: Custom::KeyPair
    DependsOn:
      - CFNSecretProvider
      - PrivateKey
    Properties:
      Name: CustomKeyPair
      PublicKeyMaterial: !GetAtt
        - PrivateKey
        - PublicKey
      ServiceToken: !Join
        - ":"
        - - arn:aws:lambda
          - !Ref "AWS::Region"
          - !Ref "AWS::AccountId"
          - !Ref CFNSecretProvider

...

  EC2Instance:
    Type: AWS::EC2::Instance
    DependsOn:
     - CertBucket
     - KeyPair
     - InstanceProfile
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      InstanceType: !Ref InstanceType
      ImageId: !FindInMap [AWSRegionToAMI, !Ref "AWS::Region", AMI]
      KeyName: !Ref KeyPair
      ...

However, when the instance is created, I get an error saying the key pair doesn't exist. Looking in the event log, the keypair is successfully created, and I can see it in the EC2 console. Any idea what the issue is?

Arn of PrivateKey and DBPassword has extra /

The demo-stack.yaml CloudFormation template example outputs:

$ aws cloudformation describe-stacks --stack-name demo
{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:...:stack/demo/6f1c99c0-2bae-11e9-bb8d-0e23fbf2c85e",
            "StackName": "demo",
            "Description": "Demo Custom CloudFormation Secret Provider",
            "Parameters": [
                {
                    "ParameterKey": "ApiKey",
                    "ParameterValue": ""
                }
            ],
            "CreationTime": "2019-02-08T14:33:00.168Z",
            "LastUpdatedTime": "2019-02-08T14:41:50.150Z",
            "RollbackConfiguration": {
                "RollbackTriggers": []
            },
            "StackStatus": "UPDATE_ROLLBACK_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_NAMED_IAM"
            ],
            "Outputs": [
...
                {
                    "OutputKey": "PrivateKeyArn",
                    "OutputValue": "arn:aws:ssm:us-east-1:225162606092:parameter//demo/demo/private-key",
                    "Description": "ARN of the private key in the Parameter Store"
                },
...
                {
                    "OutputKey": "Arn",
                    "OutputValue": "arn:aws:ssm:us-east-1:225162606092:parameter//demo/demo/PGPASSWORD",
                    "Description": "ARN of the password in the Parameter Store"
                },
...
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

Both of these SSM parameter store arns output there appear to have an extra "/" in the Arn. I assume this is a bug in the Lambda function(s), since the CloudFormation template isn't doesn't manipulate the Arn or the name.

When you ask SSM to describe the relevant parameters you get this:

$ aws ssm get-parameter --name /demo/demo/private-key
{
    "Parameter": {
        "Name": "/demo/demo/private-key",
        "Type": "SecureString",
        "Value": "AQICAHgBm2QT3JUOxkIKMnuHXtEk3CmrUYfMurx85z60f5vXngHhBMuIU1MjSvx07MJqi7QNAAAH...
VkiMO4D5cCrO/1u6N28XQqPToUPqATVmL47oQb7UeLI2K4Tn9JLnquH2",
        "Version": 1,
        "LastModifiedDate": 1549636390.838,
        "ARN": "arn:aws:ssm:us-east-1:225162606092:parameter/demo/demo/private-key"
    }
}

$ aws ssm get-parameter --name /demo/demo/PGPASSWORD
{
    "Parameter": {
        "Name": "/demo/demo/PGPASSWORD",
        "Type": "SecureString",
        "Value": "AQICAHgBm2QT3JUOxkIKMnuHXtEk3CmrUYfMurx85z60f5vXngFEYAtCUKuCUp9S0R6pNc1HAAA...4k/R6QMZOCq+UcDw=",
        "Version": 2,
        "LastModifiedDate": 1549636945.698,
        "ARN": "arn:aws:ssm:us-east-1:225162606092:parameter/demo/demo/PGPASSWORD"
    }
}

reuse secret across stacks?

Is it possible to reuse secrets/keys on different stacks?

At the moment I Get:
Custom::Secret CREATE_FAILED Failed to create resource. An error occurred (ParameterAlreadyExists) when calling the PutParameter operation: The parameter already exists. To overwrite this value, set the overwrite option in the request to true.
the use case is that I would like to reuse the value for redshift cfn template where I can destroy a redshift cluster with a deletepolicy of Snapshot and rebuild adding a reference to said snapshot.

Support for Lamda Python 3.8 Environment

Current 1.3.1 deployment pack is not compatible with AWS lambda Python 3.8 environment.

Error is:

ModuleNotFoundError: No module named '_cffi_backend'

This is most probably solvable by just rebuilding the package in a 3.8 environment.

CDK port

I'm currently working on porting this to AWS CDK. I'm writing this Typescript.

Would you be interested in having this in this repo or should I keep it separate? I'm fine with both options, but think it makes more sense if everything is kept together.

On the other hand I don't know how comfortable you are with having Typescript and CDK code in here.

Invalid PhysicalResourceId when creating AccessKeys

For some reason I am not able to use this to create access keys. I think I am following the documentation but I always end up getting the error 'Invalid PhysicalResourceId' when trying to create the keys. I have used the RSAKey, KeyPair and Secrets just fine so I believe the custom resource has been deployed properly.

Here is the relevant section from my cfn template:

JenkinsAccessKeys:
Type: Custom::AccessKey
DependsOn: CFNSecretProvider
Properties:
Description: 'jenkins-deployer user credential'
UserName: 'jenkins-deployer'
ParameterPath: 'jenkins.access.keys'
Serial: 0
Status: Active
ReturnSecret: true
ReturnPassword: true
NoEcho: true
ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

Any advice here?

Description change generates new secret

I recently updated from version v0.12.3 to v1.1.1 because of issue #25.
Updating the description (or any other property) with this new version is also triggering the generation of a new secret!
Is this expected behaviour in this new version?

  Secret:
    Type: Custom::Secret
    Properties:
      Name: '/foo/bar'
      Description: Foo Bar
      Alphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      Length: 30
      ReturnSecret: True
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:cfn-secret-provider'

Looking at the code I think the self.refresh_on_update should be called as function, not as property?
https://github.com/binxio/cfn-secret-provider/blob/master/src/cfn_secret_provider.py#L251

Store RSAKey in secret manager instead of parameter store

Is it possible to modify some setting to store RSA private key (key pair) in Secret Manager instead of parameter store?
I always use secret manager for every other secret and would be great if I could continue doing so for private keys.
This is my sample:

Resources:
  privateKey:
    Type: Custom::RSAKey
    Properties:
      Name: !Ref rsaKeyName
      KeySize: 4096
      KeyFormat: PKCS8
      Description: SSH key for Bastion Host EC2 instances
      ServiceToken: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider
      RefreshOnUpdate: false
  keyPair:
    Type: Custom::KeyPair
    DependsOn: privateKey
    Properties:
      Name: !Ref keyPairName
      PublicKeyMaterial: !GetAtt privateKey.PublicKey
      ServiceToken: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider

Failed to create resource. No module named '_cffi_backend'

Hey,

I just updated a template I've been using from version 0.13.3 to 1.0.0 but got the error message below when trying to create a resource with cloudformation that calls this function. Rolling the function back to v0.13.3 worked, but given AWS lambda's sunsetting support for python < v3 I'd like update our template to use your v1.0.0.

Have you run into this error before or having any idea how to resolve it? Thanks in advance!

Failed to create resource. No module named '_cffi_backend'

RSAKey 'Description' field does not accept a purely numeric string.

On RSAKey, the 'Description' field does not accept a purely numeric string.

Failed to update resource. invalid resource properties: 20180131 is not of type 'string' Failed validating 'type' in schema['properties']['Description']: {'default': '', 'description': 'the description of the key in the parameter store', 'type': 'string'} On instance['Description']: 20180131

As RSAKey does not provide the Version attribute from the resource, our plan was to use Description to version keys using a date string.

Thanks.

The parameter already exists error when updating cloudformation stack containing Custom::RSAKey

Occasionally when updating a cloud formation stack that contains a Custom::RSAKey the following error is thrown:

Failed to create resource. An error occurred (ParameterAlreadyExists) when calling the PutParameter operation: The parameter already exists. To overwrite this value, set the overwrite option in the request to true.

This has also been observed when deleting and recreating the stack.

The fix is to manually delete the parameter in the SSM parameter store.

I wonder whether, as per the suggestion in the error message, the code could be changed to overwrite existing parameters ?

CFN is returning SSMPutParameter Access denied

I am running your CFN to create the key pair generating lambda function. I have made no edits to your code but I am getting an error.

Failed to create resource. An error occurred (AccessDeniedException) when calling the PutParameter operation: User: arn:aws:sts::xxxxxxxxxx:assumed-role/Research3-LambdaRole-87IICXNLGUL3/binxio-cfn-secret-provider is not authorized to perform: ssm:PutParameter on resource: arn:aws:ssm:us-east-1:xxxxxxxxx:parameter/app/Research3/demo/private-key

Deploy RSA Service in Boundary?

Is there a way to deploy your RSA Service in our own account? Security may not like us making calls to an external service for private key generation.

Error deploying lambda

We are attempting to deploy the latest version 1.4.0 to one of our AWS accounts in us-east-1 and it's failing with an error that python runtime 3.9 is not available for lambda.

Add secrets-manager secrets rotation support

The secrets manager implementation as currently implemented does not support automatic secrets rotation.
The two extra fields needed are a lambda and an interval.

PR coming soon

Add support for secret usage from other stacks

Currently, it is not possible to create Custom::Secret in multiple stacks referencing the same Secure String on AWS SSM.

In my use case, I am creating a VPN Connection with a partner and, for the AWS::EC2::VPNConnection I have to set a pre-shared key. I have a stack that is responsible for all SSM parameters, and I've created a key using the Custom::Secret resource. Now, from the VPN Stack, I was hoping to create the same resource and be able to get the secret's value.

However, when I try to create my VPN Stack, CloudFormation gives me the following error:
Failed to create resource. An error occurred (ParameterAlreadyExists) when calling the PutParameter operation: The parameter already exists. To overwrite this value, set the overwrite option in the request to true.
which, in my opinion, should not happen. Instead, we could have an option like DontRecreate meaning I know the secret already exists and I'm only interested on getting its value back.

If you could give me instructions on how to do that, I would be more than happy to contribute with a Pull Request to resolve this.

custom::secret resource password policy

If i wanted to generate a secret that is according to a password policy with

  1. atleast one lower case
  2. atleast one upper case
  3. atleast one of the special chars
  4. atleast one number

how do i do it ? currently there is only the "alphabet" property on resource.

if there were alphabet1, alphabet2, alphabet3 etc available then i could provide different alphabet sets. is there some other workaround ?

Custom::RotatingSecret to generate primary/secondary secrets

Hello

We are using this resource a lot.

What we wanted to do was to have primary and secondary secrets.

Encrypting code would always encrypt from primary secret, while decrypting code would first try primary and if it fails then secondary.

At a set interval then, we would

  1. move primary secret to secondary
  2. generate a new primary and store it in primary secret

This would allow us to have a rotating secret.

Would it be possible to enhance this to support something like Custom::RotatingSecret with (a) cron expression (b) primary ssm (c) secondary ssm ?

Thank you

Cannot use Custom:RSAkey for Windows?

I have a stack with

Resources:
  PrivateKey:
    Type: Custom::RSAKey
    Properties:
      Name: !Sub '/app/${AWS::StackName}/demo/private-key'
      Version: v1
      NoEcho: False
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

  KeyPair:
    Type: Custom::KeyPair
    DependsOn: PrivateKey
    Properties:
      Name: !Sub '${AWS::StackName}-custom-key-pair'
      NoEcho: False
      PublicKeyMaterial: !GetAtt 'PrivateKey.PublicKey'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: vpc-XXX
      GroupDescription: Enable HTTP access via user defined port
      SecurityGroupIngress:
      - CidrIp: 0.0.0.0/0
        FromPort: 0
        IpProtocol: tcp
        ToPort: 65422
  Ec2InstanceWin:
    Type: AWS::EC2::Instance
    DependsOn: KeyPair
    Properties:
      Tags:
        -
          Key: Name
          Value: testinstance
        -
          Key: project
          Value: testproject
      ImageId: ami-xxx-<<WINDOWS>> 
      KeyName: !Sub '${AWS::StackName}-custom-key-pair'
      InstanceType: t2.xlarge
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      SubnetId: subnet-XXXX
      UserData:
        Fn::Base64: !Sub |
          <powershell>
          </powershell>

  Ec2InstanceLin:
    Type: AWS::EC2::Instance
    DependsOn: KeyPair
    Properties:
      Tags:
        -
          Key: Name
          Value: testinstance
        -
          Key: project
          Value: testproject
      ImageId: ami-xxx-<<LINUX>> 
      KeyName: !Sub '${AWS::StackName}-custom-key-pair'
      InstanceType: t2.xlarge
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      SubnetId: subnet-XXXX

by creating a stack called foobar4 I can see:

aws ec2 describe-key-pairs --key-names foobar4-custom-key-pair
{
    "KeyPairs": [
        {
            "KeyFingerprint": "56:bf:29:bd:93:53:5b:08:f0:a4:47:73:6b:3b:ff:5c",
            "KeyName": "foobar4-custom-key-pair"
        }
    ]
}

However when running:

$ aws ssm  get-parameter --name /app/foobar4/demo/private-key --with-decryption --query Parameter.Value --output text > /tmp/foobar4.pem
$ chmod 400 /tmp/foobar4.pem
$  ssh-keygen -E md5 -lf /tmp/foobar4.pem
2048 MD5:7d:c4:40:2e:6c:7c:8f:ce:0f:d7:44:c6:8b:0b:24:ff no comment (RSA)
$ openssl pkey -in /tmp/foobar4.pem -pubout -outform DER | openssl md5 -c
56:bf:29:bd:93:53:5b:08:f0:a4:47:73:6b:3b:ff:5c

And then trying to get a windows password for

$ aws ec2 describe-instances --instance-id  i-0618f6cc80eb9b577  --query Reservations[0].Instances[0].KeyName
"foobar4-custom-key-pair"

$ aws ec2 get-password-data --instance-id i-0618f6cc80eb9b577 --priv-launch-key /tmp/foobar4.pem
Unable to decrypt password data using provided private key file.

I can ssh key auth onto linux instances, but not windows.

The key seems right:

$head -n2 /tmp/foobar4.pem
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEgHine3zi09IU
$tail -n2 /tmp/foobar4.pem
-----END PRIVATE KEY-----

However I just cannot understand why I cannot decrypt the windows password

Can you please help

cleanup on delete

I'm not sure if this is bug or not. I'm using Custom::RSAKey to generate a public/private key pair, the private key is being written to SSM parameter store. When I deleted the stack, the SSM param that was created to store the private key was not removed. Should the resource on cleanup in turn remove the SSM param as well?

Changing the parameter path of the Custom::AccessKey recreates the access key

We have a cloudformation template that creates a very large number of users with access and secret keys that are stored in SSM parameter store using this custom resource.

I need to change the path where the items are stored.

Looking at the code it seems changing the path will cause a new key to be created, will this remove the old keys? We cannot afford for the existing keys to be invalidated.

Additionally, during testing after modifying the key path I received this error in the logs:

An error occurred (ParameterNotFound) when calling the GetParameter operation:

So my question is, how can I modify the Parameter Path within the existing cloudformation stack without removing the existing access or secret keys?

Architecture Diagram Visualization

Hi @mvanholsteijn

I came across your repo and I took the liberty to scan it with the tool that I am developing. If I caught your attention, feel free to take a look at the following diagram and let us know your thoughts on this. I am really interested to get your feedback and to understand if the diagram we presented matches the architecture you have in mind.

error deploying latest cloud formation version 1.4.1

I receive this error during create from cloud formation against 1.4.1 of the template

Received response status [FAILED] from custom resource. Message returned: ModuleNotFoundError: No module named '_cffi_backend' (RequestId: 472fd2b4-9388-47ff-aa06-2306297316ea)

Question : how is this more secure than sharing the password with devs ?

In the demo-stack.yaml, you are doing :

Outputs:
  Secret:
    Value: !GetAtt 'DBPassword.Secret'
    Description: the generated secret, do expose this as Output Parameter in production

Doing this, when I access the CloudFormation service (a service that the dev team also has access to) I can directly see the password in the Ouputs tab of the stack

So how is this more secure than sharing the password with devs ?

Use boto3 ec2.create_key_pair() function

Is there a reason you're using the python cryptography package to create the RSA key rather than using the boto3 create_key_pair function in the EC2 module?

Is it simply to allow customizing the keysize?

How to manually rotate or update a parameter

I am wondering if there is any way to update parameters each time a Cloud Formation template runs or what the options are.

For example, say we have a database such as AWS DocumentDB that requires a master user name and password when creating.
When using cfn-secret-provider I would generate the secured parameter and store it at Parameter Store

  docDbPassword:
    Type: Custom::Secret
    Properties:
      Name: !Ref docDbAdminPassword
      Description: DocumentDB password
      Alphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      Length: 16
      ReturnSecret: true
      ServiceToken: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider

being able to access now that secret with !GetAtt docDbPassword.Secret. All great.

If I re-run the cloud formation template I can see the secret is not re-generated.
Is there any recommended approach to manually "rotate" a parameter or to re-generate a new secret and update the database master password, for example, so that every time I run the cloud formation template I can flag Custom::Secret to overwrite the secret and update the AWS accordingly? Or is that too risky? (I actually don't know if all AWS resources or databases allow updating credentials that way)

PS: this is a great useful tool I have been using for some months, thank you and congrats!

Override function name

Hello,

In the first place, thx for awesome function. It helped us a lot with setting up a cluster that required SSH communication.
However, we do have a slight request.

We would like to utilize this part as a sub-stack to as a stack where we need cfn-secret-provider. That obviously mean we may have more than one copy of the function in the region which is impossible as your lambad do have a fixed name.
Would it be possible to provide both input and output to simply have it deployed.

make the private Key downloadable

Hi, so far evth is working nicely, the only thing I cant do is using the keypair I have generated to ssh into an EC2 instance since I cannot download the private key. Could you add this feature please. merci

Failed to decrypt the password for a Windows EC2 instance using the keypair

I am using the example code to create a keypair that is then associated with a Windows EC2 instance.

When accessing the private key in the SSM parameter store the output is as such:
-----BEGIN PRIVATE KEY----- MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDQ80SY1C5zcjhQ
...SNIP...
-----END PRIVATE KEY-----

Trying to use this to decrypt the password fails with the following error:
Error decrypting your password
Private key must begin with "-----BEGIN RSA PRIVATE KEY-----" and end with "-----END RSA PRIVATE KEY-----"

Changing the key to use -----BEGIN RSA PRIVATE KEY----- still fails with the following error:
Error decrypting your password
There was an error decrypting your password. Please ensure that you have entered your private key correctly.

The relevant parts of the cloud formation template I am using are:

PrivateKey:
   Type: 'Custom::RSAKey'
    Properties:
        Name: !Sub 
                - '/ec2-keypairs/${environmentType}/${AWS::StackName}-privatekey'
                - environmentType: !FindInMap
                  - EnvironmentConfigs
                  - !Ref 'AWS::AccountId'
                  - EnvironmentType
        Version: v1
        KeyAlias: !Sub '${AWS::StackName}-privatekey'
        ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'
  KeyPair:
    Type: Custom::KeyPair
    DependsOn: PrivateKey
    Properties:
      Name: !Sub 
              - '${environmentType}-${AWS::StackName}-keypair'
              - environmentType: !FindInMap
                - EnvironmentConfigs
                - !Ref 'AWS::AccountId'
                - EnvironmentType
      PublicKeyMaterial: !GetAtt 'PrivateKey.PublicKey'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

Am I doing something wrong here ? I have double checked the article here (https://binx.io/blog/2017/10/25/deploying-private-key-pairs-with-aws-cloudformation/) and the docs in the repo but cannot see anything obvious. Thanks.

Allow Custom::Secret to accept an input as Value

I'm working on a cloudformation stack in which I'd very like to be able to store some private keys as SSM SecretString parameters so I can later provision them into EC2 Instances through cfn-init files.

The custom object cfn_secret_provider.py seems to be exactly what I need, except for the fact that it does not accept a custom string value as input.

I think adding an optional content property into the input json would do the trick. Then on cfn_secret_provider.py class if content has been given, use that, if not, generate a random string as always.

The json would look something like:

{
  "Type" : "Custom::Secret",
  "Properties" : {
    "Name" : String,
    "Description" : String,
    "Alphabet" : String,
    "Length" : Integer,
    "Content" : String,
    "KeyAlias" : String,
    "ServiceToken" : String,
    "RefreshOnUpdate": Boolean,
    "ReturnSecret": Boolean,
    "Version": String
  }
}

This would be a great and useful feature to add, and could keep backward compatibility without major complication.

Broken v1.0.0

Stack stucks in CREATE_IN_PROGRESS state

AWSTemplateFormatVersion: "2010-09-09"
Description: >-
  Test Stack
Resources:
  DBPassword:
    Type: Custom::Secret
    Properties:
      Name: /test/DBPassword/PGPASSWORD
      KeyAlias: alias/aws/ssm
      Alphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      Length: 30
      ReturnSecret: true
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

Checked CloudWatch logs for lamba function and found error log:

Runtime.HandlerNotFound: Handler 'handler' missing on module 'secrets'

Deployed v0.13.3 and everything went smooth

Ship the SecretProviders up to pypi

I am currently using your cfn-resource-provider base in my organization's custom resource provider, and it's great!

I would like to add the SecretProvider to my own lambda function, but not all of the others in this repository. For me, the ideal situation would be add another pip install requirement for cfn-secret-provider and then be able to import just the ones I want into my own lambda function.

If this isn't something you would like to do, I can certainly copy-paste the ones I want as a workaround.

Thanks!

Error : "Handler 'handler' missing on module 'secrets'" when deployed from zip

I have tried both 1.4.4 and 2.0.1 zip file

My cloudformation looks like following:

  CFNSecretProvider:
    Type: AWS::Lambda::Function
    DependsOn:
      - LambdaRole
    Properties:
      Description: CloudFormation Custom:Secret implementation
      Code:
        S3Bucket: !Sub '${LambdaS3Bucket}'
        S3Key: !Sub '${LambdaS3Path}/cfn-secret-provider-2.0.1.zip'
      FunctionName: 'binxio-cfn-secret-provider'
      Handler: secrets.handler
      MemorySize: 128
      Timeout: 30
      Role: !GetAtt 'LambdaRole.Arn'
      Runtime: python3.9

Generate your own copy of the lambda zip file

Hello,

How does one go about generating our own copy of the lambda zip file? I've pulled it down, but don't see a way to download all of the dependencies instead of using the prepackaged version.

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.