const config = {
namespace: "goauthentik/",
registryTokenEndpoint: "https://ghcr.io/token",
registryService: "ghcr.io",
};
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();
console.debug(`oci-proxy[token]: Status ${tokenRes.status}`);
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");
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",
);
statusCode: 401,
"www-authenticate": `Bearer realm="https://${event.headers.host}/v2?token",service="${event.headers.host}",scope="repository:user/image:pull"`,