@microsoft/agents-hosting 1.6.1 → 1.7.0-beta.1.g8bcd4f11a7
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/package.json +3 -3
- package/dist/src/app/streaming/streamingResponse.d.ts +11 -0
- package/dist/src/app/streaming/streamingResponse.js +21 -0
- package/dist/src/app/streaming/streamingResponse.js.map +1 -1
- package/dist/src/auth/MemoryCache.d.ts +2 -1
- package/dist/src/auth/MemoryCache.js +7 -1
- package/dist/src/auth/MemoryCache.js.map +1 -1
- package/dist/src/auth/authConfiguration.d.ts +1 -1
- package/dist/src/auth/authConfiguration.js +36 -1
- package/dist/src/auth/authConfiguration.js.map +1 -1
- package/dist/src/auth/authConstants.d.ts +7 -7
- package/dist/src/auth/authConstants.js.map +1 -1
- package/dist/src/auth/connectionManager.d.ts +92 -0
- package/dist/src/auth/{msalConnectionManager.js → connectionManager.js} +50 -48
- package/dist/src/auth/connectionManager.js.map +1 -0
- package/dist/src/auth/index.d.ts +5 -3
- package/dist/src/auth/index.js +5 -3
- package/dist/src/auth/index.js.map +1 -1
- package/dist/src/auth/jwt-middleware.d.ts +6 -0
- package/dist/src/auth/jwt-middleware.js +32 -1
- package/dist/src/auth/jwt-middleware.js.map +1 -1
- package/dist/src/auth/msal/msalConnectionManager.d.ts +17 -0
- package/dist/src/auth/msal/msalConnectionManager.js +50 -0
- package/dist/src/auth/msal/msalConnectionManager.js.map +1 -0
- package/dist/src/auth/msal/msalConnectionSettings.d.ts +68 -0
- package/dist/src/auth/msal/msalConnectionSettings.js +7 -0
- package/dist/src/auth/msal/msalConnectionSettings.js.map +1 -0
- package/dist/src/auth/{msalTokenCredential.d.ts → msal/msalTokenCredential.d.ts} +1 -1
- package/dist/src/auth/{msalTokenCredential.js → msal/msalTokenCredential.js} +2 -2
- package/dist/src/auth/msal/msalTokenCredential.js.map +1 -0
- package/dist/src/auth/{msalTokenProvider.d.ts → msal/msalTokenProvider.d.ts} +23 -3
- package/dist/src/auth/{msalTokenProvider.js → msal/msalTokenProvider.js} +264 -160
- package/dist/src/auth/msal/msalTokenProvider.js.map +1 -0
- package/dist/src/auth/settings.d.ts +142 -133
- package/dist/src/auth/settings.js +49 -5
- package/dist/src/auth/settings.js.map +1 -1
- package/dist/src/auth/sidecar/sidecarAuthProvider.d.ts +74 -0
- package/dist/src/auth/sidecar/sidecarAuthProvider.js +181 -0
- package/dist/src/auth/sidecar/sidecarAuthProvider.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.d.ts +65 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.js +7 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.d.ts +95 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.js +406 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarModels.d.ts +110 -0
- package/dist/src/auth/sidecar/sidecarModels.js +48 -0
- package/dist/src/auth/sidecar/sidecarModels.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.d.ts +13 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.js +39 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.js.map +1 -0
- package/dist/src/cloudAdapter.js +1 -1
- package/dist/src/cloudAdapter.js.map +1 -1
- package/dist/src/errorHelper.js +96 -0
- package/dist/src/errorHelper.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauth/userTokenClient.d.ts +12 -0
- package/dist/src/oauth/userTokenClient.js +28 -8
- package/dist/src/oauth/userTokenClient.js.map +1 -1
- package/package.json +3 -3
- package/src/app/streaming/streamingResponse.ts +24 -1
- package/src/auth/MemoryCache.ts +7 -1
- package/src/auth/authConfiguration.ts +36 -3
- package/src/auth/authConstants.ts +7 -7
- package/src/auth/{msalConnectionManager.ts → connectionManager.ts} +65 -61
- package/src/auth/index.ts +5 -3
- package/src/auth/jwt-middleware.ts +31 -1
- package/src/auth/msal/msalConnectionManager.ts +55 -0
- package/src/auth/msal/msalConnectionSettings.ts +79 -0
- package/src/auth/{msalTokenCredential.ts → msal/msalTokenCredential.ts} +2 -1
- package/src/auth/{msalTokenProvider.ts → msal/msalTokenProvider.ts} +337 -156
- package/src/auth/settings.ts +131 -76
- package/src/auth/sidecar/sidecarAuthProvider.ts +234 -0
- package/src/auth/sidecar/sidecarConnectionSettings.ts +72 -0
- package/src/auth/sidecar/sidecarHttpClient.ts +443 -0
- package/src/auth/sidecar/sidecarModels.ts +153 -0
- package/src/auth/sidecar/sidecarTokenExpiry.ts +35 -0
- package/src/cloudAdapter.ts +1 -1
- package/src/errorHelper.ts +110 -0
- package/src/index.ts +1 -1
- package/src/oauth/userTokenClient.ts +43 -9
- package/dist/src/auth/msalConnectionManager.d.ts +0 -64
- package/dist/src/auth/msalConnectionManager.js.map +0 -1
- package/dist/src/auth/msalTokenCredential.js.map +0 -1
- package/dist/src/auth/msalTokenProvider.js.map +0 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SidecarAuthProvider = void 0;
|
|
8
|
+
const agents_telemetry_1 = require("@microsoft/agents-telemetry");
|
|
9
|
+
const agents_activity_1 = require("@microsoft/agents-activity");
|
|
10
|
+
const errorHelper_1 = require("../../errorHelper");
|
|
11
|
+
const sidecarHttpClient_1 = require("./sidecarHttpClient");
|
|
12
|
+
const sidecarTokenExpiry_1 = require("./sidecarTokenExpiry");
|
|
13
|
+
const sidecarModels_1 = require("./sidecarModels");
|
|
14
|
+
const logger = (0, agents_telemetry_1.debug)('agents:sidecar');
|
|
15
|
+
const GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16
|
+
// Refresh slightly ahead of the real expiry so callers never receive a token that expires mid-flight.
|
|
17
|
+
const EXPIRY_BUFFER_MS = 30 * 1000;
|
|
18
|
+
// Hard upper bound on cached entries; protects memory when many distinct identities are served.
|
|
19
|
+
const MAX_CACHE_ENTRIES = 500;
|
|
20
|
+
/**
|
|
21
|
+
* Authentication provider that delegates token acquisition to the Microsoft Entra Agent ID
|
|
22
|
+
* sidecar (agent container). This replaces MSAL at the connection layer, using the sidecar's
|
|
23
|
+
* `/AuthorizationHeaderUnauthenticated/{serviceName}` endpoint for app-only and agentic identity
|
|
24
|
+
* flows. The sidecar performs the full Blueprint→Instance→User chain internally; no MSAL exchange is
|
|
25
|
+
* performed in-process.
|
|
26
|
+
*/
|
|
27
|
+
class SidecarAuthProvider {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new {@link SidecarAuthProvider}.
|
|
30
|
+
* @param connectionSettings The connection authentication configuration.
|
|
31
|
+
*/
|
|
32
|
+
constructor(connectionSettings) {
|
|
33
|
+
this._tokenCache = new Map();
|
|
34
|
+
this.connectionSettings = connectionSettings;
|
|
35
|
+
this._settings = (0, sidecarModels_1.toSidecarConnectionSettings)(connectionSettings);
|
|
36
|
+
const resolvedUrl = sidecarHttpClient_1.SidecarHttpClient.resolveBaseUrl(this._settings.sidecarBaseUrl);
|
|
37
|
+
sidecarHttpClient_1.SidecarHttpClient.validateBaseUrl(resolvedUrl, this._settings.bypassLocalNetworkRestriction);
|
|
38
|
+
this._httpClient = new sidecarHttpClient_1.SidecarHttpClient(resolvedUrl, this._settings.requestTimeout, this._settings.retryCount);
|
|
39
|
+
logger.debug('SidecarAuthProvider initialized serviceName=%s blueprintServiceName=%s', this._settings.serviceName, this._settings.blueprintServiceName);
|
|
40
|
+
}
|
|
41
|
+
async getAccessToken(authConfigOrScope, scope) {
|
|
42
|
+
const actualScope = typeof authConfigOrScope === 'string' ? authConfigOrScope : scope;
|
|
43
|
+
const options = {
|
|
44
|
+
scopes: actualScope ? [actualScope] : this._settings.scopes,
|
|
45
|
+
requestAppToken: true
|
|
46
|
+
};
|
|
47
|
+
return this.getCachedToken(this._settings.serviceName, options);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Acquires the Blueprint (agent application) token from the sidecar.
|
|
51
|
+
* @param tenantId The tenant ID.
|
|
52
|
+
* @param agentAppInstanceId The agent instance ID (from the inbound activity); maps to `AgentIdentity`.
|
|
53
|
+
*/
|
|
54
|
+
async getAgenticApplicationToken(tenantId, agentAppInstanceId) {
|
|
55
|
+
this.ensureConnectionSettings();
|
|
56
|
+
const options = {
|
|
57
|
+
agentIdentity: agentAppInstanceId,
|
|
58
|
+
tenant: tenantId
|
|
59
|
+
};
|
|
60
|
+
return this.getCachedToken(this._settings.blueprintServiceName, options);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Acquires the autonomous agent (instance) token from the sidecar for the configured resource.
|
|
64
|
+
* @param tenantId The tenant ID.
|
|
65
|
+
* @param agentAppInstanceId The agent instance ID (from the inbound activity); maps to `AgentIdentity`.
|
|
66
|
+
*/
|
|
67
|
+
async getAgenticInstanceToken(tenantId, agentAppInstanceId) {
|
|
68
|
+
this.ensureConnectionSettings();
|
|
69
|
+
const options = {
|
|
70
|
+
agentIdentity: agentAppInstanceId,
|
|
71
|
+
requestAppToken: true,
|
|
72
|
+
tenant: tenantId,
|
|
73
|
+
scopes: this._settings.scopes
|
|
74
|
+
};
|
|
75
|
+
return this.getCachedToken(this._settings.serviceName, options);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Acquires the agentic user token from the sidecar for the configured resource.
|
|
79
|
+
* @param tenantId The tenant ID.
|
|
80
|
+
* @param agentAppInstanceId The agent instance ID (from the inbound activity); maps to `AgentIdentity`.
|
|
81
|
+
* @param upn The agentic user identifier. A GUID is sent as `AgentUserId`; otherwise as `AgentUsername`.
|
|
82
|
+
* @param scopes The OAuth scopes to request.
|
|
83
|
+
*/
|
|
84
|
+
async getAgenticUserToken(tenantId, agentAppInstanceId, upn, scopes) {
|
|
85
|
+
this.ensureConnectionSettings();
|
|
86
|
+
const isObjectId = GUID_REGEX.test(upn !== null && upn !== void 0 ? upn : '');
|
|
87
|
+
const options = {
|
|
88
|
+
agentIdentity: agentAppInstanceId,
|
|
89
|
+
agentUsername: isObjectId ? undefined : upn,
|
|
90
|
+
agentUserId: isObjectId ? upn : undefined,
|
|
91
|
+
tenant: tenantId,
|
|
92
|
+
scopes: scopes !== null && scopes !== void 0 ? scopes : this._settings.scopes
|
|
93
|
+
};
|
|
94
|
+
return this.getCachedToken(this._settings.serviceName, options);
|
|
95
|
+
}
|
|
96
|
+
async acquireTokenOnBehalfOf(_authConfigOrScopes, _scopesOrOboAssertion, _oboAssertion) {
|
|
97
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.OnBehalfOfNotSupportedBySidecar);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks sidecar availability via the `/healthz` endpoint.
|
|
101
|
+
* @returns `true` when the sidecar is reachable and healthy.
|
|
102
|
+
*/
|
|
103
|
+
async isHealthy() {
|
|
104
|
+
return this._httpClient.isHealthy();
|
|
105
|
+
}
|
|
106
|
+
ensureConnectionSettings() {
|
|
107
|
+
if (!this.connectionSettings) {
|
|
108
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.SidecarConnectionSettingsRequired);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async getCachedToken(serviceName, options) {
|
|
112
|
+
const forceRefresh = options.forceRefresh === true;
|
|
113
|
+
const cacheKey = SidecarAuthProvider.buildCacheKey(serviceName, options);
|
|
114
|
+
const cached = this.cacheGet(cacheKey, forceRefresh);
|
|
115
|
+
if (cached) {
|
|
116
|
+
return cached;
|
|
117
|
+
}
|
|
118
|
+
const result = await this._httpClient.getAuthorizationHeaderUnauthenticated(serviceName, options);
|
|
119
|
+
// The hosting stack always transmits the token as `Bearer {token}`. Reject any other scheme
|
|
120
|
+
// (e.g. PoP) rather than silently emitting an invalid Authorization header.
|
|
121
|
+
if (result.scheme && result.scheme.toLowerCase() !== 'bearer') {
|
|
122
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.SidecarUnsupportedAuthScheme, undefined, { scheme: result.scheme });
|
|
123
|
+
}
|
|
124
|
+
this.cacheSet(cacheKey, { token: result.token, expiresOn: (0, sidecarTokenExpiry_1.resolveTokenExpiry)(result.token) });
|
|
125
|
+
return result.token;
|
|
126
|
+
}
|
|
127
|
+
cacheGet(cacheKey, forceRefresh) {
|
|
128
|
+
const cached = this._tokenCache.get(cacheKey);
|
|
129
|
+
if (cached) {
|
|
130
|
+
if (!forceRefresh && cached.expiresOn >= Date.now() + EXPIRY_BUFFER_MS) {
|
|
131
|
+
return cached.token;
|
|
132
|
+
}
|
|
133
|
+
this._tokenCache.delete(cacheKey);
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
cacheSet(cacheKey, token) {
|
|
138
|
+
this._tokenCache.set(cacheKey, token);
|
|
139
|
+
if (this._tokenCache.size > MAX_CACHE_ENTRIES) {
|
|
140
|
+
this.pruneExpiredEntries();
|
|
141
|
+
if (this._tokenCache.size > MAX_CACHE_ENTRIES) {
|
|
142
|
+
this.evictNearestExpiry();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
pruneExpiredEntries() {
|
|
147
|
+
const now = Date.now();
|
|
148
|
+
for (const [key, value] of this._tokenCache) {
|
|
149
|
+
if (value.expiresOn <= now) {
|
|
150
|
+
this._tokenCache.delete(key);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
evictNearestExpiry() {
|
|
155
|
+
const overflow = this._tokenCache.size - MAX_CACHE_ENTRIES;
|
|
156
|
+
if (overflow <= 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const sorted = [...this._tokenCache.entries()].sort((a, b) => a[1].expiresOn - b[1].expiresOn);
|
|
160
|
+
for (let i = 0; i < overflow; i++) {
|
|
161
|
+
this._tokenCache.delete(sorted[i][0]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
static buildCacheKey(serviceName, options) {
|
|
165
|
+
var _a, _b, _c, _d;
|
|
166
|
+
const scopes = options.scopes
|
|
167
|
+
? [...new Set(options.scopes.filter((s) => s && s.trim()))].sort().join(' ')
|
|
168
|
+
: '';
|
|
169
|
+
return [
|
|
170
|
+
serviceName,
|
|
171
|
+
(_a = options.agentIdentity) !== null && _a !== void 0 ? _a : '',
|
|
172
|
+
(_b = options.agentUsername) !== null && _b !== void 0 ? _b : '',
|
|
173
|
+
(_c = options.agentUserId) !== null && _c !== void 0 ? _c : '',
|
|
174
|
+
(_d = options.tenant) !== null && _d !== void 0 ? _d : '',
|
|
175
|
+
options.requestAppToken === true ? 'app' : 'user',
|
|
176
|
+
scopes
|
|
177
|
+
].join('|');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.SidecarAuthProvider = SidecarAuthProvider;
|
|
181
|
+
//# sourceMappingURL=sidecarAuthProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecarAuthProvider.js","sourceRoot":"","sources":["../../../../src/auth/sidecar/sidecarAuthProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import type { ConnectionSettingsBase } from '../settings';
|
|
6
|
+
/**
|
|
7
|
+
* Connection settings for the Entra Agent ID sidecar (agent container) authentication provider, used when a
|
|
8
|
+
* connection's `authType` is `'EntraAuthSideCar'`.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Mirrors the .NET `Microsoft.Agents.Authentication.EntraAuthSidecar.Model.SidecarConnectionSettings`
|
|
12
|
+
* class, which likewise derives from `ConnectionSettingsBase`. These are the configuration-level
|
|
13
|
+
* properties; they are normalized (with defaults applied) before use by the sidecar token provider.
|
|
14
|
+
*/
|
|
15
|
+
export interface SidecarConnectionSettings extends ConnectionSettingsBase {
|
|
16
|
+
/**
|
|
17
|
+
* Optional base URL of the Entra Agent ID sidecar (agent container).
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Only used when `authType` is `'EntraAuthSideCar'`. Resolution order:
|
|
21
|
+
* `SIDECAR_URL` environment variable > this setting > `http://localhost:5178`.
|
|
22
|
+
* Regardless of how it is resolved, the host must be a loopback/private address
|
|
23
|
+
* unless `bypassLocalNetworkRestriction` is set.
|
|
24
|
+
*/
|
|
25
|
+
sidecarBaseUrl?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The configured downstream API service name in the sidecar's DownstreamApis configuration.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Only used when `authType` is `'EntraAuthSideCar'`. Defaults to `'default'`.
|
|
31
|
+
*/
|
|
32
|
+
serviceName?: string;
|
|
33
|
+
/**
|
|
34
|
+
* The sidecar downstream API name used to acquire the Blueprint (agent application) token for the
|
|
35
|
+
* agentic FIC chain.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Only used when `authType` is `'EntraAuthSideCar'`. Defaults to `'agenticblueprint'`. This
|
|
39
|
+
* downstream API must be configured app-only with the `api://AzureAdTokenExchange/.default` scope.
|
|
40
|
+
*/
|
|
41
|
+
blueprintServiceName?: string;
|
|
42
|
+
/**
|
|
43
|
+
* When `true`, disables the loopback/private-address safety check on the resolved sidecar base URL.
|
|
44
|
+
*
|
|
45
|
+
* @remarks
|
|
46
|
+
* UNSAFE. Leave this `false` in all normal deployments. Only enable it for a carefully validated
|
|
47
|
+
* private-network configuration where the sidecar is reachable at a non-private address that the
|
|
48
|
+
* operator explicitly trusts. Only used when `authType` is `'EntraAuthSideCar'`.
|
|
49
|
+
*/
|
|
50
|
+
bypassLocalNetworkRestriction?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* HTTP request timeout (in milliseconds) for sidecar calls.
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* Only used when `authType` is `'EntraAuthSideCar'`. Defaults to 30000 (30 seconds).
|
|
56
|
+
*/
|
|
57
|
+
requestTimeout?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Number of retry attempts for transient sidecar failures (5xx, 408, 429, network/timeout).
|
|
60
|
+
*
|
|
61
|
+
* @remarks
|
|
62
|
+
* Only used when `authType` is `'EntraAuthSideCar'`. Defaults to 3.
|
|
63
|
+
*/
|
|
64
|
+
retryCount?: number;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecarConnectionSettings.js","sourceRoot":"","sources":["../../../../src/auth/sidecar/sidecarConnectionSettings.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { SidecarRequestOptions, SidecarTokenResult } from './sidecarModels';
|
|
6
|
+
/**
|
|
7
|
+
* Reusable HTTP client for communicating with the Microsoft Entra Agent ID sidecar (agent container).
|
|
8
|
+
* Handles URL construction, query parameter building, response parsing, retry, and SSRF-safe base
|
|
9
|
+
* URL validation. Uses the native `fetch` API (Node.js 20+).
|
|
10
|
+
*/
|
|
11
|
+
export declare class SidecarHttpClient {
|
|
12
|
+
/** Default per-attempt request timeout (milliseconds). */
|
|
13
|
+
static readonly DEFAULT_TIMEOUT_MS = 30000;
|
|
14
|
+
/** Default number of retry attempts for transient failures. */
|
|
15
|
+
static readonly DEFAULT_RETRY_COUNT = 3;
|
|
16
|
+
private readonly _baseUrl;
|
|
17
|
+
private readonly _timeoutMs;
|
|
18
|
+
private readonly _retryCount;
|
|
19
|
+
private readonly _retryBackoffBaseMs;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new {@link SidecarHttpClient}.
|
|
22
|
+
* @param baseUrl The resolved (and validated) sidecar base URL.
|
|
23
|
+
* @param timeoutMs Per-attempt request timeout in milliseconds.
|
|
24
|
+
* @param retryCount Number of retry attempts for transient failures (0 disables retries).
|
|
25
|
+
* @param retryBackoffBaseMs Base delay for exponential backoff; primarily a test seam.
|
|
26
|
+
*/
|
|
27
|
+
constructor(baseUrl: string, timeoutMs?: number, retryCount?: number, retryBackoffBaseMs?: number);
|
|
28
|
+
/**
|
|
29
|
+
* Removes any trailing `/` characters from `value` using a linear scan. Avoids a regular
|
|
30
|
+
* expression so untrusted input with many `/` characters cannot trigger super-linear
|
|
31
|
+
* backtracking (ReDoS).
|
|
32
|
+
* @param value The string to trim.
|
|
33
|
+
* @returns `value` without trailing slashes.
|
|
34
|
+
*/
|
|
35
|
+
private static stripTrailingSlashes;
|
|
36
|
+
/**
|
|
37
|
+
* Resolves the sidecar base URL. Resolution order: `SIDECAR_URL` environment variable >
|
|
38
|
+
* `configuredUrl` > {@link DEFAULT_SIDECAR_BASE_URL}. Empty/whitespace values are treated as unset.
|
|
39
|
+
* @param configuredUrl The optional base URL from configuration.
|
|
40
|
+
* @returns The resolved base URL.
|
|
41
|
+
*/
|
|
42
|
+
static resolveBaseUrl(configuredUrl?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a copy of `raw` with any userinfo (credentials) removed, safe to include in logs and
|
|
45
|
+
* error messages. Falls back to a regex strip when `raw` is not a parseable URL.
|
|
46
|
+
*/
|
|
47
|
+
private static redactUrl;
|
|
48
|
+
/**
|
|
49
|
+
* Validates that the resolved sidecar base URL is safe to call. The URL must be a well-formed
|
|
50
|
+
* absolute http/https URL without userinfo. Unless `bypassLocalNetworkRestriction` is set, the host
|
|
51
|
+
* must also be a loopback address or a private network address (RFC 1918 / RFC 4193 / link-local) to
|
|
52
|
+
* avoid sending agent credentials off-box (SSRF safety).
|
|
53
|
+
* @param resolvedUrl The resolved sidecar base URL.
|
|
54
|
+
* @param bypassLocalNetworkRestriction Skip the loopback/private-address check (UNSAFE).
|
|
55
|
+
* @throws When the URL is malformed or points to a disallowed address.
|
|
56
|
+
*/
|
|
57
|
+
static validateBaseUrl(resolvedUrl: string, bypassLocalNetworkRestriction: boolean): void;
|
|
58
|
+
private static isLoopbackOrPrivateHost;
|
|
59
|
+
private static isPrivateOrLoopbackIPv4;
|
|
60
|
+
private static isPrivateOrLoopbackIPv6;
|
|
61
|
+
/**
|
|
62
|
+
* Extracts the embedded IPv4 address from an IPv4-mapped/-translated IPv6 literal, returning it
|
|
63
|
+
* in dotted-quad form, or `undefined` if `host` is not such an address. Handles both the dotted
|
|
64
|
+
* form (`::ffff:127.0.0.1`) and the hex-compressed form Node emits (`::ffff:7f00:1`).
|
|
65
|
+
*/
|
|
66
|
+
private static extractMappedIPv4;
|
|
67
|
+
/**
|
|
68
|
+
* Calls `GET /AuthorizationHeaderUnauthenticated/{serviceName}` with the specified options.
|
|
69
|
+
* @param serviceName The sidecar downstream API name.
|
|
70
|
+
* @param options The request options used to build the query string.
|
|
71
|
+
* @param signal Optional abort signal supplied by the caller.
|
|
72
|
+
* @returns The parsed token result.
|
|
73
|
+
*/
|
|
74
|
+
getAuthorizationHeaderUnauthenticated(serviceName: string, options?: SidecarRequestOptions, signal?: AbortSignal): Promise<SidecarTokenResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Checks sidecar health via `GET /healthz`.
|
|
77
|
+
* @returns `true` when the sidecar responds with a success status, `false` otherwise.
|
|
78
|
+
*/
|
|
79
|
+
isHealthy(): Promise<boolean>;
|
|
80
|
+
private buildUrl;
|
|
81
|
+
private withTimeout;
|
|
82
|
+
private fetchWithTimeout;
|
|
83
|
+
/**
|
|
84
|
+
* Performs the request and reads the full response body within a single timeout window, so a
|
|
85
|
+
* sidecar that streams response headers and then stalls the body cannot hang token acquisition
|
|
86
|
+
* beyond `requestTimeout`.
|
|
87
|
+
*/
|
|
88
|
+
private fetchAndReadText;
|
|
89
|
+
private sendAndParse;
|
|
90
|
+
private delayBeforeRetry;
|
|
91
|
+
private static isTransientStatus;
|
|
92
|
+
private static parseTokenResponse;
|
|
93
|
+
private static isKnownAuthScheme;
|
|
94
|
+
private static tryParseProblemDetails;
|
|
95
|
+
}
|