@webda/azure 0.0.0-stage → 4.0.0-beta.13
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/LICENSE +166 -0
- package/README.md +248 -2
- package/lib/auth.d.ts +30 -0
- package/lib/auth.d.ts.map +1 -0
- package/lib/auth.js +70 -0
- package/lib/auth.js.map +1 -0
- package/lib/deployers/arm.service.d.ts +108 -0
- package/lib/deployers/arm.service.d.ts.map +1 -0
- package/lib/deployers/arm.service.js +280 -0
- package/lib/deployers/arm.service.js.map +1 -0
- package/lib/deployers/containerapps.service.d.ts +156 -0
- package/lib/deployers/containerapps.service.d.ts.map +1 -0
- package/lib/deployers/containerapps.service.js +455 -0
- package/lib/deployers/containerapps.service.js.map +1 -0
- package/lib/deployers/functions-entrypoint.d.ts +48 -0
- package/lib/deployers/functions-entrypoint.d.ts.map +1 -0
- package/lib/deployers/functions-entrypoint.js +78 -0
- package/lib/deployers/functions-entrypoint.js.map +1 -0
- package/lib/deployers/functions.service.d.ts +66 -0
- package/lib/deployers/functions.service.d.ts.map +1 -0
- package/lib/deployers/functions.service.js +322 -0
- package/lib/deployers/functions.service.js.map +1 -0
- package/lib/deployers/functionspackager.service.d.ts +43 -0
- package/lib/deployers/functionspackager.service.d.ts.map +1 -0
- package/lib/deployers/functionspackager.service.js +151 -0
- package/lib/deployers/functionspackager.service.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +18 -0
- package/lib/index.js.map +1 -0
- package/lib/services/azure-parameters.d.ts +41 -0
- package/lib/services/azure-parameters.d.ts.map +1 -0
- package/lib/services/azure-parameters.js +43 -0
- package/lib/services/azure-parameters.js.map +1 -0
- package/lib/services/blob.service.d.ts +157 -0
- package/lib/services/blob.service.d.ts.map +1 -0
- package/lib/services/blob.service.js +428 -0
- package/lib/services/blob.service.js.map +1 -0
- package/lib/services/contributors.d.ts +47 -0
- package/lib/services/contributors.d.ts.map +1 -0
- package/lib/services/contributors.js +2 -0
- package/lib/services/contributors.js.map +1 -0
- package/lib/services/cosmos.service.d.ts +211 -0
- package/lib/services/cosmos.service.d.ts.map +1 -0
- package/lib/services/cosmos.service.js +554 -0
- package/lib/services/cosmos.service.js.map +1 -0
- package/lib/services/functionserver.service.d.ts +42 -0
- package/lib/services/functionserver.service.d.ts.map +1 -0
- package/lib/services/functionserver.service.js +223 -0
- package/lib/services/functionserver.service.js.map +1 -0
- package/lib/services/keyvault.service.d.ts +91 -0
- package/lib/services/keyvault.service.d.ts.map +1 -0
- package/lib/services/keyvault.service.js +225 -0
- package/lib/services/keyvault.service.js.map +1 -0
- package/lib/services/monitorlogger.service.d.ts +66 -0
- package/lib/services/monitorlogger.service.d.ts.map +1 -0
- package/lib/services/monitorlogger.service.js +131 -0
- package/lib/services/monitorlogger.service.js.map +1 -0
- package/lib/services/servicebus.service.d.ts +128 -0
- package/lib/services/servicebus.service.d.ts.map +1 -0
- package/lib/services/servicebus.service.js +324 -0
- package/lib/services/servicebus.service.js.map +1 -0
- package/lib/template.d.ts +53 -0
- package/lib/template.d.ts.map +1 -0
- package/lib/template.js +74 -0
- package/lib/template.js.map +1 -0
- package/package.json +77 -3
- package/webda.module.json +1817 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { Writable } from "node:stream";
|
|
3
|
+
import { useLog } from "@webda/workout";
|
|
4
|
+
import { CronService, emitCoreEvent, HttpContext, runWithContext, Service, ServiceParameters, traceRequest, useCore, useRouter, WebContext, WebdaError } from "@webda/core";
|
|
5
|
+
/** Azure Functions HTTP adapter settings. */
|
|
6
|
+
export class AzureFunctionServerParameters extends ServiceParameters {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.requestIdHeader = "x-request-id";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Collect bytes directly, preserving binary responses from write() and streaming routes. */
|
|
13
|
+
class AzureFunctionContext extends WebContext {
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the Azure integration.
|
|
16
|
+
* @param http - HTTP request context
|
|
17
|
+
*/
|
|
18
|
+
constructor(http) {
|
|
19
|
+
const chunks = [];
|
|
20
|
+
super(http, new Writable({
|
|
21
|
+
/**
|
|
22
|
+
* Perform write.
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
write(chunk, _encoding, callback) {
|
|
26
|
+
chunks.push(Buffer.from(chunk));
|
|
27
|
+
callback();
|
|
28
|
+
}
|
|
29
|
+
}));
|
|
30
|
+
this.savedHeaders = {};
|
|
31
|
+
this.chunks = chunks;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Perform write.
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
write(output, encoding, callback) {
|
|
38
|
+
if (Buffer.isBuffer(output)) {
|
|
39
|
+
if (this.statusCode === 204)
|
|
40
|
+
this.statusCode = 200;
|
|
41
|
+
return this._stream.write(output);
|
|
42
|
+
}
|
|
43
|
+
const result = super.write(output, encoding, callback);
|
|
44
|
+
if (this._body !== undefined) {
|
|
45
|
+
this._stream.write(this._body);
|
|
46
|
+
this._body = undefined;
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Perform reset response.
|
|
52
|
+
* @override
|
|
53
|
+
*/
|
|
54
|
+
resetResponse() {
|
|
55
|
+
super.resetResponse();
|
|
56
|
+
this.chunks.length = 0;
|
|
57
|
+
this.savedHeaders = {};
|
|
58
|
+
}
|
|
59
|
+
/** Retain headers flushed by streaming routes until the Functions response is returned.
|
|
60
|
+
* @override
|
|
61
|
+
*/
|
|
62
|
+
getResponseHeaders() {
|
|
63
|
+
return (this.savedHeaders = { ...this.savedHeaders, ...super.getResponseHeaders() });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Run Webda routes and event handlers inside the Azure Functions v4 runtime.
|
|
67
|
+
* @WebdaModda
|
|
68
|
+
*/
|
|
69
|
+
export class AzureFunctionServer extends Service {
|
|
70
|
+
/**
|
|
71
|
+
* Execute an Azure HTTP request through the Webda router.
|
|
72
|
+
* @param request - Azure Functions HTTP request
|
|
73
|
+
* @param invocation - Azure invocation metadata
|
|
74
|
+
* @returns The handle request result
|
|
75
|
+
*/
|
|
76
|
+
async handleRequest(request, invocation) {
|
|
77
|
+
const url = new URL(request.url), headers = Object.fromEntries(request.headers.entries());
|
|
78
|
+
const clientIp = this.getClientIp(headers);
|
|
79
|
+
const http = new HttpContext(url.host, request.method, url.pathname + url.search, url.protocol === "http:" ? "http" : "https", Number(url.port || (url.protocol === "http:" ? 80 : 443)), headers).setClientIp(clientIp || "");
|
|
80
|
+
if (!["GET", "HEAD"].includes(request.method))
|
|
81
|
+
http.setBody(Buffer.from(await request.arrayBuffer()));
|
|
82
|
+
const context = new AzureFunctionContext(http);
|
|
83
|
+
await context.init();
|
|
84
|
+
await emitCoreEvent("Webda.NewContext", { context, info: { http } });
|
|
85
|
+
return traceRequest({
|
|
86
|
+
protocol: "http",
|
|
87
|
+
method: request.method,
|
|
88
|
+
path: url.pathname,
|
|
89
|
+
scheme: url.protocol === "http:" ? "http" : "https",
|
|
90
|
+
headers: Object.fromEntries(Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v])),
|
|
91
|
+
clientIp
|
|
92
|
+
}, async (handle) => {
|
|
93
|
+
const result = await runWithContext(context, async () => {
|
|
94
|
+
try {
|
|
95
|
+
await emitCoreEvent("Webda.Request", { context });
|
|
96
|
+
if (this.parameters.requestIdHeader)
|
|
97
|
+
context.setHeader(this.parameters.requestIdHeader, invocation.invocationId);
|
|
98
|
+
const origin = headers.origin;
|
|
99
|
+
if (origin) {
|
|
100
|
+
if (!(await useRouter()["checkCORSRequest"](context))) {
|
|
101
|
+
// No Access-Control-* for a refused origin, but the answer still depends on it
|
|
102
|
+
context.setHeader("Vary", "Origin");
|
|
103
|
+
throw new WebdaError.Unauthorized("Origin not allowed");
|
|
104
|
+
}
|
|
105
|
+
// Access-Control-Allow-Origin/-Credentials are set by the Router
|
|
106
|
+
}
|
|
107
|
+
if (url.protocol === "https:")
|
|
108
|
+
context.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
|
|
109
|
+
await useRouter().execute(context);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error instanceof WebdaError.HttpError) {
|
|
113
|
+
context.statusCode = error.getResponseCode();
|
|
114
|
+
if (error instanceof WebdaError.Redirect)
|
|
115
|
+
context.setHeader("Location", error.location);
|
|
116
|
+
}
|
|
117
|
+
else if (typeof error === "number")
|
|
118
|
+
context.statusCode = error;
|
|
119
|
+
else {
|
|
120
|
+
context.statusCode = 500;
|
|
121
|
+
this.log("ERROR", "Azure Function request failed");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
await emitCoreEvent("Webda.Result", { context });
|
|
125
|
+
const responseHeaders = { ...context.getResponseHeaders() };
|
|
126
|
+
await context.end();
|
|
127
|
+
const merged = { ...responseHeaders, ...context.getResponseHeaders() };
|
|
128
|
+
const resultHeaders = Object.fromEntries(Object.entries(merged)
|
|
129
|
+
.filter(([name, value]) => value !== undefined &&
|
|
130
|
+
(name.toLowerCase() !== "set-cookie" || !Object.keys(context.getResponseCookies() ?? {}).length))
|
|
131
|
+
.map(([key, value]) => [key, Array.isArray(value) ? value.join(", ") : String(value)]));
|
|
132
|
+
const cookies = Object.values(context.getResponseCookies() ?? {}).map(cookie => {
|
|
133
|
+
const options = cookie.options ?? {};
|
|
134
|
+
const sameSite = options.sameSite === true ? "strict" : options.sameSite;
|
|
135
|
+
return {
|
|
136
|
+
name: cookie.name,
|
|
137
|
+
value: cookie.value,
|
|
138
|
+
domain: options.domain,
|
|
139
|
+
path: options.path,
|
|
140
|
+
secure: options.secure,
|
|
141
|
+
httpOnly: options.httpOnly,
|
|
142
|
+
expires: options.expires,
|
|
143
|
+
maxAge: options.maxAge,
|
|
144
|
+
sameSite: typeof sameSite === "string"
|
|
145
|
+
? (sameSite[0].toUpperCase() + sameSite.slice(1).toLowerCase())
|
|
146
|
+
: undefined
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
const body = Buffer.concat(context.chunks);
|
|
150
|
+
return {
|
|
151
|
+
status: context.getResponseCode(),
|
|
152
|
+
headers: resultHeaders,
|
|
153
|
+
cookies,
|
|
154
|
+
body: request.method === "HEAD" || body.length === 0 ? undefined : body
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
handle.setStatus(result.status);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
useLog("WARN", "Request tracer failed to record the status", err);
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolve the client address from the rightmost X-Forwarded-For entry, without any port. Never throws.
|
|
168
|
+
* @param headers - the request headers
|
|
169
|
+
* @returns the address, undefined if unknown or invalid
|
|
170
|
+
*/
|
|
171
|
+
getClientIp(headers) {
|
|
172
|
+
try {
|
|
173
|
+
let last = Object.entries(headers)
|
|
174
|
+
.find(([name]) => name.toLowerCase() === "x-forwarded-for")?.[1]
|
|
175
|
+
?.split(",")
|
|
176
|
+
.pop()
|
|
177
|
+
?.trim();
|
|
178
|
+
if (!last)
|
|
179
|
+
return undefined;
|
|
180
|
+
// [v6]:port, v4:port (a bare v6 contains several colons and is kept as is)
|
|
181
|
+
const bracketed = last.match(/^\[([^\]]+)\](?::\d+)?$/);
|
|
182
|
+
if (bracketed)
|
|
183
|
+
last = bracketed[1];
|
|
184
|
+
else if (last.split(":").length === 2)
|
|
185
|
+
last = last.split(":")[0];
|
|
186
|
+
return isIP(last) ? last : undefined;
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
useLog("WARN", "Cannot resolve the client address", err);
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Dispatch an Azure binding event to configured handler services.
|
|
195
|
+
* @param source - Azure binding event source
|
|
196
|
+
* @param event - Received event payload
|
|
197
|
+
* @param context - Webda or Azure invocation context
|
|
198
|
+
*/
|
|
199
|
+
async handleEvent(source, event, context) {
|
|
200
|
+
let handled = false;
|
|
201
|
+
for (const service of Object.values(useCore().getServices())) {
|
|
202
|
+
if (typeof service.handleAzureEvent === "function") {
|
|
203
|
+
handled =
|
|
204
|
+
(await service.handleAzureEvent(source, event, context)) || handled;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!handled)
|
|
208
|
+
throw new WebdaError.NotImplemented(`No Azure ${source} event handler is configured`);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Execute only the declared cron matching the exported identifier, through its operation
|
|
212
|
+
* @param id - Secret name or exported cron identifier
|
|
213
|
+
*/
|
|
214
|
+
async handleCron(id) {
|
|
215
|
+
const crons = CronService.resolveCrons().filter(cron => CronService.getExportId(cron) === id);
|
|
216
|
+
if (!crons.length)
|
|
217
|
+
throw new WebdaError.NotFound("Azure timer does not match a declared Webda cron");
|
|
218
|
+
for (const cron of crons)
|
|
219
|
+
await CronService.execute(cron, true);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
AzureFunctionServer.Parameters = AzureFunctionServerParameters;
|
|
223
|
+
//# sourceMappingURL=functionserver.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionserver.service.js","sources":["../../src/services/functionserver.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { SecretClient } from "@azure/keyvault-secrets";
|
|
2
|
+
import { ConfigurationProvider, SecretString, Service } from "@webda/core";
|
|
3
|
+
import { AzureParameters, AzureServiceParameters } from "./azure-parameters.js";
|
|
4
|
+
import { AzureContributor, AzureDeployerInfo, AzureResourceContribution } from "./contributors.js";
|
|
5
|
+
/** Settings for the Key Vault service and configuration encrypter. */
|
|
6
|
+
export declare class AzureKeyVaultParameters extends AzureParameters {
|
|
7
|
+
vaultUrl: string;
|
|
8
|
+
keyId?: string;
|
|
9
|
+
}
|
|
10
|
+
type AzureEncryptionOptions = AzureServiceParameters & {
|
|
11
|
+
keyId?: string;
|
|
12
|
+
};
|
|
13
|
+
/** Authenticated envelope encryption: only the random AES key leaves this process. */
|
|
14
|
+
export declare const azureEncrypter: {
|
|
15
|
+
/** Configure the encryption pass before application services are created.
|
|
16
|
+
* @param options - Azure credential and key settings for this configuration pass
|
|
17
|
+
*/
|
|
18
|
+
configure(options: AzureEncryptionOptions): void;
|
|
19
|
+
/**
|
|
20
|
+
* Encrypt a configuration value with a wrapped AES key.
|
|
21
|
+
* @param data - Model data or encrypted envelope
|
|
22
|
+
* @param options - Encryption or packaging options
|
|
23
|
+
* @returns The encrypt result
|
|
24
|
+
*/
|
|
25
|
+
encrypt(data: string, options?: string | AzureEncryptionOptions): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Decrypt and authenticate an Azure envelope.
|
|
28
|
+
* @param data - Model data or encrypted envelope
|
|
29
|
+
* @param params - Raw configuration parameters
|
|
30
|
+
* @returns The decrypt result
|
|
31
|
+
*/
|
|
32
|
+
decrypt(data: string, params?: AzureServiceParameters): Promise<string>;
|
|
33
|
+
};
|
|
34
|
+
/** Key Vault secrets as a configuration source, with Key Vault envelope encryption.
|
|
35
|
+
* @WebdaModda
|
|
36
|
+
*/
|
|
37
|
+
export declare class AzureKeyVault extends Service<AzureKeyVaultParameters> implements ConfigurationProvider, AzureContributor {
|
|
38
|
+
static Parameters: typeof AzureKeyVaultParameters;
|
|
39
|
+
protected client: SecretClient;
|
|
40
|
+
/**
|
|
41
|
+
* Perform init.
|
|
42
|
+
* @override
|
|
43
|
+
*/
|
|
44
|
+
init(): Promise<this>;
|
|
45
|
+
/**
|
|
46
|
+
* Key Vault has no push-based configuration subscription; ConfigurationService polls.
|
|
47
|
+
* @param _id - Configuration source identifier
|
|
48
|
+
* @param _callback - Unused configuration change callback
|
|
49
|
+
* @returns The can trigger configuration result
|
|
50
|
+
*/
|
|
51
|
+
canTriggerConfiguration(_id: string, _callback: () => void): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Retrieve a secret without exposing its value to JSON or logs.
|
|
54
|
+
* @param id - Secret name or exported cron identifier
|
|
55
|
+
* @returns Masked secret value
|
|
56
|
+
*/
|
|
57
|
+
getSecret(id: string): Promise<SecretString>;
|
|
58
|
+
/**
|
|
59
|
+
* Load a JSON configuration document. Secret fields can use crypt:azure: values.
|
|
60
|
+
* @param id - Secret name or exported cron identifier
|
|
61
|
+
* @returns Resolved configuration object
|
|
62
|
+
*/
|
|
63
|
+
getConfiguration(id: string): Promise<Record<string, any>>;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve whole-value ${keyvault:secret-name} references in a configuration document.
|
|
66
|
+
* @param configuration - Configuration tree to resolve
|
|
67
|
+
* @returns Configuration with secret references resolved
|
|
68
|
+
*/
|
|
69
|
+
resolveReferences<T>(configuration: T): Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Encrypt a configuration value with a wrapped AES key.
|
|
72
|
+
* @param data - Model data or encrypted envelope
|
|
73
|
+
* @param keyId - key id
|
|
74
|
+
* @returns The encrypt result
|
|
75
|
+
*/
|
|
76
|
+
encrypt(data: string, keyId?: string | undefined): Promise<string>;
|
|
77
|
+
/**
|
|
78
|
+
* Decrypt and authenticate an Azure envelope.
|
|
79
|
+
* @param data - Model data or encrypted envelope
|
|
80
|
+
* @returns The decrypt result
|
|
81
|
+
*/
|
|
82
|
+
decrypt(data: string): Promise<SecretString>;
|
|
83
|
+
/**
|
|
84
|
+
* Describe the Azure resources and identity permissions required by this service.
|
|
85
|
+
* @param deployer - Deployment scope and identity helpers
|
|
86
|
+
* @returns The azure resources result
|
|
87
|
+
*/
|
|
88
|
+
getAzureResources(deployer: AzureDeployerInfo): AzureResourceContribution;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=keyvault.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyvault.service.d.ts","sources":["../../src/services/keyvault.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAiB,YAAY,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAsB,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnG,sEAAsE;AACtE,qBAAa,uBAAwB,SAAQ,eAAe;IAC1D,QAAQ,EAAG,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD,KAAK,sBAAsB,GAAG,sBAAsB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAmB1E,sFAAsF;AACtF,eAAO,MAAM,cAAc;IACzB;;OAEG;IACH,SAAS,UAAU,sBAAsB,GAAG,IAAI;IAGhD;;;;;OAKG;IACG,OAAO,OAAO,MAAM,YAAW,MAAM,GAAG,sBAAsB,GAA0B,OAAO,CAAC,MAAM,CAAC;IA8B7G;;;;;OAKG;IACG,OAAO,OAAO,MAAM,WAAU,sBAAsB,GAA0B,OAAO,CAAC,MAAM,CAAC;CAiCpG,CAAC;AAIF;;GAEG;AACH,qBAAa,aAAc,SAAQ,OAAO,CAAC,uBAAuB,CAAE,YAAW,qBAAqB,EAAE,gBAAgB;IACpH,MAAM,CAAC,UAAU,iCAA2B;IAC5C,SAAS,CAAC,MAAM,EAAG,YAAY,CAAC;IAEhC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1B;IAED;;;;;OAKG;IACH,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAEnE;IAED;;;;OAIG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAWjD;IAED;;;;OAIG;IACG,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAY/D;IAED;;;;OAIG;IACG,iBAAiB,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAevD;IAED;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,qBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;IAED;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAEjD;IAED;;;;OAIG;IACH,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,yBAAyB,CASxE;CACF"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { CryptographyClient } from "@azure/keyvault-keys";
|
|
2
|
+
import { SecretClient } from "@azure/keyvault-secrets";
|
|
3
|
+
import { CryptoService, SecretString, Service, WebdaError } from "@webda/core";
|
|
4
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
5
|
+
import { AzureParameters, getAzureCredential } from "./azure-parameters.js";
|
|
6
|
+
/** Settings for the Key Vault service and configuration encrypter. */
|
|
7
|
+
export class AzureKeyVaultParameters extends AzureParameters {
|
|
8
|
+
}
|
|
9
|
+
let configuredEncryption = {};
|
|
10
|
+
/**
|
|
11
|
+
* Validate key identifiers before sending credentials or wrapped keys to their endpoints.
|
|
12
|
+
* @param keyId - key id
|
|
13
|
+
* @returns The validate key id result
|
|
14
|
+
*/
|
|
15
|
+
function validateKeyId(keyId) {
|
|
16
|
+
if (!/^https:\/\/[a-zA-Z0-9-]+\.vault\.(?:azure\.net|azure\.cn|usgovcloudapi\.net)\/keys\/[a-zA-Z0-9-]+(?:\/[a-zA-Z0-9-]+)?$/.test(keyId)) {
|
|
17
|
+
throw new WebdaError.CodeError("AZURE_KEY_ID", "A full Azure Key Vault key URL is required");
|
|
18
|
+
}
|
|
19
|
+
return keyId;
|
|
20
|
+
}
|
|
21
|
+
/** Authenticated envelope encryption: only the random AES key leaves this process. */
|
|
22
|
+
export const azureEncrypter = {
|
|
23
|
+
/** Configure the encryption pass before application services are created.
|
|
24
|
+
* @param options - Azure credential and key settings for this configuration pass
|
|
25
|
+
*/
|
|
26
|
+
configure(options) {
|
|
27
|
+
configuredEncryption = { ...options };
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Encrypt a configuration value with a wrapped AES key.
|
|
31
|
+
* @param data - Model data or encrypted envelope
|
|
32
|
+
* @param options - Encryption or packaging options
|
|
33
|
+
* @returns The encrypt result
|
|
34
|
+
*/
|
|
35
|
+
async encrypt(data, options = configuredEncryption) {
|
|
36
|
+
const params = typeof options === "string" ? { keyId: options } : options;
|
|
37
|
+
const keyId = validateKeyId(params.keyId ?? process.env.WEBDA_AZURE_KEY_ID ?? "");
|
|
38
|
+
const key = randomBytes(32);
|
|
39
|
+
try {
|
|
40
|
+
const client = new CryptographyClient(keyId, getAzureCredential(params));
|
|
41
|
+
const wrapped = await client.wrapKey("RSA-OAEP-256", key);
|
|
42
|
+
// Pin the actual key version so rotating the vault key does not break existing values.
|
|
43
|
+
const resolvedKeyId = validateKeyId(wrapped.keyID ?? keyId);
|
|
44
|
+
if (new URL(resolvedKeyId).origin !== new URL(keyId).origin || resolvedKeyId.split("/").length !== 6) {
|
|
45
|
+
throw new WebdaError.CodeError("AZURE_KEY_VERSION", "Key Vault must return a versioned key identifier");
|
|
46
|
+
}
|
|
47
|
+
const iv = randomBytes(12);
|
|
48
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
49
|
+
cipher.setAAD(Buffer.from(`1:${resolvedKeyId}`));
|
|
50
|
+
const ciphertext = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
51
|
+
const envelope = {
|
|
52
|
+
version: 1,
|
|
53
|
+
keyId: resolvedKeyId,
|
|
54
|
+
wrappedKey: Buffer.from(wrapped.result).toString("base64url"),
|
|
55
|
+
iv: iv.toString("base64url"),
|
|
56
|
+
tag: cipher.getAuthTag().toString("base64url"),
|
|
57
|
+
ciphertext: ciphertext.toString("base64url")
|
|
58
|
+
};
|
|
59
|
+
return Buffer.from(JSON.stringify(envelope)).toString("base64url");
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
key.fill(0);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Decrypt and authenticate an Azure envelope.
|
|
67
|
+
* @param data - Model data or encrypted envelope
|
|
68
|
+
* @param params - Raw configuration parameters
|
|
69
|
+
* @returns The decrypt result
|
|
70
|
+
*/
|
|
71
|
+
async decrypt(data, params = configuredEncryption) {
|
|
72
|
+
let key;
|
|
73
|
+
try {
|
|
74
|
+
const envelope = JSON.parse(Buffer.from(data, "base64url").toString());
|
|
75
|
+
if (envelope.version !== 1)
|
|
76
|
+
throw new Error();
|
|
77
|
+
validateKeyId(envelope.keyId);
|
|
78
|
+
const decode = (value, size) => {
|
|
79
|
+
if (typeof value !== "string" || !/^[\w-]*$/.test(value))
|
|
80
|
+
throw new Error();
|
|
81
|
+
const bytes = Buffer.from(value, "base64url");
|
|
82
|
+
if (bytes.toString("base64url") !== value || (size !== undefined && bytes.length !== size))
|
|
83
|
+
throw new Error();
|
|
84
|
+
return bytes;
|
|
85
|
+
};
|
|
86
|
+
const iv = decode(envelope.iv, 12), tag = decode(envelope.tag, 16);
|
|
87
|
+
const ciphertext = decode(envelope.ciphertext), wrappedKey = decode(envelope.wrappedKey);
|
|
88
|
+
if (!wrappedKey.length || envelope.keyId.split("/").length !== 6)
|
|
89
|
+
throw new Error();
|
|
90
|
+
const client = new CryptographyClient(envelope.keyId, getAzureCredential(params));
|
|
91
|
+
const unwrapped = await client.unwrapKey("RSA-OAEP-256", wrappedKey);
|
|
92
|
+
key = Buffer.from(unwrapped.result);
|
|
93
|
+
unwrapped.result.fill(0);
|
|
94
|
+
if (key.length !== 32)
|
|
95
|
+
throw new Error();
|
|
96
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
97
|
+
decipher.setAAD(Buffer.from(`1:${envelope.keyId}`));
|
|
98
|
+
decipher.setAuthTag(tag);
|
|
99
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// SDK exceptions can contain requests; never expose them with configuration secrets.
|
|
103
|
+
throw new WebdaError.CodeError("AZURE_DECRYPT_FAILED", "Unable to decrypt Azure configuration value");
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
key?.fill(0);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
CryptoService.registerEncrypter("azure", azureEncrypter);
|
|
111
|
+
/** Key Vault secrets as a configuration source, with Key Vault envelope encryption.
|
|
112
|
+
* @WebdaModda
|
|
113
|
+
*/
|
|
114
|
+
export class AzureKeyVault extends Service {
|
|
115
|
+
/**
|
|
116
|
+
* Perform init.
|
|
117
|
+
* @override
|
|
118
|
+
*/
|
|
119
|
+
async init() {
|
|
120
|
+
await super.init();
|
|
121
|
+
this.client = new SecretClient(this.parameters.vaultUrl, getAzureCredential(this.parameters));
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Key Vault has no push-based configuration subscription; ConfigurationService polls.
|
|
126
|
+
* @param _id - Configuration source identifier
|
|
127
|
+
* @param _callback - Unused configuration change callback
|
|
128
|
+
* @returns The can trigger configuration result
|
|
129
|
+
*/
|
|
130
|
+
canTriggerConfiguration(_id, _callback) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Retrieve a secret without exposing its value to JSON or logs.
|
|
135
|
+
* @param id - Secret name or exported cron identifier
|
|
136
|
+
* @returns Masked secret value
|
|
137
|
+
*/
|
|
138
|
+
async getSecret(id) {
|
|
139
|
+
let secret;
|
|
140
|
+
try {
|
|
141
|
+
secret = await this.client.getSecret(id);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error.statusCode === 404)
|
|
145
|
+
throw new WebdaError.NotFound("Key Vault secret was not found");
|
|
146
|
+
throw new WebdaError.ServiceUnavailable("Unable to retrieve Key Vault secret");
|
|
147
|
+
}
|
|
148
|
+
if (secret.value === undefined)
|
|
149
|
+
throw new WebdaError.NotFound("Key Vault secret has no value");
|
|
150
|
+
return new SecretString(secret.value, "azure");
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Load a JSON configuration document. Secret fields can use crypt:azure: values.
|
|
154
|
+
* @param id - Secret name or exported cron identifier
|
|
155
|
+
* @returns Resolved configuration object
|
|
156
|
+
*/
|
|
157
|
+
async getConfiguration(id) {
|
|
158
|
+
const value = await this.getSecret(id);
|
|
159
|
+
let configuration;
|
|
160
|
+
try {
|
|
161
|
+
configuration = JSON.parse(value.getValue());
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
throw new WebdaError.BadRequest("Key Vault configuration must be a JSON object");
|
|
165
|
+
}
|
|
166
|
+
if (!configuration || typeof configuration !== "object" || Array.isArray(configuration)) {
|
|
167
|
+
throw new WebdaError.BadRequest("Key Vault configuration must be a JSON object");
|
|
168
|
+
}
|
|
169
|
+
return this.resolveReferences(configuration);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve whole-value ${keyvault:secret-name} references in a configuration document.
|
|
173
|
+
* @param configuration - Configuration tree to resolve
|
|
174
|
+
* @returns Configuration with secret references resolved
|
|
175
|
+
*/
|
|
176
|
+
async resolveReferences(configuration) {
|
|
177
|
+
const resolve = async (value) => {
|
|
178
|
+
if (typeof value === "string") {
|
|
179
|
+
const match = /^\$\{keyvault:([a-zA-Z0-9-]+)\}$/.exec(value);
|
|
180
|
+
return match ? this.getSecret(match[1]) : value;
|
|
181
|
+
}
|
|
182
|
+
if (Array.isArray(value))
|
|
183
|
+
return Promise.all(value.map(resolve));
|
|
184
|
+
if (value && typeof value === "object" && !(value instanceof SecretString)) {
|
|
185
|
+
return Object.fromEntries(await Promise.all(Object.entries(value).map(async ([key, child]) => [key, await resolve(child)])));
|
|
186
|
+
}
|
|
187
|
+
return value;
|
|
188
|
+
};
|
|
189
|
+
return (await resolve(configuration));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Encrypt a configuration value with a wrapped AES key.
|
|
193
|
+
* @param data - Model data or encrypted envelope
|
|
194
|
+
* @param keyId - key id
|
|
195
|
+
* @returns The encrypt result
|
|
196
|
+
*/
|
|
197
|
+
encrypt(data, keyId = this.parameters.keyId) {
|
|
198
|
+
return azureEncrypter.encrypt(data, { ...this.parameters, keyId });
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Decrypt and authenticate an Azure envelope.
|
|
202
|
+
* @param data - Model data or encrypted envelope
|
|
203
|
+
* @returns The decrypt result
|
|
204
|
+
*/
|
|
205
|
+
async decrypt(data) {
|
|
206
|
+
return new SecretString(await azureEncrypter.decrypt(data, this.parameters), "azure");
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Describe the Azure resources and identity permissions required by this service.
|
|
210
|
+
* @param deployer - Deployment scope and identity helpers
|
|
211
|
+
* @returns The azure resources result
|
|
212
|
+
*/
|
|
213
|
+
getAzureResources(deployer) {
|
|
214
|
+
const name = new URL(this.parameters.vaultUrl).hostname.split(".")[0];
|
|
215
|
+
const scope = `/subscriptions/${deployer.resources.subscriptionId}/resourceGroups/${deployer.resources.resourceGroup}/providers/Microsoft.KeyVault/vaults/${name}`;
|
|
216
|
+
return {
|
|
217
|
+
roleAssignments: ["4633458b-17de-408a-b874-0445c86b69e6", "12338af0-0e69-4776-bea7-57ae8d297424"].map(role => ({
|
|
218
|
+
scope,
|
|
219
|
+
roleDefinitionId: `/subscriptions/${deployer.resources.subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/${role}`
|
|
220
|
+
}))
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
AzureKeyVault.Parameters = AzureKeyVaultParameters;
|
|
225
|
+
//# sourceMappingURL=keyvault.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyvault.service.js","sources":["../../src/services/keyvault.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { LogsIngestionClient } from "@azure/monitor-ingestion";
|
|
2
|
+
import { Service } from "@webda/core";
|
|
3
|
+
import { WorkerLogLevel, WorkerMessage } from "@webda/workout";
|
|
4
|
+
import { AzureParameters } from "./azure-parameters.js";
|
|
5
|
+
/** Azure Monitor Logs Ingestion settings. */
|
|
6
|
+
export declare class AzureMonitorLoggerParameters extends AzureParameters {
|
|
7
|
+
endpoint: string;
|
|
8
|
+
ruleId: string;
|
|
9
|
+
streamName: string;
|
|
10
|
+
logLevel: WorkerLogLevel;
|
|
11
|
+
batchSize: number;
|
|
12
|
+
flushInterval: number;
|
|
13
|
+
maxBufferedLogs: number;
|
|
14
|
+
}
|
|
15
|
+
/** Columns declared in the Data Collection Rule's stream. */
|
|
16
|
+
export interface AzureLogRecord extends Record<string, unknown> {
|
|
17
|
+
TimeGenerated: string;
|
|
18
|
+
Level: WorkerLogLevel;
|
|
19
|
+
Message: string;
|
|
20
|
+
}
|
|
21
|
+
/** Forward Webda logs to a custom Azure Monitor table.
|
|
22
|
+
* @WebdaModda
|
|
23
|
+
*/
|
|
24
|
+
export declare class AzureMonitorLogger extends Service<AzureMonitorLoggerParameters> {
|
|
25
|
+
static Parameters: typeof AzureMonitorLoggerParameters;
|
|
26
|
+
protected client: LogsIngestionClient;
|
|
27
|
+
protected buffer: AzureLogRecord[];
|
|
28
|
+
protected sending?: Promise<void>;
|
|
29
|
+
protected timer?: ReturnType<typeof setInterval>;
|
|
30
|
+
protected messageListener?: (message: WorkerMessage) => void;
|
|
31
|
+
protected resultListenerOff?: () => void;
|
|
32
|
+
/** Number of records dropped because the bounded buffer was full. */
|
|
33
|
+
droppedLogs: number;
|
|
34
|
+
/** Last delivery error, available to health checks without recursively logging it. */
|
|
35
|
+
lastDeliveryFailed: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Perform init.
|
|
38
|
+
* @override
|
|
39
|
+
*/
|
|
40
|
+
init(): Promise<this>;
|
|
41
|
+
/**
|
|
42
|
+
* Buffer one record. SecretString values retain their masked representation.
|
|
43
|
+
* @param level - Worker log level
|
|
44
|
+
* @param args - Log arguments
|
|
45
|
+
*/
|
|
46
|
+
_log(level: WorkerLogLevel, ...args: unknown[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Serialize flushes; failed records stay at the front for the next scheduled retry.
|
|
49
|
+
* @returns Completion of the current flush attempt
|
|
50
|
+
*/
|
|
51
|
+
sendLogs(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Deliver buffered records in bounded batches.
|
|
54
|
+
*/
|
|
55
|
+
protected flush(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Detach log forwarding and stop scheduled flushing.
|
|
58
|
+
*/
|
|
59
|
+
protected removeListeners(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Perform stop.
|
|
62
|
+
* @override
|
|
63
|
+
*/
|
|
64
|
+
stop(): Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=monitorlogger.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitorlogger.service.d.ts","sources":["../../src/services/monitorlogger.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAA6B,MAAM,aAAa,CAAC;AACjE,OAAO,EAA8B,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAsB,MAAM,uBAAuB,CAAC;AAE5E,6CAA6C;AAC7C,qBAAa,4BAA6B,SAAQ,eAAe;IAC/D,QAAQ,EAAG,MAAM,CAAC;IAClB,MAAM,EAAG,MAAM,CAAC;IAChB,UAAU,EAAG,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAU;IAClC,SAAS,SAAO;IAChB,aAAa,SAAQ;IACrB,eAAe,SAAS;CACzB;AAED,6DAA6D;AAC7D,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,OAAO,CAAC,4BAA4B,CAAC;IAC3E,MAAM,CAAC,UAAU,sCAAgC;IACjD,SAAS,CAAC,MAAM,EAAG,mBAAmB,CAAC;IACvC,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,CAAM;IACxC,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,SAAS,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACjD,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7D,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC,qEAAqE;IACrE,WAAW,SAAK;IAChB,sFAAsF;IACtF,kBAAkB,UAAS;IAE3B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B1B;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAOpD;IAED;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAMxB;IAED;;OAEG;IACH,UAAgB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAerC;IAED;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI,CAOhC;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAK1B;CACF"}
|