2021-10-12 08:58:02 +00:00
|
|
|
const config = {
|
|
|
|
namespace: "goauthentik/",
|
|
|
|
// Settings for GHCR
|
|
|
|
registryTokenEndpoint: "https://ghcr.io/token",
|
|
|
|
registryService: "ghcr.io",
|
|
|
|
// Settings for Harbor
|
|
|
|
// registryTokenEndpoint: "https://docker.beryju.org/service/token",
|
|
|
|
// registryService: "harbor-registry",
|
|
|
|
};
|
|
|
|
|
|
|
|
async function getToken(event) {
|
|
|
|
const fetch = await import('node-fetch');
|
|
|
|
const querystring = await import('querystring');
|
|
|
|
let scope = event.queryStringParameters["scope"];
|
|
|
|
let tokenParams = {
|
|
|
|
service: config.registryService,
|
|
|
|
};
|
|
|
|
delete event.headers.host;
|
|
|
|
let forwardHeaders = event.headers;
|
|
|
|
if (scope && scope.includes(":")) {
|
|
|
|
const repo = scope.split(":")[1];
|
|
|
|
console.debug(`oci-proxy[token]: original scope: ${scope}`);
|
|
|
|
scope = `repository:${config.namespace}${repo}:pull`;
|
|
|
|
console.debug(`oci-proxy[token]: rewritten scope: ${scope}`);
|
|
|
|
tokenParams["scope"] = scope;
|
|
|
|
// We only need to forward headers for authentication requests
|
|
|
|
forwardHeaders = {};
|
|
|
|
} else {
|
|
|
|
console.debug(`oci-proxy[token]: no scope`);
|
|
|
|
// For non-scoped requests, we need to forward some URL parameters
|
|
|
|
["account", "client_id", "offline_token", "token"].forEach(param => {
|
|
|
|
tokenParams[param] = event.queryStringParameters[param]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
const tokenUrl = `${config.registryTokenEndpoint}?${querystring.stringify(tokenParams)}`
|
|
|
|
console.debug(`oci-proxy[token]: final URL to fetch: ${tokenUrl}`)
|
|
|
|
const tokenRes = await fetch.default(tokenUrl, {
|
|
|
|
headers: forwardHeaders,
|
|
|
|
});
|
|
|
|
const tokenResult = await tokenRes.text();
|
2021-10-12 09:01:32 +00:00
|
|
|
console.debug(`oci-proxy[token]: Status ${tokenRes.status}`);
|
2021-10-12 08:58:02 +00:00
|
|
|
return {
|
|
|
|
statusCode: tokenRes.status,
|
|
|
|
body: tokenResult,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.handler = async function (event, context) {
|
|
|
|
console.debug(`oci-proxy: URL ${event.httpMethod} ${event.rawUrl}`);
|
|
|
|
if (event.queryStringParameters.hasOwnProperty("token")) {
|
|
|
|
console.debug("oci-proxy: handler=token proxy");
|
|
|
|
return await getToken(event);
|
|
|
|
}
|
|
|
|
if (event.headers.authorization && event.headers.authorization.startsWith("Bearer ")) {
|
|
|
|
console.debug("oci-proxy: authenticated root handler, returning 200");
|
|
|
|
return {
|
|
|
|
statusCode: 200,
|
|
|
|
headers: {
|
|
|
|
"Docker-Distribution-API-Version": "registry/2.0",
|
|
|
|
"content-type": "application/json",
|
|
|
|
},
|
|
|
|
body: JSON.stringify({}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
console.debug("oci-proxy: root handler, returning 401 with www-authenticate");
|
|
|
|
return {
|
|
|
|
statusCode: 401,
|
|
|
|
headers: {
|
|
|
|
"www-authenticate": `Bearer realm="https://${event.headers.host}/v2?token",service="${event.headers.host}",scope="repository:user/image:pull"`,
|
|
|
|
"Docker-Distribution-API-Version": "registry/2.0",
|
|
|
|
"content-type": "application/json",
|
|
|
|
},
|
|
|
|
body: JSON.stringify({}),
|
|
|
|
};
|
|
|
|
}
|