aws / aws-cdk-rfcs

RFCs for the AWS CDK

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CDK CLI Triggers

KingOfPoptart opened this issue · comments

Please take a look at #71 and let us know if this will address your use case.


A post-deploy hook would be handy - sometimes its useful to have something that runs after a successful cdk deploy. Otherwise, CDK will force end users have CDK run in wrapper scripts

What would also be handy is if during this postDeploy() functionality, if cloudFormation resources were no longer tokens, but were fully fleshed out and available

Something like the following would be convenient -

import cdk = require('@aws-cdk/cdk');

function runAfterCompletion(NameOfResource: string){
    notifyMyTeam(`mySuperCoolStack has deployed ${NameOfResource}`);
}


const app = new cdk.App();
const myAsg = new mySuperCoolAsgStack(app, "VPC", {props: "props"});
app.run()

app.postDeploy(runAfterCompletion, myAsg.GetAsg.autoScalingGroupName);

Very useful for working around missing CloudFormation features.

Example use case: As far as I can tell, at the moment it's not possible to tell CloudFormation to set a Cognito user pool to send a verification link in email instead of a code (VerificationMessageTemplateType in the API). With a post-deploy hook it would at least be possible to set it after the pool is created.

Pre-deploy might also be useful. Also, a separate hook for each stack if possible, and one after everything was deployed.

I am wondering if custom resources would be sufficient for these use cases...

Custom resources can't replace hooks completely. Leaving aside the ease of use, the main difference is where the code is executed.

Simple example. Use the CDK as part of CD/CI pipeline that runs on a Jenkins server. The CDK deals with EC2, so the Jenkins role only has access to EC2. With a hook, that's enough. With a custom resource, Jenkins now needs access to set up and run arbitrary Lambda functions, along with the roles attached to those functions.

Another example, a simple notification before and after deploy. To Slack, email, whatever. With a hook it's just a local script. Custom resources need more setup.

Many use cases can be worked around with custom resources. But it's clumsy and it complicates things considerably. Especially in bigger organisations, where access has to be vetted by a different team.

From Gitter, another use case for local hooks, as opposed to custom resources: "For instance, Account A stack has an iam role that Account B's bucket would like to give access to".

This could be easily solved with a post deploy hook on AccountAStack which gets the IAM role from Account A, then passes it to AccountBStack as a context variable, or in a pre-deploy hook.

To clarify, the kind of hooks I'm thinking about are the kind that Sceptre implemented. Pre/post each stack's deploy/delete. Sceptre follows the same basic idea that the CDK has, it provides a cli for building (paired with Troposphere), deploying and deleting CloudFormation stacks. The hooks are very useful for tying different stacks together and generally supplementing what CloudFormation can do.

Another use case is to create a codebuild's build parameters in a json file. Currently, we have to manually create it after the stack is created. with this feature, we can automate the creation easily.

+1.
My use case is that I need to write a config file post-deployment, which contains the resulting endpoints and ARN's and such.
This is possible with the serverless framework, and I think it's an important feature to have.
Thank you.

commented

+1
This is required in order to connect the created resources with some external site for CI/CD (for example bitbucket pipelines) and avoiding setting the names of all resources manually

Another use case would be to use this with eks iam integration - patching k8s service accounts after the iam role with oidc connect is created (need to know the name of the role, so only can patch it after the stack was created). Would like to see something like this ...

If I have a nodejs app that uses aws-sdk to populate a dynamodb table from a json, and I want to run this after the whole provisioning has completed, is this a case for this exact issue or can it be done in another way? Thanks,

I am working on some new high level mini-framework for custom resources that will make this really easy to implement.

All I want to do is print a string based on some info in the stack after it has been deployed. Not even trying to do anything fancy here. Is there any reason why it can't just accept a callback or be a promise to handle? In the mean time, I could use wait-for npm package to wait till it's done as long as there is some clear trigger for it to watch and wait for. Any ideas how one could use wait-for?

@eladb Any update on your custom resource mini framework

Yes. It’s available under the @aws-cdk/custom-resources module. Should be possible to implement this quite easily now.

So in the mean time, the easiest way to run custom scripts after deploy is to use the poststart script in package.json and make sure your start script in package.json is cdk deploy. Then simply run npm start and when it is done deploying it will run your poststart script. Since CDK uses the aws-sdk package you can pretty much do whatever you want afterward.

Please take a look at #71 and let us know if this will address your use case.

#71 is a ver nice feature. it depends on a lambda function which might have a big configuration overhead for some cases.
For our case it would be enough to have the "response" of the cdk app and the ability to run code locally with that information

@KingOfPoptart This is a very handy feature proposal! Like @bgdnlp, we had used Sceptre hooks to address situations where a feature was not exposed via CloudFormation, or that the thing we needed to do was not amenable to the CloudFormation lifecycle. A lot of times this was copying images to ECR, updating AWS app config, or doing tasks in AWS Orgs for example.

As for custom resources @eladb, logically it likely will work, but there's a lot of challenges there that i think are being overlooked. If custom resources were the chosen path, organizations will have put a lot more scrutiny on the lambda functions, IAM roles, and security groups granted to the functions. Such a feature implemented by 3rd parties will be particularly challenging. While most constructs are open-source, rarely are they actually reviewed. Especially if said lambda is not written in a language that a given team is versed in.

In environments where there is less risk tolerance (i.e. payments, FinTech, health, etc.), the overhead of reviewing the lambda code, IAM permissions, and security groups that are granted to the function increases significantly. An awful lot is going to depend on how the author implements said lambda functions and there's sufficient flexibility to adapt it meet an organizations policies. If they are not flexible enough. this would likely lead to internal development of such custom resources in order to ensure that both the function code and IAM permissions align with an organizations policies. As many have pointed out, there's additional overhead to creating and managing a function. Let's take the CDK ECR Deployment construct as an example. This construct makes it really easy to copy an image from an existing registry to ECR:

    new ecrDeploy.ECRDeployment(this, 'DeployDockerImage', {
      src: new ecrDeploy.DockerImageName(image.imageUri),
      dest: new ecrDeploy.DockerImageName(`${repo.repositoryUri}:latest`),
    });

The construct works really well and performs the task that it sets out to do. This approach will work for organizations that don't have a rigid security policy and compliance programs to contend with. For those that do have to contend with such things, you may need answer the following questions:

  • How are you limiting what repos images can be pulled from?
  • How are verifying the image integrity/validating image signatures?
  • How does one pass credentials to a non-ECR registry that requires authentication?

Surely the Construct could accommodate all of these with some more planning. But then there's the fact you now have an idle lambda function that has credentialed read access to multiple registries and write access to the ECR in the local account.

With Sceptre, we solved this problem using a hook that called skopeo copy. We also use a custom policy.json file to express the which registries were trusted and ensure signature verification.

What I liked about this approach was that account we were deploying to did not have access to the registry we were pulling from. That permission was only granted to the CD account performing the deployment. We only ever needed access to both registries at deployment time. The target account that would be running the image, never required such access. The way the CDK ECR Deployment works, it forces the target account to deploy a lambda that has read/write access to ECR and also has credentialed read access to the source repo. This is what I like about the idea of pre and post hooks in the CDK rather than running custom resources: it helps manage the separation of duties that several compliance programs demand.

+1