@adobe/helix-config 4.10.2 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/config-merge.js +1 -0
- package/src/config-view.js +57 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [4.11.0](https://github.com/adobe/helix-config/compare/v4.10.2...v4.11.0) (2025-01-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* resolve secrets ([#230](https://github.com/adobe/helix-config/issues/230)) ([90437c9](https://github.com/adobe/helix-config/commit/90437c9fc241c05939e5690f945917c3f339e8b8))
|
|
7
|
+
|
|
1
8
|
## [4.10.2](https://github.com/adobe/helix-config/compare/v4.10.1...v4.10.2) (2025-01-06)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/config-merge.js
CHANGED
package/src/config-view.js
CHANGED
|
@@ -106,12 +106,61 @@ async function getGlobalTokenHash(ctx, rso) {
|
|
|
106
106
|
.replaceAll('=', '');
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* looks up a secret hash or value depending on the `hashed` flag. it looks at the following places
|
|
111
|
+
* to resolve the secret id:
|
|
112
|
+
* - config.secrets
|
|
113
|
+
* - config.tokens
|
|
114
|
+
* - orgConfig.secrets
|
|
115
|
+
* - orgConfig.tokens
|
|
116
|
+
*
|
|
117
|
+
* @param {object} config
|
|
118
|
+
* @param {object} orgConfig
|
|
119
|
+
* @param {string} id
|
|
120
|
+
* @param {boolean} [hashed=false]
|
|
121
|
+
* @returns {string|null}
|
|
122
|
+
*/
|
|
123
|
+
function lookupSecret(config, orgConfig, id, hashed = false) {
|
|
124
|
+
if (!id) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
for (const list of [config?.secrets, config?.tokens, orgConfig?.secrets, orgConfig?.tokens]) {
|
|
128
|
+
const secret = list?.[id];
|
|
129
|
+
if (secret?.hash && hashed) {
|
|
130
|
+
return secret.hash;
|
|
131
|
+
}
|
|
132
|
+
if (secret?.value && !hashed) {
|
|
133
|
+
return secret.value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Resolves a secret addressed with the `idProp` and stores it in the `dstProp`. This function has
|
|
141
|
+
* no effect, if the secret does not exist, or is not a key secret (i.e. a hashed secret).
|
|
142
|
+
* @param object
|
|
143
|
+
* @param idProp
|
|
144
|
+
* @param dstProp
|
|
145
|
+
* @param siteConfig
|
|
146
|
+
* @param orgConfig
|
|
147
|
+
*/
|
|
148
|
+
function resolveSecret(object, idProp, dstProp, siteConfig, orgConfig) {
|
|
149
|
+
const id = object?.[idProp];
|
|
150
|
+
if (id) {
|
|
151
|
+
const secret = lookupSecret(siteConfig, orgConfig, id);
|
|
152
|
+
if (secret) {
|
|
153
|
+
// eslint-disable-next-line no-param-reassign
|
|
154
|
+
object[dstProp] = secret;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
109
159
|
/**
|
|
110
160
|
* Returns the normalized access configuration for the give partition.
|
|
111
161
|
*/
|
|
112
162
|
export async function getAccessConfig(ctx, config, orgConfig, partition, rso) {
|
|
113
163
|
const { access } = config;
|
|
114
|
-
const tokens = { ...orgConfig?.tokens || {}, ...config.tokens };
|
|
115
164
|
const pAccess = access[partition] ?? {};
|
|
116
165
|
const apiKeyId = toArray(pAccess.apiKeyId ?? access.site?.apiKeyId);
|
|
117
166
|
const allow = toArray(pAccess.allow ?? access.site?.allow);
|
|
@@ -121,7 +170,7 @@ export async function getAccessConfig(ctx, config, orgConfig, partition, rso) {
|
|
|
121
170
|
tokenHash: apiKeyId
|
|
122
171
|
// token ids are always stored in base64url format, but legacy apiKeyIds are not
|
|
123
172
|
.map((jti) => jti.replaceAll('/', '_').replaceAll('+', '-'))
|
|
124
|
-
.map((id) =>
|
|
173
|
+
.map((id) => lookupSecret(config, orgConfig, id, true))
|
|
125
174
|
.filter((hash) => !!hash),
|
|
126
175
|
};
|
|
127
176
|
// if an allow is defined but no apiKeyId, create a fake one so that auth is still enforced.
|
|
@@ -240,6 +289,7 @@ async function resolveConfig(ctx, rso, scope) {
|
|
|
240
289
|
if (config) {
|
|
241
290
|
const profile = await loadProfile(ctx, rso, 'default');
|
|
242
291
|
config.data.tokens = profile?.data.tokens || {};
|
|
292
|
+
config.data.secrets = profile?.data.secrets || {};
|
|
243
293
|
}
|
|
244
294
|
return config;
|
|
245
295
|
}
|
|
@@ -465,8 +515,12 @@ export async function getConfigResponse(ctx, opts) {
|
|
|
465
515
|
});
|
|
466
516
|
}
|
|
467
517
|
|
|
468
|
-
//
|
|
518
|
+
// resolve well known secrets
|
|
519
|
+
resolveSecret(config.code.source, 'secretId', 'secret', config, orgConfig);
|
|
520
|
+
|
|
469
521
|
delete config.tokens;
|
|
522
|
+
delete config.secrets;
|
|
523
|
+
// delete token hashes but keep for pipeline because the cloudflare worker still needs them
|
|
470
524
|
if (opts.scope !== SCOPE_PIPELINE) {
|
|
471
525
|
delete config.access?.preview?.tokenHash;
|
|
472
526
|
delete config.access?.live?.tokenHash;
|