-
Notifications
You must be signed in to change notification settings - Fork 380
Registries Proxy: Support feeding a base64 encoded configuration #2404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
dc92ab6
3b3012e
e4afb79
f736881
1bd7fdc
5b34615
7baf392
0b84d89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
|
||
import * as actionsUtil from "./actions-util"; | ||
import * as util from "./util"; | ||
import { getActionsLogger, Logger } from "./logging"; | ||
|
||
const UPDATEJOB_PROXY = "update-job-proxy"; | ||
const UPDATEJOB_PROXY_VERSION = "v2.0.20240722180912"; | ||
|
@@ -89,46 +90,41 @@ | |
} | ||
|
||
async function runWrapper() { | ||
const logger = getActionsLogger(); | ||
|
||
// Setup logging for the proxy | ||
const tempDir = actionsUtil.getTemporaryDirectory(); | ||
const logFilePath = path.resolve(tempDir, "proxy.log"); | ||
const input = actionsUtil.getOptionalInput("registry_secrets") || "[]"; | ||
const credentials = JSON.parse(input) as Credential[]; | ||
const proxyLogFilePath = path.resolve(tempDir, "proxy.log"); | ||
core.saveState("proxy-log-file", proxyLogFilePath); | ||
|
||
// Get the configuration options | ||
const credentials = getCredentials(); | ||
logger.debug(`Credentials loaded for the following URLs:\n ${credentials.map(c => c.host).join("\n")}`) | ||
|
||
|
||
const ca = generateCertificateAuthority(); | ||
const proxy_password = actionsUtil.getOptionalInput("proxy_password"); | ||
core.saveState("proxy-log-file", logFilePath); | ||
const proxyAuth = getProxyAuth(); | ||
|
||
let proxy_auth: BasicAuthCredentials | undefined = undefined; | ||
if (proxy_password) { | ||
proxy_auth = { | ||
username: PROXY_USER, | ||
password: proxy_password, | ||
}; | ||
} | ||
const proxyConfig: ProxyConfig = { | ||
all_credentials: credentials, | ||
ca, | ||
proxy_auth, | ||
proxy_auth: proxyAuth, | ||
}; | ||
|
||
// Start the Proxy | ||
const proxyBin = await getProxyBinaryPath(); | ||
await startProxy(proxyBin, proxyConfig, proxyLogFilePath, logger); | ||
} | ||
|
||
async function startProxy(binPath: string, config: ProxyConfig, logFilePath: string, logger: Logger) { | ||
const host = "127.0.0.1"; | ||
let proxyBin = toolcache.find(UPDATEJOB_PROXY, UPDATEJOB_PROXY_VERSION); | ||
if (!proxyBin) { | ||
const temp = await toolcache.downloadTool(UPDATEJOB_PROXY_URL); | ||
const extracted = await toolcache.extractTar(temp); | ||
proxyBin = await toolcache.cacheDir( | ||
extracted, | ||
UPDATEJOB_PROXY, | ||
UPDATEJOB_PROXY_VERSION, | ||
); | ||
} | ||
proxyBin = path.join(proxyBin, UPDATEJOB_PROXY); | ||
let port = 49152; | ||
try { | ||
let subprocess: ChildProcess | undefined = undefined; | ||
let tries = 5; | ||
let subprocessError: Error | undefined = undefined; | ||
while (tries-- > 0 && !subprocess && !subprocessError) { | ||
subprocess = spawn( | ||
proxyBin, | ||
binPath, | ||
["-addr", `${host}:${port}`, "-config", "-", "-logfile", logFilePath], | ||
{ | ||
detached: true, | ||
|
@@ -149,23 +145,65 @@ | |
subprocess = undefined; | ||
} | ||
}); | ||
subprocess.stdin?.write(JSON.stringify(proxyConfig)); | ||
subprocess.stdin?.write(JSON.stringify(config)); | ||
subprocess.stdin?.end(); | ||
// Wait a little to allow the proxy to start | ||
await util.delay(1000); | ||
} | ||
if (subprocessError) { | ||
throw subprocessError; | ||
} | ||
core.info(`Proxy started on ${host}:${port}`); | ||
logger.info(`Proxy started on ${host}:${port}`); | ||
core.setOutput("proxy_host", host); | ||
core.setOutput("proxy_port", port.toString()); | ||
core.setOutput("proxy_ca_certificate", ca.cert); | ||
core.setOutput("proxy_ca_certificate", config.ca.cert); | ||
} catch (error) { | ||
core.setFailed( | ||
`start-proxy action failed: ${util.wrapError(error).message}`, | ||
); | ||
} | ||
} | ||
|
||
// getCredentials returns registry credentials from action inputs. | ||
// It prefers `registries_credentials` over `registry_secrets`. | ||
// If neither is set, it returns an empty array. | ||
function getCredentials(): Credential[] { | ||
const encodedCredentials = actionsUtil.getOptionalInput("registries_credentials"); | ||
if (encodedCredentials !== undefined) { | ||
const credentialsStr = Buffer.from(encodedCredentials, "base64").toString(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like some extra hoops to go through for the workflow file to send base64 encoded credentials. Does it make more sense to accept non-encoded credentials and only base64 encode them in the action? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, there are some extra steps, but I think they are justified. The proxy takes a JSON object as previously defined in
Therefore, we encode it as a single string to make scrubbing possible. The underlying reason we need a struct is that (due to the integration with default setup) we need to provide a potentially arbitrary number of credentials, and we cannot easily know which ones/how many beforehand. |
||
return JSON.parse(credentialsStr) as Credential[]; | ||
} | ||
core.info(`Using structured credentials.`); | ||
const registrySecrets = actionsUtil.getOptionalInput("registry_secrets") || "[]"; | ||
return JSON.parse(registrySecrets) as Credential[]; | ||
} | ||
|
||
// getProxyAuth returns the authentication information for the proxy itself. | ||
function getProxyAuth(): BasicAuthCredentials | undefined{ | ||
const proxy_password = actionsUtil.getOptionalInput("proxy_password"); | ||
if (proxy_password) { | ||
return { | ||
username: PROXY_USER, | ||
password: proxy_password, | ||
}; | ||
} | ||
return ; | ||
} | ||
|
||
|
||
async function getProxyBinaryPath(): Promise<string> { | ||
let proxyBin = toolcache.find(UPDATEJOB_PROXY, UPDATEJOB_PROXY_VERSION); | ||
if (!proxyBin) { | ||
const temp = await toolcache.downloadTool(UPDATEJOB_PROXY_URL); | ||
const extracted = await toolcache.extractTar(temp); | ||
proxyBin = await toolcache.cacheDir( | ||
extracted, | ||
UPDATEJOB_PROXY, | ||
UPDATEJOB_PROXY_VERSION, | ||
); | ||
} | ||
proxyBin = path.join(proxyBin, UPDATEJOB_PROXY); | ||
return proxyBin; | ||
} | ||
|
||
void runWrapper(); |
Uh oh!
There was an error while loading. Please reload this page.