UNPKG

snowflake-sdk

Version:
138 lines 5.87 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DETECTION_TIMEOUT_MS = void 0; exports.getDetectedPlatforms = getDetectedPlatforms; const node_http_1 = __importDefault(require("node:http")); const client_sts_1 = require("@aws-sdk/client-sts"); const AWS_METADATA_BASE_URL = 'http://169.254.169.254'; const AZURE_METADATA_BASE_URL = 'http://169.254.169.254'; const GCE_METADATA_ROOT_URL = 'http://metadata.google.internal'; const GCE_METADATA_BASE_URL = 'http://metadata.google.internal/computeMetadata/v1'; exports.DETECTION_TIMEOUT_MS = 200; const DETECTORS = { is_aws_lambda: isAwsLambda, is_azure_function: isAzureFunction, is_gce_cloud_run_service: isGceCloudRunService, is_gce_cloud_run_job: isGceCloudRunJob, is_github_action: isGithubAction, is_ec2_instance: isEc2Instance, has_aws_identity: hasAwsIdentity, is_azure_vm: isAzureVm, has_azure_managed_identity: hasAzureManagedIdentity, is_gce_vm: isGceVm, has_gcp_identity: hasGcpIdentity, }; const DETECTION_RESULT = detectPlatforms(); function getDetectedPlatforms() { return DETECTION_RESULT; } async function detectPlatforms() { if (process.env['SNOWFLAKE_DISABLE_PLATFORM_DETECTION']?.toLowerCase() === 'true') { return ['disabled']; } const abortSignal = AbortSignal.timeout(exports.DETECTION_TIMEOUT_MS); const results = await Promise.all(Object.entries(DETECTORS).map(async ([name, detector]) => ({ name, detected: await Promise.resolve(detector(abortSignal)).catch(() => false), }))); return results.filter(({ detected }) => detected).map(({ name }) => name); } function isAwsLambda() { return envPresent('LAMBDA_TASK_ROOT'); } function isAzureFunction() { return envPresent('FUNCTIONS_WORKER_RUNTIME', 'FUNCTIONS_EXTENSION_VERSION', 'AzureWebJobsStorage'); } function isGceCloudRunService() { return envPresent('K_SERVICE', 'K_REVISION', 'K_CONFIGURATION'); } function isGceCloudRunJob() { return envPresent('CLOUD_RUN_JOB', 'CLOUD_RUN_EXECUTION'); } function isGithubAction() { return envPresent('GITHUB_ACTIONS'); } // Intentionally not using the available AWS SDK, as it does not support abort signals and is easy to // misconfigure retry logic. async function isEc2Instance(abortSignal) { const tokenResult = await httpRequest(`${AWS_METADATA_BASE_URL}/latest/api/token`, abortSignal, { 'X-aws-ec2-metadata-token-ttl-seconds': '21600' }, 'PUT').catch(() => null); const token = tokenResult?.ok ? tokenResult.body.trim() : null; const result = await httpRequest(`${AWS_METADATA_BASE_URL}/latest/dynamic/instance-identity/document`, abortSignal, token ? { 'X-aws-ec2-metadata-token': token } : undefined); if (!result.ok) return false; const doc = JSON.parse(result.body); return !!doc.instanceId; } async function hasAwsIdentity(abortSignal) { const client = new client_sts_1.STSClient({}); const response = await client.send(new client_sts_1.GetCallerIdentityCommand({}), { abortSignal, }); if (!response.Arn) return false; return isValidArnForWif(response.Arn); } async function isAzureVm(abortSignal) { const result = await httpRequest(`${AZURE_METADATA_BASE_URL}/metadata/instance?api-version=2021-02-01`, abortSignal, { Metadata: 'true' }); return result.ok; } async function hasAzureManagedIdentity(abortSignal) { if (isAzureFunction() && envPresent('IDENTITY_HEADER')) { return true; } const params = new URLSearchParams({ 'api-version': '2018-02-01', resource: 'https://management.azure.com', }); const result = await httpRequest(`${AZURE_METADATA_BASE_URL}/metadata/identity/oauth2/token?${params}`, abortSignal, { Metadata: 'true' }); return result.ok; } async function isGceVm(abortSignal) { const result = await httpRequest(GCE_METADATA_ROOT_URL, abortSignal); return result.headers['metadata-flavor'] === 'Google'; } async function hasGcpIdentity(abortSignal) { const result = await httpRequest(`${GCE_METADATA_BASE_URL}/instance/service-accounts/default/email`, abortSignal, { 'Metadata-Flavor': 'Google' }); return result.ok; } function envPresent(...envVars) { return envVars.every((v) => { const val = process.env[v]; return val !== undefined && val !== ''; }); } function httpRequest(url, signal, headers, method = 'GET') { const isBun = typeof process !== 'undefined' && !!process.versions?.bun; return isBun ? httpRequestFetch(url, signal, headers, method) : httpRequestNode(url, signal, headers, method); } async function httpRequestFetch(url, signal, headers, method) { const res = await fetch(url, { method, headers, signal }); const body = await res.text(); const resHeaders = {}; res.headers.forEach((value, key) => { resHeaders[key] = value; }); return { ok: res.ok, headers: resHeaders, body }; } function httpRequestNode(url, signal, headers, method) { return new Promise((resolve, reject) => { const req = node_http_1.default.request(url, { method, signal, headers }, (res) => { let body = ''; const statusCode = res.statusCode ?? 0; res.on('data', (chunk) => (body += chunk)); res.on('end', () => resolve({ ok: statusCode >= 200 && statusCode < 300, headers: res.headers, body })); res.on('error', reject); }); req.on('error', reject); req.end(); }); } function isValidArnForWif(arn) { return [/^arn:[^:]+:iam::[^:]+:user\/.+$/, /^arn:[^:]+:sts::[^:]+:assumed-role\/.+$/].some((pattern) => pattern.test(arn)); } //# sourceMappingURL=platform_detection.js.map