aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.1k stars 53 forks source link

AWS::SSM::Parameter - Type-SecureString #82

Open benlucas11 opened 4 years ago

benlucas11 commented 4 years ago

1. Title - AWS::SSM::Parameter-Type-SecureString

2. Scope of request

When creating a new SSM Parameter resource you can create using the String and StringList Type however not SecureString.

This is currently possible with additional lambda functions within the template however it will make for easier to follow templates for both parameter creation and dynamic linking to ssm parameters.

We use SSM Parameters for variables, including sensitive data, so the ability to continue utilising these without manual creation before a stack deployment is desired.

Sample:

AWS::SSM::Parameter-Type-SecureString supports String and StringList but not SecureString.

3. Expected behaviour

As part of the Console or API, we can create a new SecureString Parameter. It's expected that CloudFormation should also include this functionality.

4. Suggest specific test cases

Common use case: Creating a securestring parameter during stack creation from inputted parameters. These parameters can then be dynamically referenced throughout the stack.

Test case recommendation: Ability to create a securestring value and reference it from the same stack.

5. Helpful Links to speed up research and evaluation

Reference Doc detailing the feature doesn't yet exist. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html

6. Category

Management - Systems Manager

7. Any additional context (optional)

We currently get around this using 3 ways:

  1. Manual SecureString Parameter creation pre stack create.
  2. Addition lambda function to create the secure parameter (Add complexity to the template).
  3. Create and use Secrets Manager. (This works well however at scale the cost of Secrets Manager become prohibitive)
benkehoe commented 4 years ago

How do you expect to use this without disclosing the value of the parameter in the template?

benlucas11 commented 4 years ago

Typically we’d use NoEcho on any sensitive parameters plus our deployment tooling would pass the values from it’s own secure store during stack creation which shouldn’t expose the value at any point of creation.

trav-c commented 4 years ago

How do you expect to use this without disclosing the value of the parameter in the template?

Another use case is just to be able to create the parameter as a placeholder with an empty value so that it can be easily manually populated with the security sensitive details later, but it's existence can be referenced elsewhere in the stack immediately. We do this in our existing stack using a custom resource

benbridts commented 4 years ago

Additionally, our Custom Resources supports generation a random value when the Parameter is created. This could be something that CloudFormation does itself, or CloudFormation could call secretsmanager get-random-password or kms generate-random behind the scenes.

RajanAOz commented 4 years ago

Would like to be able to dynamically pull values from SSM for example with {environment} or {version} where environment for example is, test, staging, production and version is, 1, 2, 3, etc..

"{{resolve:ssm-secure:/{environment}/password:{version}}}"

cmarshall10450 commented 4 years ago

Has anyone been able to use the ssm dynamic referencing with the Join or Sub intrinsic functions? I'm trying to write a file in the CloudFormation::Init metadata of an EC2 instance with a username and password for a service but it writes out the reference syntax to the file instead of resolving.

jospas commented 4 years ago

How do you expect to use this without disclosing the value of the parameter in the template?

Another use case is just to be able to create the parameter as a placeholder with an empty value so that it can be easily manually populated with the security sensitive details later, but it's existence can be referenced elsewhere in the stack immediately. We do this in our existing stack using a custom resource

This is a common ask, create a SecureString ParameterStore parameter with a dummy value and have another team update the value for various environments. Can we get support for this feature please?

KasperFranz commented 3 years ago

Any update on this? For us to properly utilise SSM Parameter store with CloudFormation we need to be able to create Secure parameters

martavoi commented 3 years ago

Wow, such a required feature and still no support...

unfor19 commented 3 years ago

If you're ok with using a custom resource, then this is a great solution - https://github.com/glassechidna/ssmcfn, I'm using it for creating SecureString parameters with a dummy initial value "empty".

Deploy this CloudFormation template (per region if you're working across regions):

[cfn.yml](https://github.com/glassechidna/ssmcfn/blob/master/cfn.yml) - Expand/Collapse I commented out the support for `UPDATE`, so it only works upon CREATE+DELETE and does not attempt to update the value. I also updated the runtime from `node4.3` to node `12.x` (latest version that supports ZipFile) ```yaml # Source: https://github.com/glassechidna/ssmcfn/blob/master/cfn.yml AWSTemplateFormatVersion: "2010-09-09" Resources: Lambda: Type: AWS::Lambda::Function Properties: Handler: index.handler Role: !GetAtt Role.Arn Runtime: nodejs12.x Timeout: 300 Code: ZipFile: > var response = require('cfn-response'); var aws = require('aws-sdk'); exports.handler = function(event, context) { console.log(event); var ssm = new aws.SSM(); var props = event.ResourceProperties; var splitStackArn = event.StackId.split(':'); var region = splitStackArn[3]; var accountId = splitStackArn[4]; var stackName = splitStackArn[5].split("/")[1]; var paramName = props.Name || "cfn-" + stackName + "-" + event.LogicalResourceId; // TODO: add rand on end? var paramArn = "arn:aws:ssm:" + region + ":" + accountId + ":parameter/" + paramName; var cb = function(err, resp) { var cfnRespData = { Arn: paramArn, Name: paramName }; if (err) { console.log(err); response.send(event, context, response.FAILED, cfnRespData, paramArn); } else { console.log(resp); response.send(event, context, response.SUCCESS, cfnRespData, paramArn); } }; if (event.RequestType == "Create") { var params = { Name: paramName, Type: "SecureString", // Hardcoded SecureString instead of using props.Type Value: props.Value, KeyId: props.KeyId, Overwrite: false }; if (props.Description) params.Description = props.Description; if (props.KeyId) params.KeyId = props.KeyId; ssm.putParameter(params, cb); } /* Skipping update, we only want to create it else if (event.RequestType == "Update") { var params = { Name: paramName, Type: props.Type, Value: props.Value, KeyId: props.KeyId, Overwrite: true }; if (props.Description) params.Description = props.Description; if (props.KeyId) params.KeyId = props.KeyId; ssm.putParameter(params, cb); } */ else if (event.RequestType == "Delete") { ssm.deleteParameter({ Name: paramName }, cb); } }; Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: root PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* - Effect: Allow Action: - ssm:PutParameter - ssm:DeleteParameter - kms:Encrypt Resource: "*" Outputs: Lambda: Description: Cfn polyfill for SSM parameter store Value: !GetAtt Lambda.Arn Export: Name: CfnParamStore HelperRole: Description: IAM Role Value: !GetAtt Role.Arn Export: Name: SSMHelperRole ```
[example.yaml](https://github.com/glassechidna/ssmcfn/blob/master/example.yml) - Expand/Collapse I added the `Name` property and some comments. Also, there's no need to define the `Type` since the default type in the Lambda is `SecureString`. ```yaml AWSTemplateFormatVersion: "2010-09-09" Resources: SecureParam: Type: Custom::CfnParamStore Properties: Name: /my-app/development/my-secret ServiceToken: !ImportValue CfnParamStore # Required to use the Helper Value: empty # Initial dummy value Outputs: ParamArn: Description: Arn of param in SSM param store Value: !GetAtt SecureParam.Arn ```
ckabalan commented 3 years ago

Any update on this? Our organization has use cases as described above. Our workflow is like what @jospas describes. For new deployments which require secrets we deploy the app with a dummy value REPLACE_WITH_SECRET_STRING and as part of our deployment process manually replace that value with the actual secret content. Having to change the parameter type introduces undesirable configuration drift and another step in our deployment process.

Any fear of invalid/insecure usage has already been accepted because AWS::SecretsManager::Secret already has a SecretString field.

It would be nice to get this prioritized.

trademark18 commented 2 years ago

Any fear of invalid/insecure usage has already been accepted because AWS::SecretsManager::Secret already has a SecretString field.

I second that. It seems like the risk was already accepted and this limitation isn't intuitive since it breaks that precedent. I have been using Secrets Manager for some things that I realized could be a better fit in Parameter Store as SecretStrings, but without proper IaC support I'm moving it back to Secrets Manager.

dtphuc commented 2 years ago

Any news update on this feature? We’re waiting for a while

mayormaier commented 1 year ago

Want to put a bump on this- not sure if it will be in development, but definitely a good idea.

cbaker commented 1 year ago

+1

tazatwell commented 1 year ago

Hi, for any newcomers to this thread I wrote a workaround for creating/updating/deleting SecureString Parameters at https://github.com/tazatwell/ssm-securestring-cfn-macro. It follows the suggested workaround solution, a Lambda-backed CloudFormation macro.

beck3905 commented 1 year ago

I'll add another use case to this thread. Our organization has a requirement that all configuration be stored encrypted at rest. This includes things like ARNs and URLs, etc. that our applications may need to use. Our templates create resources and then save the ARNs, etc to SSM parameters for our applications to read as configuration. But our requirements dictate that those SSM parameters must be SecureString. So we have a need to create new SecureString parameters directly in our template and put values from other resources created by the stack.

Lu-dorado commented 8 months ago

Any news about this? It would be a great news to be discovered art re:Invent!

pepitoenpeligro commented 5 months ago

Hi team, any news about this? It's a tricky but important use case :)

esuter-rms commented 4 months ago

Just adding another "vote" on this: like others have mentioned elsewhere in the thread, creating a blank secure string parameter is quite a common usecase. All my organization needs is to be able to create placeholder secure string parameters when deploying with CDK, which will be updated later via another process external to our deployment pipeline.

Before anyone suggests using SecretsManager: it's overkill for the the majority of the secrets we need to store, most do not need frequent (or any) rotation, and we overwrite SecretsManager's auto-generated strings 99% of the time anyway with something else. SecretsManager isn't exactly cheap either.

I'm honestly surprised that there's been no visible effort to implement this use case for almost 5 years.

djravine commented 4 months ago

+1

MichaelDavisTSN commented 3 months ago

We need this to support Instance Scheduler on AWS, so that SecureString can be created with the published templates. Our company policy requires encrypted parameters. Thanks!

valeriosalvucci commented 3 months ago

+1

ThomasVaccarini commented 3 months ago

Waiting for this...

lechgajewski commented 3 months ago

Upvoting this request as well 👍

Feature like this would be extremely useful when specifying the Parameter for the CloudFormation template, e.g.:

Parameters:
  SomeSecureParam:
    Type: AWS::SSM::Parameter::Value<SecureString>
    Default: /path/to/some/secure/param

Unfortunately the support for the dynamic SSM Parameter resolution aka. {{{{resolve:ssm-secure:/path/to/some/secure/param}} is so limited that it's not really a viable alternative 😞

frankieshum commented 2 months ago

Feels like there's no interest in implementing this feature because storing secure SSM parameters isn't profitable, whereas storing secrets in Secrets Manager generates $0.40 per month...

Untitled

bcoddens commented 2 weeks ago

Can this be given priority ? This is blocking us to create a security baseline in our Organization.

CGarces commented 1 week ago

Can this be given priority ? This is blocking us to create a security baseline in our Organization.

I think that https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/82#issuecomment-2120472605 has the key of when will be implemented.