aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.47k stars 3.83k forks source link

Update AWSCustomResource runtime version from node.js14 to node.js16 #30373

Closed jacido closed 2 months ago

jacido commented 2 months ago

Describe the feature

Update Runtime version of AWSCustomResource from node.js14 to node.js16 or recommended runtime. Currently using certain constructs and properties are resulting in deploying with a deprecated runtime.

Use Case

When deploying a solution using AWSCustomResource, it results in using an old deprecated runtime version.

cdk.out/ tree.json code snippet:

"Resource": { "id": "Resource", "path": "Cognito-lane36/AWSXXXXXXXXXXXXXXXXXXX7982bd2287/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { "s3Bucket": "cdk-hnb659fds-assets-XXXXXXXX7970-us-west-2", "s3Key": "XXXXXXXXXXXXXXXXXXXXXXXXX226d161a5cfe96f4648b21f9e4912c698bf30.zip" }, "role": { "Fn::GetAtt": [ "AWSXXXXXXXXXXXXXXXXXXX7982bd2287ServiceRoleC1XXXFF2", "Arn" ] }, "functionName": "MyCustomLmbdFn", "handler": "index.handler", "runtime": "nodejs14.x", "tags": [ { "key": "AppManagerCFNStackKey", "value": "Cognito-lane36" } ], "timeout": 120 } }, "constructInfo": { "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", "version": "2.72.1" } }


Proposed Solution

Update to latest runtime.

Other Information

Current workaround regarding the issue is using property override escape hatch.


test = self.node.find_child("AWSXXXXXXXXXXXXXXXXXXX7982bd2287").node.default_child test.add_property_override("Runtime", "nodejs20.x")

[Link] - add_property_override https://constructs.dev/packages/aws-cdk-lib/v/2.135.0/api/CfnHoursOfOperation?lang=python&submodule=aws_connect#addPropertyOverride

Acknowledgements

CDK version used

2.142.1

Environment details (OS name and version, etc.)

Python

khushail commented 2 months ago

Hey @jacido , could you please share the repro code for which particular construct, this runtime is being generated.

jacido commented 2 months ago

Lambda_Function.py

''' Module to create a Lambda function''' import aws_cdk as cdk import aws_cdk.aws_lambda as _lambda import aws_cdk.aws_iam as _iam import aws_cdk.aws_ssm as _ssm import aws_cdk.aws_ec2 as _ec2

from aws_cdk.custom_resources import ( AwsCustomResource as _awsCustomResource, AwsCustomResourcePolicy as _awsCustomResourcePolicy, PhysicalResourceId as _physicalResourceId, AwsSdkCall as _awsSdkCall )

from os import path

def create(self, name: str, app_name: str, env_name: str, role: _iam.Role, security_groups, vpc, subnets):

ToDo switch dbpassword to secure string

function = _lambda.Function(
    self, 
    id=name,
    runtime=_lambda.Runtime.NODEJS_16_X,
    handler=name +'.handler',
    code=_lambda.Code.from_asset(
        path="../lambda-triggers/"),    
    function_name="{0}-{1}-{2}".format(name, app_name, env_name),
    memory_size = self.node.try_get_context('environments')[env_name]['memory_size'],
    timeout=cdk.Duration.seconds(self.node.try_get_context('environments')[env_name]['timeout']),
    layers=[
        _lambda.LayerVersion.from_layer_version_arn(self, 'aws_sdk_layer'+name, self.node.try_get_context('environments')[env_name]['aws_sdk_layer']),
        _lambda.LayerVersion.from_layer_version_arn(self, 'cognito_layer'+name, self.node.try_get_context('environments')[env_name]['cognito_custom_auth_layer'])
    ],
    security_groups=security_groups,
    vpc=vpc,
    vpc_subnets=subnets,
    role=role
)

cdk.CfnOutput(self, name+"Name", value=function.function_name)
cdk.CfnOutput(self, name+"Arn", value=function.function_arn)
return function

def add_resource_policy(self, name: str, lambda_arn: str, user_pool_arn: str ): _lambda.CfnPermission( self, name, action="lambda:InvokeFunction", function_name=lambda_arn, principal="cognito-idp.amazonaws.com", source_arn=user_pool_arn)

def setup_environment_variables(self, lane_name:str, function_name:str, function_arn: str, user_pool_id: str, client_id: str ):

custom_resource = _awsCustomResource(
    scope=self,
    id='AWSCustomResource_'+function_name,  
    install_latest_aws_sdk=True,  
    function_name="MyCustomLmbdFn",       
    on_create=_awsSdkCall(
        service='Lambda',                
        action='updateFunctionConfiguration',
        parameters={
            "FunctionName" : function_arn,
            "Environment": {
                "Variables" : {
                    'DB_USERNAME' : _ssm.StringParameter.value_from_lookup(self, "/cognito/{0}/db_user_name".format(lane_name)),
                    'DB_PASSWORD' : _ssm.StringParameter.value_from_lookup(self, "/cognito/{0}/db_password".format(lane_name)),
                    'DB_CONNECTION_STRING' : _ssm.StringParameter.value_from_lookup(self, "/cognito/{0}/db_connection_string".format(lane_name)),
                    'HOSTALIASES' : self.node.try_get_context('environments')[lane_name]['host_aliases'],
                    'REGION' : self.node.try_get_context('environments')[lane_name]['aws_region'],
                    "CLIENTID" : client_id,
                    "USERPOOLID" : user_pool_id
                }
            }
        },
        physical_resource_id=_physicalResourceId.of('LambdaEnvUpdate_'+function_name)
    ),
    policy=_awsCustomResourcePolicy.from_sdk_calls( resources=_awsCustomResourcePolicy.ANY_RESOURCE)
)

cognito_custom_auth_stack.py

from aws_cdk import (

Duration,

Stack,
Tags
# aws_sqs as sqs,

)

import os from constructs import Construct import aws_cdk.aws_ec2 as _ec2 import aws_cdk.aws_cognito as _cognito

from . import cognito from . import iam_role from . import lambda_function from . import vpc from . import tags

class CognitoCustomAuthStack(Stack):

def __init__(self, scope: Construct, construct_id: str, app_name: str, env_name: str, **kwargs) -> None:
    super().__init__(scope, construct_id, **kwargs)

    lambda_execution_role = iam_role.create(self, app_name=app_name, env_name=env_name)

    _vpc = vpc.get_vpc(self, env_name=env_name)
    subnets = vpc.get_subnets(self, lane_name=env_name)

    security_group = _ec2.SecurityGroup.from_lookup_by_id(
        self,
        "SecurityGroup",
        security_group_id=self.node.try_get_context('environments')[env_name]['security_group']
    )

    migrate_user = lambda_function.create(
        self, 
        name='migrate-user', 
        app_name=app_name, 
        env_name=env_name,    
        role=lambda_execution_role,
        security_groups=[security_group],
        vpc=_vpc,
        subnets=subnets
    )

    pre_auth = lambda_function.create(
        self, 
        name='pre-auth', 
        app_name=app_name, 
        env_name=env_name,     
        role=lambda_execution_role,
        security_groups=[security_group],
        vpc=_vpc,
        subnets=subnets
    )

    cfn_user_pool=cognito.create_user_pool(self, app_name=app_name, env_name=env_name, migrate_function_arn=migrate_user.function_arn, pre_authenticate_function_arn=pre_auth.function_arn)
    user_pool_id = cfn_user_pool.ref
    client_id=cognito.create_user_pool_client(self,  lane_name=env_name, user_pool_id=user_pool_id)

    lambda_function.add_resource_policy(
        self,
        name="pre-auth-policy",
        lambda_arn=pre_auth.function_arn,
        user_pool_arn=cfn_user_pool.attr_arn
    )

    lambda_function.add_resource_policy(
        self,
        name="migrate-policy",
        lambda_arn=migrate_user.function_arn,
        user_pool_arn=cfn_user_pool.attr_arn
    )

    lambda_function.setup_environment_variables(
        self, 
        lane_name=env_name, 
        function_name="migrate_user", 
        function_arn=migrate_user.function_arn, 
        user_pool_id=user_pool_id, 
        client_id=client_id
    )

    lambda_function.setup_environment_variables(
        self, 
        lane_name=env_name, 
        function_name="pre_auth", 
        function_arn=pre_auth.function_arn, 
        user_pool_id=user_pool_id, 
        client_id=client_id
    )

    tags.create(self, env_name=env_name, cfn_user_pool=cfn_user_pool)
    Tags.of(self).add('AppManagerCFNStackKey', self.stack_name)
scanlonp commented 2 months ago

Hey @jacido, I believe we have updated our AwsCustomResource construct to use NodeJS 18. In your initial code snippet, I see that in construct info, the version is 2.72.1.

Make sure that both your aws-cdk-lib and aws-cdk versions are updated.

ashishdhingra commented 2 months ago

@jacido Please review last comment https://github.com/aws/aws-cdk/issues/30373#issuecomment-2138335726 and share your findings.

github-actions[bot] commented 2 months ago

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

aws-cdk-automation commented 4 weeks ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.