Skip to content

Conversation

@w601sxs
Copy link
Contributor

@w601sxs w601sxs commented Oct 23, 2025

Amazon Bedrock AgentCore Samples Pull Request

Important

  1. We strictly follow a issue-first approach, please first open an issue relating to this Pull Request.
  2. Once this Pull Request is ready for review please attach review ready label to it. Only PRs with review ready will be reviewed.

Issue number:

Concise description of the PR

Changes to ..., because ...

User experience

Please share what the user experience looks like before and after this change

Checklist

If your change doesn't seem to apply, please leave them unchecked.

  • I have reviewed the contributing guidelines
  • Add your name to CONTRIBUTORS.md
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?
  • Are you uploading a dataset?
  • Have you documented Introduction, Architecture Diagram, Prerequisites, Usage, Sample Prompts, and Clean Up steps in your example README?
  • I agree to resolve any issues created for this example in the future.
  • I have performed a self-review of this change
  • Changes have been tested
  • Changes are documented

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

Signed-off-by: Shreyas Subramanian <shreyas.f117@gmail.com>
@github-actions github-actions bot added 03-integrations 03-integrations agentic-frameworks 03-integrations/agentic-frameworks labels Oct 23, 2025
@github-actions
Copy link

github-actions bot commented Oct 23, 2025

Latest scan for commit: acbfd18 | Updated: 2025-10-23 19:28:24 UTC

Security Scan Results

Scan Metadata

  • Project: ASH
  • Scan executed: 2025-10-23T19:28:02+00:00
  • ASH version: 3.0.0

Summary

Scanner Results

The table below shows findings by scanner, with status based on severity thresholds and dependencies:

Column Explanations:

Severity Levels (S/C/H/M/L/I):

  • Suppressed (S): Security findings that have been explicitly suppressed/ignored and don't affect the scanner's pass/fail status
  • Critical (C): The most severe security vulnerabilities requiring immediate remediation (e.g., SQL injection, remote code execution)
  • High (H): Serious security vulnerabilities that should be addressed promptly (e.g., authentication bypasses, privilege escalation)
  • Medium (M): Moderate security risks that should be addressed in normal development cycles (e.g., weak encryption, input validation issues)
  • Low (L): Minor security concerns with limited impact (e.g., information disclosure, weak recommendations)
  • Info (I): Informational findings for awareness with minimal security risk (e.g., code quality suggestions, best practice recommendations)

Other Columns:

  • Time: Duration taken by each scanner to complete its analysis
  • Action: Total number of actionable findings at or above the configured severity threshold that require attention

Scanner Results:

  • PASSED: Scanner found no security issues at or above the configured severity threshold - code is clean for this scanner
  • FAILED: Scanner found security vulnerabilities at or above the threshold that require attention and remediation
  • MISSING: Scanner could not run because required dependencies/tools are not installed or available
  • SKIPPED: Scanner was intentionally disabled or excluded from this scan
  • ERROR: Scanner encountered an execution error and could not complete successfully

Severity Thresholds (Thresh Column):

  • CRITICAL: Only Critical severity findings cause scanner to fail
  • HIGH: High and Critical severity findings cause scanner to fail
  • MEDIUM (MED): Medium, High, and Critical severity findings cause scanner to fail
  • LOW: Low, Medium, High, and Critical severity findings cause scanner to fail
  • ALL: Any finding of any severity level causes scanner to fail

Threshold Source: Values in parentheses indicate where the threshold is configured:

  • (g) = global: Set in the global_settings section of ASH configuration
  • (c) = config: Set in the individual scanner configuration section
  • (s) = scanner: Default threshold built into the scanner itself

Statistics calculation:

  • All statistics are calculated from the final aggregated SARIF report
  • Suppressed findings are counted separately and do not contribute to actionable findings
  • Scanner status is determined by comparing actionable findings to the threshold
Scanner S C H M L I Time Action Result Thresh
bandit 0 0 0 0 0 0 686ms 0 PASSED MED (g)
cdk-nag 0 10 0 0 0 4 28.0s 10 FAILED MED (g)
cfn-nag 0 0 0 9 0 0 685ms 9 FAILED MED (g)
checkov 0 8 0 0 0 0 6.1s 8 FAILED MED (g)
detect-secrets 0 0 0 0 0 0 681ms 0 PASSED MED (g)
grype 0 0 0 0 0 0 29.7s 0 PASSED MED (g)
npm-audit 0 0 0 0 0 0 224ms 0 PASSED MED (g)
opengrep 0 0 0 0 0 0 <1ms 0 SKIPPED MED (g)
semgrep 0 0 0 0 0 0 12.8s 0 PASSED MED (g)
syft 0 0 0 0 0 0 2.8s 0 PASSED MED (g)

Detailed Findings

Show 27 actionable findings

Finding 1: CFN_NAG_W32

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W32
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:456

Description:
CodeBuild project should specify an EncryptionKey value


Finding 2: CFN_NAG_W11

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W11
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:122

Description:
IAM role should not allow * resource on its permissions policy


Finding 3: CFN_NAG_W11

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W11
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:213

Description:
IAM role should not allow * resource on its permissions policy


Finding 4: CFN_NAG_W89

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W89
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:342

Description:
Lambda functions should be deployed inside a VPC


Finding 5: CFN_NAG_W92

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W92
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:342

Description:
Lambda functions should define ReservedConcurrentExecutions to reserve simultaneous executions


Finding 6: CFN_NAG_W28

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W28
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:89

Description:
Resource found with an explicit name, this disallows updates that require replacement of this resource


Finding 7: CFN_NAG_W28

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W28
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:122

Description:
Resource found with an explicit name, this disallows updates that require replacement of this resource


Finding 8: CFN_NAG_W28

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W28
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:213

Description:
Resource found with an explicit name, this disallows updates that require replacement of this resource


Finding 9: CFN_NAG_W28

  • Severity: MEDIUM
  • Scanner: cfn-nag
  • Rule ID: CFN_NAG_W28
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:266

Description:
Resource found with an explicit name, this disallows updates that require replacement of this resource


Finding 10: CKV_AWS_136

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_136
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:88-114

Description:
Ensure that ECR repositories are encrypted using KMS

Code Snippet:

ECRRepository:
    Type: AWS::ECR::Repository
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:
      RepositoryName: !Sub "${AWS::StackName}-${ECRRepositoryName}"
      ImageTagMutability: MUTABLE
      EmptyOnDelete: true
      ImageScanningConfiguration:
        ScanOnPush: true
      RepositoryPolicyText:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowPullFromAccount
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action:
              - ecr:BatchGetImage
              - ecr:GetDownloadUrlForLayer
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-ecr-repository"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: ECR

Finding 11: CKV_AWS_51

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_51
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:88-114

Description:
Ensure ECR Image Tags are immutable

Code Snippet:

ECRRepository:
    Type: AWS::ECR::Repository
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:
      RepositoryName: !Sub "${AWS::StackName}-${ECRRepositoryName}"
      ImageTagMutability: MUTABLE
      EmptyOnDelete: true
      ImageScanningConfiguration:
        ScanOnPush: true
      RepositoryPolicyText:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowPullFromAccount
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action:
              - ecr:BatchGetImage
              - ecr:GetDownloadUrlForLayer
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-ecr-repository"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: ECR

Finding 12: CKV_AWS_111

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_111
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:121-209

Description:
Ensure IAM policies does not allow write access without constraints

Code Snippet:

AgentExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-agent-execution-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: AssumeRolePolicy
            Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
              ArnLike:
                aws:SourceArn: !Sub "arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:*"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess
      Policies:
        - PolicyName: AgentCoreExecutionPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: ECRImageAccess
                Effect: Allow
                Action:
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchCheckLayerAvailability
                Resource: !GetAtt ECRRepository.Arn
              - Sid: ECRTokenAccess
                Effect: Allow
                Action:
                  - ecr:GetAuthorizationToken
                Resource: "*"
              - Sid: CloudWatchLogs
                Effect: Allow
                Action:
                  - logs:DescribeLogStreams
                  - logs:CreateLogGroup
                  - logs:DescribeLogGroups
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
              - Sid: XRayTracing
                Effect: Allow
                Action:
                  - xray:PutTraceSegments
                  - xray:PutTelemetryRecords
                  - xray:GetSamplingRules
                  - xray:GetSamplingTargets
                Resource: "*"
              - Sid: CloudWatchMetrics
                Effect: Allow
                Resource: "*"
                Action: cloudwatch:PutMetricData
                Condition:
                  StringEquals:
                    cloudwatch:namespace: bedrock-agentcore
              - Sid: GetAgentAccessToken
                Effect: Allow
                Action:
                  - bedrock-agentcore:GetWorkloadAccessToken
                  - bedrock-agentcore:GetWorkloadAccessTokenForJWT
                  - bedrock-agentcore:GetWorkloadAccessTokenForUserId
                Resource:
                  - !Sub "arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default"
                  - !Sub "arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default/workload-identity/*"
              - Sid: BedrockModelInvocation
                Effect: Allow
                Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Resource: "*"
              - Sid: SSMParameterAccess
                Effect: Allow
                Action:
                  - ssm:GetParameter
                  - ssm:GetParameters
                Resource:
                  - !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/agentcore/${AWS::StackName}/*"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-agent-execution-role"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: IAM

Finding 13: CKV_AWS_111

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_111
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:212-262

Description:
Ensure IAM policies does not allow write access without constraints

Code Snippet:

CodeBuildRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-codebuild-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodeBuildPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: CloudWatchLogs
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
              - Sid: ECRAccess
                Effect: Allow
                Action:
                  - ecr:BatchCheckLayerAvailability
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchGetImage
                  - ecr:GetAuthorizationToken
                  - ecr:PutImage
                  - ecr:InitiateLayerUpload
                  - ecr:UploadLayerPart
                  - ecr:CompleteLayerUpload
                Resource:
                  - !GetAtt ECRRepository.Arn
                  - "*"
              - Sid: SSMParameterAccess
                Effect: Allow
                Action:
                  - ssm:GetParameter
                  - ssm:GetParameters
                Resource:
                  - !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/agentcore/${AWS::StackName}/*"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-role"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: IAM

Finding 14: CKV_AWS_117

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_117
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:341-449

Description:
Ensure that AWS Lambda function is configured inside a VPC

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.9
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))

              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return

                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'

                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")

                  codebuild = boto3.client('codebuild')

                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise

                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']

                  logger.info(f"Successfully started build: {build_id}")

                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return

                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30
                  start_time = time.time()

                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return

                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']

                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)

                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")

                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return

                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)

              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 15: CKV_AWS_363

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_363
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:341-449

Description:
Ensure Lambda Runtime is not deprecated

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.9
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))

              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return

                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'

                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")

                  codebuild = boto3.client('codebuild')

                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise

                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']

                  logger.info(f"Successfully started build: {build_id}")

                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return

                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30
                  start_time = time.time()

                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return

                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']

                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)

                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")

                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return

                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)

              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 16: CKV_AWS_116

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_116
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:341-449

Description:
Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.9
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))

              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return

                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'

                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")

                  codebuild = boto3.client('codebuild')

                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise

                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']

                  logger.info(f"Successfully started build: {build_id}")

                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return

                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30
                  start_time = time.time()

                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return

                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']

                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)

                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")

                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return

                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)

              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 17: CKV_AWS_115

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_115
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:341-449

Description:
Ensure that AWS Lambda function is configured for function-level concurrent execution limit

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.9
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))

              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return

                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'

                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")

                  codebuild = boto3.client('codebuild')

                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise

                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']

                  logger.info(f"Successfully started build: {build_id}")

                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return

                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30
                  start_time = time.time()

                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return

                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']

                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)

                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")

                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return

                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)

              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 18: AwsSolutions-IAM4

  • Severity: HIGH
  • Scanner: cdk-nag
  • Rule ID: AwsSolutions-IAM4
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:120

Description:
The IAM user, role, or group uses AWS managed policies.

Exception Reason: N/A

Code Snippet:

Resources:
  AgentExecutionRole:
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Condition:
              ArnLike:
                aws:SourceArn:
                  Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount:
                  Ref: AWS::AccountId
            Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Sid: AssumeRolePolicy
        Version: '2012-10-17'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchCheckLayerAvailability
                Effect: Allow
                Resource:
                  Fn::GetAtt:
                    - ECRRepository
                    - Arn
                Sid: ECRImageAccess
              - Action:
                  - ecr:GetAuthorizationToken
                Effect: Allow
                Resource: '*'
                Sid: ECRTokenAccess
              - Action:
                  - logs:DescribeLogStreams
                  - logs:CreateLogGroup
                  - logs:DescribeLogGroups
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchLogs
              - Action:
                  - xray:PutTraceSegments
                  - xray:PutTelemetryRecords
                  - xray:GetSamplingRules
                  - xray:GetSamplingTargets
                Effect: Allow
                Resource: '*'
                Sid: XRayTracing
              - Action: cloudwatch:PutMetricData
                Condition:
                  StringEquals:
                    cloudwatch:namespace: bedrock-agentcore
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchMetrics
              - Action:
                  - bedrock-agentcore:GetWorkloadAccessToken
                  - bedrock-agentcore:GetWorkloadAccessTokenForJWT
                  - bedrock-agentcore:GetWorkloadAccessTokenForUserId
                Effect: Allow
                Resource:
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default/workload-identity/*
                Sid: GetAgentAccessToken
              - Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Effect: Allow
                Resource: '*'
                Sid: BedrockModelInvocation
              - Action:
                  - ssm:GetParameter
                  - ssm:GetParameters
                Effect: Allow
                Resource:
                  - Fn::Sub: arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/agentcore/${AWS::StackName}/*
                Sid: SSMParameterAccess
            Version: '2012-10-17'
          PolicyName: AgentCoreExecutionPolicy
      RoleName:
        Fn::Sub: ${AWS::StackName}-agent-execution-role
      Tags:
        - Key: Name
          Value:
            Fn::Sub: ${AWS::StackName}-agent-execution-role
        - Key: StackName
          Value:
            Ref: AWS::StackName
        - Key: Module
          Value: IAM
    Type: AWS::IAM::Role

Finding 19: AwsSolutions-IAM5

  • Severity: HIGH
  • Scanner: cdk-nag
  • Rule ID: AwsSolutions-IAM5
  • Location: 03-integrations/agentic-frameworks/agentcore-parameterized-template.yaml:120

Description:
The IAM entity contains wildcard permissions and does not have a cdk-nag rule suppression with evidence for those permission.

Exception Reason: N/A

Code Snippet:



<!-- ASH-SECURITY-SCAN-COMMENT -->

Signed-off-by: Shreyas Subramanian <shreyas.f117@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

03-integrations 03-integrations agentic-frameworks 03-integrations/agentic-frameworks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant