binxio / cfn-secret-provider

A CloudFormation custom resource provider for deploying secrets and keys
Apache License 2.0
141 stars 70 forks source link

Add support for secret usage from other stacks #34

Closed lefperuch closed 4 years ago

lefperuch commented 4 years ago

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.

mvanholsteijn commented 4 years ago

I would recommend to have one stack create the parameter, and the other stack reference the parameter dynamically.

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html

The required version of the secret can be obtained using `!GetAtt Secret.Version'.

lefperuch commented 4 years ago

As stated before, AWS::EC2::VPNConnection's VpnTunnelOptionsSpecification doesn't offer support for dynamic reference of a SecureString parameter, so '{{resolve:ssm-secure:/path/to/my/secret:version}}' wouldn't work.

What I was hoping for is, given the following VPN Connection and that I've already created a secret on another stack,

  PrimaryVpnConnection:
    Type: AWS::EC2::VPNConnection
    DependsOn:
      - VpnPreSharedKey
    Properties:
      Type: ipsec.1
      CustomerGatewayId: !Ref VpnCustomerGateway
      StaticRoutesOnly: true
      VpnGatewayId: !Ref VpnGateway
      VpnTunnelOptionsSpecifications:
        - PreSharedKey: !Sub ${VpnPreSharedKey.Secret}

that I was able to, in the same stack as the VPN's, create a

  VpnPreSharedKey:
    Type: Custom::Secret
    Properties:
      ServiceToken: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider
      Name: /path/to/my/secret
      ReturnSecret: true
      Recreate: false # This is my suggestion

and obtain the secret's value, since this is a limitation imposed by CloudFormation. From what I have seen, the code is already there, we just need to add a new property to enable this feature.

mvanholsteijn commented 4 years ago

I see. it requires a resource with supports the resolution 🤦‍♂ I do not want it as a parameter, but I am happy to add a resource `Custom::ReadOnlySecret'. Which requires the parameter to be present. Would that work for you?

lefperuch commented 4 years ago

Absolutely.

mvanholsteijn commented 4 years ago

Please try release v1.1.0.

lefperuch commented 4 years ago

Worked like a charm. Thanks for the quick response.