Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposed way to use iam access and secretKey in cdk #4661

Closed
konstantinj opened this issue Oct 24, 2019 · 19 comments
Closed

Proposed way to use iam access and secretKey in cdk #4661

konstantinj opened this issue Oct 24, 2019 · 19 comments
Labels
@aws-cdk/aws-iam Related to AWS Identity and Access Management effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. needs-cfn This issue is waiting on changes to CloudFormation before it can be addressed.

Comments

@konstantinj
Copy link

❓ General Issue

There are a lot of application out there that still require an access/secretKey pair and do not work with roles. What's the ideal/secure way to use those in cdk without creating resources manually beforehand.

The Question

There is the parameter store (SSM) and the secrets manager (SM) available. In SSM I can only create "normal" strings from cdk/cloudformation - not secure strings. In SM I can only get a new secret but not store my own one.

So the only option currently seems to be this:

const user = new iam.User(this, 'User', {
    userName: this.getConfig('bucketName'),
})

const accessKey = new iam.CfnAccessKey(this, 'AccessKey', {
    userName: user.userName,
})

const ssmSecretKey = new ssm.StringParameter(this, 'SsmSecretKey', {
    parameterName: '/' + [this.account, this.stackName, 'secretKey'].join('/'),
    stringValue: accessKey.attrSecretAccessKey,
})

const bucket = new s3.Bucket(this, 'Bucket', {
    bucketName: this.getConfig('bucketName'),
    versioned: false,
    removalPolicy: RemovalPolicy.RETAIN,
    publicReadAccess: false,
    blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
})

bucket.grantReadWrite(user)

and then of course using it later in my case in ecs:

const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service(this, 'Service', {
    cluster: cluster,
    memoryLimitMiB: 1024,
    taskImageOptions: {
        image: ecs.ContainerImage.fromEcrRepository(asset.repository),
        environment: {
            AWS_ACCESS_KEY_ID: accessKey.ref,
            AWS_DEFAULT_REGION: this.region,
        },
        secrets: {
            AWS_SECRET_ACCESS_KEY: ecs.Secret.fromSsmParameter(ssmSecretKey),
        },
        containerPort: 4873,
    },
    desiredCount: 1,
    domainName: this.getConfig('domainName'),
    protocol: ApplicationProtocol.HTTPS,
    domainZone: domainZone,
    healthCheckGracePeriod: cdk.Duration.seconds(60),
})

Other information

#1857 #3520

@konstantinj konstantinj added the needs-triage This issue or PR still needs to be triaged. label Oct 24, 2019
@SomayaB SomayaB added the guidance Question that needs advice or information. label Oct 24, 2019
@SomayaB SomayaB added @aws-cdk/aws-iam Related to AWS Identity and Access Management and removed needs-triage This issue or PR still needs to be triaged. labels Oct 24, 2019
@rix0rrr
Copy link
Contributor

rix0rrr commented Dec 2, 2019

Unfortunately we are a little bound by what CloudFormation supports in this area. I think a Custom Resource that creates the keypair and stores it in SecretsManager is going to be your best bet.

@sblackstone
Copy link
Contributor

I'd like to add that I'm also running into this exact scenario where I want to create an IAM user with keys at stack creation and store the secret key that's created for later use.....

@rix0rrr rix0rrr added feature-request A feature should be added or improved. needs-cfn This issue is waiting on changes to CloudFormation before it can be addressed. and removed guidance Question that needs advice or information. labels Jan 23, 2020
@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 23, 2020

I'm going to classify this as a feature request, even though there is nothing that CDK can do for you.

Someone out there could make a Custom Resource that does this for you.

@hoegertn
Copy link
Contributor

This is exactly what is on my roadmap. A custom resource to create AccessKeys and store them in secrets manager. Regarding your example, why are you using AccessKey/SecretKey as env instead of an IAM role for the Fargate task?

@konstantinj
Copy link
Author

@hoegertn because the taskrole's accessKey expires and I need to handle that in the application. If the application is not made by you that's often not possible.

@hoegertn
Copy link
Contributor

What is the application doing that needs a "static" key? The only thing I can currently imagine is creating pre-signed URLs for S3.

@konstantinj
Copy link
Author

The application just needs access- and secret-key and I can't modify the application to include logic to fetch it differently.

@hoegertn
Copy link
Contributor

Normally the applications will use an AWS SDK and it will fetch it automatically but we are getting too off-topic I think.

@rix0rrr rix0rrr added the effort/medium Medium work item – several days of effort label Jan 23, 2020
@swe-ds
Copy link

swe-ds commented Feb 3, 2020

I am having the same need.

I would like to create a new IAM user with Access/Secret keys and store them in the SecretsManager protected by a customer managed KMS key. To finish out the pattern, I want to schedule automatic rotation of this API key.

The only ways I can see to accomplish this with CDK is via a hack or possibly with a lower level contruct.

My use case is to establish a principal identity to be used in sts:AssumeRole across account boundaries.

Doug

@liamor
Copy link

liamor commented Feb 28, 2020

My use case for this is when a Java Lambda needs to access an AppSync GraphQL endpoint that is more secure than just using the API Key.

@BryanPan342
Copy link
Contributor

@liamor I would suggest looking into auth type AWS_IAM for your AppSync GraphQL Api. There is an example in the readme on how to use a grant to accomplish your use case.

@binarythinktank
Copy link

binarythinktank commented Aug 7, 2020

just musing here, but what if CDK could support an encrypted "credentials" file. This should not be committed to the git, its encrypted, and developers can add key-value pairs to it for sensitive data such as passwords. Then provide developers a means to reference a key in this file from anywhere in the code such as lambda params or ssm params (which is supported by cfm: https://aws.amazon.com/about-aws/whats-new/2018/08/aws-cloudformation-introduces-dynamic-references-to-support-aws-/). Such values should also be added as params in CFM with NoEcho enabled to avoid them appearing in describe stack.

if multiple developers are working on a project, then they can be given the same keys to include in the cdk project that they clone IF they need it. If a referenced key is missing, then do not deploy it to avoid overwriting a valid value in the cloud with a null/empty value. this should not throw an error, or perhaps only a warning as there are plenty of cases where only the lead dev would be managing the actual secrets but other devs don't need access.

@sblackstone
Copy link
Contributor

Ideally when creating a user, you would be able to just specify a key and it would populate that key in your secrets manager on your behalf... Then you'd never need to actually see the key in the first place and it would programatically be available to your app.

@binarythinktank
Copy link

That only works if you need a new key generated, it would be useful to have a mechanism for dealing with existing keys/secrets/passwords/etc. too. Also SM charged per secret and really only worth it if you want automatic rotation (e.g. for RDS), SSM Params is free and suits most cases.

@flochaz
Copy link
Contributor

flochaz commented Sep 16, 2020

Unfortunately we are a little bound by what CloudFormation supports in this area. I think a Custom Resource that creates the keypair and stores it in SecretsManager is going to be your best bet.

Here is an example using awsCustomResource to store accessKeyId and secretAccessKey in

const adminPassword = new secretsmanager.Secret(this, "AdminUserPassword");

    const mainAdminUser = new iam.User(this, "admin", {
      userName: "admin",
      password: adminPassword.secretValue,
    });

    const accessKey = new iam.CfnAccessKey(this, "AdminUserAccessKey", {
      userName: mainAdminUser.userName,
    });

    new cr.AwsCustomResource(this, 
      "AdminAccessKeyIdSecret", 
      {
        onCreate: {
          service: 'SecretsManager',
          action: 'createSecret',
          physicalResourceId: cr.PhysicalResourceId.fromResponse('Name'),
          parameters:
            {
              Name: "AdminAccessKeyId", 
              SecretString: accessKey.ref
            }
        },
        installLatestAwsSdk: false, 
        policy: cr.AwsCustomResourcePolicy.fromSdkCalls(
          {
            resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE
          }
        ),
        logRetention: RetentionDays.ONE_DAY
      }
    );

    new cr.AwsCustomResource(this, 
      "AdminSecretAccessKeySecret", 
      {
        onCreate: {
          service: 'SecretsManager',
          action: 'createSecret',
          physicalResourceId: cr.PhysicalResourceId.fromResponse('Name'),
          parameters:
            {
              Name: "AdminSecretAccessKey", 
              SecretString: accessKey.attrSecretAccessKey
            }
        },
        installLatestAwsSdk: false, 
        policy: cr.AwsCustomResourcePolicy.fromSdkCalls(
          {
            resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE
          }
        ),
        logRetention: RetentionDays.ONE_DAY
      }
    );

But custom resource lambda logs will contains your secret for 24h (might have a way to force delete the logStream though)

@peterwoodworth
Copy link
Contributor

If you would like to see native CDK support for this instead of with custom resources, I recommend checking out the Cloudformation coverage roadmap to see if they are planning to implement it. Feel free to open a request there if this feature isn't currently being tracked 🙂

@laurelmay
Copy link
Contributor

I believe that this can be accomplished natively today.

const user = new iam.User(this, "User");
const accessKey = new iam.AccessKey(this, "AccessKey", { user });
const secret = new secrets.Secret(this, "Secret", {
  secretObjectValue: {
    accessKeyId: cdk.SecretValue.resourceAttribute(accessKey.accessKeyId),
    secretAccessKey: accessKey.secretAccessKey,
  }
});

I think that between #18180 and #21091, this has been resolved. I'd highly recommend adopting the @aws-cdk/core:checkSecretUsage feature flag before going down this path.

@comcalvi
Copy link
Contributor

Closing as this appears to have been resolved.

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-iam Related to AWS Identity and Access Management effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. needs-cfn This issue is waiting on changes to CloudFormation before it can be addressed.
Projects
None yet
Development

No branches or pull requests