@adobe/helix-config 4.10.1 → 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 CHANGED
@@ -1,3 +1,17 @@
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
+
8
+ ## [4.10.2](https://github.com/adobe/helix-config/compare/v4.10.1...v4.10.2) (2025-01-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency @adobe/helix-shared-config to v11.0.13 ([#229](https://github.com/adobe/helix-config/issues/229)) ([c1831c6](https://github.com/adobe/helix-config/commit/c1831c657e95a46a2161a0ec97e63f65ea7709b6))
14
+
1
15
  ## [4.10.1](https://github.com/adobe/helix-config/compare/v4.10.0...v4.10.1) (2025-01-04)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-config",
3
- "version": "4.10.1",
3
+ "version": "4.11.0",
4
4
  "description": "Helix Config",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@adobe/fetch": "4.1.11",
59
- "@adobe/helix-shared-config": "11.0.12",
59
+ "@adobe/helix-shared-config": "11.0.13",
60
60
  "@adobe/helix-shared-utils": "3.0.2"
61
61
  }
62
62
  }
@@ -32,6 +32,7 @@ const ROOT_PROPERTIES = {
32
32
  robots: {},
33
33
  extends: {},
34
34
  tokens: {},
35
+ secrets: {},
35
36
  public: {},
36
37
  groups: {},
37
38
  };
@@ -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) => tokens[id]?.hash)
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
- // delete token hashes but keep for pipeline because the cloudflare worker still needs them
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;