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

aws_lambda: enforced code signing causes deployment failure #29474

Open
cjhelloletsgo opened this issue Mar 13, 2024 · 15 comments · Fixed by #31500
Open

aws_lambda: enforced code signing causes deployment failure #29474

cjhelloletsgo opened this issue Mar 13, 2024 · 15 comments · Fixed by #31500
Labels
@aws-cdk/aws-lambda Related to AWS Lambda effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2

Comments

@cjhelloletsgo
Copy link

cjhelloletsgo commented Mar 13, 2024

Describe the bug

While configuring code signing on an aws lambda if you specify a code signing config where the untrusted_artifact_on_deployment parameter is set to ENFORCE the deployment will always fail. If the policy is set to warn there is no problem.

test_signing_profile = signer.SigningProfile(
    self,
    "Test Signing Profile",
    platform=signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
)

test_code_signing_config = lambda_.CodeSigningConfig(
    self,
    "Test Code Signing Config",
    signing_profiles=[
        test_signing_profile,
    ],
    description="Test",
    # setting untrusted_artifact_on_deployment to ENFORCE causes deployment to fail
    untrusted_artifact_on_deployment=lambda_.UntrustedArtifactOnDeployment.ENFORCE,
)

test_lambda = lambda_.Function(
    self,
    "Test Lambda",
    runtime=lambda_.Runtime.PYTHON_3_12,
    handler="lambda_function.lambda_handler",
    code_signing_config=test_code_signing_config,
    code=lambda_.Code.from_asset(
        "lambda/api/websocket/test",
    ),
    timeout=Duration.seconds(15),
    memory_size=256,
    architecture=lambda_.Architecture.X86_64,
    retry_attempts=0,
    description="Test Lambda delete later.",
    initial_policy=[],
)

Expected Behavior

The lambda to be signed using the code signing configuration

Current Behavior

The code fails to deploy with an error message: Lambda cannot deploy the function. The function or layer might be signed using a signature that the client is not configured to accept. Check the provided signature for LAMBDA_ARN_HERE

Reproduction Steps

Create a stack with the above resources, try to deploy a lambda with warn, it will work. Try to deploy the lambda with enforce, it will not work

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.132.1

Framework Version

No response

Node.js Version

v20.11.1

OS

Ubuntu 23.10

Language

Python

Language Version

Python 3.11

Other information

No response

@cjhelloletsgo cjhelloletsgo added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Mar 13, 2024
@github-actions github-actions bot added the @aws-cdk/aws-lambda Related to AWS Lambda label Mar 13, 2024
@pahud
Copy link
Contributor

pahud commented Mar 15, 2024

Hi

I was able to deploy it with UntrustedArtifactOnDeployment.ENFORCE with cdk v2.133.0.

Please check my code in TypeScript:

    const signingProfile = new signer.SigningProfile(this, 'SigningProfile', {
      platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
    });
    
    const codeSigningConfig = new lambda.CodeSigningConfig(this, 'CodeSigningConfig', {
      signingProfiles: [signingProfile],
      untrustedArtifactOnDeployment: lambda.UntrustedArtifactOnDeployment.ENFORCE,
    });
    
    new lambda.Function(this, 'Function', {
      codeSigningConfig,
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')),
    });

synth

Resources:
  SigningProfile2139A0F9:
    Type: AWS::Signer::SigningProfile
    Properties:
      PlatformId: AWSLambda-SHA384-ECDSA
      SignatureValidityPeriod:
        Type: MONTHS
        Value: 135
    Metadata:
      aws:cdk:path: dummy-stack4/SigningProfile/Resource
  CodeSigningConfigD8D41C10:
    Type: AWS::Lambda::CodeSigningConfig
    Properties:
      AllowedPublishers:
        SigningProfileVersionArns:
          - Fn::GetAtt:
              - SigningProfile2139A0F9
              - ProfileVersionArn
      CodeSigningPolicies:
        UntrustedArtifactOnDeployment: Enforce
    Metadata:
      aws:cdk:path: dummy-stack4/CodeSigningConfig/Resource
  FunctionServiceRole675BB04A:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    Metadata:
      aws:cdk:path: dummy-stack4/Function/ServiceRole/Resource
  Function76856677:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: cdk-hnb659fds-assets-903779448426-us-east-1
        S3Key: 297e4961275717170c4e122c4dd6e629b83080796b88b6716027321ec3f4e2c7.zip
      CodeSigningConfigArn:
        Fn::GetAtt:
          - CodeSigningConfigD8D41C10
          - CodeSigningConfigArn
      Handler: index.handler
      Role:
        Fn::GetAtt:
          - FunctionServiceRole675BB04A
          - Arn
      Runtime: nodejs18.x
    DependsOn:
      - FunctionServiceRole675BB04A
    Metadata:
      aws:cdk:path: dummy-stack4/Function/Resource
      aws:asset:path: asset.297e4961275717170c4e122c4dd6e629b83080796b88b6716027321ec3f4e2c7
      aws:asset:is-bundled: false
      aws:asset:property: Code
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/2WPzw6CMAzGn8X7qCKJ8Sokng0+ABljkPJnS+jQw7J3twM8GE9f+/3afO0Z0iyD00G+KVHNkIxYg386qQbBVuUJO6NntljRdI/ZtjhqUbTm1wlilFPdSPCFbfTOCmta7OLwv3lfjHJoTaTfOgiUE/jSbglRg6CskkTaEdyicA/5ogbtckmMS012mZUWK+XLO85Yt3cQhOFw6On4Sq+QXvjZnhCTeTEOJw3lph8kXNDoCQEAAA==
    Metadata:
      aws:cdk:path: dummy-stack4/CDKMetadata/Default
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Rules:
  CheckBootstrapVersion:
    Assertions:
      - Assert:
          Fn::Not:
            - Fn::Contains:
                - - "1"
                  - "2"
                  - "3"
                  - "4"
                  - "5"
                - Ref: BootstrapVersion
        AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.

cdk deploy works great to me. And I can see this from the lambda console.

image

Is your error coming from cloudformation? Can you share your cdk synth template? I believe it should work.

@pahud pahud added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. p2 effort/medium Medium work item – several days of effort and removed needs-triage This issue or PR still needs to be triaged. labels Mar 15, 2024
@cjhelloletsgo
Copy link
Author

Sure, this is the template it generates:

Resources:
  TestSigningProfile98254211:
    Type: AWS::Signer::SigningProfile
    Properties:
      PlatformId: AWSLambda-SHA384-ECDSA
      SignatureValidityPeriod:
        Type: MONTHS
        Value: 135
    Metadata:
      aws:cdk:path: IssueStack/Test Signing Profile/Resource
  TestCodeSigningConfig2952C7DC:
    Type: AWS::Lambda::CodeSigningConfig
    Properties:
      AllowedPublishers:
        SigningProfileVersionArns:
          - Fn::GetAtt:
              - TestSigningProfile98254211
              - ProfileVersionArn
      CodeSigningPolicies:
        UntrustedArtifactOnDeployment: Enforce
      Description: Test
    Metadata:
      aws:cdk:path: IssueStack/Test Code Signing Config/Resource
  TestLambdaServiceRoleECB4CB18:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    Metadata:
      aws:cdk:path: IssueStack/Test Lambda/ServiceRole/Resource
  TestLambda93B0066B:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - x86_64
      Code:
        S3Bucket: cdk-hnb659fds-assets-308665918648-us-east-1
        S3Key: 851da26868933e8ab521e3bc2c318bd2a7f9220284d9b35ce3ab5c31fce99feb.zip
      CodeSigningConfigArn:
        Fn::GetAtt:
          - TestCodeSigningConfig2952C7DC
          - CodeSigningConfigArn
      Description: Test Lambda delete later.
      Handler: lambda_function.lambda_handler
      MemorySize: 256
      Role:
        Fn::GetAtt:
          - TestLambdaServiceRoleECB4CB18
          - Arn
      Runtime: python3.12
    DependsOn:
      - TestLambdaServiceRoleECB4CB18
    Metadata:
      aws:cdk:path: IssueStack/Test Lambda/Resource
      aws:asset:path: asset.851da26868933e8ab521e3bc2c318bd2a7f9220284d9b35ce3ab5c31fce99feb
      aws:asset:is-bundled: false
      aws:asset:property: Code
  TestLambdaEventInvokeConfig9F084114:
    Type: AWS::Lambda::EventInvokeConfig
    Properties:
      FunctionName:
        Ref: TestLambda93B0066B
      MaximumRetryAttempts: 0
      Qualifier: $LATEST
    Metadata:
      aws:cdk:path: IssueStack/Test Lambda/EventInvokeConfig/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/2WO0W7CMAxFv4X31IzmC6Bi0t5Q+wHIpG7w2jpSnYJQlH9HBbZp4ulY99jWLWFjLXys8KqFa/ti4BOkJqLrDV71mJS90ASpYS8s/jCFjgcyVSf/k2wGHE8tQqpCSy9XBenYL8vv4ecsLnKQxf7O+wtJ/JJL6Onv9i3MhnGEVIdnkYXZqD2iKkWF7QKjFnaz6ynuUCmbmjTMkyPzsE1Ez/L4/iOyOdziOcjawqaEcvWtzMU0S+SRoH7yDppk/rctAQAA
    Metadata:
      aws:cdk:path: IssueStack/CDKMetadata/Default
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Rules:
  CheckBootstrapVersion:
    Assertions:
      - Assert:
          Fn::Not:
            - Fn::Contains:
                - - "1"
                  - "2"
                  - "3"
                  - "4"
                  - "5"
                - Ref: BootstrapVersion
        AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.

As well as the entire stack if that helps

from aws_cdk import (
    Stack,
)
from aws_cdk import aws_lambda as lambda_
from aws_cdk import aws_signer as signer
from constructs import Construct


class IssueStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        test_signing_profile = signer.SigningProfile(
            self,
            "Test Signing Profile",
            platform=signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
        )

        test_code_signing_config = lambda_.CodeSigningConfig(
            self,
            "Test Code Signing Config",
            signing_profiles=[
                test_signing_profile,
            ],
            description="Test",
            # setting untrusted_artifact_on_deployment to ENFORCE causes deployment to fail
            untrusted_artifact_on_deployment=lambda_.UntrustedArtifactOnDeployment.ENFORCE,
        )

        test_lambda = lambda_.Function(
            self,
            "Test Lambda",
            runtime=lambda_.Runtime.PYTHON_3_12,
            handler="lambda_function.lambda_handler",
            code_signing_config=test_code_signing_config,
            code=lambda_.Code.from_asset(
                "lambda/test",
            ),
            memory_size=256,
            architecture=lambda_.Architecture.X86_64,
            retry_attempts=0,
            description="Test Lambda delete later.",
            initial_policy=[],
        )

And a screenshot to match yours
image

So everything seems good except the lambda will always fail to deploy.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Mar 16, 2024
@cjhelloletsgo
Copy link
Author

@pahud Have you got a chance to look into this any more?

@cjhelloletsgo
Copy link
Author

This is still a problem, I have a repo here to help reproduce the problem. https://github.com/cjhelloletsgo/cdk_signing_profile_issue

@pahud
Copy link
Contributor

pahud commented Sep 18, 2024

Yes now I can reproduce this

export class DummyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const signingProfile = new signer.SigningProfile(this, 'SigningProfile', {
      platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
    });
    
    const codeSigningConfig = new lambda.CodeSigningConfig(this, 'CodeSigningConfig', {
      signingProfiles: [signingProfile],
      untrustedArtifactOnDeployment: lambda.UntrustedArtifactOnDeployment.ENFORCE,
    });
    
    const myFunction = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')),
      codeSigningConfig: codeSigningConfig,
    });
  }
}

6:41:26 PM | CREATE_FAILED | AWS::Lambda::Function | MyFunction
Resource handler returned message: "Lambda cannot deploy the function. The function or layer might be signed u
sing a signature that the client is not configured to accept. Check the provided signature for dummy-stackk-My
Function3BAA72D1-wrnBDfNVr1Ik." (RequestToken: d6b8497f-0573-c147-72f4-f5264e22883f, HandlerErrorCode: Invalid
Request)

CDK v2.158.0

synth

{
 "Resources": {
  "SigningProfile2E013C934": {
   "Type": "AWS::Signer::SigningProfile",
   "Properties": {
    "PlatformId": "AWSLambda-SHA384-ECDSA",
    "SignatureValidityPeriod": {
     "Type": "MONTHS",
     "Value": 135
    }
   },
   "Metadata": {
    "aws:cdk:path": "dummy-stackk/SigningProfile2/Resource"
   }
  },
  "CodeSigningConfig202ACE0C5": {
   "Type": "AWS::Lambda::CodeSigningConfig",
   "Properties": {
    "AllowedPublishers": {
     "SigningProfileVersionArns": [
      {
       "Fn::GetAtt": [
        "SigningProfile2E013C934",
        "ProfileVersionArn"
       ]
      }
     ]
    },
    "CodeSigningPolicies": {
     "UntrustedArtifactOnDeployment": "Enforce"
    }
   },
   "Metadata": {
    "aws:cdk:path": "dummy-stackk/CodeSigningConfig2/Resource"
   }
  },
  "MyFunctionServiceRole3C357FF2": {
   "Type": "AWS::IAM::Role",
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
        "Service": "lambda.amazonaws.com"
       }
      }
     ],
     "Version": "2012-10-17"
    },
    "ManagedPolicyArns": [
     {
      "Fn::Join": [
       "",
       [
        "arn:",
        {
         "Ref": "AWS::Partition"
        },
        ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
       ]
      ]
     }
    ]
   },
   "Metadata": {
    "aws:cdk:path": "dummy-stackk/MyFunction/ServiceRole/Resource"
   }
  },
  "MyFunction3BAA72D1": {
   "Type": "AWS::Lambda::Function",
   "Properties": {
    "Code": {
     "S3Bucket": "cdk-hnb659fds-assets-903779448426-us-east-1",
     "S3Key": "3988ba077676d6ed0bb4481ec971bf54da0c66e1ff656338ecfe5b3a001c5511.zip"
    },
    "CodeSigningConfigArn": {
     "Fn::GetAtt": [
      "CodeSigningConfig202ACE0C5",
      "CodeSigningConfigArn"
     ]
    },
    "Handler": "index.handler",
    "Role": {
     "Fn::GetAtt": [
      "MyFunctionServiceRole3C357FF2",
      "Arn"
     ]
    },
    "Runtime": "nodejs18.x"
   },
   "DependsOn": [
    "MyFunctionServiceRole3C357FF2"
   ],
   "Metadata": {
    "aws:cdk:path": "dummy-stackk/MyFunction/Resource",
    "aws:asset:path": "asset.3988ba077676d6ed0bb4481ec971bf54da0c66e1ff656338ecfe5b3a001c5511",
    "aws:asset:is-bundled": false,
    "aws:asset:property": "Code"
   }
  },
  "CDKMetadata": {
   "Type": "AWS::CDK::Metadata",
   "Properties": {
    "Analytics": "v2:deflate64:H4sIAAAAAAAA/2WNwWrDQAxEvyV3WXUSQnttDD0X+wOCspYXxbYWrHVyWPbfg+P4UHp6w7yBOeD+9IXljh5WuLYvBrliaiK5Huhhl2TilSdMjXgV9b9T6GRgqDr922QYaLy2hKkKLb9dFbQTv4z/lz+zuihBF7vlDEIjpjqsDwsz2PFCZhwNvxeAHfE8u57jmYwz1GxhnhzDyzaRvOjrchMZNLSMN/u4H0rcf2K5u5lIMc0aZWSsVz4BnGZHOQkBAAA="
   },
   "Metadata": {
    "aws:cdk:path": "dummy-stackk/CDKMetadata/Default"
   }
  }
 },
 "Parameters": {
  "BootstrapVersion": {
   "Type": "AWS::SSM::Parameter::Value<String>",
   "Default": "/cdk-bootstrap/hnb659fds/version",
   "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
  }
 },
 "Rules": {
  "CheckBootstrapVersion": {
   "Assertions": [
    {
     "Assert": {
      "Fn::Not": [
       {
        "Fn::Contains": [
         [
          "1",
          "2",
          "3",
          "4",
          "5"
         ],
         {
          "Ref": "BootstrapVersion"
         }
        ]
       }
      ]
     },
     "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
    }
   ]
  }
 }
}

@pahud
Copy link
Contributor

pahud commented Sep 18, 2024

I am making it a p1 bug now.

@pahud pahud added p1 and removed p2 labels Sep 18, 2024
@cjhelloletsgo
Copy link
Author

Thank you!

@pahud
Copy link
Contributor

pahud commented Sep 18, 2024

@cjhelloletsgo FYI we are still investigating. Will let you know shortly if we have any updates.

@pahud
Copy link
Contributor

pahud commented Sep 18, 2024

Looks like it's Lambda service's responsibility to proceed the signing operation but I can't find relevant document about it.

image

I'll cut an internal ticket for clarifying.

@pahud
Copy link
Contributor

pahud commented Sep 19, 2024

internal tracking: V1521555433

@pahud pahud added the needs-cfn This issue is waiting on changes to CloudFormation before it can be addressed. label Sep 19, 2024
@pahud
Copy link
Contributor

pahud commented Sep 19, 2024

I believe it's relevant to #12216 (comment) which mentioned that CDK actually didn't sign the bundle from local and aws/aws-cdk-rfcs#305 was attempting to address that but was closed. At this moment, I am afraid you need to sign the bundle using AWS CLI start-signing-job or from the AWS Signer console.

We still welcome any idea to continue from where aws/aws-cdk-rfcs#305 (comment) was stopped. I will submit a small PR to mention that in the lambda doc.

@pahud pahud added p3 and removed p1 needs-cfn This issue is waiting on changes to CloudFormation before it can be addressed. labels Sep 19, 2024
@cjhelloletsgo
Copy link
Author

From reading through those links it seems this is broken with no plans of being fixed? Are you saying I can use start-signing-job somehow in the bundling options? Doing it through the signer console doesn't make sense as I am deploying through the CLI how would that be possible?

@mergify mergify bot closed this as completed in #31500 Sep 19, 2024
@mergify mergify bot closed this as completed in 76e83a5 Sep 19, 2024
Copy link

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.

1 similar comment
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 19, 2024
@pahud
Copy link
Contributor

pahud commented Sep 20, 2024

From reading through those links it seems this is broken with no plans of being fixed? Are you saying I can use start-signing-job somehow in the bundling options? Doing it through the signer console doesn't make sense as I am deploying through the CLI how would that be possible?

Yes unfortunately CDK CLI at this moment does not support it out-of-the-box and the experience would not be expected.

My workaround here. This is not great but it explains how it works in action.

  1. cdk synth to synthesize assets into cdk.out.
  2. publish the assets using npx cdk-assets -p cdk.out/your_stack_name.assets.json publish
  3. you need to have a script like this to sign the zip bundle into a new file and rename it back to the origin filename

Using Shell Script

#!/bin/sh
set -x

ZIP_FILE='a5936dcaa6ccdbc6eacb1209c70d2eed716e9040937124c26b5cc53b954846a0.zip'
PROFILE_NAME='SigningProfile2139A0F9_IvT8c6lPa2rl'
BUCKET='cdk-hnb659fds-assets-123456789012-us-east-1'

LATEST_VERSION=$(aws s3api list-object-versions \
  --bucket $BUCKET \
  --prefix $ZIP_FILE \
  --query 'Versions[0].VersionId' \
  --output text)


JOB_ID=$(aws signer start-signing-job \
  --source "s3={bucketName=$BUCKET,key=$ZIP_FILE, version=$LATEST_VERSION}" \
  --destination "s3={bucketName=$BUCKET,prefix=signed-}" \
  --profile-name $PROFILE_NAME --query 'jobId' --output text)

sleep 2
# get the signedObject s3 key
newObjectKey=$(aws signer describe-signing-job --job-id $JOB_ID --query signedObject.s3.key --output text)

# rename the signed object to origin object name
aws s3 mv s3://$BUCKET/$newObjectKey s3://$BUCKET/$ZIP_FILE
  1. finally, cdk deploy, it should work!

Using Python

If you are comfortable with python, this is my proof of concept(by Amazon Q Developer), you can revise and build your own tool like this before CDK CLI has native support for that.

import json, boto3, time

# Path to your JSON file
file_path = '/Your/Path/To/cdk.out/dummy-stack.assets.json'
profile_name = 'SigningProfile2139A0F9_IvT8c6lPa2rl'

# Function to parse the JSON and extract required information
def parse_assets_json(file_path):
    with open(file_path, 'r') as file:
        data = json.load(file)
    
    assets = []
    for asset_id, asset_info in data.get('files', {}).items():
        source = asset_info.get('source', {})
        destinations = asset_info.get('destinations', {})
        
        # Get the first destination (assuming there's only one)
        destination = next(iter(destinations.values()), {})
        
        packaging = source.get('packaging')
        object_key = destination.get('objectKey')
        bucket_name = destination.get('bucketName')
        
        if packaging == 'zip' and object_key and bucket_name:
            assets.append({
                'assetId': asset_id,
                'packaging': packaging,
                'objectKey': object_key,
                'bucketName': bucket_name
            })
    
    return assets
  
# get_latest_version()
def get_latest_version(s3, bucket_name, object_key):
    response = s3.list_object_versions(
        Bucket=bucket_name,
        Prefix=object_key,
        MaxKeys=1
    )
    if 'Versions' in response and response['Versions']:
        return response['Versions'][0]['VersionId']
    return None
  
def sign_s3_object(bucket_name, object_key, profile_name, destination_bucket=None):
    # Initialize AWS clients
    session = boto3.Session()
    s3 = session.client('s3')
    signer = session.client('signer')
    my_account = session.client('sts').get_caller_identity()['Account']

    # If destination bucket is not specified, use the source bucket
    if not destination_bucket:
        destination_bucket = bucket_name

    # Start the signing job
    response = signer.start_signing_job(
        source={
            's3': {
                'bucketName': bucket_name,
                'key': object_key,
                'version': get_latest_version(s3, bucket_name, object_key)
            }
        },
        destination={
            's3': {
                'bucketName': destination_bucket,
                'prefix': 'sign-',
            }
        },
        profileName=profile_name
    )

    job_id = response['jobId']
    print(f"Signing job started. Job ID: {job_id}")
    # sleep 5 seconds
    time.sleep(5)
    # get signed_object_key from a new describing signing job call
    response = signer.describe_signing_job(jobId=job_id)
    print(response)
    signed_object_key = response['signedObject'].get('s3').get('key')
  
    # Wait for the signing job to complete
    while True:
        response = signer.describe_signing_job(jobId=job_id)
        status = response['status']
        if status == 'Succeeded':
            break
        elif status in ['Failed', 'Revoked']:
            raise Exception(f"Signing job failed with status: {status}")
        time.sleep(5)  # Wait for 5 seconds before checking again

    # Get the signed object key
    print(f"Signing completed. Signed object key: {signed_object_key}")

    # Move the signed object to replace the original object
    s3.copy_object(
        Bucket=bucket_name,
        CopySource={'Bucket': destination_bucket, 'Key': signed_object_key},
        Key=object_key,
        ExpectedBucketOwner=my_account,
        ExpectedSourceBucketOwner=my_account,
        
    )
    print(f"Signed object moved to original key: {object_key}")

    # Delete the temporary signed object
    s3.delete_object(Bucket=destination_bucket, Key=signed_object_key)
    print(f"Temporary signed object deleted: {signed_object_key}")

    return object_key

# Parse the JSON file
result = parse_assets_json(file_path)

# Print the results
for asset in result:
    print(f"Asset ID: {asset['assetId']}")
    print(f"Object Key: {asset['objectKey']}")
    print(f"Bucket Name: {asset['bucketName']}")
    print("---")
    # sign the object
    sign_s3_object(asset['bucketName'], asset['objectKey'], profile_name=profile_name)

Output:

Signing completed. Signed object key: sign-5e21daf1-d34e-4233-bbe2-e63207d7c914.zip
Signed object moved to original key: a5936dcaa6ccdbc6eacb1209c70d2eed716e9040937124c26b5cc53b954846a0.zip
Temporary signed object deleted: sign-5e21daf1-d34e-4233-bbe2-e63207d7c914.zip

Now, I just reopened this issue as p2 feature request.

We welcome community PRs and please help us prioritize with 👍 on the issue description.

@pahud pahud reopened this Sep 20, 2024
@pahud pahud added p2 feature-request A feature should be added or improved. and removed p3 bug This issue is a bug. labels Sep 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
@aws-cdk/aws-lambda Related to AWS Lambda effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants