root: migrate docker images to netlify proxy (#1603)

* migrate to netlify proxy

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* relative forward to func

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* custom logic for go paths

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* fix const

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* missing break

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* add default for new repos

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens L 2021-10-12 10:58:02 +02:00 committed by GitHub
parent db79244ba4
commit 5753182e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 3 deletions

View File

@ -1,11 +1,18 @@
[[redirects]] [[redirects]]
from = "/v2/" from = "/*"
to = "https://ghcr.registry.beryju.org/v2/" to = "/.netlify/functions/go-get"
status = 200
force = true
query = {go-get = "1"}
[[redirects]]
from = "/v2"
to = "/.netlify/functions/oci-proxy"
status = 200 status = 200
force = true force = true
[[redirects]] [[redirects]]
from = "/v2/*" from = "/v2/*"
to = "https://ghcr.registry.beryju.org/v2/goauthentik/:splat" to = "https://ghcr.io/v2/goauthentik/:splat"
status = 200 status = 200
force = true force = true

View File

@ -0,0 +1,23 @@
const gitHubNamespace = "goauthentik.io";
exports.handler = async function (event, context) {
let repo = "";
switch (event.path) {
case "/":
repo = "/authentik.git";
break;
case "/api":
repo = "/client-go.git";
break;
default:
repo = `${event.path}.git`;
break;
}
return {
statusCode: 200,
headers: {
"content-type": "text/html",
},
body: `<meta name="go-import" content="${event.headers.host}${event.path} git https://github.com/${gitHubNamespace}${repo}">`
};
}

View File

@ -0,0 +1,75 @@
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();
console.debug(`oci-proxy[token]: Status ${tokenRes.status} body '${tokenResult}'`)
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({}),
};
}