forked from dbsystel/cdk-sops-secrets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMultiStringParameter.ts
115 lines (105 loc) · 3.45 KB
/
MultiStringParameter.ts
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import * as fs from 'fs';
import { IKey } from 'aws-cdk-lib/aws-kms';
import { ParameterTier, StringParameter } from 'aws-cdk-lib/aws-ssm';
import { ResourceEnvironment, Stack } from 'aws-cdk-lib/core';
import { Construct } from 'constructs';
import * as YAML from 'yaml';
import { SopsStringParameterProps } from './SopsStringParameter';
import { ResourceType, SopsSync, SopsSyncOptions } from './SopsSync';
interface JSONObject {
[key: string]: any;
}
export interface MultiStringParameterProps extends SopsStringParameterProps {
readonly keySeparator?: string;
readonly keyPrefix?: string;
}
function flattenJSON(
data: JSONObject,
parentKey: string = '',
result: JSONObject = {},
keySeparator = '',
): JSONObject {
for (let key in data) {
if (data.hasOwnProperty(key)) {
let newKey = parentKey ? `${parentKey}${keySeparator}${key}` : key;
if (Array.isArray(data[key])) {
data[key].forEach((item: JSONObject | null, index: any) => {
let arrayKey = `${newKey}[${index}]`;
if (typeof item === 'object' && item !== null) {
flattenJSON(item, arrayKey, result, keySeparator);
} else {
result[arrayKey] = item;
}
});
} else if (typeof data[key] === 'object' && data[key] !== null) {
flattenJSON(data[key], newKey, result, keySeparator);
} else {
result[newKey] = data[key];
}
}
}
return result;
}
export class MultiStringParameter extends Construct {
readonly sync: SopsSync;
readonly encryptionKey: IKey;
readonly stack: Stack;
readonly env: ResourceEnvironment;
readonly keyPrefix: string;
readonly keySeparator: string;
constructor(scope: Construct, id: string, props: MultiStringParameterProps) {
super(scope, id);
this.encryptionKey = props.encryptionKey;
this.stack = Stack.of(scope);
this.env = {
account: this.stack.account,
region: this.stack.region,
};
this.keyPrefix = props.keyPrefix ?? '/';
this.keySeparator = props.keySeparator ?? '/';
const keys = this.parseFile(props.sopsFilePath!, this.keySeparator)
.filter((key) => !key.startsWith('sops'))
.map((value) => `${this.keyPrefix}${value}`);
keys.forEach((key) => {
new StringParameter(this, 'Resource' + key, {
parameterName: key,
tier: ParameterTier.STANDARD,
stringValue: ' ',
});
});
this.sync = new SopsSync(this, 'SopsSync', {
encryptionKey: this.encryptionKey,
resourceType: ResourceType.PARAMETER_MULTI,
flatten: true,
flattenSeparator: this.keySeparator,
parameterKeyPrefix: this.keyPrefix,
parameterNames: keys,
...(props as SopsSyncOptions),
});
}
private parseFile(sopsFilePath: string, keySeparator: string): string[] {
const _sopsFileFormat = sopsFilePath.split('.').pop();
switch (_sopsFileFormat) {
case 'json': {
return Object.keys(
flattenJSON(
JSON.parse(fs.readFileSync(sopsFilePath, 'utf-8')),
'',
undefined,
keySeparator,
),
);
}
case 'yaml': {
const content = fs.readFileSync(sopsFilePath, 'utf-8');
const data = YAML.parse(content) as JSONObject;
return Object.keys(flattenJSON(data, '', undefined, keySeparator));
}
default: {
throw new Error(
`Unsupported sopsFileFormat for multiple parameters: ${_sopsFileFormat}`,
);
}
}
}
}