Skip to content

Commit

Permalink
Merge pull request #407 from aws-solutions/release/v1.13.0
Browse files Browse the repository at this point in the history
Update to v1.13.0
  • Loading branch information
dch90 authored Aug 21, 2023
2 parents 078ccd2 + c8cacde commit 51c6be0
Show file tree
Hide file tree
Showing 30 changed files with 359 additions and 1,109 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.13.0] - August 2023

### Added

* Added functionality to opt out of Anonymized Data Reporting before deploying the solution

### Changed

* Updated Cloudfront distribution to L2 construct in browser stack

### Fixed

* #379 Fixed VPC inputs from throwing an exception when the Source is an Entitlement and there is a VPC Interface attached that is used for output only
* #380 Add missing f-string prefix
* #381 Add empty Tags to ec2 node if none returned from service

### Removed

* Removed fuzzywuzzy library and replaced its usage with built-in python functions

## [1.12.0] - May 2023

### Added
Expand Down
345 changes: 0 additions & 345 deletions NOTICE.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Note: If you want to use the solution without building from source, navigate to
- [Deploy](#deploy)
- [File structure](#file-structure)
- [License](#license)
- [Collection of operational metrics](#collection-of-operational-metrics)
- [Navigate](#navigate)
- [Anonymous Metrics](#metrics)

<a name="solution-overview"></a>
# Solution Overview
Expand Down Expand Up @@ -170,9 +170,9 @@ See license [here](LICENSE.txt).


<a name="metrics"></a>
# Anonymous Metrics
# Collection of operational metrics

This solution collects anonymous operational metrics to help AWS improve the quality of features of the solution. For more information about this capability, please see the [Install Guide](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper/collection-of-operational-metrics.html) for details on the data sent, and how to enable and disable this capability.
This solution collects anonymized operational metrics to help AWS improve the quality of features of the solution. For more information about this capability, please see the [implementation guide](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper-on-aws/references.html).

## Navigate
Navigate to [Architecture](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper/architecture-overview.html) | [Workshop](docs/WORKSHOP.md) | [Install](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper/automated-deployment.html) | [Usage](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper/using-the-browser-application.html) | [Uninstall](https://docs.aws.amazon.com/solutions/latest/media-services-application-mapper/uninstall-the-solution.html) | [Rest API](docs/REST_API.md) | [Contributing](CONTRIBUTING.md)
345 changes: 0 additions & 345 deletions THIRD-PARTY-LICENSES.txt

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion deployment/cdk-solution-helper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fs.readdirSync(global_s3_assets).forEach((file) => {
if (file === 'msam-core-release.template') {
// Manually add the API Gateway Stage dependency
// The API Gateway Stage is generated dynamically in SAM templates,
// therefore the stage is not visible toCDK when synthesizing the template
// therefore the stage is not visible to CDK when synthesizing the template
// and throws an exception.
const [usagePlanKey] = Object.keys(resources).filter(key => /UsagePlan[A-Z\d]{8}/.test(key));
resources[usagePlanKey].DependsOn = 'RestAPImsamStage';
Expand All @@ -56,6 +56,12 @@ fs.readdirSync(global_s3_assets).forEach((file) => {
},
Stage: 'msam',
}];

// Add AWS:LanguageExtensions Transform to support intrinsic functions
// See https://github.com/aws/serverless-application-model/issues/2533 for more details
if (typeof template.Transform === 'string') {
template.Transform = ['AWS::LanguageExtensions', template.Transform]
}
}

// Remove unnecessary CDK metadata
Expand Down
1 change: 0 additions & 1 deletion deployment/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ botocore
cfn-lint
crhelper
defusedxml
fuzzywuzzy
jsonpath_ng
pylint
requests
Expand Down
14 changes: 14 additions & 0 deletions source/cdk/lib/media-services-application-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ export class MediaServicesApplicationMapper extends Stack {
constraintDescription: 'Please enter a value for this field.',
});

/**
* Cfn Mapping
*/
utils.createCfnMapping(this, 'AnonymizedData', {
mapping: {
SendAnonymizedData: {
Data: 'Yes',
},
},
});

/**
* Nested Stacks
*/
Expand Down Expand Up @@ -84,6 +95,9 @@ export class MediaServicesApplicationMapper extends Stack {
NotesTableName: dynamoDBModuleStack.NotesTable,
CacheItemTTL: cacheItemTTL.valueAsString,
RootStackName: Aws.STACK_NAME,
parameters: {
SendAnonymizedData: Fn.findInMap('AnonymizedData', 'SendAnonymizedData', 'Data'),
},
});
utils.addTemplateUrl(
coreModuleStack,
Expand Down
147 changes: 34 additions & 113 deletions source/cdk/lib/msam-browser-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
Aws,
aws_cloudfront as cloudfront,
aws_cloudfront_origins as origins,
aws_iam as iam,
aws_lambda as lambda,
aws_s3 as s3,
Expand Down Expand Up @@ -91,114 +92,42 @@ export class MsamBrowserApp extends NestedStack {
Aws.REGION,
]);

// CloudFront OriginAccessIdentity
const cloudfrontOriginAccessIdentity = new cloudfront.OriginAccessIdentity(this, 'MSAMAppBucketOriginAccessIdentity', {
// CloudFront Distribution
const cloudfrontDistribution = new cloudfront.Distribution(this, 'MSAMAppBucketCloudFrontDistribution', {
enabled: true,
defaultBehavior: {
origin: new origins.S3Origin(s3BucketBrowserApp),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.HTTPS_ONLY,
cachePolicy: new cloudfront.CachePolicy(this, 'MSAMAppBucketCloudFrontCachePolicy', {
minTtl: Duration.seconds(3600),
defaultTtl: Duration.seconds(7200),
maxTtl: Duration.seconds(86400),
headerBehavior: cloudfront.CacheHeaderBehavior.allowList(
'Origin',
'Access-Control-Request-Method',
'Access-Control-Request-Headers',
),
queryStringBehavior: cloudfront.CacheQueryStringBehavior.none(),
}),
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
compress: true,
},
comment: Fn.join('', [
'Origin Access Identity for ',
'CDN for ',
s3BucketBrowserApp.bucketName,
])
]),
defaultRootObject: 'index.html',
priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2019,
enableLogging: true,
logBucket: s3BucketbrowserAppLogs,
logFilePrefix: 'cloudfront/',
});

// Browser App S3 Bucket Policy
const s3BucketAppPolicy = this.createS3BucketPolicy('MSAMBrowserAppBucketPolicy', {
bucket: s3BucketBrowserApp.bucketName,
policyDocument: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
principals: [new iam.CanonicalUserPrincipal(cloudfrontOriginAccessIdentity.cloudFrontOriginAccessIdentityS3CanonicalUserId)],
actions: ['s3:GetObject'],
resources: [
Fn.join('', [
s3BucketBrowserApp.bucketArn,
'/*',
]),
],
}),
],
}),
});

utils.setNagSuppressRules(s3BucketAppPolicy,
{
id: 'AwsSolutions-S10',
reason: 'HTTPS requirement not supported at this time.',
}
)

// CloudFront Distribution
/**
* Distribution L2 construct is available for use
* The solution, however, requires many cloudfront propeties not supported in L2 construct's native props
* Thus, the L1 CfnCloudfront is used instead.
*/
const cloudfrontDistribution = new cloudfront.CfnDistribution(this, 'MSAMAppBucketCloudFrontDistribution', {
distributionConfig: {
comment: Fn.join('', [
'CDN for ',
s3BucketBrowserApp.bucketName,
]),
defaultCacheBehavior: {
targetOriginId: s3BucketBrowserApp.bucketName,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.HTTPS_ONLY,
minTtl: 3600,
defaultTtl: 7200,
maxTtl: 86400,
allowedMethods: [
'HEAD',
'GET',
'OPTIONS',
],
cachedMethods: [
'HEAD',
'GET',
'OPTIONS',
],
compress: true,
forwardedValues: {
queryString: false,
cookies: {
forward: 'none',
},
headers: [
'Origin',
'Access-Control-Request-Method',
'Access-Control-Request-Headers',
],
},
},
defaultRootObject: 'index.html',
enabled: true,
origins: [{
domainName: s3BucketBrowserApp.bucketRegionalDomainName,
id: s3BucketBrowserApp.bucketName,
s3OriginConfig: {
originAccessIdentity: Fn.join('', [
'origin-access-identity/cloudfront/',
cloudfrontOriginAccessIdentity.originAccessIdentityId,
]),
},
}],
priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
restrictions: {
geoRestriction: {
restrictionType: 'none',
locations: [],
},
},
viewerCertificate: {
cloudFrontDefaultCertificate: true,
minimumProtocolVersion: 'TLSv1.2_2019',
},
logging: {
bucket: s3BucketbrowserAppLogs.bucketRegionalDomainName,
prefix: 'cloudfront/',
},
}
});
this.MSAMBrowserURL = Fn.join('', [
'https://',
cloudfrontDistribution.attrDomainName,
cloudfrontDistribution.domainName,
]);
utils.setNagSuppressRules(cloudfrontDistribution,
{
Expand Down Expand Up @@ -235,7 +164,7 @@ export class MsamBrowserApp extends NestedStack {
description: 'MSAM Lambda for custom CloudFormation resource for loading web application',
memorySize: 2560,
role: props.WebIAMRole,
runtime: lambda.Runtime.PYTHON_3_8,
runtime: lambda.Runtime.PYTHON_3_10,
timeout: Duration.seconds(900),
});
utils.setNagSuppressRules(webContentLambda,
Expand All @@ -251,10 +180,6 @@ export class MsamBrowserApp extends NestedStack {
id: 'W92',
reason: 'Lambda does not need ReservedConcurrentExecutions.'
},
{
id: 'AwsSolutions-L1',
reason: 'Latest runtime version not supported at this time.',
},
)

// Web Content Custom Resource
Expand Down Expand Up @@ -287,7 +212,7 @@ export class MsamBrowserApp extends NestedStack {
description: 'MSAM Lambda for custom resource for invalidating CloudFront after update',
memorySize: 2560,
role: props.WebIAMRole,
runtime: lambda.Runtime.PYTHON_3_8,
runtime: lambda.Runtime.PYTHON_3_10,
timeout: Duration.seconds(300),
});
utils.setNagSuppressRules(webInvalidationResourceLambda,
Expand All @@ -303,10 +228,6 @@ export class MsamBrowserApp extends NestedStack {
id: 'W92',
reason: 'Lambda does not need ReservedConcurrentExecutions.'
},
{
id: 'AwsSolutions-L1',
reason: 'Latest runtime version not supported at this time.',
},
);

// Web Invalidator Custom Resource
Expand All @@ -317,7 +238,7 @@ export class MsamBrowserApp extends NestedStack {
StackName: Aws.STACK_NAME,
BUILD_STAMP: 'DEV_0_0_0',
ZIP_DIGEST: 'ZIP_DIGEST_VALUE',
DistributionId: cloudfrontDistribution.attrId,
DistributionId: cloudfrontDistribution.distributionId,
},
});
}
Expand Down
38 changes: 38 additions & 0 deletions source/cdk/lib/msam-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
aws_ssm as ssm,
aws_sam as sam,
cloudformation_include as cfnInc,
CfnCondition,
CfnParameter,
Fn,
NestedStack,
NestedStackProps,
} from 'aws-cdk-lib';
Expand Down Expand Up @@ -65,6 +68,18 @@ export class MsamCore extends NestedStack {
// Core Module Stack
const coreStack = this.initStackFromTemplate('CoreModuleStack', '../dist/msam-core-release.template');


/**
* Parameters
*/
const sendAnonymizedData = new CfnParameter(this, 'SendAnonymizedData', {
default: 'No',
description: 'Enable or Disable Anonymized Data Reporting',
type: 'String',
allowedValues: ['Yes', 'No'],
constraintDescription: 'Please provide a value of Yes or No'
});

/**
* Resources
*/
Expand Down Expand Up @@ -251,6 +266,29 @@ export class MsamCore extends NestedStack {
},
};
reportMetrics.description = 'MSAM Lambda for periodically emitting metrics to multiple targets';
// override event enabled setting based on user setting
const sendAnonymizedDataCondition = new CfnCondition(this, 'sendAnonymizedDataCondition', {
expression: Fn.conditionEquals(sendAnonymizedData, 'Yes'),
});
reportMetrics.events = {
ReportMetricsEvent: Fn.conditionIf(
sendAnonymizedDataCondition.logicalId,
{
Properties: {
Schedule: "rate(24 hours)",
Enabled: true,
},
Type: 'Schedule'
},
{
Properties: {
Schedule: "rate(24 hours)",
Enabled: false,
},
Type: 'Schedule'
},
)
};
this.applyCommonLambdaProperties(reportMetrics, props.CoreIAMRole);

// APIHandler
Expand Down
6 changes: 1 addition & 5 deletions source/cdk/lib/msam-dynamodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class MsamDynamoDB extends NestedStack {
SOLUTION_ID: 'AwsSolution/SO0048/%%VERSION%%',
},
role: props.DynamoDBIAMRole,
runtime: lambda.Runtime.PYTHON_3_8,
runtime: lambda.Runtime.PYTHON_3_10,
timeout: Duration.seconds(300),
});

Expand All @@ -113,10 +113,6 @@ export class MsamDynamoDB extends NestedStack {
id: 'W89',
reason: 'Lambda does not need to be in a VPC.',
},
{
id: 'AwsSolutions-L1',
reason: 'Latest runtime version not supported at this time.',
},
);

/**
Expand Down
Loading

0 comments on commit 51c6be0

Please sign in to comment.