-
Notifications
You must be signed in to change notification settings - Fork 329
Expand file tree
/
Copy pathaws-partition.utils.ts
More file actions
99 lines (82 loc) · 3.07 KB
/
Copy pathaws-partition.utils.ts
File metadata and controls
99 lines (82 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import type { AwsCredentialIdentity } from '@aws-sdk/types';
export type AwsPartition = 'aws' | 'aws-us-gov';
const AWS_PARTITIONS = new Set<AwsPartition>(['aws', 'aws-us-gov']);
export function normalizeAwsPartition(value: unknown): AwsPartition {
return typeof value === 'string' && AWS_PARTITIONS.has(value as AwsPartition)
? (value as AwsPartition)
: 'aws';
}
export function getAwsDefaultRegion(partition: AwsPartition): string {
return partition === 'aws-us-gov' ? 'us-gov-west-1' : 'us-east-1';
}
export function getAwsPartitionForRegion(region: string): AwsPartition {
return region.startsWith('us-gov-') ? 'aws-us-gov' : 'aws';
}
export function getAwsRoleAssumerEnvName(partition: AwsPartition): string {
return partition === 'aws-us-gov'
? 'SECURITY_HUB_GOVCLOUD_ROLE_ASSUMER_ARN'
: 'SECURITY_HUB_ROLE_ASSUMER_ARN';
}
export function getAwsRoleAssumerArn(partition: AwsPartition): string | undefined {
return process.env[getAwsRoleAssumerEnvName(partition)];
}
export function getAwsBaseCredentials(
partition: AwsPartition,
): AwsCredentialIdentity | undefined {
if (partition !== 'aws-us-gov') return undefined;
const accessKeyId = process.env.SECURITY_HUB_GOVCLOUD_ACCESS_KEY_ID;
const secretAccessKey =
process.env.SECURITY_HUB_GOVCLOUD_SECRET_ACCESS_KEY;
if (!accessKeyId || !secretAccessKey) return undefined;
return {
accessKeyId,
secretAccessKey,
};
}
export function parseAwsRoleArn(
roleArn: string,
): { partition: AwsPartition; accountId: string } | null {
const match = roleArn.match(/^arn:(aws|aws-us-gov):iam::(\d{12}):role\/.+$/);
if (!match) return null;
return {
partition: match[1] as AwsPartition,
accountId: match[2],
};
}
export function validateAwsPartitionConfig(params: {
partition: AwsPartition;
roleArn: string;
regions: string[];
remediationRoleArn?: string;
}): string[] {
const errors: string[] = [];
const parsedRoleArn = parseAwsRoleArn(params.roleArn);
if (!parsedRoleArn) {
errors.push(
'Invalid IAM Role ARN format. Expected: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME or arn:aws-us-gov:iam::ACCOUNT_ID:role/ROLE_NAME',
);
} else if (parsedRoleArn.partition !== params.partition) {
errors.push(
`IAM Role ARN partition (${parsedRoleArn.partition}) must match selected AWS environment (${params.partition}).`,
);
}
if (params.remediationRoleArn) {
const parsedRemediationArn = parseAwsRoleArn(params.remediationRoleArn);
if (!parsedRemediationArn) {
errors.push('Invalid Remediation Role ARN format.');
} else if (parsedRemediationArn.partition !== params.partition) {
errors.push(
`Remediation Role ARN partition (${parsedRemediationArn.partition}) must match selected AWS environment (${params.partition}).`,
);
}
}
const mismatchedRegions = params.regions.filter(
(region) => getAwsPartitionForRegion(region) !== params.partition,
);
if (mismatchedRegions.length > 0) {
errors.push(
`Selected regions do not match ${params.partition}: ${mismatchedRegions.join(', ')}.`,
);
}
return errors;
}