Skip to content

Commit 1c49d6f

Browse files
dcrooteSiegrift
andauthored
Use secret interpolation from api3/commons (#1962)
* Update dependency: @api3/commons@^0.7.1 * Use secret interpolation from api3/commons * Add back secret name validation to config validation --------- Co-authored-by: Emanuel Tesař <[email protected]>
1 parent e07a3b9 commit 1c49d6f

File tree

5 files changed

+22
-53
lines changed

5 files changed

+22
-53
lines changed

.changeset/tiny-years-move.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@api3/airnode-validator": patch
3+
---
4+
5+
Use secret interpolation from api3/commons

packages/airnode-node/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@api3/airnode-utilities": "^0.14.0",
3131
"@api3/airnode-validator": "^0.14.0",
3232
"@api3/chains": "^4.9.0",
33-
"@api3/commons": "^0.6.2",
33+
"@api3/commons": "^0.7.1",
3434
"@api3/ois": "2.3.2",
3535
"@api3/promise-utils": "^0.4.0",
3636
"@aws-sdk/client-lambda": "^3.518.0",

packages/airnode-validator/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"dependencies": {
2424
"@api3/airnode-protocol": "^0.14.0",
25+
"@api3/commons": "^0.7.1",
2526
"@api3/ois": "2.3.2",
2627
"@api3/promise-utils": "^0.4.0",
2728
"dotenv": "^16.4.5",
+9-48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { goSync } from '@api3/promise-utils';
2-
import template from 'lodash/template';
3-
import reduce from 'lodash/reduce';
2+
import { interpolateSecretsIntoConfig } from '@api3/commons';
43
import { z } from 'zod';
54
import { Config, configSchema } from '../config';
65
import { Receipt, receiptSchema } from '../receipt';
@@ -18,7 +17,9 @@ export function parseConfigWithSecrets(config: unknown, secrets: unknown): Valid
1817
const parsedSecrets = parseSecrets(secrets);
1918
if (!parsedSecrets.success) return parsedSecrets;
2019

21-
const interpolateConfigRes = interpolateSecrets(config, parsedSecrets.data);
20+
const interpolateConfigRes = goSync(() =>
21+
interpolateSecretsIntoConfig(config, parsedSecrets.data, { allowBlankSecretValue: false, validateSecretName: true })
22+
);
2223
if (!interpolateConfigRes.success) {
2324
return {
2425
success: false,
@@ -59,56 +60,16 @@ export function parseReceipt(receipt: unknown): ValidationResult<Receipt> {
5960
return receiptSchema.safeParse(receipt);
6061
}
6162

62-
// Regular expression that does not match anything, ensuring no escaping or interpolation happens
63-
// https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L199
64-
const NO_MATCH_REGEXP = /($^)/;
65-
// Regular expression matching ES template literal delimiter (${}) with escaping
66-
// https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L175
67-
const ES_MATCH_REGEXP = /(?<!\\)\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
68-
// Regular expression matching the escaped ES template literal delimiter (${}). We need to use "\\\\" (four backslashes)
69-
// because "\\" becomes "\\\\" when converted to string
70-
const ESCAPED_ES_MATCH_REGEXP = /\\\\(\$\{([^\\}]*(?:\\.[^\\}]*)*)\})/g;
71-
72-
function interpolateSecrets(config: unknown, secrets: Secrets): ValidationResult<unknown> {
73-
const stringifiedSecrets = reduce(
74-
secrets,
75-
(acc, value, key) => {
76-
return {
77-
...acc,
78-
// Convert to value to JSON to encode new lines as "\n". The resulting value will be a JSON string with quotes
79-
// which are sliced off.
80-
[key]: JSON.stringify(value).slice(1, -1),
81-
};
82-
},
83-
{} as Secrets
84-
);
85-
86-
const interpolationRes = goSync(() =>
87-
JSON.parse(
88-
template(JSON.stringify(config), {
89-
escape: NO_MATCH_REGEXP,
90-
evaluate: NO_MATCH_REGEXP,
91-
interpolate: ES_MATCH_REGEXP,
92-
})(stringifiedSecrets)
93-
)
94-
);
95-
96-
if (!interpolationRes.success) return interpolationRes;
97-
98-
const interpolatedConfig = JSON.stringify(interpolationRes.data);
99-
// Un-escape the escaped config interpolations (e.g. to enable interpolation in processing snippets)
100-
return goSync(() => JSON.parse(interpolatedConfig.replace(ESCAPED_ES_MATCH_REGEXP, '$1')));
101-
}
102-
10363
/**
10464
* Used to interpolate secrets into config. This function only interpolates the secrets and does not perform any
10565
* validation. Only use this function when you are sure the interpolation result is a valid Airnode config.
10666
*
10767
* In case there is an error when interpolating secrets the function throws an error.
10868
*/
10969
export function unsafeParseConfigWithSecrets(config: unknown, secrets: Secrets): Config {
110-
const interpolationResult = interpolateSecrets(config, secrets);
111-
if (!interpolationResult.success) throw interpolationResult.error;
112-
113-
return interpolationResult.data as Config;
70+
// System and docker secrets passed via process.env do not necessarily obey the expected secret name pattern
71+
return interpolateSecretsIntoConfig(config, secrets, {
72+
allowBlankSecretValue: true,
73+
validateSecretName: false,
74+
}) as Config;
11475
}

yarn.lock

+6-4
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,17 @@
3535
viem "^2.7.1"
3636
zod "^3.22.4"
3737

38-
"@api3/commons@^0.6.2":
39-
version "0.6.2"
40-
resolved "https://registry.yarnpkg.com/@api3/commons/-/commons-0.6.2.tgz#e25d1bce560e53bf44075d08295bf243365c0bfd"
41-
integrity sha512-IBR9WAcbglFdMyehiv3MWFVK1jKv2jAao6tU2DcUmMztea0H+Nn9xAomHCwAlg7mTNn3qk7ZpWosZNGZjfeSTw==
38+
"@api3/commons@^0.7.1":
39+
version "0.7.1"
40+
resolved "https://registry.npmjs.org/@api3/commons/-/commons-0.7.1.tgz#f9c99ce31cfc2dc332945e396a4d9b646199d698"
41+
integrity sha512-Cm2OfuLklEffSh2/DFnfyOBpa/JC3mXi4Xx0MUVZU8aqcGkc62bD3CqLXRXHEsxe2IQLg3B4NZhOZeNEWFl0nQ==
4242
dependencies:
4343
"@api3/ois" "^2.3.0"
4444
"@api3/promise-utils" "^0.4.0"
4545
"@typescript-eslint/eslint-plugin" "^6.2.1"
4646
"@typescript-eslint/parser" "^6.2.1"
47+
axios "^1.6.7"
48+
dotenv "^16.4.5"
4749
eslint-config-next "^13.1.6"
4850
eslint-plugin-check-file "^2.6.2"
4951
eslint-plugin-cypress "^2.14.0"

0 commit comments

Comments
 (0)