Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1a73383
Added new LambdaCFT.yml to support Lambda function deployment for egr…
Anusha-janardhan Jul 2, 2025
4b544e8
Add egress-lambda.zip deployment package for Lambda setup
Anusha-janardhan Jul 2, 2025
0b71caa
remove zip file
Anusha-janardhan Jul 3, 2025
4198b0f
feat(lambda): add Lambda function with index.js, package.json, and pa…
Anusha-janardhan Jul 3, 2025
6255f81
feat: move Lambda section to egress template and remove function URL
Anusha-janardhan Jul 15, 2025
51778d6
Merge pull request #201 from Anusha-janardhan/topic-release
RLIndia Oct 28, 2025
2d3c5c4
feat(settings): added settings configuration in settings-config.json …
Anusha-janardhan Oct 30, 2025
02b012d
feat: update standard catalog items and config.json with latest confi…
Anusha-janardhan Oct 31, 2025
a82eb6f
feat(config): add privateSPCert and SNS event trigger URLs to configu…
Anusha-janardhan Oct 31, 2025
46686cc
Merge pull request #205 from Anusha-janardhan/topic-release
RLIndia Oct 31, 2025
356e8a6
feat(catalog): remove deprecated catalog items and update Amazon Sage…
Anusha-janardhan Oct 31, 2025
9dfa17b
Merge branch 'RLOpenCatalyst:topic-release' into topic-release
Anusha-janardhan Oct 31, 2025
77af9b1
feat(upload-assets): add script for uploading assets to S3 with valid…
Anusha-janardhan Nov 4, 2025
31ce0ae
Merge pull request #206 from Anusha-janardhan/topic-release
RLIndia Jan 30, 2026
b3102f7
Enhancement: Added a flag to skip copy to S3 if repeated deployment a…
RLIndia Jan 30, 2026
e166ea8
Merge branch 'topic-release' of https://github.com/RLOpenCatalyst/rgd…
RLIndia Jan 30, 2026
d23eb4c
Update the base account policy to modify the S3 bucket policy, update…
harshithNayakRelevanceLab Feb 9, 2026
4848ee7
Merge pull request #209 from harshithNayakRelevanceLab/topic-release
harshithNayakRelevanceLab Feb 9, 2026
10e0534
Fix: not able to attach cross account policy to rg portal role.
harshithNayakRelevanceLab Feb 19, 2026
663f905
Merge pull request #211 from harshithNayakRelevanceLab/topic-release
RLIndia Feb 25, 2026
5c150aa
Update pcs_quick_lt.yaml: Add new IAM policy document and S3 mounts p…
May 14, 2026
cd943b8
Merge pull request #213 from shashank1333/topic-release
RLIndia May 14, 2026
5f71b66
Merge pull request #215 from RLOpenCatalyst/main
RLIndia Jun 1, 2026
bbf73d4
feat(ec2-rockyLinux): add password parameter and update user data scr…
Anusha-janardhan Jun 1, 2026
9230589
Remove unused configurations which are not used anywhere in the code.
RLIndia Jun 2, 2026
fdee219
Fixed Code Rabbit review comments for PR #216
RLIndia Jun 2, 2026
8d72ffb
Merge pull request #217 from Anusha-janardhan/topic-release
RLIndia Jun 2, 2026
74724d0
Update config/config.json
RLIndia Jun 2, 2026
de1b8af
Update cft-templates/sagemakerUserProfile.yaml
RLIndia Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 149 additions & 51 deletions SRE/Egress/Setup-templates/egressresources.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
# (c) 2022 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
# This AWS Content is provided subject to the terms of the AWS Customer
# Agreement available at https://aws.amazon.com/agreement or other written
# agreement between Customer and Amazon Web Services, Inc

###############################################################################

AWSTemplateFormatVersion: "2010-09-09"
Description: Provision all the required resources for TRE Egress application setup in RG.
Description: >
Combined CloudFormation template for TRE Egress application setup in RG.
Creates egressstore and egressnotification buckets, Lambda function, and all required resources.
Lambda permissions are restricted to only the created buckets and KMS key.

Parameters:
LambdaFunctionName:
Type: String
Description: Name of the Lambda function
AllowedPattern: ^[a-zA-Z0-9\-_.]{3,63}
Default: rg-EgressLambda
S3BucketName:
Type: String
Description: Name of the S3 bucket containing the Lambda zip file
S3ObjectKey:
Type: String
Description: Key of the Lambda zip file in the S3 bucket
Default: egress-copy.zip

Resources:
EgressStoreEncryptionKey:
Type: AWS::KMS::Key
Properties:
Description: >-
Master key used to encrypt objects stored in the egress-store bucket
Description: Master key used to encrypt objects stored in the egress-store bucket
EnableKeyRotation: true
KeyPolicy:
Version: "2012-10-17"
Expand All @@ -27,39 +36,13 @@ Resources:
Action:
- "kms:*"
Resource: "*"
# - Sid: Allow API access to create object and update policy for new workspaces
# Effect: Allow
# Principal:
# AWS:
# - !Sub "arn:aws:iam::${AWS::AccountId}:role/RGPortalUser"
# Action:
# - kms:GenerateDataKey
# - kms:DescribeKey
# - kms:GetKeyPolicy
# - kms:PutKeyPolicy
# Resource: "*"
# - Sid: Allow workflows to update key policy for new workspaces
# Effect: Allow
# Principal:
# AWS:
# - !Sub "arn:aws:iam::${AWS::AccountId}:role/RGPortalUser"
# Action:
# - kms:GenerateDataKey
# - kms:Decrypt
# - kms:DescribeKey
# - kms:Encrypt
# - kms:ReEncrypt*
# - kms:GetKeyPolicy
# - kms:PutKeyPolicy
# Resource: "*"

EgressStoreEncryptionKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: !Sub "alias/${AWS::AccountId}-rg/s3/egressstorever"
TargetKeyId: !Ref EgressStoreEncryptionKey

# S3 bucket used to store egress data from workspace
EgressStoreBucket:
Type: AWS::S3::Bucket
Properties:
Expand All @@ -72,9 +55,6 @@ Resources:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
# LoggingConfiguration:
# DestinationBucketName: "915161961510-treprod-ldn-pj1-logging"
# LogFilePrefix: egressStore/
VersioningConfiguration:
Status: Enabled
CorsConfiguration:
Expand All @@ -85,12 +65,12 @@ Resources:
- POST
ExposedHeaders:
- ETag
PublicAccessBlockConfiguration: # Block all public access configuration for the S3 bucket
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
# S3 bucket policy used to store egress data from workspace

EgressStoreBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Expand All @@ -117,7 +97,7 @@ Resources:
Condition:
StringNotEquals:
s3:signatureversion: "AWS4-HMAC-SHA256"
# S3 snapshot(egress copy) bucket used to copy the egress data from workspace bucket

EgressNotificationBucket:
Type: AWS::S3::Bucket
Properties:
Expand All @@ -130,9 +110,8 @@ Resources:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
# LoggingConfiguration:
# DestinationBucketName: "915161961510-treprod-ldn-pj1-logging"
# LogFilePrefix: egressNotificationBucket/
VersioningConfiguration:
Status: Enabled
CorsConfiguration:
CorsRules:
- AllowedOrigins:
Expand All @@ -141,14 +120,12 @@ Resources:
- POST
ExposedHeaders:
- ETag
PublicAccessBlockConfiguration: # Block all public access configuration for the S3 bucket
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
# S3 snapshot(copy egress) bucket policy used to copy the egress data from workspace bucket

EgressNotificationBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Expand All @@ -175,14 +152,14 @@ Resources:
Condition:
StringNotEquals:
s3:signatureversion: "AWS4-HMAC-SHA256"
#SNS topic is created as part of this stack but Subscriptions would happen from egress stack

EgressNotificationTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: "rg-EgressTopicTest"
KmsMasterKeyId: !Ref EgressStoreEncryptionKey
TopicName: "EgressTopicTest"
#Egress Store dynamoDB

EgressStoreDb:
Type: AWS::DynamoDB::Table
Properties:
Expand All @@ -203,3 +180,124 @@ Resources:
KeyType: "HASH"
Projection:
ProjectionType: "ALL"

LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: EgressLambdaBasicExecution
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: RGLambdaBasics
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "*"
- Sid: AllowEgressLambdaToCopyFromStoreToNotification
Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:ListBucket"
- "s3:DeleteObject"
- "s3:GetBucketLocation"
- "s3:ListBucketMultipartUploads"
- "s3:AbortMultipartUpload"
- "s3:ListMultipartUploadParts"
- "s3:PutObjectAcl"
- "s3:GetObjectAcl"
- "s3:DeleteObjectVersion"
- "s3:GetObjectVersion"
- "s3:PutObjectVersionAcl"
- "s3:GetObjectVersionAcl"
Resource:
- !GetAtt EgressStoreBucket.Arn
- !Join ["/", [!GetAtt EgressStoreBucket.Arn, "*"]]
- !GetAtt EgressNotificationBucket.Arn
- !Join ["/", [!GetAtt EgressNotificationBucket.Arn, "*"]]
- Sid: AllowKMSForEgressBuckets
Effect: "Allow"
Action:
- "kms:Decrypt"
- "kms:Encrypt"
- "kms:GenerateDataKey"
- "kms:DescribeKey"
Resource: !GetAtt EgressStoreEncryptionKey.Arn

LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Ref LambdaFunctionName
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: nodejs18.x
Code:
S3Bucket: !Ref S3BucketName
S3Key: !Ref S3ObjectKey
Timeout: 900

LambdaFunctionUrl:
Type: AWS::Lambda::Url
Properties:
TargetFunctionArn: !Ref LambdaFunction
AuthType: AWS_IAM

InvokeLambdaPermissionPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName:
Fn::Sub: "InvokeLambda-${LambdaFunctionName}"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "lambda:InvokeFunctionUrl"
Resource: !GetAtt LambdaFunction.Arn
Condition:
StringEquals:
lambda:FunctionUrlAuthType: "AWS_IAM"

Outputs:
EgressStoreBucketArn:
Description: ARN of the Egress Store S3 bucket
Value: !GetAtt EgressStoreBucket.Arn

EgressStoreKmsArn:
Description: ARN of the Egress Store KMS Key
Value: !GetAtt EgressStoreEncryptionKey.Arn

EgressStoreBucketName:
Description: Name of the Egress Store S3 bucket
Value: !Ref EgressStoreBucket

EgressNotificationBucketName:
Description: Name of the Egress Notification S3 bucket
Value: !Ref EgressNotificationBucket

EgressStoreLambdaUrl:
Description: Lambda Function Url
Value: !GetAtt LambdaFunctionUrl.FunctionUrl

EgressStoreLambdaArn:
Description: ARN of the Lambda function
Value: !GetAtt LambdaFunction.Arn

EgressStoreDbTableName:
Description: Name of the Egress Store DynamoDB table
Value: !Ref EgressStoreDb

EgressNotificationTopicArn:
Description: ARN of the Egress Notification SNS Topic
Value: !Ref EgressNotificationTopic
94 changes: 94 additions & 0 deletions SRE/lambdaresources/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import AWS from 'aws-sdk';
import archiver from 'archiver';
import stream from 'stream';

const s3 = new AWS.S3();

export const handler = async (event) => {

try {
const reqBody = JSON.parse(event.body);
const sourceBucket = reqBody.sourceBucket;
const sourcePrefix = reqBody.sourcePrefix;
const destinationBucket = reqBody.destinationBucket;
const destinationPrefix = reqBody.destinationPrefix;
console.log(`Zipping and uploading files from ${sourcePrefix} to ${destinationPrefix}`);

// List objects in the source S3 folder
const listParams = {
Bucket: sourceBucket,
Prefix: sourcePrefix
};
const contents = [];
let continuationToken;

do {
const page = await s3.listObjectsV2({
...listParams,
ContinuationToken: continuationToken
}).promise();
contents.push(...(page.Contents ?? []));
continuationToken = page.IsTruncated ? page.NextContinuationToken : undefined;
} while (continuationToken);

if (listedObjects.Contents.length === 0) {
console.log('No files found in the source folder');
return { statusCode: 404, body: 'No files found in the source folder' };
}

// PassThrough stream and archive setup
const passThroughStream = new stream.PassThrough();
const archive = archiver('zip', { zlib: { level: 9 } });

archive.on('error', (error) => {
throw new Error(`Archiving error: ${error.message}`);
});

archive.pipe(passThroughStream);

// Start S3 upload process asynchronously
const uploadParams = {
Bucket: destinationBucket,
Key: destinationPrefix,
Body: passThroughStream,
ContentType: 'application/zip'
};
const uploadPromise = s3.upload(uploadParams).promise();

// Add files to archive
for (const obj of contents) {
const fileKey = obj.Key;
const fileStream = s3.getObject({ Bucket: sourceBucket, Key: fileKey }).createReadStream();
const filePath = fileKey.replace(sourcePrefix, '');

if (!filePath) continue; // Skip empty paths

archive.append(fileStream, { name: filePath });
console.log(`Appended file to archive: ${filePath}`);
}

// Finalize the archive to signal completion
await archive.finalize();

// Wait for S3 upload to complete
await uploadPromise;

console.log('Zip file created and uploaded successfully');

return {
statusCode: 201,
headers: { "Content-Type": "application/json" },
body: 'Zip file created and uploaded successfully',
isBase64Encoded: false
};

} catch (error) {
console.error('Error creating or uploading zip file:', error.message);
return {
statusCode: 500,
headers: { "Content-Type": "application/json" },
body: `Error creating or uploading zip file: ${error.message}`,
isBase64Encoded: false
};
}
};
Loading