Skip to content

Commit 3d2c341

Browse files
committed
Merge branch 'fix/sec-scan-findings' into 'develop'
Add suppression of false positives for cfn_nag and checkov DSR security findings, and address security_matrix finding on ECR Image Scanning. See merge request genaiic-reusable-assets/engagement-artifacts/genaiic-idp-accelerator!365
2 parents 9d098d8 + 0d785b8 commit 3d2c341

File tree

13 files changed

+130
-14
lines changed

13 files changed

+130
-14
lines changed

.gitlab-ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,16 @@ integration_tests:
6161
# Add rules to only run on develop branch
6262
rules:
6363
- if: $CI_COMMIT_BRANCH == "develop"
64-
when: always # always # When idp-accelerator CICD is reconfigured
64+
when: on_success
6565
- if: $CI_COMMIT_BRANCH =~ /^feature\/.*/
66-
when: always
66+
when: on_success
6767
- if: $CI_COMMIT_BRANCH =~ /^fix\/.*/
68-
when: always
68+
when: on_success
6969
- if: $CI_COMMIT_BRANCH =~ /^hotfix\/.*/
7070
when: manual
7171
- if: $CI_COMMIT_BRANCH =~ /^release\/.*/
7272
when: manual
73-
- when: manual # This will make it available on all other branches
73+
- when: manual
7474

7575
before_script:
7676
- python --version
@@ -98,7 +98,7 @@ integration_tests:
9898
deployment_validation:
9999
stage: deployment_validation
100100
rules:
101-
- when: always
101+
- when: on_success
102102

103103
before_script:
104104
- apt-get update -y

Dockerfile.optimized

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Optimized Dockerfile for Lambda functions with minimal dependencies
22
# This builds each function with ONLY the dependencies it needs
33

4+
# checkov:skip=CKV_DOCKER_3: "The Dockerfile uses the official AWS Lambda Python base image (public.ecr.aws/lambda/python:3.12-arm64), which already configures the appropriate non-root user for Lambda execution"
5+
# checkov:skip=CKV_DOCKER_2: "The Dockerfile.optimized is specifically designed for AWS Lambda container images, which don't use Docker HEALTHCHECK instructions."
6+
7+
48
FROM public.ecr.aws/lambda/python:3.12-arm64 AS builder
59

610
# Copy uv from official distroless image

iam-roles/cloudformation-management/IDP-Cloudformation-Service-Role.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ Description: >
1212
Resources:
1313
CloudFormationServiceRole:
1414
Type: AWS::IAM::Role
15+
Metadata:
16+
cfn_nag:
17+
rules_to_suppress:
18+
- id: W11
19+
reason: "Broad permissions required for non-admin users to deploy IDP stacks via delegated CloudFormation service role"
20+
- id: W28
21+
reason: "Explicit role name required for consistent cross-stack references in delegated deployment model"
22+
- id: F38
23+
reason: "Resource wildcard needed with broad permissions required for non-admin users to deploy IDP stacks via delegated CloudFormation service role"
24+
- id: W76
25+
reason: "Suppressing W76: SPCM for IAM policy document is higher than 25"
26+
- id: F3
27+
reason: "Suppressing F3: wildcard action on named services required for cloudformation service role, to allow CRUD on stack respources"
28+
# checkov:skip=CKV_AWS_110: "CloudFormation service role requires IAM permissions to create Lambda execution roles and service-linked roles during stack deployment. Trust policy restricts to cloudformation.amazonaws.com service principal."
29+
# checkov:skip=CKV_AWS_109: "CloudFormation service role requires IAM policy management permissions to attach policies to created roles during infrastructure deployment. Constrained by trust policy."
30+
# checkov:skip=CKV_AWS_108: "CloudFormation service role requires S3/KMS permissions to create and configure encrypted data buckets for the IDP solution. All buckets use customer-managed KMS encryption."
31+
# checkov:skip=CKV_AWS_111: "CloudFormation service role requires write permissions across AWS services to deploy complete IDP infrastructure. Trust policy limits to CloudFormation service. Use in conjunction with CloudTrail auditing."
32+
# checkov:skip=CKV_AWS_107: "CloudFormation service role may need to create/configure secrets for service integrations. Actual secret values are provided via parameters, not embedded in templates."
1533
Properties:
1634
RoleName: !Sub '${AWS::StackName}-CFServiceRole'
1735
AssumeRolePolicyDocument:
@@ -108,6 +126,11 @@ Resources:
108126

109127
PassRolePolicy:
110128
Type: AWS::IAM::ManagedPolicy
129+
Metadata:
130+
cfn_nag:
131+
rules_to_suppress:
132+
- id: W28
133+
reason: "Explicit role name required for consistent cross-stack references in delegated deployment model"
111134
Properties:
112135
ManagedPolicyName: !Sub '${AWS::StackName}-PassRolePolicy'
113136
Description: Policy to allow passing the IDP CloudFormation service role

lib/idp_common_pkg/idp_common/model_finetuning/prepare_nova_finetuning_data.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ def load_dataset(
165165
"""
166166
if dataset_name:
167167
logger.info(f"Loading dataset {dataset_name} (split: {split})")
168+
# nosec B615 - Sample training script for model fine-tuning preparation
169+
# This code is not used in production and loads from trusted Hugging Face datasets
170+
# For production use, implement revision pinning via model_versions.py
168171
ds = load_dataset(dataset_name, split=split)
169172
elif local_path:
170173
logger.info(f"Loading local dataset from {local_path}")

options/bedrockkb/template.yaml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,11 @@ Resources:
374374
#
375375
S3VectorManagerRole:
376376
Type: AWS::IAM::Role
377+
Metadata:
378+
cfn_nag:
379+
rules_to_suppress:
380+
- id: W11
381+
reason: Specified permissions do not appy to specific resources
377382
Condition: UseS3Vectors
378383
Properties:
379384
AssumeRolePolicyDocument:
@@ -448,6 +453,8 @@ Resources:
448453
reason: "Function does not require VPC access as it only interacts with AWS services via APIs"
449454
- id: W92
450455
reason: "Function does not require reserved concurrency as it scales based on demand"
456+
- id: W58
457+
reason: "DLQ not required for Cfn Custom Resource function"
451458
# checkov:skip=CKV_AWS_116: "DLQ not required for Cfn Custom Resource function"
452459
# checkov:skip=CKV_AWS_117: "Function does not require VPC access as it only interacts with AWS services via APIs"
453460
# checkov:skip=CKV_AWS_115: "Function does not require reserved concurrency as it scales based on demand"
@@ -542,6 +549,11 @@ Resources:
542549

543550
OpenSearchLambdaExecutionRole:
544551
Type: AWS::IAM::Role
552+
Metadata:
553+
cfn_nag:
554+
rules_to_suppress:
555+
- id: W11
556+
reason: Specified permissions do not appy to specific resources
545557
Condition: UseOpenSearchServerless
546558
Properties:
547559
AssumeRolePolicyDocument:
@@ -611,11 +623,6 @@ Resources:
611623
- aoss:APIAccessAll
612624
Resource:
613625
Fn::Sub: arn:${AWS::Partition}:aoss:${AWS::Region}:${AWS::AccountId}:collection/*
614-
Metadata:
615-
cfn_nag:
616-
rules_to_suppress:
617-
- id: W11
618-
reason: Specified permissions do not appy to specific resources
619626

620627
CreateOSSIndexLambdaFunction:
621628
Type: AWS::Serverless::Function

patterns/pattern-1/template.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,10 @@ Resources:
750750
reason: "This Lambda function does not require VPC access as it only interacts with AWS services via AWS APIs"
751751
- id: W92
752752
reason: "Function does not require concurrent execution limits as it is designed to scale based on demand"
753+
# checkov:skip=CKV_AWS_116: "DLQ not required for this function as StepFunctions will handle retries"
754+
# checkov:skip=CKV_AWS_173: "Environment variables do not contain sensitive data - only configuration values like feature flags and non-sensitive settings"
755+
# checkov:skip=CKV_AWS_117: "Function does not require VPC access as it only interacts with AWS services via APIs"
756+
# checkov:skip=CKV_AWS_115: "Function does not require reserved concurrency as it scales based on demand"
753757
Properties:
754758
PermissionsBoundary: !If [HasPermissionsBoundary, !Ref PermissionsBoundaryArn, !Ref AWS::NoValue]
755759
CodeUri: src/bda_discovery_function/
@@ -1320,7 +1324,7 @@ Resources:
13201324
- id: W92
13211325
reason: "Function does not require concurrent execution limits as it is designed to scale based on demand"
13221326
- id: W58
1323-
reason: "DLQ not required for EventBridge triggered function as it handles A2I status updates"
1327+
reason: "Lambda function has CloudWatch Logs permissions via AWSLambdaBasicExecutionRole managed policy"
13241328
# checkov:skip=CKV_AWS_116: "DLQ not required for EventBridge triggered function as it handles A2I status updates"
13251329
# checkov:skip=CKV_AWS_117: "Function does not require VPC access as it only interacts with AWS services via APIs"
13261330
# checkov:skip=CKV_AWS_115: "Function does not require reserved concurrency as it scales based on demand"

patterns/pattern-2/buildspec.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,36 @@ phases:
5757
- echo "All Pattern-2 Docker images successfully built and pushed to ECR"
5858
- echo "ECR Repository - $ECR_URI"
5959
- echo "Image Version - $IMAGE_VERSION"
60+
- echo "Waiting for vulnerability scans to complete..."
61+
- |
62+
# Wait for and check vulnerability scan results for all images
63+
IMAGES=("ocr-function" "classification-function" "extraction-function" "assessment-function" "processresults-function" "hitl-wait-function" "hitl-status-update-function" "hitl-process-function" "summarization-function")
64+
for IMAGE in "${IMAGES[@]}"; do
65+
echo "Checking scan results for $IMAGE-$IMAGE_VERSION..."
66+
# Wait for scan to complete (max 10 minutes)
67+
for i in {1..60}; do
68+
SCAN_STATUS=$(aws ecr describe-image-scan-findings --repository-name $(basename $ECR_URI) --image-id imageTag=$IMAGE-$IMAGE_VERSION --region $AWS_REGION --query 'imageScanStatus.status' --output text 2>/dev/null || echo "IN_PROGRESS")
69+
if [ "$SCAN_STATUS" = "COMPLETE" ]; then
70+
echo "Scan completed for $IMAGE-$IMAGE_VERSION"
71+
# Get vulnerability counts
72+
CRITICAL=$(aws ecr describe-image-scan-findings --repository-name $(basename $ECR_URI) --image-id imageTag=$IMAGE-$IMAGE_VERSION --region $AWS_REGION --query 'imageScanFindings.findingCounts.CRITICAL' --output text 2>/dev/null || echo "0")
73+
HIGH=$(aws ecr describe-image-scan-findings --repository-name $(basename $ECR_URI) --image-id imageTag=$IMAGE-$IMAGE_VERSION --region $AWS_REGION --query 'imageScanFindings.findingCounts.HIGH' --output text 2>/dev/null || echo "0")
74+
echo "Vulnerabilities found in $IMAGE-$IMAGE_VERSION: CRITICAL=$CRITICAL, HIGH=$HIGH"
75+
# Fail build if critical vulnerabilities found
76+
if [ "$CRITICAL" != "0" ] && [ "$CRITICAL" != "None" ]; then
77+
echo "ERROR: Critical vulnerabilities found in $IMAGE-$IMAGE_VERSION. Build failed."
78+
exit 1
79+
fi
80+
break
81+
elif [ "$SCAN_STATUS" = "FAILED" ]; then
82+
echo "WARNING: Vulnerability scan failed for $IMAGE-$IMAGE_VERSION"
83+
break
84+
fi
85+
echo "Scan in progress for $IMAGE-$IMAGE_VERSION... (attempt $i/60)"
86+
sleep 10
87+
done
88+
if [ "$SCAN_STATUS" != "COMPLETE" ]; then
89+
echo "WARNING: Scan did not complete within timeout for $IMAGE-$IMAGE_VERSION"
90+
fi
91+
done
92+
- echo "Vulnerability scanning completed for all images"

patterns/pattern-2/template.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,16 @@ Resources:
185185
- logs:CreateLogGroup
186186
- logs:CreateLogStream
187187
- logs:PutLogEvents
188+
- Resource:
189+
- !GetAtt Pattern2ECRRepository.Arn
190+
Effect: Allow
191+
Action:
192+
- ecr:DescribeImageScanFindings
193+
- ecr:StartImageScan
188194

189195
Pattern2ECRRepository:
190196
Type: AWS::ECR::Repository
197+
# checkov:skip=CKV_AWS_51: "Mutable tags allowed for workflow flexibility and version updates."
191198
Properties:
192199
ImageScanningConfiguration:
193200
ScanOnPush: true
@@ -1921,8 +1928,13 @@ Resources:
19211928
rules_to_suppress:
19221929
- id: W11
19231930
reason: "IAM policy allows broad permissions for DynamoDB operations which are necessary for tracking HITL tokens across multiple tables"
1931+
- id: W92
1932+
reason: "Function does not require reserved concurrency as it scales based on demand"
1933+
- id: W89
1934+
reason: "Function does not require VPC access as it only interacts with AWS services via APIs"
19241935
# checkov:skip=CKV_AWS_173: "Environment variables do not contain sensitive data - only configuration values like feature flags and non-sensitive settings"
19251936
# checkov:skip=CKV_AWS_117: "Function does not require VPC access as it only interacts with AWS services via APIs"
1937+
# checkov:skip=CKV_AWS_116: "DLQ not required for this function as StepFunctions will handle retries"
19261938
# checkov:skip=CKV_AWS_115: "Function does not require reserved concurrency as it scales based on demand"
19271939
Properties:
19281940
PermissionsBoundary:
@@ -1997,6 +2009,7 @@ Resources:
19972009
reason: "Function does not require reserved concurrency as it scales based on demand"
19982010
# checkov:skip=CKV_AWS_117: "Function does not require VPC access as it only interacts with AWS services via APIs"
19992011
# checkov:skip=CKV_AWS_115: "Function does not require reserved concurrency as it scales based on demand"
2012+
# checkov:skip=CKV_AWS_116: "DLQ not required for Cfn Custom Resource function"
20002013
Properties:
20012014
PermissionsBoundary:
20022015
!If [
@@ -2101,6 +2114,11 @@ Resources:
21012114

21022115
HITLProcessLambdaRole:
21032116
Type: AWS::IAM::Role
2117+
Metadata:
2118+
cfn_nag:
2119+
rules_to_suppress:
2120+
- id: W11
2121+
reason: "State Machine send states does not support resource-level permissions"
21042122
Properties:
21052123
PermissionsBoundary:
21062124
!If [

patterns/pattern-3/fine-tune-sm-udop-classification/code/inference.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ def model_fn(model_dir):
4646
logger.info(f"Loading processor for {model_id} with pinned revision: {revision}")
4747
processor = AutoProcessor.from_pretrained(model_id, revision=revision, apply_ocr=False)
4848
else:
49-
# Fallback for custom models without managed versions
49+
# nosec B615 - Sample training/inference code for demonstration purposes
50+
# This fallback path is only for custom models during development/testing
51+
# Production deployments should use pinned revisions from model_versions.py
5052
logger.info(f"Loading processor for {model_id} without revision pinning (not in managed list)")
5153
processor = AutoProcessor.from_pretrained(model_id, apply_ocr=False)
5254
with open(os.path.join(model_dir, "validation_prompt.json"), 'r') as f:

patterns/pattern-3/fine-tune-sm-udop-classification/code/model.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ def __init__(
3737
model_id, revision=revision, dropout_rate=dropout_rate
3838
)
3939
else:
40-
# Fallback for custom models without managed versions
40+
# nosec B615 - Sample training code for demonstration purposes
41+
# This fallback path is only for custom models during development/testing
42+
# Production deployments should use pinned revisions from model_versions.py
4143
print(f"Loading model {model_id} without revision pinning (not in managed list)")
4244
self.model = UdopForConditionalGeneration.from_pretrained(
4345
model_id, dropout_rate=dropout_rate

0 commit comments

Comments
 (0)