Skip to content

Commit d132c55

Browse files
authored
Merge pull request #14 from doitintl/tyler/CSI-1648
Validate tags before allowing CDK to deploy changes
2 parents 18515c2 + 5c8c836 commit d132c55

File tree

5 files changed

+55
-30
lines changed

5 files changed

+55
-30
lines changed

config/eks/global_baseline_eks_config.ts

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,14 @@ import request from 'sync-request-curl'; //npm install sync-request-curl (cdk re
99

1010
//export function apply_config(config: Easy_EKS_Config_Data, stack: cdk.Stack, cluster: eks.Cluster){ //config: is of type Easy_EKS_Config_Data
1111
export function apply_config(config: Easy_EKS_Config_Data, stack: cdk.Stack){ //config: is of type Easy_EKS_Config_Data
12-
config.addTag("AWS Tag Allowed Characters", "letters numbers + - = . _ : / @ WebSiteLinks");
13-
config.addTag("AWS Tag Forbidden Characters", "Hashtag Comma SingleQuote DoubleQuote Parenthesis QuestionMark Asterisk Ampersand https://docs.aws.amazon.com/codeguru/latest/bugbust-ug/limits-tags.html");
1412
config.addTag("IaC Tooling used for Provisioning and Management of this EKS Cluster", "cdk: a CLI tool that stands for AWS Cloud Development Kit.");
1513
config.addTag("Upstream Methodology Docs", "https://github.com/doitintl/easyeks");
16-
//^-- NOTE: hashtag(#) comma(,) singlequote(') doublequote(\") parenthesis() and more are not valid tag values
17-
// https://docs.aws.amazon.com/codeguru/latest/bugbust-ug/limits-tags.html
18-
/*Note it's possible when updating tags, that you could see
19-
An error like AWS::EKS::Nodegroup "Update is not supported for the following properties"
20-
If that happens temporarily edit the following line in Easy_EKS.ts
21-
this.cluster.addNodegroupCapacity(`default_MNG`, default_MNG);
22-
to
23-
this.cluster.addNodegroupCapacity(`default_MNG-1`, default_MNG);
24-
redeploy and it'll go through
25-
then rename it back
26-
Note:
27-
After setting default_MNG-1, you may see ...is in UPDATE_ROLLBACK_FAILED state and can not be updated
28-
If so, go to CloudFormation -> stack -> Stack actions -> continue update rollback for stack - Advanced troubleshooting
29-
--> resources to skip - optional (check the box) --> Continue update rollback.
30-
(wait 10 sec, then retry cdk deploy stack)
31-
*/
32-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33-
14+
//^-- NOTE: AWS tag restrictions vary by service, but generally only letters, numbers, spaces, and the following characters are allowed: + - = . _ : / @
15+
// Tags are validated by the validateTag() function in lib/Utilities.ts before deployment
16+
// More details:
17+
// - https://docs.aws.amazon.com/eks/latest/userguide/eks-using-tags.html#tag-restrictions
18+
// - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions
19+
3420
}//end apply_config()
3521

3622
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

config/vpc/global_baseline_vpc_config.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { Opinionated_VPC_Config_Data } from '../../lib/Opinionated_VPC_Config_Da
22
import * as cdk from 'aws-cdk-lib';
33

44
export function apply_config(config: Opinionated_VPC_Config_Data, stack: cdk.Stack){ //config: is of type Opinionated_VPC_Config_Data
5-
config.addTag("AWS Tag Allowed Characters", "letters numbers + - = . _ : / @ WebSiteLinks");
6-
config.addTag("AWS Tag Forbidden Character", "Hashtag Comma SingleQuote DoubleQuote Parenthesis QuestionMark Asterisk Ampersand https://docs.aws.amazon.com/codeguru/latest/bugbust-ug/limits-tags.html");
75
config.addTag("IaC Tooling used for Provisioning and Management of this VPC", "cdk: a CLI tool that stands for AWS Cloud Development Kit.");
86
config.addTag("Upstream Methodology Docs", "https://github.com/doitintl/easyeks");
9-
//^-- NOTE: hashtag(#) comma(,) singlequote(') doublequote(\") parenthesis() and more are not valid tag values
10-
// https://docs.aws.amazon.com/codeguru/latest/bugbust-ug/limits-tags.html
7+
//^-- NOTE: AWS tag restrictions vary by service, but generally only letters, numbers, spaces, and the following characters are allowed: + - = . _ : / @
8+
// Tags are validated by the validateTag() function in lib/Utilities.ts before deployment
9+
// More details:
10+
// - https://docs.aws.amazon.com/eks/latest/userguide/eks-using-tags.html#tag-restrictions
11+
// - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions
1112
}//end apply_config

lib/Easy_EKS_Config_Data.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as eks from 'aws-cdk-lib/aws-eks';
44
import * as ec2 from 'aws-cdk-lib/aws-ec2';
55
import * as iam from 'aws-cdk-lib/aws-iam';
66
import { execSync } from 'child_process';
7+
import { validateTag } from './Utilities';
78

89
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
910
type EKSAddOnInput = Optional<eks.CfnAddonProps, 'clusterName'>; //makes clusterName Optional parameter
@@ -83,9 +84,15 @@ export class Easy_EKS_Config_Data { //This object just holds config data.
8384
}
8485
setKubernetesVersion(version: KubernetesVersion){ this.kubernetesVersion = version; }
8586
setKubectlLayer(version: cdk.aws_lambda.ILayerVersion ){ this.kubectlLayer = version; }
86-
addTag(key: string, value: string){
87-
if(this.tags === undefined){ this.tags = { [key] : value } }
88-
else{ this.tags = { ...this.tags, [key] : value }}
87+
addTag(key: string, value: string){
88+
try {
89+
validateTag(key, value)
90+
if(this.tags === undefined){ this.tags = { [key] : value } }
91+
else{ this.tags = { ...this.tags, [key] : value }}
92+
} catch (error: any) {
93+
console.error("Error:", error.message)
94+
throw "Error validating tags. See details above"// Using throw here to stop the checks; otherwise an error will print out for every place this tag would be applied, and the process will continue
95+
}
8996
}
9097
setBaselineMNGSize(num_baseline_nodes: number){
9198
this.baselineNodesNumber = num_baseline_nodes;

lib/Opinionated_VPC_Config_Data.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FckNatInstanceProvider, FckNatInstanceProps } from 'cdk-fck-nat' //source: npm install cdk-fck-nat@latest
22
import * as ec2 from 'aws-cdk-lib/aws-ec2';
3+
import { validateTag } from './Utilities';
34

45
export class Opinionated_VPC_Config_Data { //This object just holds config data.
56
//Typescript(TS) readability notes
@@ -30,9 +31,15 @@ export class Opinionated_VPC_Config_Data { //This object just holds config data.
3031

3132

3233
//Config Snippet Population Methods
33-
addTag(key: string, value: string){
34-
if(this.tags === undefined){ this.tags = [{key: key, value: value}] }
35-
else{ this.tags.push({key: key, value: value}) }
34+
addTag(key: string, value: string){
35+
try {
36+
validateTag(key, value)
37+
if(this.tags === undefined){ this.tags = [{key: key, value: value}] }
38+
else{ this.tags.push({key: key, value: value}) }
39+
} catch (error: any) {
40+
console.error("Error:", error.message)
41+
throw "Error validating tags. See details above"// Using throw here to stop the checks; otherwise an error will print out for every place this tag would be applied, and the process will continue
42+
}
3643
}
3744
setNatGatewayProviderAsFckNat(props: FckNatInstanceProps){
3845
this.natGatewayProvider = new FckNatInstanceProvider( props );

lib/Utilities.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class InvalidInputError extends Error {
2+
constructor(message: string) {
3+
super(message);
4+
this.name = "InvalidInputError";
5+
}
6+
}
7+
8+
export function validateTag(key: string, value: string){
9+
const allowedChars = "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$"; // https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Tag.html; also using cfn-lint as a baseline
10+
// The set of allowed characters varies by service, from basically any character to a strict set of English alphanumeric characters and a few symbols
11+
const allowedCharsText = "The string can only contain Unicode letters, digits, whitespace, and the characters _.:/=+\-@";
12+
const allowedRegex = new RegExp(allowedChars, "mu");
13+
14+
if (!allowedRegex.test(key)){
15+
throw new InvalidInputError(`Invalid tag key: "${key}". ${allowedCharsText}`)
16+
} else if (key.toLowerCase().startsWith("aws:")) {
17+
throw new InvalidInputError(`Invalid tag key "${key}". Tag keys cannot start with "aws:".`)
18+
} else if (!allowedRegex.test(value)){
19+
throw new InvalidInputError(`Invalid tag value: "${value}". ${allowedCharsText}`)
20+
} else {
21+
return true
22+
}
23+
}
24+

0 commit comments

Comments
 (0)