Skip to content

Commit 915bcad

Browse files
authored
feat: Support dockerPrivateKey to specify path to SSH key (#674)
1 parent 3edf0e0 commit 915bcad

File tree

6 files changed

+64
-10
lines changed

6 files changed

+64
-10
lines changed

README.md

+16-3
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,20 @@ custom:
7777
```
7878

7979
The `dockerSsh` option will mount your `$HOME/.ssh/id_rsa` and `$HOME/.ssh/known_hosts` as a
80-
volume in the docker container. If your SSH key is password protected, you can use `ssh-agent`
81-
because `$SSH_AUTH_SOCK` is also mounted & the env var set.
80+
volume in the docker container.
81+
82+
In case you want to use a different key, you can specify the path (absolute) to it through `dockerPrivateKey` option:
83+
84+
```yaml
85+
custom:
86+
pythonRequirements:
87+
dockerizePip: true
88+
dockerSsh: true
89+
dockerPrivateKey: /home/.ssh/id_ed25519
90+
```
91+
92+
If your SSH key is password protected, you can use `ssh-agent`
93+
because `$SSH_AUTH_SOCK` is also mounted & the env var is set.
8294
It is important that the host of your private repositories has already been added in your
8395
`$HOME/.ssh/known_hosts` file, as the install process will fail otherwise due to host authenticity
8496
failure.
@@ -213,7 +225,7 @@ the names in `slimPatterns`
213225

214226
#### Option not to strip binaries
215227

216-
In some cases, stripping binaries leads to problems like "ELF load command address/offset not properly aligned", even when done in the Docker environment. You can still slim down the package without `*.so` files with
228+
In some cases, stripping binaries leads to problems like "ELF load command address/offset not properly aligned", even when done in the Docker environment. You can still slim down the package without `*.so` files with:
217229

218230
```yaml
219231
custom:
@@ -566,3 +578,4 @@ package:
566578
- [@jacksgt](https://github.com/jacksgt) - Fixing pip issues
567579
- [@lephuongbg](https://github.com/lephuongbg) - Fixing single function deployment
568580
- [@rileypriddle](https://github.com/rileypriddle) - Introducing schema validation for `module` property
581+
- [@martinezpl](https://github.com/martinezpl) - Fixing test issues, adding `dockerPrivateKey` option

index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const { installAllRequirements } = require('./lib/pip');
1515
const { pipfileToRequirements } = require('./lib/pipenv');
1616
const { pyprojectTomlToRequirements } = require('./lib/poetry');
1717
const { cleanup, cleanupCache } = require('./lib/clean');
18-
1918
BbPromise.promisifyAll(fse);
2019

2120
/**
@@ -45,6 +44,7 @@ class ServerlessPythonRequirements {
4544
: this.serverless.service.provider.runtime || 'python',
4645
dockerizePip: false,
4746
dockerSsh: false,
47+
dockerPrivateKey: null,
4848
dockerImage: null,
4949
dockerFile: null,
5050
dockerEnv: false,
@@ -71,7 +71,10 @@ class ServerlessPythonRequirements {
7171
}
7272
if (
7373
!options.dockerizePip &&
74-
(options.dockerSsh || options.dockerImage || options.dockerFile)
74+
(options.dockerSsh ||
75+
options.dockerImage ||
76+
options.dockerFile ||
77+
options.dockerPrivateKey)
7578
) {
7679
if (!this.warningLogged) {
7780
if (this.log) {

lib/pip.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,16 @@ async function installRequirements(targetFolder, pluginInstance) {
275275

276276
dockerCmd.push('docker', 'run', '--rm', '-v', `${bindPath}:/var/task:z`);
277277
if (options.dockerSsh) {
278+
const homePath = require('os').homedir();
279+
const sshKeyPath =
280+
options.dockerPrivateKey || `${homePath}/.ssh/id_rsa`;
281+
278282
// Mount necessary ssh files to work with private repos
279283
dockerCmd.push(
280284
'-v',
281-
`${process.env.HOME}/.ssh/id_rsa:/root/.ssh/id_rsa:z`,
285+
`${sshKeyPath}:/root/.ssh/${sshKeyPath.split('/').splice(-1)[0]}:z`,
282286
'-v',
283-
`${process.env.HOME}/.ssh/known_hosts:/root/.ssh/known_hosts:z`,
287+
`${homePath}/.ssh/known_hosts:/root/.ssh/known_hosts:z`,
284288
'-v',
285289
`${process.env.SSH_AUTH_SOCK}:/tmp/ssh_sock:z`,
286290
'-e',

test.js

+30-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const glob = require('glob-all');
33
const JSZip = require('jszip');
44
const sha256File = require('sha256-file');
55
const tape = require('tape-promise/tape');
6+
67
const {
78
chmodSync,
89
removeSync,
@@ -23,7 +24,7 @@ const mkCommand =
2324
(cmd) =>
2425
(args, options = {}) => {
2526
options['env'] = Object.assign(
26-
{ SLS_DEBUG: 't' },
27+
{ SLS_DEBUG: 'true' },
2728
process.env,
2829
options['env']
2930
);
@@ -32,11 +33,11 @@ const mkCommand =
3233
args,
3334
options
3435
);
35-
if (error) {
36+
if (error && !options['noThrow']) {
3637
console.error(`Error running: ${quote([cmd, ...args])}`); // eslint-disable-line no-console
3738
throw error;
3839
}
39-
if (status) {
40+
if (status && !options['noThrow']) {
4041
console.error('STDOUT: ', stdout.toString()); // eslint-disable-line no-console
4142
console.error('STDERR: ', stderr.toString()); // eslint-disable-line no-console
4243
throw new Error(
@@ -200,6 +201,32 @@ const canUseDocker = () => {
200201
// Skip if running on these platforms.
201202
const brokenOn = (...platforms) => platforms.indexOf(process.platform) != -1;
202203

204+
test(
205+
'dockerPrivateKey option correctly resolves docker command',
206+
async (t) => {
207+
process.chdir('tests/base');
208+
const path = npm(['pack', '../..']);
209+
npm(['i', path]);
210+
const stdout = sls(['package'], {
211+
noThrow: true,
212+
env: {
213+
dockerizePip: true,
214+
dockerSsh: true,
215+
dockerPrivateKey: `${__dirname}${sep}tests${sep}base${sep}custom_ssh`,
216+
dockerImage: 'break the build to log the command',
217+
},
218+
});
219+
t.true(
220+
stdout.includes(
221+
`-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z`
222+
),
223+
'docker command properly resolved'
224+
);
225+
t.end();
226+
},
227+
{ skip: !canUseDocker() || brokenOn('win32') }
228+
);
229+
203230
test(
204231
'default pythonBin can package flask with default options',
205232
async (t) => {

tests/base/custom_ssh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SOME KEY

tests/base/serverless.yml

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ custom:
1010
pythonRequirements:
1111
zip: ${env:zip, self:custom.defaults.zip}
1212
dockerizePip: ${env:dockerizePip, self:custom.defaults.dockerizePip}
13+
dockerSsh: ${env:dockerSsh, self:custom.defaults.dockerSsh}
14+
dockerPrivateKey: ${env:dockerPrivateKey, self:custom.defaults.dockerPrivateKey}
15+
dockerImage: ${env:dockerImage, self:custom.defaults.dockerImage}
1316
slim: ${env:slim, self:custom.defaults.slim}
1417
slimPatterns: ${file(./slimPatterns.yml):slimPatterns, self:custom.defaults.slimPatterns}
1518
slimPatternsAppendDefaults: ${env:slimPatternsAppendDefaults, self:custom.defaults.slimPatternsAppendDefaults}
@@ -24,6 +27,9 @@ custom:
2427
slimPatternsAppendDefaults: true
2528
zip: false
2629
dockerizePip: false
30+
dockerSsh: false
31+
dockerPrivateKey: ''
32+
dockerImage: ''
2733
individually: false
2834
useStaticCache: true
2935
useDownloadCache: true

0 commit comments

Comments
 (0)