Skip to content

Commit 634ebb2

Browse files
authored
Merge pull request #81 from sanjay-reddy-kandi/main
release/v2.7.6
2 parents a987cd0 + 37e31ff commit 634ebb2

14 files changed

+883
-751
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [2.7.6] - 2025-04
8+
### Added
9+
- Updated AppRegistry implementation to use tag-based approach instead of CFN-based association.
10+
11+
### Fixed
12+
- Update base python image to mitigate [CVE-2025-0395](https://nvd.nist.gov/vuln/detail/CVE-2025-0395), [CVE-2024-12133](https://nvd.nist.gov/vuln/detail/CVE-2024-12133), [CVE-2024-12243](https://nvd.nist.gov/vuln/detail/CVE-2024-12243)
13+
714
## [2.7.5] - 2025-01
815
### Fixed
916
- Updated aws-lambda-powertools from version 2.39.1 to 3.4.1

deployment/run-unit-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ main() {
1414
echo "Installing python packages including development dependencies"
1515
cd "$source_dir"
1616
"$POETRY_HOME"/bin/poetry install --with dev
17-
17+
1818
# Activate the virtual environment.
1919
source $("$POETRY_HOME"/bin/poetry env info --path)/bin/activate
2020

source/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM public.ecr.aws/docker/library/python:3.12.7-slim-bookworm
1+
FROM public.ecr.aws/docker/library/python:3.12.9-slim-bookworm
22

33
# Set up a non-root user
44
RUN adduser -uid 1001 nonroot
Lines changed: 12 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33
import * as cdk from "aws-cdk-lib";
4-
import * as appreg from "@aws-cdk/aws-servicecatalogappregistry-alpha";
5-
import { Aws, CfnCondition, Fn, Tags } from "aws-cdk-lib";
6-
import { CfnApplication } from "aws-cdk-lib/aws-applicationinsights";
7-
import {
8-
CfnAttributeGroup,
9-
CfnAttributeGroupAssociation,
10-
CfnResourceAssociation,
11-
} from "aws-cdk-lib/aws-servicecatalogappregistry";
12-
import { CfnResourceShare } from "aws-cdk-lib/aws-ram";
4+
import * as servicecatalogappregistry from "aws-cdk-lib/aws-servicecatalogappregistry";
5+
import { Aws, Fn, Tags } from "aws-cdk-lib";
136
import { Construct } from "constructs";
14-
import overrideLogicalId from "../cdk-helper/override-logical-id";
15-
import setCondition from "../cdk-helper/set-condition";
167

178
export interface AppRegistryHubResourcesProps extends cdk.StackProps {
189
solutionId: string;
@@ -21,104 +12,26 @@ export interface AppRegistryHubResourcesProps extends cdk.StackProps {
2112
solutionVersion: string;
2213
appRegistryApplicationName: string;
2314
applicationType: string;
24-
managementAccountId: string;
25-
orgId: string;
26-
multiAccountDeploymentCondition: CfnCondition;
2715
}
2816

2917
export class AppRegistryHubResources extends Construct {
18+
public readonly applicationTagValue: string;
3019
constructor(scope: Construct, id: string, props: AppRegistryHubResourcesProps) {
3120
super(scope, id);
32-
const application = new appreg.Application(this, "AppRegistry", {
33-
applicationName: Fn.join("-", [props.appRegistryApplicationName, Aws.REGION, Aws.ACCOUNT_ID]),
21+
const application = new servicecatalogappregistry.CfnApplication(this, "AppRegistry", {
22+
name: Fn.join("-", [props.appRegistryApplicationName, Aws.REGION, Aws.ACCOUNT_ID]),
3423
description: `Service Catalog application to track and manage all your resources for the solution ${props.solutionName}`,
3524
});
36-
const cfnApplication = application.node.defaultChild as CfnApplication;
37-
overrideLogicalId(cfnApplication, "Application");
38-
39-
const cfnresourceAssociation = new CfnResourceAssociation(this, "CfnResourceAssociation", {
40-
application: application.applicationId,
41-
resource: Aws.STACK_ID,
42-
resourceType: "CFN_STACK",
43-
});
44-
overrideLogicalId(cfnresourceAssociation, "AppRegistryApplicationStackAssociation");
45-
46-
const attributeGroup = new appreg.AttributeGroup(this, "DefaultApplicationAttributeGroup", {
47-
attributeGroupName: Fn.join("-", [props.appRegistryApplicationName, Aws.REGION, Aws.ACCOUNT_ID]),
48-
description: "Attribute group for solution information",
49-
attributes: {
50-
applicationType: props.applicationType,
51-
version: props.solutionVersion,
52-
solutionID: props.solutionId,
53-
solutionName: props.solutionName,
54-
},
55-
});
56-
57-
const cfnAttributeGroup = attributeGroup.node.defaultChild as CfnAttributeGroup;
58-
overrideLogicalId(cfnAttributeGroup, "DefaultApplicationAttributeGroup");
59-
60-
const cfnAttributeGroupAssociation = new CfnAttributeGroupAssociation(this, "AttributeGroupAssociation", {
61-
application: application.applicationId,
62-
attributeGroup: attributeGroup.attributeGroupId,
63-
});
64-
overrideLogicalId(cfnAttributeGroupAssociation, "AppRegistryApplicationAttributeAssociation");
65-
66-
const appInsights = new CfnApplication(this, "ApplicationInsightsConfiguration", {
67-
resourceGroupName: Fn.join("-", [
68-
"AWS_AppRegistry_Application",
69-
props.appRegistryApplicationName,
70-
Aws.REGION,
71-
Aws.ACCOUNT_ID,
72-
]),
73-
autoConfigurationEnabled: true,
74-
cweMonitorEnabled: true,
75-
opsCenterEnabled: true,
76-
});
77-
appInsights.addDependency(cfnApplication);
78-
overrideLogicalId(appInsights, "ApplicationInsightsConfiguration");
79-
80-
const resourceShare = new CfnResourceShare(this, "ApplicationShare", {
81-
name: Aws.STACK_NAME,
82-
allowExternalPrincipals: false,
83-
permissionArns: [
84-
cdk.Arn.format(
85-
{
86-
service: "ram",
87-
resource: "permission",
88-
resourceName: "AWSRAMPermissionServiceCatalogAppRegistryApplicationAllowAssociation",
89-
partition: Aws.PARTITION,
90-
region: "",
91-
account: "aws",
92-
},
93-
cdk.Stack.of(this),
94-
),
95-
],
96-
principals: [
97-
cdk.Arn.format(
98-
{
99-
service: "organizations",
100-
resource: "organization",
101-
resourceName: `${props.orgId}`,
102-
partition: Aws.PARTITION,
103-
region: "",
104-
account: props.managementAccountId,
105-
},
106-
cdk.Stack.of(this),
107-
),
108-
],
109-
resourceArns: [application.applicationArn],
110-
});
111-
112-
overrideLogicalId(resourceShare, "ApplicationShare");
113-
setCondition(resourceShare, props.multiAccountDeploymentCondition);
25+
application.overrideLogicalId("Application");
26+
this.applicationTagValue = application.attrApplicationTagValue;
11427

11528
// Tags for application
11629

117-
Tags.of(application).add("SolutionID", props.solutionId);
118-
Tags.of(application).add("SolutionName", props.solutionName);
119-
Tags.of(application).add("SolutionVersion", props.solutionVersion);
120-
Tags.of(application).add("ApplicationType", props.applicationType);
121-
Tags.of(application).add("SolutionDomain", props.solutionDomain);
30+
Tags.of(application).add("Solutions:SolutionID", props.solutionId);
31+
Tags.of(application).add("Solutions:SolutionName", props.solutionName);
32+
Tags.of(application).add("Solutions:SolutionVersion", props.solutionVersion);
33+
Tags.of(application).add("Solutions:ApplicationType", props.applicationType);
34+
Tags.of(application).add("Solutions:SolutionDomain", props.solutionDomain);
12235
Tags.of(application).add("CloudFoundations:CostOptimizerForWorkspaces", Aws.STACK_NAME);
12336
}
12437
}

source/lib/components/app-registry-spoke-resources.ts

Lines changed: 0 additions & 65 deletions
This file was deleted.

source/lib/cost-optimizer-for-amazon-workspaces-hub-stack.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ export class CostOptimizerHubStack extends cdk.Stack {
413413
const reportingBucket = new UsageReportBucketResources(this, "UsageReportBucketResources");
414414

415415
const spokeAccountTable = new Table(this, "SpokeAccountTable", {
416-
pointInTimeRecovery: true,
416+
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
417417
removalPolicy: cdk.RemovalPolicy.RETAIN,
418418
encryption: TableEncryption.AWS_MANAGED,
419419
billingMode: BillingMode.PAY_PER_REQUEST,
@@ -435,7 +435,7 @@ export class CostOptimizerHubStack extends cdk.Stack {
435435
sortKey: { name: "Region", type: AttributeType.STRING },
436436
removalPolicy: cdk.RemovalPolicy.RETAIN,
437437
encryption: TableEncryption.AWS_MANAGED,
438-
pointInTimeRecovery: true,
438+
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
439439
billingMode: BillingMode.PAY_PER_REQUEST,
440440
});
441441
const usageTableNode = usageTable.node.findChild("Resource") as cdk.aws_dynamodb.CfnTable;
@@ -450,7 +450,7 @@ export class CostOptimizerHubStack extends cdk.Stack {
450450
sortKey: { name: "SessionTime", type: AttributeType.STRING },
451451
removalPolicy: cdk.RemovalPolicy.RETAIN,
452452
encryption: TableEncryption.AWS_MANAGED,
453-
pointInTimeRecovery: true,
453+
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
454454
billingMode: BillingMode.PAY_PER_REQUEST,
455455
});
456456
const sessionTableNode = userSessionTable.node.findChild("Resource") as cdk.aws_dynamodb.CfnTable;
@@ -543,7 +543,7 @@ export class CostOptimizerHubStack extends cdk.Stack {
543543
stableTagInUse: stableTagging.valueAsString,
544544
};
545545

546-
new EcsClusterResources(this, "EcsClusterResources", ecsClusterProps);
546+
const ecsClusterResources = new EcsClusterResources(this, "EcsClusterResources", ecsClusterProps);
547547

548548
const registerSpokeAccountProps: RegisterSpokeAccountResourcesProps = {
549549
solutionId: props.solutionId,
@@ -577,12 +577,30 @@ export class CostOptimizerHubStack extends cdk.Stack {
577577
solutionVersion: props.solutionVersion,
578578
applicationType: "AWS-Solutions",
579579
appRegistryApplicationName: mappings.findInMap("Data", "AppRegistryApplicationName"),
580-
managementAccountId: managementAccountId.valueAsString,
581-
orgId: organizationID.valueAsString,
582-
multiAccountDeploymentCondition: multiAccountDeploymentCondition,
583580
};
584581

585-
new AppRegistryHubResources(this, "AppRegistryHubResources", appRegistryHubProps);
582+
const appRegistry = new AppRegistryHubResources(this, "AppRegistryHubResources", appRegistryHubProps);
583+
584+
// Function to add tags to a construct
585+
const addTags = (construct: Construct) => {
586+
cdk.Tags.of(construct).add("SolutionIdKey", props.solutionId);
587+
cdk.Tags.of(construct).add("SolutionNameKey", props.solutionName);
588+
cdk.Tags.of(construct).add("SolutionVersionKey", props.solutionVersion);
589+
cdk.Tags.of(construct).add("awsApplication", appRegistry.applicationTagValue);
590+
};
591+
592+
[
593+
reportingBucket,
594+
costOptimizerVpc,
595+
ecsClusterResources,
596+
uuidGenerator,
597+
registerSpokeAccountFunction,
598+
spokeAccountTable,
599+
usageTable,
600+
userSessionTable,
601+
].forEach((resource) => {
602+
if (resource) addTags(resource);
603+
});
586604

587605
// Outputs
588606
new CfnOutput(this, "BucketNameOutput", {

source/lib/cost-optimizer-for-amazon-workspaces-spoke-stack.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { Policy, Role, PolicyDocument, PolicyStatement, ServicePrincipal, ArnPri
88
import { Bucket } from "aws-cdk-lib/aws-s3";
99
import * as lambda from "aws-cdk-lib/aws-lambda";
1010
import { Code, Runtime } from "aws-cdk-lib/aws-lambda";
11-
import { AppRegistrySpokeResources, AppRegistrySpokeResourcesProps } from "./components/app-registry-spoke-resources";
1211
import overrideLogicalId from "./cdk-helper/override-logical-id";
1312
import { addCfnNagSuppression } from "./cdk-helper/add-cfn-nag-suppression";
1413
export interface CostOptimizerSpokeStackProps extends cdk.StackProps {
@@ -272,17 +271,6 @@ export class CostOptimizerSpokeStack extends cdk.Stack {
272271
customResource.node.addDependency(accountRegistrationProviderRolePolicy);
273272
overrideLogicalId(customResource, "AccountRegistration");
274273

275-
const appRegistrySpokeResourcesProps: AppRegistrySpokeResourcesProps = {
276-
solutionId: props.solutionId,
277-
solutionName: props.solutionName,
278-
solutionVersion: props.solutionVersion,
279-
hubAccountId: hubAccountId.valueAsString,
280-
appRegistryApplicationName: "workspaces-cost-optimizer",
281-
applicationType: "AWS-Solutions",
282-
};
283-
284-
new AppRegistrySpokeResources(this, "AppRegistrySpokeResources", appRegistrySpokeResourcesProps);
285-
286274
new CfnOutput(this, "SolutionIDOutput", {
287275
value: mappings.findInMap("Data", "ID"),
288276
exportName: "SolutionID",

0 commit comments

Comments
 (0)