Skip to content

Commit

Permalink
feat(1079): Add key pair generation method and push public key to scm…
Browse files Browse the repository at this point in the history
… [4] (#163)

* feat(scm-github): Add key pair generation method and push pub key to scm

* feat(scm-github): Add key pair generation method and push pub key to scm

* feat(): add accessor function for checking autoDeployKeyGeneration

* feat(scm-github): add tests for addDeployKey and checkAutoDeployKeyGeneration

* refactor(): change function names and localize constants

* refactor(): use object destructing in config and use maps
  • Loading branch information
supra08 authored Aug 4, 2020
1 parent 543fcc9 commit 9d807e2
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 2 deletions.
82 changes: 82 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { verify } = require('@octokit/webhooks');
const hoek = require('hoek');
const Path = require('path');
const joi = require('joi');
const keygen = require('ssh-keygen');
const schema = require('screwdriver-data-schema');
const CHECKOUT_URL_REGEX = schema.config.regex.CHECKOUT_URL;
const Scm = require('screwdriver-scm-base');
Expand Down Expand Up @@ -43,6 +44,13 @@ const PERMITTED_RELEASE_EVENT = [
'published'
];

const DEPLOY_KEY_GENERATOR_CONFIG = {
DEPLOY_KEYS_FILE: `${__dirname}/keys_rsa`,
DEPLOY_KEYS_FORMAT: 'PEM',
DEPLOY_KEYS_PASSWORD: '',
DEPLOY_KEY_TITLE: 'sd@screwdriver.cd'
};

/**
* Get repo information
* @method getInfo
Expand Down Expand Up @@ -124,6 +132,7 @@ class GithubScm extends Scm {
username: joi.string().optional().default('sd-buildbot'),
email: joi.string().optional().default('dev-null@screwdriver.cd'),
commentUserToken: joi.string().optional().description('Token for PR comments'),
autoDeployKeyGeneration: joi.boolean().optional().default(false),
https: joi.boolean().optional().default(false),
oauthClientId: joi.string().required(),
oauthClientSecret: joi.string().required(),
Expand Down Expand Up @@ -299,6 +308,79 @@ class GithubScm extends Scm {
}
}

/**
* Generate a deploy private and public key pair
* @async generateDeployKey
* @return {Promise} Resolves to object containing the public and private key pair
*/
async generateDeployKey() {
return new Promise((resolve, reject) => {
const location = DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEYS_FILE;
const comment = this.config.email;
const password = DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEYS_PASSWORD;
const format = DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEYS_FORMAT;

keygen({
location,
comment,
password,
read: true,
format
}, (err, keyPair) => {
if (err) {
logger.error('Failed to create keys: ', err);

return reject(err);
}

return resolve(keyPair);
});
});
}

/**
* Adds deploy public key to the github repo and returns the private key
* @async _addDeployKey
* @param {Object} config
* @param {Object} config.token Admin token for repo
* @param {String} config.checkoutUrl The checkoutUrl to parse
* @return {Promise} Resolves to the private key string
*/
async _addDeployKey(config) {
const { token, checkoutUrl } = config;
const { owner, repo } = getInfo(checkoutUrl);
const { pubKey, key } = await this.generateDeployKey();

try {
await this.breaker.runCommand({
action: 'createDeployKey',
scopeType: 'repos',
token,
params: {
owner,
repo,
title: DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEY_TITLE,
key: pubKey,
read_only: true
}
});

return key;
} catch (err) {
logger.error('Failed to add token: ', err);
throw err;
}
}

/**
* Returns whether auto deploy key generation is enabled or not
* @async _autoDeployKeyGenerationEnabled
* @return {Boolean} Resolves to the private key string
*/
async _autoDeployKeyGenerationEnabled() {
return this.config.autoDeployKeyGeneration;
}

/**
* Look up a webhook from a repo
* @async _findWebhook
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@
"hoek": "^6.1.2",
"joi": "^13.7.0",
"screwdriver-data-schema": "^19.1.1",
"screwdriver-logger": "^1.0.0",
"screwdriver-scm-base": "^6.0.0",
"screwdriver-logger": "^1.0.0"
"ssh-keygen": "^0.5.0"
},
"release": {
"debug": false,
Expand Down
48 changes: 47 additions & 1 deletion test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ describe('index', function () {
getCommitRefSha: sinon.stub(),
getContents: sinon.stub(),
listHooks: sinon.stub(),
listBranches: sinon.stub()
listBranches: sinon.stub(),
createDeployKey: sinon.stub()
},
users: {
getByUsername: sinon.stub()
Expand Down Expand Up @@ -1916,6 +1917,51 @@ jobs:
});
});

describe('generateDeployKey', () => {
it('returns a public and private key pair object', () => {
scm.generateDeployKey().then((keys) => {
assert.isObject(keys);
assert.property(keys, 'pubKey');
assert.property(keys, 'key');
});
});
});

describe('addDeployKey', () => {
const addDepKeyConfig = {
checkoutUrl: 'git@github.com:baxterthehacker/public-repo.git',
token: 'token'
};
const pubKey = 'public_key';
const privKey = 'private_Key';
let generateDeployKeyStub;

beforeEach(() => {
generateDeployKeyStub = sinon.stub(scm, 'generateDeployKey');
});

afterEach(() => {
generateDeployKeyStub.restore();
});

it('returns a private key', async () => {
generateDeployKeyStub.returns(Promise.resolve({ pubKey, key: privKey }));
githubMock.repos.createDeployKey.resolves({ data: pubKey });
const privateKey = await scm.addDeployKey(addDepKeyConfig);

assert.isString(privateKey);
assert.deepEqual(privateKey, privKey);
});
});

describe('autoDeployKeyGenerationEnabled', () => {
it('returns a boolean check', () =>
scm.autoDeployKeyGenerationEnabled().then((check) => {
assert.isBoolean(check);
})
);
});

describe('getBellConfiguration', () => {
it('returns a default configuration', () => (
scm.getBellConfiguration().then((config) => {
Expand Down

0 comments on commit 9d807e2

Please sign in to comment.