qa360 1.4.5 → 2.0.1
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/README.md +1 -1
- package/dist/commands/ai.d.ts +41 -0
- package/dist/commands/ai.js +499 -0
- package/dist/commands/ask.js +12 -12
- package/dist/commands/coverage.d.ts +8 -0
- package/dist/commands/coverage.js +252 -0
- package/dist/commands/explain.d.ts +27 -0
- package/dist/commands/explain.js +630 -0
- package/dist/commands/flakiness.d.ts +73 -0
- package/dist/commands/flakiness.js +435 -0
- package/dist/commands/generate.d.ts +66 -0
- package/dist/commands/generate.js +438 -0
- package/dist/commands/init.d.ts +56 -9
- package/dist/commands/init.js +217 -10
- package/dist/commands/monitor.d.ts +27 -0
- package/dist/commands/monitor.js +225 -0
- package/dist/commands/ollama.d.ts +40 -0
- package/dist/commands/ollama.js +301 -0
- package/dist/commands/pack.d.ts +37 -9
- package/dist/commands/pack.js +240 -141
- package/dist/commands/regression.d.ts +8 -0
- package/dist/commands/regression.js +340 -0
- package/dist/commands/repair.d.ts +26 -0
- package/dist/commands/repair.js +307 -0
- package/dist/commands/retry.d.ts +43 -0
- package/dist/commands/retry.js +275 -0
- package/dist/commands/run.d.ts +8 -3
- package/dist/commands/run.js +45 -31
- package/dist/commands/slo.d.ts +8 -0
- package/dist/commands/slo.js +327 -0
- package/dist/core/adapters/playwright-native-api.d.ts +183 -0
- package/dist/core/adapters/playwright-native-api.js +461 -0
- package/dist/core/adapters/playwright-ui.d.ts +7 -0
- package/dist/core/adapters/playwright-ui.js +29 -1
- package/dist/core/ai/anthropic-provider.d.ts +50 -0
- package/dist/core/ai/anthropic-provider.js +211 -0
- package/dist/core/ai/deepseek-provider.d.ts +81 -0
- package/dist/core/ai/deepseek-provider.js +254 -0
- package/dist/core/ai/index.d.ts +60 -0
- package/dist/core/ai/index.js +18 -0
- package/dist/core/ai/llm-client.d.ts +45 -0
- package/dist/core/ai/llm-client.js +7 -0
- package/dist/core/ai/mock-provider.d.ts +49 -0
- package/dist/core/ai/mock-provider.js +121 -0
- package/dist/core/ai/ollama-provider.d.ts +78 -0
- package/dist/core/ai/ollama-provider.js +192 -0
- package/dist/core/ai/openai-provider.d.ts +48 -0
- package/dist/core/ai/openai-provider.js +188 -0
- package/dist/core/ai/provider-factory.d.ts +160 -0
- package/dist/core/ai/provider-factory.js +269 -0
- package/dist/core/auth/api-key-provider.d.ts +16 -0
- package/dist/core/auth/api-key-provider.js +63 -0
- package/dist/core/auth/aws-iam-provider.d.ts +35 -0
- package/dist/core/auth/aws-iam-provider.js +177 -0
- package/dist/core/auth/azure-ad-provider.d.ts +15 -0
- package/dist/core/auth/azure-ad-provider.js +99 -0
- package/dist/core/auth/basic-auth-provider.d.ts +26 -0
- package/dist/core/auth/basic-auth-provider.js +111 -0
- package/dist/core/auth/gcp-adc-provider.d.ts +27 -0
- package/dist/core/auth/gcp-adc-provider.js +126 -0
- package/dist/core/auth/index.d.ts +238 -0
- package/dist/core/auth/index.js +82 -0
- package/dist/core/auth/jwt-provider.d.ts +19 -0
- package/dist/core/auth/jwt-provider.js +160 -0
- package/dist/core/auth/manager.d.ts +84 -0
- package/dist/core/auth/manager.js +230 -0
- package/dist/core/auth/oauth2-provider.d.ts +17 -0
- package/dist/core/auth/oauth2-provider.js +114 -0
- package/dist/core/auth/totp-provider.d.ts +31 -0
- package/dist/core/auth/totp-provider.js +134 -0
- package/dist/core/auth/ui-login-provider.d.ts +26 -0
- package/dist/core/auth/ui-login-provider.js +198 -0
- package/dist/core/cache/index.d.ts +7 -0
- package/dist/core/cache/index.js +6 -0
- package/dist/core/cache/lru-cache.d.ts +203 -0
- package/dist/core/cache/lru-cache.js +397 -0
- package/dist/core/coverage/analyzer.d.ts +101 -0
- package/dist/core/coverage/analyzer.js +415 -0
- package/dist/core/coverage/collector.d.ts +74 -0
- package/dist/core/coverage/collector.js +459 -0
- package/dist/core/coverage/config.d.ts +37 -0
- package/dist/core/coverage/config.js +156 -0
- package/dist/core/coverage/index.d.ts +11 -0
- package/dist/core/coverage/index.js +15 -0
- package/dist/core/coverage/types.d.ts +267 -0
- package/dist/core/coverage/types.js +6 -0
- package/dist/core/coverage/vault.d.ts +95 -0
- package/dist/core/coverage/vault.js +405 -0
- package/dist/core/dashboard/assets.d.ts +6 -0
- package/dist/core/dashboard/assets.js +690 -0
- package/dist/core/dashboard/index.d.ts +6 -0
- package/dist/core/dashboard/index.js +5 -0
- package/dist/core/dashboard/server.d.ts +72 -0
- package/dist/core/dashboard/server.js +354 -0
- package/dist/core/dashboard/types.d.ts +70 -0
- package/dist/core/dashboard/types.js +5 -0
- package/dist/core/discoverer/index.d.ts +115 -0
- package/dist/core/discoverer/index.js +250 -0
- package/dist/core/flakiness/index.d.ts +228 -0
- package/dist/core/flakiness/index.js +384 -0
- package/dist/core/generation/code-formatter.d.ts +111 -0
- package/dist/core/generation/code-formatter.js +307 -0
- package/dist/core/generation/code-generator.d.ts +144 -0
- package/dist/core/generation/code-generator.js +293 -0
- package/dist/core/generation/generator.d.ts +40 -0
- package/dist/core/generation/generator.js +76 -0
- package/dist/core/generation/index.d.ts +30 -0
- package/dist/core/generation/index.js +28 -0
- package/dist/core/generation/pack-generator.d.ts +107 -0
- package/dist/core/generation/pack-generator.js +416 -0
- package/dist/core/generation/prompt-builder.d.ts +132 -0
- package/dist/core/generation/prompt-builder.js +672 -0
- package/dist/core/generation/source-analyzer.d.ts +213 -0
- package/dist/core/generation/source-analyzer.js +657 -0
- package/dist/core/generation/test-optimizer.d.ts +117 -0
- package/dist/core/generation/test-optimizer.js +328 -0
- package/dist/core/generation/types.d.ts +214 -0
- package/dist/core/generation/types.js +4 -0
- package/dist/core/index.d.ts +23 -1
- package/dist/core/index.js +39 -0
- package/dist/core/pack/validator.js +31 -1
- package/dist/core/pack-v2/index.d.ts +9 -0
- package/dist/core/pack-v2/index.js +8 -0
- package/dist/core/pack-v2/loader.d.ts +62 -0
- package/dist/core/pack-v2/loader.js +231 -0
- package/dist/core/pack-v2/migrator.d.ts +56 -0
- package/dist/core/pack-v2/migrator.js +455 -0
- package/dist/core/pack-v2/validator.d.ts +61 -0
- package/dist/core/pack-v2/validator.js +577 -0
- package/dist/core/regression/detector.d.ts +107 -0
- package/dist/core/regression/detector.js +497 -0
- package/dist/core/regression/index.d.ts +9 -0
- package/dist/core/regression/index.js +11 -0
- package/dist/core/regression/trend-analyzer.d.ts +102 -0
- package/dist/core/regression/trend-analyzer.js +345 -0
- package/dist/core/regression/types.d.ts +222 -0
- package/dist/core/regression/types.js +7 -0
- package/dist/core/regression/vault.d.ts +87 -0
- package/dist/core/regression/vault.js +289 -0
- package/dist/core/repair/engine/fixer.d.ts +24 -0
- package/dist/core/repair/engine/fixer.js +226 -0
- package/dist/core/repair/engine/suggestion-engine.d.ts +18 -0
- package/dist/core/repair/engine/suggestion-engine.js +187 -0
- package/dist/core/repair/index.d.ts +10 -0
- package/dist/core/repair/index.js +13 -0
- package/dist/core/repair/repairer.d.ts +90 -0
- package/dist/core/repair/repairer.js +284 -0
- package/dist/core/repair/types.d.ts +91 -0
- package/dist/core/repair/types.js +6 -0
- package/dist/core/repair/utils/error-analyzer.d.ts +28 -0
- package/dist/core/repair/utils/error-analyzer.js +264 -0
- package/dist/core/retry/flakiness-integration.d.ts +60 -0
- package/dist/core/retry/flakiness-integration.js +228 -0
- package/dist/core/retry/index.d.ts +14 -0
- package/dist/core/retry/index.js +16 -0
- package/dist/core/retry/retry-engine.d.ts +80 -0
- package/dist/core/retry/retry-engine.js +296 -0
- package/dist/core/retry/types.d.ts +178 -0
- package/dist/core/retry/types.js +52 -0
- package/dist/core/retry/vault.d.ts +77 -0
- package/dist/core/retry/vault.js +304 -0
- package/dist/core/runner/e2e-helpers.d.ts +102 -0
- package/dist/core/runner/e2e-helpers.js +153 -0
- package/dist/core/runner/phase3-runner.d.ts +101 -2
- package/dist/core/runner/phase3-runner.js +559 -24
- package/dist/core/self-healing/assertion-healer.d.ts +97 -0
- package/dist/core/self-healing/assertion-healer.js +371 -0
- package/dist/core/self-healing/engine.d.ts +122 -0
- package/dist/core/self-healing/engine.js +538 -0
- package/dist/core/self-healing/index.d.ts +10 -0
- package/dist/core/self-healing/index.js +11 -0
- package/dist/core/self-healing/selector-healer.d.ts +103 -0
- package/dist/core/self-healing/selector-healer.js +372 -0
- package/dist/core/self-healing/types.d.ts +152 -0
- package/dist/core/self-healing/types.js +6 -0
- package/dist/core/slo/config.d.ts +107 -0
- package/dist/core/slo/config.js +360 -0
- package/dist/core/slo/index.d.ts +11 -0
- package/dist/core/slo/index.js +15 -0
- package/dist/core/slo/sli-calculator.d.ts +92 -0
- package/dist/core/slo/sli-calculator.js +364 -0
- package/dist/core/slo/slo-tracker.d.ts +148 -0
- package/dist/core/slo/slo-tracker.js +379 -0
- package/dist/core/slo/types.d.ts +281 -0
- package/dist/core/slo/types.js +7 -0
- package/dist/core/slo/vault.d.ts +102 -0
- package/dist/core/slo/vault.js +427 -0
- package/dist/core/tui/index.d.ts +7 -0
- package/dist/core/tui/index.js +6 -0
- package/dist/core/tui/monitor.d.ts +92 -0
- package/dist/core/tui/monitor.js +271 -0
- package/dist/core/tui/renderer.d.ts +33 -0
- package/dist/core/tui/renderer.js +218 -0
- package/dist/core/tui/types.d.ts +63 -0
- package/dist/core/tui/types.js +5 -0
- package/dist/core/types/pack-v2.d.ts +425 -0
- package/dist/core/types/pack-v2.js +8 -0
- package/dist/core/vault/index.d.ts +116 -0
- package/dist/core/vault/index.js +400 -5
- package/dist/core/watch/index.d.ts +7 -0
- package/dist/core/watch/index.js +6 -0
- package/dist/core/watch/watch-mode.d.ts +213 -0
- package/dist/core/watch/watch-mode.js +389 -0
- package/dist/index.js +68 -68
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +136 -0
- package/package.json +5 -1
- package/dist/core/adapters/playwright-api.d.ts +0 -82
- package/dist/core/adapters/playwright-api.js +0 -264
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS IAM Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles AWS authentication using IAM credentials.
|
|
5
|
+
* Supports credential chains, environment variables, and profiles.
|
|
6
|
+
*/
|
|
7
|
+
import { authCache, createCacheKey } from './index.js';
|
|
8
|
+
export class AWSIamProvider {
|
|
9
|
+
type = 'aws_iam';
|
|
10
|
+
async authenticate(config) {
|
|
11
|
+
const cacheKey = this.getCacheKey(config);
|
|
12
|
+
// Check cache first
|
|
13
|
+
if (config.cache?.enabled !== false) {
|
|
14
|
+
const cached = authCache.get(cacheKey);
|
|
15
|
+
if (cached) {
|
|
16
|
+
return { success: true, credentials: cached };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Get AWS credentials
|
|
20
|
+
const awsCreds = await this.getCredentials(config);
|
|
21
|
+
if (!awsCreds) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
error: 'Failed to obtain AWS credentials. Ensure you have configured AWS credentials via environment variables, ~/.aws/credentials, or IAM role.'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Sign request to get session token if using temporary credentials
|
|
28
|
+
const credentials = {
|
|
29
|
+
type: 'aws_iam',
|
|
30
|
+
headers: {
|
|
31
|
+
'X-Amz-Security-Token': awsCreds.session_token || '',
|
|
32
|
+
'X-Amz-Date': this.getAmzDate()
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
// Add basic auth header for some AWS services
|
|
36
|
+
if (awsCreds.access_key_id && awsCreds.secret_access_key) {
|
|
37
|
+
credentials.headers['X-Amz-Credential'] = `${awsCreds.access_key_id}`;
|
|
38
|
+
}
|
|
39
|
+
// Cache credentials (AWS temp tokens expire in 1 hour typically)
|
|
40
|
+
if (config.cache?.enabled !== false) {
|
|
41
|
+
const ttl = config.cache?.ttl || 3600;
|
|
42
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
credentials,
|
|
47
|
+
expiresAt: awsCreds.expiration || Date.now() + 3600 * 1000
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async refresh(config) {
|
|
51
|
+
authCache.clear(this.getCacheKey(config));
|
|
52
|
+
return this.authenticate(config);
|
|
53
|
+
}
|
|
54
|
+
clear(config) {
|
|
55
|
+
const key = this.getCacheKey(config);
|
|
56
|
+
authCache.clear(key);
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
}
|
|
59
|
+
async validate(config) {
|
|
60
|
+
const key = this.getCacheKey(config);
|
|
61
|
+
return authCache.has(key);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get AWS credentials from various sources
|
|
65
|
+
*/
|
|
66
|
+
async getCredentials(config) {
|
|
67
|
+
// Method 1: Direct credentials from config
|
|
68
|
+
if (config.access_key_id && config.secret_access_key) {
|
|
69
|
+
return {
|
|
70
|
+
access_key_id: config.access_key_id,
|
|
71
|
+
secret_access_key: config.secret_access_key,
|
|
72
|
+
session_token: config.session_token
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Method 2: Environment variables
|
|
76
|
+
const envCreds = this.getFromEnv();
|
|
77
|
+
if (envCreds)
|
|
78
|
+
return envCreds;
|
|
79
|
+
// Method 3: AWS profile
|
|
80
|
+
if (config.profile) {
|
|
81
|
+
const profileCreds = await this.getFromProfile(config.profile);
|
|
82
|
+
if (profileCreds)
|
|
83
|
+
return profileCreds;
|
|
84
|
+
}
|
|
85
|
+
// Method 4: Try AWS SDK if available
|
|
86
|
+
const sdkCreds = await this.getFromSDK(config);
|
|
87
|
+
if (sdkCreds)
|
|
88
|
+
return sdkCreds;
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get credentials from environment variables
|
|
93
|
+
*/
|
|
94
|
+
getFromEnv() {
|
|
95
|
+
const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
96
|
+
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
97
|
+
const sessionToken = process.env.AWS_SESSION_TOKEN;
|
|
98
|
+
if (accessKeyId && secretAccessKey) {
|
|
99
|
+
return {
|
|
100
|
+
access_key_id: accessKeyId,
|
|
101
|
+
secret_access_key: secretAccessKey,
|
|
102
|
+
session_token: sessionToken
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get credentials from AWS profile file
|
|
109
|
+
*/
|
|
110
|
+
async getFromProfile(profile) {
|
|
111
|
+
try {
|
|
112
|
+
const fs = require('node:fs');
|
|
113
|
+
const path = require('node:path');
|
|
114
|
+
const { execSync } = require('node:child_process');
|
|
115
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
116
|
+
const credentialsPath = path.join(homeDir, '.aws', 'credentials');
|
|
117
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
// Use AWS CLI to get credentials for profile
|
|
121
|
+
const creds = execSync(`aws configure export --profile ${profile}`, {
|
|
122
|
+
encoding: 'utf-8',
|
|
123
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
124
|
+
});
|
|
125
|
+
// Parse the export output
|
|
126
|
+
const accessKeyMatch = creds.match(/AWS_ACCESS_KEY_ID="([^"]+)"/);
|
|
127
|
+
const secretKeyMatch = creds.match(/AWS_SECRET_ACCESS_KEY="([^"]+)"/);
|
|
128
|
+
const sessionMatch = creds.match(/AWS_SESSION_TOKEN="([^"]+)"/);
|
|
129
|
+
if (accessKeyMatch && secretKeyMatch) {
|
|
130
|
+
return {
|
|
131
|
+
access_key_id: accessKeyMatch[1],
|
|
132
|
+
secret_access_key: secretKeyMatch[1],
|
|
133
|
+
session_token: sessionMatch?.[1]
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get credentials from AWS SDK v3
|
|
144
|
+
*/
|
|
145
|
+
async getFromSDK(config) {
|
|
146
|
+
try {
|
|
147
|
+
// Try to import AWS SDK
|
|
148
|
+
// @ts-ignore - AWS SDK is optional dependency
|
|
149
|
+
const { defaultProvider } = await import('@aws-sdk/credential-providers');
|
|
150
|
+
const provider = defaultProvider({
|
|
151
|
+
profile: config.profile
|
|
152
|
+
});
|
|
153
|
+
const creds = await provider();
|
|
154
|
+
return {
|
|
155
|
+
access_key_id: creds.accessKeyId,
|
|
156
|
+
secret_access_key: creds.secretAccessKey,
|
|
157
|
+
session_token: creds.sessionToken,
|
|
158
|
+
expiration: creds.expiration?.getTime()
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// AWS SDK not available or error
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get AMZ date format for AWS signing
|
|
168
|
+
*/
|
|
169
|
+
getAmzDate() {
|
|
170
|
+
const now = new Date();
|
|
171
|
+
return now.toISOString().replace(/[:\-]|\.\d{3}/g, '');
|
|
172
|
+
}
|
|
173
|
+
getCacheKey(config) {
|
|
174
|
+
const identifier = config.profile || config.region || 'default';
|
|
175
|
+
return createCacheKey('aws_iam', identifier);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure AD Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles Azure Active Directory authentication.
|
|
5
|
+
* Supports OAuth2 client credentials flow with Azure AD.
|
|
6
|
+
*/
|
|
7
|
+
import { AuthProvider, AuthResult, AzureADConfig } from './index.js';
|
|
8
|
+
export declare class AzureADProvider implements AuthProvider<AzureADConfig> {
|
|
9
|
+
readonly type: "azure_ad";
|
|
10
|
+
authenticate(config: AzureADConfig): Promise<AuthResult>;
|
|
11
|
+
refresh(config: AzureADConfig): Promise<AuthResult>;
|
|
12
|
+
clear(config: AzureADConfig): Promise<void>;
|
|
13
|
+
validate(config: AzureADConfig): Promise<boolean>;
|
|
14
|
+
private getCacheKey;
|
|
15
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure AD Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles Azure Active Directory authentication.
|
|
5
|
+
* Supports OAuth2 client credentials flow with Azure AD.
|
|
6
|
+
*/
|
|
7
|
+
import { authCache, createCacheKey } from './index.js';
|
|
8
|
+
export class AzureADProvider {
|
|
9
|
+
type = 'azure_ad';
|
|
10
|
+
async authenticate(config) {
|
|
11
|
+
const { tenant_id, client_id, client_secret, scope = 'https://management.azure.com/.default' } = config;
|
|
12
|
+
if (!tenant_id || !client_id) {
|
|
13
|
+
return {
|
|
14
|
+
success: false,
|
|
15
|
+
error: 'Azure AD requires tenant_id and client_id'
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const cacheKey = this.getCacheKey(config);
|
|
19
|
+
// Check cache first
|
|
20
|
+
if (config.cache?.enabled !== false) {
|
|
21
|
+
const cached = authCache.get(cacheKey);
|
|
22
|
+
if (cached) {
|
|
23
|
+
return { success: true, credentials: cached };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Default token endpoint for Azure AD
|
|
27
|
+
const tokenEndpoint = config.token_endpoint ||
|
|
28
|
+
`https://login.microsoftonline.com/${tenant_id}/oauth2/v2.0/token`;
|
|
29
|
+
try {
|
|
30
|
+
const body = new URLSearchParams({
|
|
31
|
+
grant_type: 'client_credentials',
|
|
32
|
+
client_id,
|
|
33
|
+
client_secret: client_secret || '',
|
|
34
|
+
scope
|
|
35
|
+
});
|
|
36
|
+
const response = await fetch(tokenEndpoint, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
40
|
+
},
|
|
41
|
+
body: body.toString()
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
const error = await response.text().catch(() => 'Unknown error');
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
error: `Azure AD token request failed: ${response.status} ${error}`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
const token = data.access_token;
|
|
52
|
+
if (!token) {
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
error: 'No access_token in Azure AD response'
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const credentials = {
|
|
59
|
+
type: 'azure_ad',
|
|
60
|
+
headers: {
|
|
61
|
+
'Authorization': `Bearer ${token}`
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
// Cache with calculated expiration
|
|
65
|
+
if (config.cache?.enabled !== false) {
|
|
66
|
+
const expiresIn = data.expires_in || 3600;
|
|
67
|
+
const ttl = config.cache?.ttl || expiresIn;
|
|
68
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
success: true,
|
|
72
|
+
credentials,
|
|
73
|
+
expiresAt: data.expires_in ? Date.now() + data.expires_in * 1000 : undefined
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
error: `Azure AD authentication failed: ${error.message}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async refresh(config) {
|
|
84
|
+
authCache.clear(this.getCacheKey(config));
|
|
85
|
+
return this.authenticate(config);
|
|
86
|
+
}
|
|
87
|
+
clear(config) {
|
|
88
|
+
const key = this.getCacheKey(config);
|
|
89
|
+
authCache.clear(key);
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
async validate(config) {
|
|
93
|
+
const key = this.getCacheKey(config);
|
|
94
|
+
return authCache.has(key);
|
|
95
|
+
}
|
|
96
|
+
getCacheKey(config) {
|
|
97
|
+
return createCacheKey('azure_ad', config.client_id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bearer Token and Basic Authentication Providers
|
|
3
|
+
*
|
|
4
|
+
* Handles generic bearer token and HTTP Basic Authentication.
|
|
5
|
+
*/
|
|
6
|
+
import { AuthProvider, AuthResult, BearerAuthConfig, BasicAuthConfig } from './index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Bearer Token Authentication Provider
|
|
9
|
+
*/
|
|
10
|
+
export declare class BearerProvider implements AuthProvider<BearerAuthConfig> {
|
|
11
|
+
readonly type: "bearer";
|
|
12
|
+
authenticate(config: BearerAuthConfig): Promise<AuthResult>;
|
|
13
|
+
clear(config: BearerAuthConfig): Promise<void>;
|
|
14
|
+
validate(config: BearerAuthConfig): Promise<boolean>;
|
|
15
|
+
private getCacheKey;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Basic Authentication Provider
|
|
19
|
+
*/
|
|
20
|
+
export declare class BasicAuthProvider implements AuthProvider<BasicAuthConfig> {
|
|
21
|
+
readonly type: "basic";
|
|
22
|
+
authenticate(config: BasicAuthConfig): Promise<AuthResult>;
|
|
23
|
+
clear(config: BasicAuthConfig): Promise<void>;
|
|
24
|
+
validate(config: BasicAuthConfig): Promise<boolean>;
|
|
25
|
+
private getCacheKey;
|
|
26
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bearer Token and Basic Authentication Providers
|
|
3
|
+
*
|
|
4
|
+
* Handles generic bearer token and HTTP Basic Authentication.
|
|
5
|
+
*/
|
|
6
|
+
import { parseToken, encodeBasicAuth, authCache, createCacheKey } from './index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Bearer Token Authentication Provider
|
|
9
|
+
*/
|
|
10
|
+
export class BearerProvider {
|
|
11
|
+
type = 'bearer';
|
|
12
|
+
async authenticate(config) {
|
|
13
|
+
const { token, cache } = config;
|
|
14
|
+
const cacheKey = this.getCacheKey(config);
|
|
15
|
+
// Check cache first
|
|
16
|
+
if (cache?.enabled !== false) {
|
|
17
|
+
const cached = authCache.get(cacheKey);
|
|
18
|
+
if (cached) {
|
|
19
|
+
return { success: true, credentials: cached };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const cleanToken = parseToken(token);
|
|
23
|
+
const credentials = {
|
|
24
|
+
type: 'bearer',
|
|
25
|
+
headers: {
|
|
26
|
+
'Authorization': `Bearer ${cleanToken}`
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
// Cache if enabled
|
|
30
|
+
if (cache?.enabled !== false) {
|
|
31
|
+
const ttl = cache?.ttl || 3600;
|
|
32
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
credentials
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async clear(config) {
|
|
40
|
+
const key = this.getCacheKey(config);
|
|
41
|
+
authCache.clear(key);
|
|
42
|
+
}
|
|
43
|
+
async validate(config) {
|
|
44
|
+
const cacheKey = this.getCacheKey(config);
|
|
45
|
+
// Check cache first, then validate token
|
|
46
|
+
if (authCache.has(cacheKey)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return !!config.token && config.token.length > 0;
|
|
50
|
+
}
|
|
51
|
+
getCacheKey(config) {
|
|
52
|
+
// Use token hash as identifier
|
|
53
|
+
const crypto = require('node:crypto');
|
|
54
|
+
const hash = crypto.createHash('sha256').update(config.token || '').digest('hex').substring(0, 16);
|
|
55
|
+
return createCacheKey('bearer', hash);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Basic Authentication Provider
|
|
60
|
+
*/
|
|
61
|
+
export class BasicAuthProvider {
|
|
62
|
+
type = 'basic';
|
|
63
|
+
async authenticate(config) {
|
|
64
|
+
const { username, password, cache } = config;
|
|
65
|
+
if (!username || !password) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'Username and password are required for Basic auth'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const cacheKey = this.getCacheKey(config);
|
|
72
|
+
// Check cache first
|
|
73
|
+
if (cache?.enabled !== false) {
|
|
74
|
+
const cached = authCache.get(cacheKey);
|
|
75
|
+
if (cached) {
|
|
76
|
+
return { success: true, credentials: cached };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const credentials = {
|
|
80
|
+
type: 'basic',
|
|
81
|
+
headers: {
|
|
82
|
+
'Authorization': encodeBasicAuth(username, password)
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
// Cache if enabled
|
|
86
|
+
if (cache?.enabled !== false) {
|
|
87
|
+
const ttl = cache?.ttl || 3600;
|
|
88
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
success: true,
|
|
92
|
+
credentials
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async clear(config) {
|
|
96
|
+
const key = this.getCacheKey(config);
|
|
97
|
+
authCache.clear(key);
|
|
98
|
+
}
|
|
99
|
+
async validate(config) {
|
|
100
|
+
const cacheKey = this.getCacheKey(config);
|
|
101
|
+
// Check cache first, then validate credentials
|
|
102
|
+
if (authCache.has(cacheKey)) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return !!config.username && !!config.password;
|
|
106
|
+
}
|
|
107
|
+
getCacheKey(config) {
|
|
108
|
+
// Use username as identifier
|
|
109
|
+
return createCacheKey('basic', config.username || 'default');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP Application Default Credentials Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles GCP authentication using Application Default Credentials.
|
|
5
|
+
* Supports service account credentials and ADC resolution.
|
|
6
|
+
*/
|
|
7
|
+
import { AuthProvider, AuthResult, GCPADCConfig } from './index.js';
|
|
8
|
+
export declare class GCPADCProvider implements AuthProvider<GCPADCConfig> {
|
|
9
|
+
readonly type: "gcp_adc";
|
|
10
|
+
authenticate(config: GCPADCConfig): Promise<AuthResult>;
|
|
11
|
+
refresh(config: GCPADCConfig): Promise<AuthResult>;
|
|
12
|
+
clear(config: GCPADCConfig): Promise<void>;
|
|
13
|
+
validate(config: GCPADCConfig): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Get GCP access token from various sources
|
|
16
|
+
*/
|
|
17
|
+
private getAccessToken;
|
|
18
|
+
/**
|
|
19
|
+
* Get token from gcloud CLI
|
|
20
|
+
*/
|
|
21
|
+
private getTokenFromGcloud;
|
|
22
|
+
/**
|
|
23
|
+
* Get token from GCP metadata server
|
|
24
|
+
*/
|
|
25
|
+
private getTokenFromMetadataServer;
|
|
26
|
+
private getCacheKey;
|
|
27
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP Application Default Credentials Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles GCP authentication using Application Default Credentials.
|
|
5
|
+
* Supports service account credentials and ADC resolution.
|
|
6
|
+
*/
|
|
7
|
+
import { authCache, createCacheKey } from './index.js';
|
|
8
|
+
export class GCPADCProvider {
|
|
9
|
+
type = 'gcp_adc';
|
|
10
|
+
async authenticate(config) {
|
|
11
|
+
const cacheKey = this.getCacheKey(config);
|
|
12
|
+
// Check cache first
|
|
13
|
+
if (config.cache?.enabled !== false) {
|
|
14
|
+
const cached = authCache.get(cacheKey);
|
|
15
|
+
if (cached) {
|
|
16
|
+
return { success: true, credentials: cached };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Try to get GCP access token
|
|
20
|
+
try {
|
|
21
|
+
const token = await this.getAccessToken(config);
|
|
22
|
+
if (!token) {
|
|
23
|
+
return {
|
|
24
|
+
success: false,
|
|
25
|
+
error: 'Failed to obtain GCP access token. Ensure you are authenticated with gcloud auth application-default login or have a service account key.'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const credentials = {
|
|
29
|
+
type: 'gcp_adc',
|
|
30
|
+
headers: {
|
|
31
|
+
'Authorization': `Bearer ${token}`
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// GCP tokens typically expire in 1 hour
|
|
35
|
+
if (config.cache?.enabled !== false) {
|
|
36
|
+
const ttl = config.cache?.ttl || 3600;
|
|
37
|
+
authCache.set(cacheKey, credentials, ttl);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
credentials,
|
|
42
|
+
expiresAt: Date.now() + 3600 * 1000
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
success: false,
|
|
48
|
+
error: `GCP ADC authentication failed: ${error.message}`
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async refresh(config) {
|
|
53
|
+
// Clear cache and re-authenticate
|
|
54
|
+
authCache.clear(this.getCacheKey(config));
|
|
55
|
+
return this.authenticate(config);
|
|
56
|
+
}
|
|
57
|
+
clear(config) {
|
|
58
|
+
const key = this.getCacheKey(config);
|
|
59
|
+
authCache.clear(key);
|
|
60
|
+
return Promise.resolve();
|
|
61
|
+
}
|
|
62
|
+
async validate(config) {
|
|
63
|
+
const key = this.getCacheKey(config);
|
|
64
|
+
return authCache.has(key);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get GCP access token from various sources
|
|
68
|
+
*/
|
|
69
|
+
async getAccessToken(config) {
|
|
70
|
+
// Method 1: Try environment variable (GOOGLE_TOKEN)
|
|
71
|
+
if (process.env.GOOGLE_TOKEN) {
|
|
72
|
+
return process.env.GOOGLE_TOKEN;
|
|
73
|
+
}
|
|
74
|
+
// Method 2: Try gcloud auth print-access-token
|
|
75
|
+
const token = await this.getTokenFromGcloud();
|
|
76
|
+
if (token)
|
|
77
|
+
return token;
|
|
78
|
+
// Method 3: Try metadata server (for GCE/GKE)
|
|
79
|
+
const metadataToken = await this.getTokenFromMetadataServer();
|
|
80
|
+
if (metadataToken)
|
|
81
|
+
return metadataToken;
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get token from gcloud CLI
|
|
86
|
+
*/
|
|
87
|
+
async getTokenFromGcloud() {
|
|
88
|
+
try {
|
|
89
|
+
const { execSync } = require('node:child_process');
|
|
90
|
+
const token = execSync('gcloud auth print-access-token', {
|
|
91
|
+
encoding: 'utf-8',
|
|
92
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
93
|
+
}).trim();
|
|
94
|
+
return token || null;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get token from GCP metadata server
|
|
102
|
+
*/
|
|
103
|
+
async getTokenFromMetadataServer() {
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch('http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token', {
|
|
106
|
+
headers: {
|
|
107
|
+
'Metadata-Flavor': 'Google'
|
|
108
|
+
},
|
|
109
|
+
// Timeout for metadata server
|
|
110
|
+
signal: AbortSignal.timeout(2000)
|
|
111
|
+
});
|
|
112
|
+
if (!response.ok) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const data = await response.json();
|
|
116
|
+
return data.access_token;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
getCacheKey(config) {
|
|
123
|
+
const identifier = config.project_id || 'default';
|
|
124
|
+
return createCacheKey('gcp_adc', identifier);
|
|
125
|
+
}
|
|
126
|
+
}
|