Skip to content

Commit 98de986

Browse files
committed
feat: Add support for sensitive parameters
1 parent d3938fa commit 98de986

File tree

10 files changed

+67
-24
lines changed

10 files changed

+67
-24
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"dependencies": {
1717
"ajv": "^8.12.0",
1818
"ajv-formats": "^2.1.1",
19-
"codify-schemas": "1.0.77",
19+
"codify-schemas": "1.0.83",
2020
"@npmcli/promise-spawn": "^7.0.1",
2121
"@homebridge/node-pty-prebuilt-multiarch": "^0.12.0-beta.5",
2222
"uuid": "^10.0.0",

src/plan/change-set.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ describe('Change set tests', () => {
8787
it('Correctly diffs two resource configs (destory)', () => {
8888
const cs = ChangeSet.destroy({
8989
propA: 'prop',
90-
propB: 'propB'
90+
propB: 'propB',
9191
});
9292

9393
expect(cs.parameterChanges.length).to.eq(2);

src/plan/change-set.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ParameterOperation, ResourceOperation, StringIndexedObject } from 'codify-schemas';
22

33
import { ParsedParameterSetting } from '../resource/parsed-resource-settings.js';
4+
import { ResourceSettings } from '../resource/resource-settings.js';
45

56
/**
67
* A parameter change describes a parameter level change to a resource.
@@ -25,6 +26,11 @@ export interface ParameterChange<T extends StringIndexedObject> {
2526
* The new value of the resource (the desired value)
2627
*/
2728
newValue: any | null;
29+
30+
/**
31+
* Whether the parameter is sensitive
32+
*/
33+
isSensitive: boolean;
2834
}
2935

3036
// Change set will coerce undefined values to null because undefined is not valid JSON
@@ -60,37 +66,40 @@ export class ChangeSet<T extends StringIndexedObject> {
6066
return new ChangeSet<T>(ResourceOperation.NOOP, []);
6167
}
6268

63-
static create<T extends StringIndexedObject>(desired: Partial<T>): ChangeSet<T> {
69+
static create<T extends StringIndexedObject>(desired: Partial<T>, settings?: ResourceSettings<T>): ChangeSet<T> {
6470
const parameterChanges = Object.entries(desired)
6571
.map(([k, v]) => ({
6672
name: k,
6773
operation: ParameterOperation.ADD,
6874
previousValue: null,
6975
newValue: v ?? null,
76+
isSensitive: settings?.parameterSettings?.[k]?.isSensitive ?? false,
7077
}))
7178

7279
return new ChangeSet(ResourceOperation.CREATE, parameterChanges);
7380
}
7481

75-
static noop<T extends StringIndexedObject>(parameters: Partial<T>): ChangeSet<T> {
82+
static noop<T extends StringIndexedObject>(parameters: Partial<T>, settings?: ResourceSettings<T>): ChangeSet<T> {
7683
const parameterChanges = Object.entries(parameters)
7784
.map(([k, v]) => ({
7885
name: k,
7986
operation: ParameterOperation.NOOP,
8087
previousValue: v ?? null,
8188
newValue: v ?? null,
89+
isSensitive: settings?.parameterSettings?.[k]?.isSensitive ?? false,
8290
}))
8391

8492
return new ChangeSet(ResourceOperation.NOOP, parameterChanges);
8593
}
8694

87-
static destroy<T extends StringIndexedObject>(current: Partial<T>): ChangeSet<T> {
95+
static destroy<T extends StringIndexedObject>(current: Partial<T>, settings?: ResourceSettings<T>): ChangeSet<T> {
8896
const parameterChanges = Object.entries(current)
8997
.map(([k, v]) => ({
9098
name: k,
9199
operation: ParameterOperation.REMOVE,
92100
previousValue: v ?? null,
93101
newValue: null,
102+
isSensitive: settings?.parameterSettings?.[k]?.isSensitive ?? false,
94103
}))
95104

96105
return new ChangeSet(ResourceOperation.DESTROY, parameterChanges);
@@ -160,6 +169,7 @@ export class ChangeSet<T extends StringIndexedObject> {
160169
previousValue: current[k] ?? null,
161170
newValue: desired[k] ?? null,
162171
operation: ParameterOperation.NOOP,
172+
isSensitive: parameterOptions?.[k]?.isSensitive ?? false,
163173
})
164174

165175
continue;
@@ -171,6 +181,7 @@ export class ChangeSet<T extends StringIndexedObject> {
171181
previousValue: current[k] ?? null,
172182
newValue: null,
173183
operation: ParameterOperation.REMOVE,
184+
isSensitive: parameterOptions?.[k]?.isSensitive ?? false,
174185
})
175186

176187
continue;
@@ -182,6 +193,7 @@ export class ChangeSet<T extends StringIndexedObject> {
182193
previousValue: null,
183194
newValue: desired[k] ?? null,
184195
operation: ParameterOperation.ADD,
196+
isSensitive: parameterOptions?.[k]?.isSensitive ?? false,
185197
})
186198

187199
continue;
@@ -192,6 +204,7 @@ export class ChangeSet<T extends StringIndexedObject> {
192204
previousValue: current[k] ?? null,
193205
newValue: desired[k] ?? null,
194206
operation: ParameterOperation.MODIFY,
207+
isSensitive: parameterOptions?.[k]?.isSensitive ?? false,
195208
})
196209
}
197210

src/plan/plan.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export class Plan<T extends StringIndexedObject> {
118118
if (!filteredCurrentParameters && desired) {
119119
return new Plan(
120120
uuidV4(),
121-
ChangeSet.create(desired),
121+
ChangeSet.create(desired, settings),
122122
core,
123123
isStateful,
124124
)
@@ -130,15 +130,15 @@ export class Plan<T extends StringIndexedObject> {
130130
if (!settings.canDestroy) {
131131
return new Plan(
132132
uuidV4(),
133-
ChangeSet.noop(filteredCurrentParameters),
133+
ChangeSet.noop(filteredCurrentParameters, settings),
134134
core,
135135
isStateful,
136136
)
137137
}
138138

139139
return new Plan(
140140
uuidV4(),
141-
ChangeSet.destroy(filteredCurrentParameters),
141+
ChangeSet.destroy(filteredCurrentParameters, settings),
142142
core,
143143
isStateful,
144144
)
@@ -171,7 +171,10 @@ export class Plan<T extends StringIndexedObject> {
171171
uuidV4(),
172172
new ChangeSet<T>(
173173
data.operation,
174-
data.parameters
174+
data.parameters.map((p) => ({
175+
...p,
176+
isSensitive: p.isSensitive ?? false,
177+
})),
175178
),
176179
{
177180
type: data.resourceType,

src/plugin/plugin.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,14 @@ export class Plugin {
6262
.map((r) => ({
6363
dependencies: r.dependencies,
6464
type: r.typeId,
65+
sensitiveParameters: Object.entries(r.settings.parameterSettings ?? {})
66+
.filter(([, v]) => v?.isSensitive)
67+
.map(([k]) => k),
6568
}))
6669
}
6770
}
6871

69-
async getResourceInfo(data: GetResourceInfoRequestData): Promise<GetResourceInfoResponseData> {
72+
getResourceInfo(data: GetResourceInfoRequestData): GetResourceInfoResponseData {
7073
if (!this.resourceControllers.has(data.type)) {
7174
throw new Error(`Cannot get info for resource ${data.type}, resource doesn't exist`);
7275
}
@@ -84,6 +87,10 @@ export class Plugin {
8487
const allowMultiple = resource.settings.allowMultiple !== undefined
8588
&& resource.settings.allowMultiple !== false;
8689

90+
const sensitiveParameters = Object.entries(resource.settings.parameterSettings ?? {})
91+
.filter(([, v]) => v?.isSensitive)
92+
.map(([k]) => k);
93+
8794
return {
8895
plugin: this.name,
8996
type: data.type,
@@ -96,6 +103,7 @@ export class Plugin {
96103
import: {
97104
requiredParameters: requiredPropertyNames,
98105
},
106+
sensitiveParameters,
99107
allowMultiple
100108
}
101109
}

src/resource/resource-controller-stateful-mode.test.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,23 @@ describe('Resource tests for stateful plans', () => {
142142
name: "propA",
143143
newValue: "propA",
144144
previousValue: "propA",
145-
operation: ParameterOperation.NOOP
145+
operation: ParameterOperation.NOOP,
146+
isSensitive: false,
147+
146148
},
147149
{
148150
name: "propB",
149151
newValue: 10,
150152
previousValue: null,
151-
operation: ParameterOperation.ADD
153+
operation: ParameterOperation.ADD,
154+
isSensitive: false,
152155
},
153156
{
154157
name: "propC",
155158
newValue: 'propC',
156159
previousValue: 'propC',
157-
operation: ParameterOperation.NOOP
160+
operation: ParameterOperation.NOOP,
161+
isSensitive: false,
158162
},
159163
])
160164
},
@@ -214,25 +218,29 @@ describe('Resource tests for stateful plans', () => {
214218
name: "propA",
215219
newValue: "propA",
216220
previousValue: "propA",
217-
operation: ParameterOperation.NOOP
221+
operation: ParameterOperation.NOOP,
222+
isSensitive: false,
218223
},
219224
{
220225
name: "propB",
221226
newValue: 10,
222227
previousValue: null,
223-
operation: ParameterOperation.ADD
228+
operation: ParameterOperation.ADD,
229+
isSensitive: false,
224230
},
225231
{
226232
name: "propC",
227233
newValue: 'propC',
228234
previousValue: 'propC',
229-
operation: ParameterOperation.NOOP
235+
operation: ParameterOperation.NOOP,
236+
isSensitive: false,
230237
},
231238
{
232239
name: "propD",
233240
newValue: 'propD',
234241
previousValue: null,
235-
operation: ParameterOperation.ADD
242+
operation: ParameterOperation.ADD,
243+
isSensitive: false,
236244
},
237245
])
238246
},

src/resource/resource-controller.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,15 @@ describe('Resource tests', () => {
8080
name: 'propA',
8181
previousValue: 'propABefore',
8282
newValue: 'propA',
83-
operation: 'modify'
83+
operation: 'modify',
84+
isSensitive: false,
8485
})
8586
expect(result.changeSet.parameterChanges[1]).to.deep.eq({
8687
name: 'propB',
8788
previousValue: 10,
8889
newValue: 10,
89-
operation: 'noop'
90+
operation: 'noop',
91+
isSensitive: false,
9092
})
9193
})
9294

src/resource/resource-settings.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,12 +717,14 @@ describe('Resource parameter tests', () => {
717717
operation: ParameterOperation.NOOP,
718718
previousValue: null,
719719
newValue: 'setting',
720+
isSensitive: false,
720721
},
721722
{
722723
name: 'propB',
723724
operation: ParameterOperation.NOOP,
724725
previousValue: 64,
725726
newValue: 64,
727+
isSensitive: false,
726728
}
727729
])
728730
)

src/resource/resource-settings.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
163163
* @param input
164164
* @param context
165165
*/
166-
refreshMapper?: (input: Partial<T>, context: RefreshContext<T>) => Partial<T>
166+
refreshMapper?: (input: Partial<T>, context: RefreshContext<T>) => Partial<T>;
167167
}
168168
}
169169

@@ -207,6 +207,13 @@ export interface DefaultParameterSetting {
207207
*/
208208
type?: ParameterSettingType;
209209

210+
/**
211+
* Mark the field as sensitive. Defaults to false. This has two side effects:
212+
* 1. When displaying this field in the plan, it will be replaced with asterisks
213+
* 2. When importing, resources with sensitive fields will be skipped unless the user explicitly allows it.
214+
*/
215+
isSensitive?: boolean;
216+
210217
/**
211218
* Default value for the parameter. If a value is not provided in the config, then this value will be used.
212219
*/

0 commit comments

Comments
 (0)