UNPKG

zephyr-agent

Version:
113 lines (112 loc) • 4.08 kB
import "node:module"; import { claimMatchesEnv, decodeJwtPayload, getEmail, getEmailClaims, getEmails, getStringClaim, stringifyId } from "./utils.mjs"; const GITLAB_JOB_FETCH_TIMEOUT_MS = 10000; const gitLabCiIdentityProvider = { provider: 'gitlab', detect: isGitLabCi, infer: inferGitLabIdentity }; function isGitLabCi(env) { return 'true' === env['GITLAB_CI'] || 'GitLab' === env['CI_SERVER_NAME']; } async function inferGitLabIdentity(env) { const payload = decodeJwtPayload(env['CI_JOB_TOKEN']); const jwtEmails = getEmailClaims(payload, [ 'user_email', 'email' ]); if (payload && jwtEmails.length > 0 && gitLabClaimsMatchEnvironment(payload, env)) return { provider: 'gitlab', email: jwtEmails[0], emails: jwtEmails, issuer: getGitLabIssuer(env), providerSubject: getStringClaim(payload, [ 'user_id', 'user_login', 'sub' ]), username: getStringClaim(payload, [ 'user_login', 'username' ]), source: 'jwt' }; const apiIdentity = await inferGitLabIdentityFromApi(env); if (apiIdentity) return apiIdentity; const envEmail = getEmail(env['GITLAB_USER_EMAIL']); if (envEmail) return { provider: 'gitlab', email: envEmail, emails: [ envEmail ], issuer: getGitLabIssuer(env), providerSubject: env['GITLAB_USER_ID']?.trim(), username: env['GITLAB_USER_LOGIN']?.trim() || void 0, source: 'env' }; } async function inferGitLabIdentityFromApi(env) { const apiUrl = getGitLabApiUrl(env); const jobToken = env['CI_JOB_TOKEN']?.trim(); if (!apiUrl || !jobToken) return; try { const job = await fetchGitLabJob(apiUrl, jobToken); if (!gitLabJobMatchesEnvironment(job, env)) return; const emails = getEmails([ job.user?.email, job.user?.public_email, job.commit?.author_email ]); if (0 === emails.length) return; return { provider: 'gitlab', email: emails[0], emails, issuer: getGitLabIssuer(env), providerSubject: stringifyId(job.user?.id) ?? env['GITLAB_USER_ID']?.trim(), username: job.user?.username?.trim() || void 0, source: 'api' }; } catch { return; } } function getGitLabIssuer(env) { const serverUrl = env['CI_SERVER_URL']?.trim(); if (serverUrl) return serverUrl.replace(/\/+$/, '').toLowerCase(); const apiUrl = env['CI_API_V4_URL']?.trim(); return apiUrl ? apiUrl.replace(/\/api\/v4\/?$/, '').replace(/\/+$/, '').toLowerCase() : void 0; } function getGitLabApiUrl(env) { const apiUrl = env['CI_API_V4_URL']?.trim(); if (apiUrl) return apiUrl; const serverUrl = env['CI_SERVER_URL']?.trim(); return serverUrl ? `${serverUrl.replace(/\/$/, '')}/api/v4` : void 0; } async function fetchGitLabJob(apiUrl, jobToken) { const url = new URL('job', apiUrl.endsWith('/') ? apiUrl : `${apiUrl}/`); const response = await fetch(url.toString(), { headers: { 'JOB-TOKEN': jobToken }, signal: AbortSignal.timeout(GITLAB_JOB_FETCH_TIMEOUT_MS) }); if (!response.ok) return {}; return await response.json(); } function gitLabClaimsMatchEnvironment(payload, env) { if (!payload) return false; return claimMatchesEnv(payload, 'job_id', env['CI_JOB_ID']) && claimMatchesEnv(payload, 'project_id', env['CI_PROJECT_ID']) && claimMatchesEnv(payload, 'pipeline_id', env['CI_PIPELINE_ID']); } function gitLabJobMatchesEnvironment(job, env) { return claimMatchesEnv({ job_id: job.id }, 'job_id', env['CI_JOB_ID']) && claimMatchesEnv({ project_id: job.pipeline?.project_id }, 'project_id', env['CI_PROJECT_ID']) && claimMatchesEnv({ pipeline_id: job.pipeline?.id }, 'pipeline_id', env['CI_PIPELINE_ID']); } export { gitLabCiIdentityProvider }; //# sourceMappingURL=gitlab.mjs.map