zephyr-agent
Version:
Zephyr plugin agent
213 lines (212 loc) • 11.4 kB
JavaScript
;
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, getters, values)=>{
var define = (defs, kind)=>{
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
[kind]: defs[key]
});
};
define(getters, "get");
define(values, "value");
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
cleanTokens: ()=>cleanTokens,
getToken: ()=>getToken,
removeToken: ()=>removeToken,
saveToken: ()=>saveToken
});
const external_node_crypto_namespaceObject = require("node:crypto");
const external_secret_token_js_namespaceObject = require("./secret-token.js");
const external_storage_js_namespaceObject = require("./storage.js");
const external_storage_keys_js_namespaceObject = require("./storage-keys.js");
const external_storage_lock_js_namespaceObject = require("./storage-lock.js");
const http_request_js_namespaceObject = require("../http/http-request.js");
const external_ci_token_js_namespaceObject = require("./ci-token.js");
const external_server_token_js_namespaceObject = require("./server-token.js");
const external_zephyr_edge_contract_namespaceObject = require("zephyr-edge-contract");
const external_user_email_js_namespaceObject = require("./user-email.js");
const debug_js_namespaceObject = require("../logging/debug.js");
const external_ci_token_identity_js_namespaceObject = require("./ci-token-identity.js");
const index_js_namespaceObject = require("../errors/index.js");
const auth_flags_js_namespaceObject = require("../auth/auth-flags.js");
const token_expiry_js_namespaceObject = require("../auth/token-expiry.js");
const CI_TOKEN_CACHE_VERSION = 1;
const CI_TOKEN_SCOPE_CONTEXT = 'zephyr-ci-token-cache\0';
const activeCiTokenCacheKeys = new Set();
const TOKEN_LOCK = {
whenUnavailable: 'proceed'
};
async function saveToken(token) {
await (0, external_storage_lock_js_namespaceObject.withStorageLock)('auth-token', ()=>(0, external_storage_js_namespaceObject.setPrivateItem)(external_storage_keys_js_namespaceObject.StorageKeys.ze_auth_token, token), TOKEN_LOCK);
}
async function getToken(git_config) {
const tokenFromEnv = (0, external_secret_token_js_namespaceObject.getSecretToken)();
const server_token = (0, external_server_token_js_namespaceObject.getServerToken)();
const ci_token = (0, external_ci_token_js_namespaceObject.getCiToken)();
if (tokenFromEnv) return tokenFromEnv;
if (ci_token) {
const ciIdentity = await (0, external_ci_token_identity_js_namespaceObject.inferCiTokenIdentity)();
if (ciIdentity) {
debug_js_namespaceObject.ze_log.auth(`Using ${ciIdentity.provider} ${ciIdentity.source} identity for CI token attribution`);
return await getTokenFromCiToken(ci_token, ciIdentity);
}
throwCiTokenAuthError(void 0, `${external_storage_keys_js_namespaceObject.StorageKeys.ze_ci_token} was provided, but no supported CI identity was detected.`);
}
if (server_token && git_config) return await getTokenFromServerToken(server_token, git_config.git.email);
const token = await (0, external_storage_lock_js_namespaceObject.withStorageLock)('auth-token', async ()=>{
await external_storage_js_namespaceObject.storage;
return (0, external_storage_js_namespaceObject.getItem)(external_storage_keys_js_namespaceObject.StorageKeys.ze_auth_token);
}, TOKEN_LOCK);
if (token) return token;
if (server_token) return void debug_js_namespaceObject.ze_log.error('No git config provided, skipping server token check');
}
async function removeToken(expectedToken) {
await (0, external_storage_lock_js_namespaceObject.withStorageLock)('auth-token', async ()=>{
await external_storage_js_namespaceObject.storage;
const storedToken = await (0, external_storage_js_namespaceObject.getItem)(external_storage_keys_js_namespaceObject.StorageKeys.ze_auth_token);
if (void 0 === expectedToken || storedToken === expectedToken) await (0, external_storage_js_namespaceObject.removeItem)(external_storage_keys_js_namespaceObject.StorageKeys.ze_auth_token);
}, TOKEN_LOCK);
}
async function cleanTokens(rejectedToken) {
await removeToken(rejectedToken);
const cacheKeys = Array.from(activeCiTokenCacheKeys);
await Promise.all(cacheKeys.map((cacheKey)=>(0, external_storage_lock_js_namespaceObject.withStorageLock)(getCiTokenLockName(cacheKey), async ()=>{
await external_storage_js_namespaceObject.storage;
const cached = await (0, external_storage_js_namespaceObject.getItem)(cacheKey);
if (void 0 === rejectedToken || isStoredCiAccessToken(cached) && cached.accessToken === rejectedToken) await (0, external_storage_js_namespaceObject.removeItem)(cacheKey);
}, TOKEN_LOCK)));
}
async function getTokenFromServerToken(server_token, git_email) {
const email = (0, external_user_email_js_namespaceObject.getUserEmail)() ?? git_email;
const [ok, cause, data] = await (0, http_request_js_namespaceObject.makeRequest)({
path: external_zephyr_edge_contract_namespaceObject.ze_api_gateway.get_access_token_by_server_token,
base: (0, external_zephyr_edge_contract_namespaceObject.ZE_API_ENDPOINT)(),
query: {
email
}
}, {
headers: {
Authorization: `Bearer ${server_token}`
},
credentialToken: server_token
});
if (!ok) {
if (cause instanceof Error) debug_js_namespaceObject.ze_log.error('Failed to get token from server token:', cause.message);
else debug_js_namespaceObject.ze_log.error('Failed to get token from server token:', cause);
return;
}
await saveToken(data?.access_token ?? '');
return data?.access_token;
}
async function getTokenFromCiToken(ci_token, identity) {
const scope = getCiTokenScope(ci_token, identity);
const cacheKey = `${external_storage_keys_js_namespaceObject.StorageKeys.ze_ci_auth_token}:${scope}`;
activeCiTokenCacheKeys.add(cacheKey);
return (0, external_storage_lock_js_namespaceObject.withStorageLock)(getCiTokenLockName(cacheKey), async ()=>{
await external_storage_js_namespaceObject.storage;
const cached = await (0, external_storage_js_namespaceObject.getItem)(cacheKey);
if (isReusableCiAccessToken(cached, scope)) return cached.accessToken;
const [ok, cause, data] = await (0, http_request_js_namespaceObject.makeRequest)({
path: external_zephyr_edge_contract_namespaceObject.ze_api_gateway.ci_token_exchange,
base: (0, external_zephyr_edge_contract_namespaceObject.ZE_API_ENDPOINT)(),
query: {}
}, {
method: 'POST',
headers: {
Authorization: `Bearer ${ci_token}`,
'Content-Type': 'application/json'
},
credentialToken: ci_token,
skipTokenCleanup: true
}, JSON.stringify(identity));
if (!ok) {
await (0, external_storage_js_namespaceObject.removeItem)(cacheKey);
throwCiTokenAuthError(identity, cause);
}
const accessToken = data?.access_token;
if (!accessToken || !(0, token_expiry_js_namespaceObject.isTokenStillValid)(accessToken, auth_flags_js_namespaceObject.TOKEN_EXPIRY.SHORT_VALIDITY_CHECK_SEC)) {
await (0, external_storage_js_namespaceObject.removeItem)(cacheKey);
throwCiTokenAuthError(identity, new Error('CI token exchange returned an invalid or expiring access token'));
}
const expiresAtMs = (0, token_expiry_js_namespaceObject.getTokenExpirationMs)(accessToken) ?? Date.now();
await (0, external_storage_js_namespaceObject.setPrivateItem)(cacheKey, {
version: CI_TOKEN_CACHE_VERSION,
scope,
accessToken
}, {
ttl: expiresAtMs - Date.now()
});
return accessToken;
}, TOKEN_LOCK);
}
function getCiTokenScope(ciToken, identity) {
const identityScope = [
(0, external_zephyr_edge_contract_namespaceObject.ZE_API_ENDPOINT)(),
identity.provider,
identity.source,
identity.issuer ?? '',
identity.providerSubject ?? '',
identity.username ?? '',
identity.providerActorType ?? '',
identity.email ?? '',
[
...identity.emails ?? []
].sort()
];
return (0, external_node_crypto_namespaceObject.createHash)('sha256').update(CI_TOKEN_SCOPE_CONTEXT).update(ciToken).update('\0').update(JSON.stringify(identityScope)).digest('hex');
}
function getCiTokenLockName(cacheKey) {
return `ci-auth-${cacheKey.substring(cacheKey.lastIndexOf(':') + 1)}`;
}
function isReusableCiAccessToken(value, scope) {
return isStoredCiAccessToken(value) && value.scope === scope && (0, token_expiry_js_namespaceObject.isTokenStillValid)(value.accessToken, auth_flags_js_namespaceObject.TOKEN_EXPIRY.SHORT_VALIDITY_CHECK_SEC);
}
function isStoredCiAccessToken(value) {
return Boolean(value && 'object' == typeof value && value.version === CI_TOKEN_CACHE_VERSION && 'string' == typeof value.scope && 'string' == typeof value.accessToken);
}
function throwCiTokenAuthError(identity, cause) {
const details = cause instanceof Error ? cause.message : String(cause);
debug_js_namespaceObject.ze_log.error('Failed to get token from CI token:', details);
throw new index_js_namespaceObject.ZephyrError(index_js_namespaceObject.ZeErrors.ERR_CI_TOKEN_AUTH, {
cause,
provider: identity?.provider ?? 'unknown',
username: identity?.username ?? 'unknown',
source: identity?.source ?? 'unknown',
issuer: identity?.issuer ?? 'unknown',
actorType: identity?.providerActorType ?? 'unknown',
resolution: identity?.providerActorType === 'bot' ? 'This bot is authorized by the CI token creator. Check that the token creator is still an active member of the Zephyr organization.' : "Link this CI actor's Git provider account in Zephyr Cloud, then rerun the workflow. Zephyr uses linked Git provider identities to map provider-native CI actor data, such as GitHub actor IDs or GitLab user IDs/emails, to a Zephyr user.",
details
});
}
exports.cleanTokens = __webpack_exports__.cleanTokens;
exports.getToken = __webpack_exports__.getToken;
exports.removeToken = __webpack_exports__.removeToken;
exports.saveToken = __webpack_exports__.saveToken;
for(var __rspack_i in __webpack_exports__)if (-1 === [
"cleanTokens",
"getToken",
"removeToken",
"saveToken"
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
Object.defineProperty(exports, '__esModule', {
value: true
});
//# sourceMappingURL=token.js.map