diff --git a/__tests__/proxy-integration.test.ts b/__tests__/proxy-integration.test.ts index 3c673ae..18b6e61 100644 --- a/__tests__/proxy-integration.test.ts +++ b/__tests__/proxy-integration.test.ts @@ -4,6 +4,9 @@ import {ImageService} from '../src/image-service' import {PROXY_IMAGE_NAME} from '../src/main' import {ProxyBuilder} from '../src/proxy' import {removeDanglingUpdaterContainers} from './helpers' +import {spawnSync} from 'child_process' +import fs from 'fs' +import path from 'path' describe('ProxyBuilder', () => { const docker = new Docker() @@ -46,6 +49,7 @@ describe('ProxyBuilder', () => { } const proxy = await builder.run(details, credentials) + await proxy.container.start() expect(proxy.networkName).toBe('job-1-network') expect(proxy.url).toMatch(/^http:\/\/1:.+job-1-proxy:1080$/) @@ -53,11 +57,51 @@ describe('ProxyBuilder', () => { const containerInfo = await proxy.container.inspect() expect(containerInfo.Name).toBe('/job-1-proxy') expect(containerInfo.HostConfig.NetworkMode).toBe('job-1-network') + expect(containerInfo.Config.Cmd).toEqual([ + 'sh', + '-c', + '/usr/sbin/update-ca-certificates && /update-job-proxy' + ]) const networkInfo = await proxy.network.inspect() expect(networkInfo.Name).toBe('job-1-network') expect(networkInfo.Internal).toBe(false) + // run a bash command that executes docker and returns contents of /config.json + const id = proxy.container.id + const proc = spawnSync('docker', ['exec', id, 'cat', '/config.json']) + const stdout = proc.stdout.toString() + const config = JSON.parse(stdout) + expect(config.all_credentials).toEqual(credentials) + await proxy.shutdown() }) + + it('copies in a custom root CA if configured', async () => { + if (process.env.SKIP_INTEGRATION_TESTS) { + return + } + + // make a tmp dir at the repo root unless it already exists + const tmpDir = path.join(__dirname, '../tmp') + if (!fs.existsSync(tmpDir)) { + fs.mkdirSync(tmpDir) + } + const certPath = path.join(__dirname, '../tmp/custom-cert.crt') + fs.writeFileSync(certPath, 'ca-pem-contents') + process.env.CUSTOM_CA_PATH = certPath + + const proxy = await builder.run(details, credentials) + await proxy.container.start() + + const id = proxy.container.id + const proc = spawnSync('docker', [ + 'exec', + id, + 'cat', + '/usr/local/share/ca-certificates/custom-ca-cert.crt' + ]) + const stdout = proc.stdout.toString() + expect(stdout).toEqual('ca-pem-contents') + }) }) diff --git a/src/proxy.ts b/src/proxy.ts index fe0a6bf..839eaa7 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1,3 +1,4 @@ +import fs from 'fs' import * as core from '@actions/core' import Docker, {Container, Network} from 'dockerode' import crypto from 'crypto' @@ -15,6 +16,8 @@ const KEY_SIZE = 2048 const KEY_EXPIRY_YEARS = 2 const CONFIG_FILE_PATH = '/' const CONFIG_FILE_NAME = 'config.json' +const CA_CERT_INPUT_PATH = '/usr/local/share/ca-certificates' +const CUSTOM_CA_CERT_NAME = 'custom-ca-cert.crt' const CERT_SUBJECT = [ { name: 'commonName', @@ -74,6 +77,18 @@ export class ProxyBuilder { config ) + if (process.env.CUSTOM_CA_PATH) { + const customCert = fs + .readFileSync(process.env.CUSTOM_CA_PATH, 'utf8') + .toString() + await ContainerService.storeCert( + CUSTOM_CA_CERT_NAME, + CA_CERT_INPUT_PATH, + container, + customCert + ) + } + const stream = await container.attach({ stream: true, stdout: true, @@ -85,7 +100,6 @@ export class ProxyBuilder { errStream(' proxy') ) - container.start() const url = `http://${config.proxy_auth.username}:${config.proxy_auth.password}@${name}:1080` return { container, @@ -161,6 +175,12 @@ export class ProxyBuilder { AttachStdout: true, AttachStderr: true, Env: [`JOB_ID=${jobID}`], + Cmd: [ + 'sh', + '-c', + '/usr/sbin/update-ca-certificates && /update-job-proxy' + ], + HostConfig: { NetworkMode: networkName } diff --git a/src/updater.ts b/src/updater.ts index 6bdaa78..924f3bc 100644 --- a/src/updater.ts +++ b/src/updater.ts @@ -38,6 +38,7 @@ export class Updater { this.details, this.credentials ) + proxy.container.start() try { const files = await this.runFileFetcher(proxy)