commit
f0ad70c1de
@ -0,0 +1,88 @@
|
||||
import {describe, expect, jest, test, beforeEach} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as auth from '../src/auth';
|
||||
|
||||
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-jest')).split(path.sep).join(path.posix.sep);
|
||||
const dockerConfigHome = path.join(tmpdir, '.docker');
|
||||
const credsdir = path.join(dockerConfigHome, 'buildx', 'creds');
|
||||
|
||||
describe('setCredentials', () => {
|
||||
beforeEach(() => {
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith(auth.envPrefix)) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
'mycontext',
|
||||
'docker-container',
|
||||
{},
|
||||
[],
|
||||
[]
|
||||
],
|
||||
[
|
||||
'docker-container://mycontainer',
|
||||
'docker-container',
|
||||
{},
|
||||
[],
|
||||
[]
|
||||
],
|
||||
[
|
||||
'tcp://graviton2:1234',
|
||||
'remote',
|
||||
{},
|
||||
[],
|
||||
[]
|
||||
],
|
||||
[
|
||||
'tcp://graviton2:1234',
|
||||
'remote',
|
||||
{
|
||||
'BUILDER_NODE_0_AUTH_TLS_CACERT': 'foo',
|
||||
'BUILDER_NODE_0_AUTH_TLS_CERT': 'foo',
|
||||
'BUILDER_NODE_0_AUTH_TLS_KEY': 'foo'
|
||||
},
|
||||
[
|
||||
path.join(credsdir, 'cacert_graviton2-1234.pem'),
|
||||
path.join(credsdir, 'cert_graviton2-1234.pem'),
|
||||
path.join(credsdir, 'key_graviton2-1234.pem')
|
||||
],
|
||||
[
|
||||
`cacert=${path.join(credsdir, 'cacert_graviton2-1234.pem')}`,
|
||||
`cert=${path.join(credsdir, 'cert_graviton2-1234.pem')}`,
|
||||
`key=${path.join(credsdir, 'key_graviton2-1234.pem')}`
|
||||
]
|
||||
],
|
||||
[
|
||||
'tcp://graviton2:1234',
|
||||
'docker-container',
|
||||
{
|
||||
'BUILDER_NODE_0_AUTH_TLS_CACERT': 'foo',
|
||||
'BUILDER_NODE_0_AUTH_TLS_CERT': 'foo',
|
||||
'BUILDER_NODE_0_AUTH_TLS_KEY': 'foo'
|
||||
},
|
||||
[
|
||||
path.join(credsdir, 'cacert_graviton2-1234.pem'),
|
||||
path.join(credsdir, 'cert_graviton2-1234.pem'),
|
||||
path.join(credsdir, 'key_graviton2-1234.pem')
|
||||
],
|
||||
[]
|
||||
],
|
||||
])('given %p endpoint', async (endpoint: string, driver: string, envs: Record<string, string>, expectedFiles: Array<string>, expectedOpts: Array<string>) => {
|
||||
fs.mkdirSync(credsdir, {recursive: true});
|
||||
for (const [key, value] of Object.entries(envs)) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
expect(auth.setCredentials(credsdir, 0, driver, endpoint)).toEqual(expectedOpts);
|
||||
expectedFiles.forEach( (file) => {
|
||||
expect(fs.existsSync(file)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,69 @@
|
||||
# Authentication support
|
||||
|
||||
## SSH authentication
|
||||
|
||||
To be able to connect to an SSH endpoint using the [`docker-container` driver](https://docs.docker.com/build/building/drivers/docker-container/),
|
||||
you have to set up the SSH private key and configuration on the GitHub Runner:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Set up SSH
|
||||
uses: MrSquaare/ssh-setup-action@523473d91581ccbf89565e12b40faba93f2708bd # v1.1.0
|
||||
with:
|
||||
host: graviton2
|
||||
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
private-key-name: aws_graviton2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
endpoint: ssh://me@graviton2
|
||||
```
|
||||
|
||||
## TLS authentication
|
||||
|
||||
You can also [set up a remote BuildKit instance](https://docs.docker.com/build/building/drivers/remote/#remote-buildkit-in-docker-container)
|
||||
using the remote driver. To ease the integration in your workflow, we put in
|
||||
place environment variables that will set up authentication using the BuildKit
|
||||
client certificates for the `tcp://` endpoint where `<idx>` is the position of
|
||||
the node in the list of nodes:
|
||||
|
||||
* `BUILDER_NODE_<idx>_AUTH_TLS_CACERT`
|
||||
* `BUILDER_NODE_<idx>_AUTH_TLS_CERT`
|
||||
* `BUILDER_NODE_<idx>_AUTH_TLS_KEY`
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The index is always `0` at the moment as we don't support (yet) appending new
|
||||
> nodes with this action.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver: remote
|
||||
endpoint: tcp://graviton2:1234
|
||||
env:
|
||||
BUILDER_NODE_0_AUTH_TLS_CACERT: ${{ secrets.GRAVITON2_CA }}
|
||||
BUILDER_NODE_0_AUTH_TLS_CERT: ${{ secrets.GRAVITON2_CERT }}
|
||||
BUILDER_NODE_0_AUTH_TLS_KEY: ${{ secrets.GRAVITON2_KEY }}
|
||||
```
|
@ -0,0 +1,51 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
export const envPrefix = 'BUILDER_NODE';
|
||||
|
||||
export function setCredentials(credsdir: string, index: number, driver: string, endpoint: string): Array<string> {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(endpoint);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
switch (url.protocol) {
|
||||
case 'tcp:': {
|
||||
return setBuildKitClientCerts(credsdir, index, driver, url);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function setBuildKitClientCerts(credsdir: string, index: number, driver: string, endpoint: URL): Array<string> {
|
||||
const driverOpts: Array<string> = [];
|
||||
const buildkitCacert = process.env[`${envPrefix}_${index}_AUTH_TLS_CACERT`] || '';
|
||||
const buildkitCert = process.env[`${envPrefix}_${index}_AUTH_TLS_CERT`] || '';
|
||||
const buildkitKey = process.env[`${envPrefix}_${index}_AUTH_TLS_KEY`] || '';
|
||||
if (buildkitCacert.length == 0 && buildkitCert.length == 0 && buildkitKey.length == 0) {
|
||||
return driverOpts;
|
||||
}
|
||||
let host = endpoint.hostname;
|
||||
if (endpoint.port.length > 0) {
|
||||
host += `-${endpoint.port}`;
|
||||
}
|
||||
if (buildkitCacert.length > 0) {
|
||||
const cacertpath = `${credsdir}/cacert_${host}.pem`;
|
||||
fs.writeFileSync(cacertpath, buildkitCacert);
|
||||
driverOpts.push(`cacert=${cacertpath}`);
|
||||
}
|
||||
if (buildkitCert.length > 0) {
|
||||
const certpath = `${credsdir}/cert_${host}.pem`;
|
||||
fs.writeFileSync(certpath, buildkitCert);
|
||||
driverOpts.push(`cert=${certpath}`);
|
||||
}
|
||||
if (buildkitKey.length > 0) {
|
||||
const keypath = `${credsdir}/key_${host}.pem`;
|
||||
fs.writeFileSync(keypath, buildkitKey);
|
||||
driverOpts.push(`key=${keypath}`);
|
||||
}
|
||||
if (driver != 'remote') {
|
||||
return [];
|
||||
}
|
||||
return driverOpts;
|
||||
}
|
Loading…
Reference in New Issue