@usebruno/filestore 0.10.0 → 0.12.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/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/workers/worker-script.js +1 -1
- package/dist/cjs/workers/worker-script.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/workers/worker-script.js +1 -1
- package/dist/esm/workers/worker-script.js.map +1 -1
- package/dist/formats/bru/index.d.ts.map +1 -1
- package/dist/formats/bru/utils/redact-large-text-blocks.d.ts +11 -0
- package/dist/formats/bru/utils/redact-large-text-blocks.d.ts.map +1 -0
- package/dist/formats/yml/common/app.d.ts +8 -0
- package/dist/formats/yml/common/app.d.ts.map +1 -0
- package/dist/formats/yml/common/auth.d.ts.map +1 -1
- package/dist/formats/yml/common/body.d.ts.map +1 -1
- package/dist/formats/yml/common/datatype.d.ts +14 -0
- package/dist/formats/yml/common/datatype.d.ts.map +1 -0
- package/dist/formats/yml/common/headers.d.ts.map +1 -1
- package/dist/formats/yml/common/variables.d.ts +1 -2
- package/dist/formats/yml/common/variables.d.ts.map +1 -1
- package/dist/formats/yml/index.d.ts +3 -1
- package/dist/formats/yml/index.d.ts.map +1 -1
- package/dist/formats/yml/items/parseApp.d.ts +13 -0
- package/dist/formats/yml/items/parseApp.d.ts.map +1 -0
- package/dist/formats/yml/items/parseGraphQLRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/parseGrpcRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/parseHttpRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/parseWebsocketRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/stringifyApp.d.ts +4 -0
- package/dist/formats/yml/items/stringifyApp.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/stringifyGrpcRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/stringifyHttpRequest.d.ts.map +1 -1
- package/dist/formats/yml/items/stringifyWebsocketRequest.d.ts.map +1 -1
- package/dist/formats/yml/mockServerTypes.d.ts +95 -0
- package/dist/formats/yml/mockServerTypes.d.ts.map +1 -0
- package/dist/formats/yml/parseCollection.d.ts.map +1 -1
- package/dist/formats/yml/parseEnvironment.d.ts +3 -1
- package/dist/formats/yml/parseEnvironment.d.ts.map +1 -1
- package/dist/formats/yml/parseFolder.d.ts.map +1 -1
- package/dist/formats/yml/parseItem.d.ts.map +1 -1
- package/dist/formats/yml/parseMockServer.d.ts +4 -0
- package/dist/formats/yml/parseMockServer.d.ts.map +1 -0
- package/dist/formats/yml/stringifyCollection.d.ts.map +1 -1
- package/dist/formats/yml/stringifyEnvironment.d.ts +3 -1
- package/dist/formats/yml/stringifyEnvironment.d.ts.map +1 -1
- package/dist/formats/yml/stringifyFolder.d.ts.map +1 -1
- package/dist/formats/yml/stringifyItem.d.ts.map +1 -1
- package/dist/formats/yml/stringifyMockServer.d.ts +4 -0
- package/dist/formats/yml/stringifyMockServer.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/secretsJsonToEnvironments.d.ts +38 -0
- package/dist/utils/secretsJsonToEnvironments.d.ts.map +1 -0
- package/dist/workers/WorkerQueue/index.d.ts +3 -2
- package/dist/workers/WorkerQueue/index.d.ts.map +1 -1
- package/dist/workers/index.d.ts +4 -0
- package/dist/workers/index.d.ts.map +1 -1
- package/package.json +7 -5
- package/src/constants.ts +13 -0
- package/src/formats/bru/index.ts +52 -0
- package/src/formats/bru/tests/parseBruEnvironment.spec.js +63 -0
- package/src/formats/bru/tests/redact-large-text-blocks.spec.js +472 -0
- package/src/formats/bru/utils/redact-large-text-blocks.ts +143 -0
- package/src/formats/yml/common/actions.ts +1 -1
- package/src/formats/yml/common/app.ts +27 -0
- package/src/formats/yml/common/auth.ts +53 -1
- package/src/formats/yml/common/body.spec.ts +62 -0
- package/src/formats/yml/common/body.ts +27 -9
- package/src/formats/yml/common/datatype.spec.ts +110 -0
- package/src/formats/yml/common/datatype.ts +57 -0
- package/src/formats/yml/common/headers.ts +4 -0
- package/src/formats/yml/common/variables.spec.ts +127 -0
- package/src/formats/yml/common/variables.ts +14 -22
- package/src/formats/yml/index.ts +5 -1
- package/src/formats/yml/items/parseApp.ts +37 -0
- package/src/formats/yml/items/parseGraphQLRequest.ts +14 -16
- package/src/formats/yml/items/parseGrpcRequest.ts +24 -3
- package/src/formats/yml/items/parseHttpRequest.ts +19 -16
- package/src/formats/yml/items/parseWebsocketRequest.ts +29 -9
- package/src/formats/yml/items/stringifyApp.ts +45 -0
- package/src/formats/yml/items/stringifyGraphQLRequest.ts +7 -6
- package/src/formats/yml/items/stringifyGrpcRequest.ts +9 -11
- package/src/formats/yml/items/stringifyHttpRequest.ts +14 -6
- package/src/formats/yml/items/stringifyWebsocketRequest.ts +22 -9
- package/src/formats/yml/mockServerTypes.ts +95 -0
- package/src/formats/yml/parseCollection.spec.ts +193 -0
- package/src/formats/yml/parseCollection.ts +24 -6
- package/src/formats/yml/parseEnvironment.spec.ts +99 -0
- package/src/formats/yml/parseEnvironment.ts +41 -19
- package/src/formats/yml/parseFolder.spec.ts +70 -0
- package/src/formats/yml/parseFolder.ts +19 -22
- package/src/formats/yml/parseItem.spec.ts +147 -0
- package/src/formats/yml/parseItem.ts +4 -0
- package/src/formats/yml/parseMockServer.spec.ts +180 -0
- package/src/formats/yml/parseMockServer.ts +113 -0
- package/src/formats/yml/stringifyCollection.spec.ts +223 -0
- package/src/formats/yml/stringifyCollection.ts +26 -9
- package/src/formats/yml/stringifyEnvironment.spec.ts +91 -0
- package/src/formats/yml/stringifyEnvironment.ts +55 -20
- package/src/formats/yml/stringifyFolder.spec.ts +70 -0
- package/src/formats/yml/stringifyFolder.ts +7 -2
- package/src/formats/yml/stringifyItem.spec.ts +53 -0
- package/src/formats/yml/stringifyItem.ts +4 -0
- package/src/formats/yml/stringifyMockServer.spec.ts +177 -0
- package/src/formats/yml/stringifyMockServer.ts +129 -0
- package/src/formats/yml/tests/defaultEnvironment.spec.js +50 -0
- package/src/formats/yml/tests/fixtures/presets/empty-request.yml +7 -0
- package/src/formats/yml/tests/fixtures/presets/no-presets.yml +3 -0
- package/src/formats/yml/tests/fixtures/presets/no-request-key.yml +6 -0
- package/src/formats/yml/tests/fixtures/presets/type-only-realistic.yml +24 -0
- package/src/formats/yml/tests/fixtures/presets/url-only-realistic.yml +25 -0
- package/src/formats/yml/tests/fixtures/presets/with-type-and-url.yml +9 -0
- package/src/formats/yml/tests/parseCollection.spec.js +63 -0
- package/src/formats/yml/tests/parseEnvironment.spec.js +24 -63
- package/src/formats/yml/tests/parseEnvironment.spec.ts +160 -0
- package/src/formats/yml/tests/stringifyEnvironment.spec.ts +230 -0
- package/src/formats/yml/tests/variables.spec.js +7 -7
- package/src/formats/yml/utils.ts +1 -1
- package/src/index.ts +39 -1
- package/src/types/bruno-lang.d.ts +1 -0
- package/src/types.ts +8 -0
- package/src/utils/secretsJsonToEnvironments.spec.ts +211 -0
- package/src/utils/secretsJsonToEnvironments.ts +129 -0
- package/src/workers/WorkerQueue/index.ts +10 -2
- package/src/workers/index.ts +25 -1
- package/src/workers/worker-script.ts +45 -21
- package/dist/formats/bru/tests/example-status-swap.spec.d.ts +0 -2
- package/dist/formats/bru/tests/example-status-swap.spec.d.ts.map +0 -1
- package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts +0 -57
- package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts.map +0 -1
- package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts +0 -2
- package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts.map +0 -1
- package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts +0 -2
- package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts.map +0 -1
- package/dist/formats/yml/tests/parseEnvironment.spec.d.ts +0 -2
- package/dist/formats/yml/tests/parseEnvironment.spec.d.ts.map +0 -1
- package/dist/formats/yml/tests/variables.spec.d.ts +0 -2
- package/dist/formats/yml/tests/variables.spec.d.ts.map +0 -1
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { migrateSecretsJsonToEnvironments } from './secretsJsonToEnvironments';
|
|
2
|
+
import type { Environment as BrunoEnvironment } from '@usebruno/schema-types/collection/environment';
|
|
3
|
+
|
|
4
|
+
const env = (name: string, overrides: Partial<BrunoEnvironment> = {}): BrunoEnvironment => ({
|
|
5
|
+
uid: `uid-${name}`,
|
|
6
|
+
name,
|
|
7
|
+
variables: [],
|
|
8
|
+
color: null,
|
|
9
|
+
...overrides
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// collects the nested external-secrets fields and strips the randomly generated uid
|
|
13
|
+
// so they can be compared by value
|
|
14
|
+
const withoutUids = (environment: any) => ({
|
|
15
|
+
secretProviderType: environment.externalSecrets?.type,
|
|
16
|
+
variables: (environment.externalSecrets?.variables || []).map(({ uid, ...rest }: any) => rest)
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('migrateSecretsJsonToEnvironments', () => {
|
|
20
|
+
it('sets an external secrets group from a vault secrets.json file, preserving existing variables', () => {
|
|
21
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
22
|
+
secretsJsonData: {
|
|
23
|
+
type: 'vault',
|
|
24
|
+
data: [
|
|
25
|
+
{
|
|
26
|
+
environment: 'test',
|
|
27
|
+
secrets: [
|
|
28
|
+
{ name: 'cloudSecret', path: 'secret/data/cloud' },
|
|
29
|
+
{ name: 'dbPassword', path: 'secret/data/db-password', enabled: false }
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
environments: [
|
|
35
|
+
env('test', { variables: [{ uid: 'v1', name: 'existing', value: 'keep-me', type: 'text', enabled: true }] })
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(result[0].changed).toBe(true);
|
|
40
|
+
expect(result[0].environment.variables).toEqual([
|
|
41
|
+
{ uid: 'v1', name: 'existing', value: 'keep-me', type: 'text', enabled: true }
|
|
42
|
+
]);
|
|
43
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
44
|
+
secretProviderType: 'hashicorp-vault-server',
|
|
45
|
+
variables: [
|
|
46
|
+
{ name: 'cloudSecret', path: 'secret/data/cloud', enabled: true },
|
|
47
|
+
{ name: 'dbPassword', path: 'secret/data/db-password', enabled: false }
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('sets a hashicorp-vault-cloud group when cli.type is vault-cloud', () => {
|
|
53
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
54
|
+
secretsJsonData: {
|
|
55
|
+
type: 'vault',
|
|
56
|
+
cli: { type: 'vault-cloud' },
|
|
57
|
+
data: [{ environment: 'test', secrets: [{ name: 'cloudSecret', path: 'app/secret' }] }]
|
|
58
|
+
},
|
|
59
|
+
environments: [env('test')]
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(result[0].changed).toBe(true);
|
|
63
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
64
|
+
secretProviderType: 'hashicorp-vault-cloud',
|
|
65
|
+
variables: [{ name: 'cloudSecret', path: 'app/secret', enabled: true }]
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('sets a hashicorp-vault-server group when cli.type is vault-server', () => {
|
|
70
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
71
|
+
secretsJsonData: {
|
|
72
|
+
type: 'vault',
|
|
73
|
+
cli: { type: 'vault-server' },
|
|
74
|
+
data: [{ environment: 'test', secrets: [{ name: 'serverSecret', path: 'secret/data/x' }] }]
|
|
75
|
+
},
|
|
76
|
+
environments: [env('test')]
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(withoutUids(result[0].environment).secretProviderType)
|
|
80
|
+
.toBe('hashicorp-vault-server');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('sets an aws-secrets-manager group from an aws secrets.json file', () => {
|
|
84
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
85
|
+
secretsJsonData: {
|
|
86
|
+
type: 'aws-secrets-manager',
|
|
87
|
+
data: [{ environment: 'test', secrets: [{ name: 'awsSecret', secretName: 'my-aws-secret' }] }]
|
|
88
|
+
},
|
|
89
|
+
environments: [env('test')]
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(result[0].changed).toBe(true);
|
|
93
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
94
|
+
secretProviderType: 'aws-secrets-manager',
|
|
95
|
+
variables: [{ name: 'awsSecret', secretName: 'my-aws-secret', enabled: true }]
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('sets an azure-key-vault group from an azure secrets.json file', () => {
|
|
100
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
101
|
+
secretsJsonData: {
|
|
102
|
+
type: 'azure-key-vault',
|
|
103
|
+
data: [{ environment: 'test', secrets: [{ name: 'azureSecret', vaultName: 'my-key-vault' }] }]
|
|
104
|
+
},
|
|
105
|
+
environments: [env('test')]
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(result[0].changed).toBe(true);
|
|
109
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
110
|
+
secretProviderType: 'azure-key-vault',
|
|
111
|
+
variables: [{ name: 'azureSecret', vaultName: 'my-key-vault', enabled: true }]
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('applies the provider type to every environment, with empty variables when there is no matching entry', () => {
|
|
116
|
+
const test = env('test');
|
|
117
|
+
const prod = env('prod');
|
|
118
|
+
|
|
119
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
120
|
+
secretsJsonData: {
|
|
121
|
+
type: 'vault',
|
|
122
|
+
data: [{ environment: 'test', secrets: [{ name: 'a', path: 'p/a' }] }]
|
|
123
|
+
},
|
|
124
|
+
environments: [test, prod]
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// `test` gets the type and its secret...
|
|
128
|
+
expect(result[0].changed).toBe(true);
|
|
129
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
130
|
+
secretProviderType: 'hashicorp-vault-server',
|
|
131
|
+
variables: [{ name: 'a', path: 'p/a', enabled: true }]
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ...and `prod` (no matching entry) gets the same type with no variables.
|
|
135
|
+
expect(result[1].changed).toBe(true);
|
|
136
|
+
expect(withoutUids(result[1].environment)).toEqual({
|
|
137
|
+
secretProviderType: 'hashicorp-vault-server',
|
|
138
|
+
variables: []
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('applies the provider type with empty variables when secrets.json data is empty', () => {
|
|
143
|
+
const test = env('test');
|
|
144
|
+
|
|
145
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
146
|
+
secretsJsonData: { type: 'vault', data: [] },
|
|
147
|
+
environments: [test]
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect(result[0].changed).toBe(true);
|
|
151
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
152
|
+
secretProviderType: 'hashicorp-vault-server',
|
|
153
|
+
variables: []
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('leaves environments unchanged when no provider type can be resolved', () => {
|
|
158
|
+
const test = env('test');
|
|
159
|
+
|
|
160
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
161
|
+
secretsJsonData: { type: 'unknown-provider', data: [{ environment: 'test', secrets: [{ name: 'a', path: 'p/a' }] }] },
|
|
162
|
+
environments: [test]
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
expect(result[0].changed).toBe(false);
|
|
166
|
+
expect(result[0].environment).toBe(test);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('skips environments that already have external secret variables', () => {
|
|
170
|
+
const test = env('test', {
|
|
171
|
+
externalSecrets: {
|
|
172
|
+
type: 'hashicorp-vault-server',
|
|
173
|
+
variables: [{ uid: 'e1', name: 'existing', path: 'secret/data/existing', enabled: true }]
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
178
|
+
secretsJsonData: {
|
|
179
|
+
type: 'vault',
|
|
180
|
+
data: [{ environment: 'test', secrets: [{ name: 'incoming', path: 'secret/data/incoming' }] }]
|
|
181
|
+
},
|
|
182
|
+
environments: [test]
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expect(result[0].changed).toBe(false);
|
|
186
|
+
expect(result[0].environment).toBe(test);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('skips secrets with a missing identifier', () => {
|
|
190
|
+
const result = migrateSecretsJsonToEnvironments({
|
|
191
|
+
secretsJsonData: {
|
|
192
|
+
type: 'vault',
|
|
193
|
+
data: [
|
|
194
|
+
{
|
|
195
|
+
environment: 'test',
|
|
196
|
+
secrets: [
|
|
197
|
+
{ name: 'good', path: 'p/good' },
|
|
198
|
+
{ name: 'bad', path: '' }
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
environments: [env('test')]
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
expect(withoutUids(result[0].environment)).toEqual({
|
|
207
|
+
secretProviderType: 'hashicorp-vault-server',
|
|
208
|
+
variables: [{ name: 'good', path: 'p/good', enabled: true }]
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Environment as BrunoEnvironment,
|
|
3
|
+
ExternalSecrets as BrunoExternalSecrets,
|
|
4
|
+
ExternalSecretProviderType,
|
|
5
|
+
HashicorpVaultEnvironmentVariable,
|
|
6
|
+
AwsSecretsManagerEnvironmentVariable,
|
|
7
|
+
AzureKeyVaultEnvironmentVariable
|
|
8
|
+
} from '@usebruno/schema-types/collection/environment';
|
|
9
|
+
import { uuid } from './index';
|
|
10
|
+
|
|
11
|
+
type LegacySecretsJsonSecret = {
|
|
12
|
+
name?: string;
|
|
13
|
+
path?: string;
|
|
14
|
+
secretName?: string;
|
|
15
|
+
vaultName?: string;
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export interface SecretsJsonData {
|
|
20
|
+
type?: string;
|
|
21
|
+
data?: { environment: string; type?: string; secrets: LegacySecretsJsonSecret[] }[];
|
|
22
|
+
cli?: { type?: string };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface EnvironmentFileResult {
|
|
26
|
+
name: string;
|
|
27
|
+
environment: BrunoEnvironment;
|
|
28
|
+
changed: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// secrets.json is the legacy format being migrated away from; its provider group lives in
|
|
32
|
+
// `type` (`'vault' | 'aws-secrets-manager' | 'azure-key-vault'`). `'vault'` doesn't distinguish
|
|
33
|
+
// cloud vs server — that split lives in the legacy `cli.type` (`vault-cloud`/`vault-server`).
|
|
34
|
+
// Fall back to server when no cli config is present.
|
|
35
|
+
const resolveSecretProviderType = (
|
|
36
|
+
secretsJsonData: SecretsJsonData
|
|
37
|
+
): ExternalSecretProviderType | null => {
|
|
38
|
+
const fileType = secretsJsonData?.type;
|
|
39
|
+
if (fileType === 'aws-secrets-manager') return 'aws-secrets-manager';
|
|
40
|
+
if (fileType === 'azure-key-vault') return 'azure-key-vault';
|
|
41
|
+
if (fileType === 'vault') {
|
|
42
|
+
return secretsJsonData?.cli?.type === 'vault-cloud' ? 'hashicorp-vault-cloud' : 'hashicorp-vault-server';
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Builds the environment's external-secrets group for the given provider type. Invalid/empty
|
|
48
|
+
// secrets are filtered out; the group is still returned with an empty `variables` list so the
|
|
49
|
+
// provider type lands on the environment even when it has no usable secrets.
|
|
50
|
+
const buildExternalSecrets = (
|
|
51
|
+
secrets: LegacySecretsJsonSecret[] | undefined,
|
|
52
|
+
type: ExternalSecretProviderType
|
|
53
|
+
): BrunoExternalSecrets | null => {
|
|
54
|
+
if (type === 'aws-secrets-manager') {
|
|
55
|
+
const variables = (secrets || [])
|
|
56
|
+
.filter((s) => s?.name && typeof s.secretName === 'string' && s.secretName.length > 0)
|
|
57
|
+
.map((s): AwsSecretsManagerEnvironmentVariable => ({
|
|
58
|
+
uid: uuid(),
|
|
59
|
+
name: s.name as string,
|
|
60
|
+
secretName: s.secretName as string,
|
|
61
|
+
enabled: s.enabled !== false
|
|
62
|
+
}));
|
|
63
|
+
return { type, variables };
|
|
64
|
+
}
|
|
65
|
+
if (type === 'azure-key-vault') {
|
|
66
|
+
const variables = (secrets || [])
|
|
67
|
+
.filter((s) => s?.name && typeof s.vaultName === 'string' && s.vaultName.length > 0)
|
|
68
|
+
.map((s): AzureKeyVaultEnvironmentVariable => ({
|
|
69
|
+
uid: uuid(),
|
|
70
|
+
name: s.name as string,
|
|
71
|
+
vaultName: s.vaultName as string,
|
|
72
|
+
enabled: s.enabled !== false
|
|
73
|
+
}));
|
|
74
|
+
return { type, variables };
|
|
75
|
+
}
|
|
76
|
+
if (type === 'hashicorp-vault-cloud' || type === 'hashicorp-vault-server') {
|
|
77
|
+
const variables = (secrets || [])
|
|
78
|
+
.filter((s) => s?.name && typeof s.path === 'string' && s.path.length > 0)
|
|
79
|
+
.map((s): HashicorpVaultEnvironmentVariable => ({
|
|
80
|
+
uid: uuid(),
|
|
81
|
+
name: s.name as string,
|
|
82
|
+
path: s.path as string,
|
|
83
|
+
enabled: s.enabled !== false
|
|
84
|
+
}));
|
|
85
|
+
return { type, variables };
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Applies the secrets.json provider `type` to every environment's `externalSecrets`, moving each
|
|
92
|
+
* environment's matching secrets onto it. The provider type lands on every environment that
|
|
93
|
+
* doesn't already have `externalSecrets` — including ones with no matching secrets.json entry or
|
|
94
|
+
* only invalid secrets (those get the type with an empty `variables` list). Environments that
|
|
95
|
+
* already carry `externalSecrets` are returned unchanged, as is everything when no provider type
|
|
96
|
+
* can be resolved. Format-agnostic and pure; file IO is the caller's responsibility.
|
|
97
|
+
*/
|
|
98
|
+
export const migrateSecretsJsonToEnvironments = ({
|
|
99
|
+
secretsJsonData,
|
|
100
|
+
environments
|
|
101
|
+
}: {
|
|
102
|
+
secretsJsonData: SecretsJsonData;
|
|
103
|
+
environments: BrunoEnvironment[];
|
|
104
|
+
}): EnvironmentFileResult[] => {
|
|
105
|
+
const secretProviderType = resolveSecretProviderType(secretsJsonData);
|
|
106
|
+
|
|
107
|
+
return environments.map((environment) => {
|
|
108
|
+
const unchanged = { name: environment.name, environment, changed: false };
|
|
109
|
+
|
|
110
|
+
if (environment.externalSecrets || !secretProviderType) {
|
|
111
|
+
return unchanged;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const entry = secretsJsonData?.data?.find((d) => d?.environment === environment.name);
|
|
115
|
+
const externalSecrets = buildExternalSecrets(entry?.secrets, secretProviderType);
|
|
116
|
+
if (!externalSecrets) {
|
|
117
|
+
return unchanged;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
name: environment.name,
|
|
122
|
+
environment: {
|
|
123
|
+
...environment,
|
|
124
|
+
externalSecrets
|
|
125
|
+
},
|
|
126
|
+
changed: true
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
};
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Worker } from 'node:worker_threads';
|
|
2
2
|
|
|
3
|
+
type WorkerTaskType
|
|
4
|
+
= | 'parse'
|
|
5
|
+
| 'stringify'
|
|
6
|
+
| 'parseFolder'
|
|
7
|
+
| 'stringifyFolder'
|
|
8
|
+
| 'parseEnvironment'
|
|
9
|
+
| 'stringifyEnvironment';
|
|
10
|
+
|
|
3
11
|
interface QueuedTask {
|
|
4
12
|
priority: number;
|
|
5
13
|
scriptPath: string;
|
|
6
14
|
data: any;
|
|
7
|
-
taskType:
|
|
15
|
+
taskType: WorkerTaskType;
|
|
8
16
|
resolve?: (value: any) => void;
|
|
9
17
|
reject?: (reason?: any) => void;
|
|
10
18
|
}
|
|
@@ -58,7 +66,7 @@ class WorkerQueue {
|
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
async runWorker({ scriptPath, data, taskType }: { scriptPath: string; data: any; taskType:
|
|
69
|
+
async runWorker({ scriptPath, data, taskType }: { scriptPath: string; data: any; taskType: WorkerTaskType }) {
|
|
62
70
|
return new Promise(async (resolve, reject) => {
|
|
63
71
|
let worker = await this.getWorkerForScriptPath(scriptPath);
|
|
64
72
|
|
package/src/workers/index.ts
CHANGED
|
@@ -55,7 +55,15 @@ class BruParserWorker {
|
|
|
55
55
|
return queueForSize?.workerQueue ?? this.workerQueues[this.workerQueues.length - 1].workerQueue;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
private async enqueueTask({
|
|
58
|
+
private async enqueueTask({
|
|
59
|
+
data,
|
|
60
|
+
taskType,
|
|
61
|
+
format = DEFAULT_COLLECTION_FORMAT
|
|
62
|
+
}: {
|
|
63
|
+
data: any;
|
|
64
|
+
taskType: 'parse' | 'stringify' | 'parseFolder' | 'stringifyFolder' | 'parseEnvironment' | 'stringifyEnvironment';
|
|
65
|
+
format?: CollectionFormat;
|
|
66
|
+
}): Promise<any> {
|
|
59
67
|
const size = getSize(data);
|
|
60
68
|
const workerQueue = this.getWorkerQueue(size);
|
|
61
69
|
const workerScriptPath = path.join(__dirname, './workers/worker-script.js');
|
|
@@ -76,6 +84,22 @@ class BruParserWorker {
|
|
|
76
84
|
return this.enqueueTask({ data, taskType: 'stringify', format });
|
|
77
85
|
}
|
|
78
86
|
|
|
87
|
+
async parseFolder(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
|
|
88
|
+
return this.enqueueTask({ data, taskType: 'parseFolder', format });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async stringifyFolder(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
|
|
92
|
+
return this.enqueueTask({ data, taskType: 'stringifyFolder', format });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async parseEnvironment(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
|
|
96
|
+
return this.enqueueTask({ data, taskType: 'parseEnvironment', format });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async stringifyEnvironment(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
|
|
100
|
+
return this.enqueueTask({ data, taskType: 'stringifyEnvironment', format });
|
|
101
|
+
}
|
|
102
|
+
|
|
79
103
|
async cleanup(): Promise<void> {
|
|
80
104
|
const cleanupPromises = this.workerQueues.map(({ workerQueue }) =>
|
|
81
105
|
workerQueue.cleanup()
|
|
@@ -1,39 +1,63 @@
|
|
|
1
1
|
import { parentPort } from 'node:worker_threads';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
parseBruRequest,
|
|
4
|
+
parseBruCollection,
|
|
5
|
+
parseBruEnvironment,
|
|
6
|
+
stringifyBruRequest,
|
|
7
|
+
stringifyBruCollection,
|
|
8
|
+
stringifyBruEnvironment
|
|
9
|
+
} from '../formats/bru';
|
|
10
|
+
import {
|
|
11
|
+
parseYmlItem,
|
|
12
|
+
parseYmlFolder,
|
|
13
|
+
parseYmlEnvironment,
|
|
14
|
+
stringifyYmlItem,
|
|
15
|
+
stringifyYmlFolder,
|
|
16
|
+
stringifyYmlEnvironment
|
|
17
|
+
} from '../formats/yml';
|
|
4
18
|
import { CollectionFormat } from '../types';
|
|
5
19
|
import { DEFAULT_COLLECTION_FORMAT } from '../constants';
|
|
6
20
|
|
|
21
|
+
type TaskType
|
|
22
|
+
= | 'parse'
|
|
23
|
+
| 'stringify'
|
|
24
|
+
| 'parseFolder'
|
|
25
|
+
| 'stringifyFolder'
|
|
26
|
+
| 'parseEnvironment'
|
|
27
|
+
| 'stringifyEnvironment';
|
|
28
|
+
|
|
7
29
|
interface WorkerMessage {
|
|
8
|
-
taskType:
|
|
30
|
+
taskType: TaskType;
|
|
9
31
|
data: {
|
|
10
32
|
data: any;
|
|
11
33
|
format?: CollectionFormat;
|
|
12
34
|
};
|
|
13
35
|
}
|
|
14
36
|
|
|
37
|
+
const runTask = (taskType: TaskType, data: any, format: CollectionFormat): any => {
|
|
38
|
+
switch (taskType) {
|
|
39
|
+
case 'parse':
|
|
40
|
+
return format === 'yml' ? parseYmlItem(data) : parseBruRequest(data);
|
|
41
|
+
case 'stringify':
|
|
42
|
+
return format === 'yml' ? stringifyYmlItem(data) : stringifyBruRequest(data);
|
|
43
|
+
case 'parseFolder':
|
|
44
|
+
return format === 'yml' ? parseYmlFolder(data) : parseBruCollection(data);
|
|
45
|
+
case 'stringifyFolder':
|
|
46
|
+
return format === 'yml' ? stringifyYmlFolder(data) : stringifyBruCollection(data, true);
|
|
47
|
+
case 'parseEnvironment':
|
|
48
|
+
return format === 'yml' ? parseYmlEnvironment(data) : parseBruEnvironment(data);
|
|
49
|
+
case 'stringifyEnvironment':
|
|
50
|
+
return format === 'yml' ? stringifyYmlEnvironment(data) : stringifyBruEnvironment(data);
|
|
51
|
+
default:
|
|
52
|
+
throw new Error(`Unknown task type: ${taskType}`);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
15
56
|
parentPort?.on('message', async (message: WorkerMessage) => {
|
|
16
57
|
try {
|
|
17
58
|
const { taskType, data: messageData } = message;
|
|
18
59
|
const { data, format = DEFAULT_COLLECTION_FORMAT } = messageData;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (taskType === 'parse') {
|
|
22
|
-
if (format === 'yml') {
|
|
23
|
-
result = parseYmlItem(data);
|
|
24
|
-
} else {
|
|
25
|
-
result = parseBruRequest(data);
|
|
26
|
-
}
|
|
27
|
-
} else if (taskType === 'stringify') {
|
|
28
|
-
if (format === 'yml') {
|
|
29
|
-
result = stringifyYmlItem(data);
|
|
30
|
-
} else {
|
|
31
|
-
result = stringifyBruRequest(data);
|
|
32
|
-
}
|
|
33
|
-
} else {
|
|
34
|
-
throw new Error(`Unknown task type: ${taskType}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
60
|
+
const result = runTask(taskType, data, format);
|
|
37
61
|
parentPort?.postMessage(result);
|
|
38
62
|
} catch (error: any) {
|
|
39
63
|
console.error('Worker error:', error);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"example-status-swap.spec.d.ts","sourceRoot":"","sources":["../../../../src/formats/bru/tests/example-status-swap.spec.js"],"names":[],"mappings":""}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
export function getBruJsonWithAdditionalParams(grantType: any): {
|
|
2
|
-
meta: {
|
|
3
|
-
name: string;
|
|
4
|
-
type: string;
|
|
5
|
-
seq: number;
|
|
6
|
-
};
|
|
7
|
-
http: {
|
|
8
|
-
method: string;
|
|
9
|
-
url: string;
|
|
10
|
-
};
|
|
11
|
-
auth: {
|
|
12
|
-
oauth2: {
|
|
13
|
-
grantType: any;
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
oauth2_additional_parameters_auth_req_headers: {
|
|
17
|
-
name: string;
|
|
18
|
-
value: string;
|
|
19
|
-
enabled: boolean;
|
|
20
|
-
}[];
|
|
21
|
-
oauth2_additional_parameters_auth_req_queryparams: {
|
|
22
|
-
name: string;
|
|
23
|
-
value: string;
|
|
24
|
-
enabled: boolean;
|
|
25
|
-
}[];
|
|
26
|
-
oauth2_additional_parameters_access_token_req_headers: {
|
|
27
|
-
name: string;
|
|
28
|
-
value: string;
|
|
29
|
-
enabled: boolean;
|
|
30
|
-
}[];
|
|
31
|
-
oauth2_additional_parameters_access_token_req_queryparams: {
|
|
32
|
-
name: string;
|
|
33
|
-
value: string;
|
|
34
|
-
enabled: boolean;
|
|
35
|
-
}[];
|
|
36
|
-
oauth2_additional_parameters_access_token_req_bodyvalues: {
|
|
37
|
-
name: string;
|
|
38
|
-
value: string;
|
|
39
|
-
enabled: boolean;
|
|
40
|
-
}[];
|
|
41
|
-
oauth2_additional_parameters_refresh_token_req_headers: {
|
|
42
|
-
name: string;
|
|
43
|
-
value: string;
|
|
44
|
-
enabled: boolean;
|
|
45
|
-
}[];
|
|
46
|
-
oauth2_additional_parameters_refresh_token_req_queryparams: {
|
|
47
|
-
name: string;
|
|
48
|
-
value: string;
|
|
49
|
-
enabled: boolean;
|
|
50
|
-
}[];
|
|
51
|
-
oauth2_additional_parameters_refresh_token_req_bodyvalues: {
|
|
52
|
-
name: string;
|
|
53
|
-
value: string;
|
|
54
|
-
enabled: boolean;
|
|
55
|
-
}[];
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=oauth2-additional-params.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-additional-params.d.ts","sourceRoot":"","sources":["../../../../../src/formats/bru/tests/fixtures/oauth2-additional-params.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+GE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-additional-params.spec.d.ts","sourceRoot":"","sources":["../../../../src/formats/bru/tests/oauth2-additional-params.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-parse-and-redact-body-data.spec.d.ts","sourceRoot":"","sources":["../../../../src/formats/bru/tests/request-parse-and-redact-body-data.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parseEnvironment.spec.d.ts","sourceRoot":"","sources":["../../../../src/formats/yml/tests/parseEnvironment.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"variables.spec.d.ts","sourceRoot":"","sources":["../../../../src/formats/yml/tests/variables.spec.js"],"names":[],"mappings":""}
|