From b9a18e1677b42438c59d4e341ee74cf4d1c276c3 Mon Sep 17 00:00:00 2001 From: Warren Seine Date: Wed, 5 Aug 2020 23:02:41 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Support=20loading=20GPG=20private?= =?UTF-8?q?=20key=20from=20file=20path.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ __tests__/gpg.test.ts | 18 ++++++++++++++++++ action.yml | 3 +++ dist/cleanup/index.js | 22 +++++++++++++--------- dist/setup/index.js | 38 +++++++++++++++++++++++++------------- src/constants.ts | 2 ++ src/gpg.ts | 19 ++++++++++--------- src/setup-java.ts | 17 +++++++++++++---- 8 files changed, 86 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 2cd5af64..0ff919c7 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,8 @@ If `gpg-private-key` input is provided, the private key will be written to a fil See the help docs on [Publishing a Package](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages#publishing-a-package) for more information on the `pom.xml` file. +Alternatively, you can use `gpg-private-key-path` to point to a key file. + ## Publishing using Gradle ```yaml jobs: diff --git a/__tests__/gpg.test.ts b/__tests__/gpg.test.ts index f19e9a67..cd4ba87b 100644 --- a/__tests__/gpg.test.ts +++ b/__tests__/gpg.test.ts @@ -1,4 +1,5 @@ import path = require('path'); +import fs = require('fs'); import io = require('@actions/io'); import exec = require('@actions/exec'); @@ -41,6 +42,23 @@ describe('gpg tests', () => { }); }); + describe('importKeyFromPath', () => { + it('attempts to import private key from path and returns null key id on failure', async () => { + const privateKey = 'KEY CONTENTS'; + const privateKeyPath = path.join(tempDir, 'test.asc'); + fs.writeFileSync(privateKeyPath, privateKey); + const keyId = await gpg.importKeyFromPath(privateKeyPath); + + expect(keyId).toBeNull(); + + expect(exec.exec).toHaveBeenCalledWith( + 'gpg', + expect.anything(), + expect.anything() + ); + }); + }); + describe('deleteKey', () => { it('deletes private key', async () => { const keyId = 'asdfhjkl'; diff --git a/action.yml b/action.yml index 74572687..7d132a86 100644 --- a/action.yml +++ b/action.yml @@ -42,6 +42,9 @@ inputs: gpg-private-key: description: 'GPG private key to import. Default is empty string.' required: false + gpg-private-key-path: + description: 'Path to the GPG private key to import. Default is empty string. Overriden by gpg-private-key' + required: false gpg-passphrase: description: 'Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE.' diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index 6647ad59..85731d88 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -963,8 +963,10 @@ exports.INPUT_SERVER_ID = 'server-id'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; exports.INPUT_SETTINGS_PATH = 'settings-path'; +exports.INPUT_GPG_PRIVATE_KEY_PATH = 'gpg-private-key-path'; exports.INPUT_GPG_PRIVATE_KEY = 'gpg-private-key'; exports.INPUT_GPG_PASSPHRASE = 'gpg-passphrase'; +exports.INPUT_DEFAULT_GPG_PRIVATE_KEY_PATH = undefined; exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined; exports.INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE'; exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = 'gpg-private-key-fingerprint'; @@ -1627,6 +1629,15 @@ function importKey(privateKey) { encoding: 'utf-8', flag: 'w' }); + const keyFingerprint = yield importKeyFromPath(exports.PRIVATE_KEY_FILE); + yield io.rmRF(exports.PRIVATE_KEY_FILE); + return keyFingerprint; + }); +} +exports.importKey = importKey; +function importKeyFromPath(privateKeyPath) { + return __awaiter(this, void 0, void 0, function* () { + console.log(`from path: ${privateKeyPath}`); let output = ''; const options = { silent: true, @@ -1636,19 +1647,12 @@ function importKey(privateKey) { } } }; - yield exec.exec('gpg', [ - '--batch', - '--import-options', - 'import-show', - '--import', - exports.PRIVATE_KEY_FILE - ], options); - yield io.rmRF(exports.PRIVATE_KEY_FILE); + yield exec.exec('gpg', ['--batch', '--import-options', 'import-show', '--import', privateKeyPath], options); const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX); return match && match[0]; }); } -exports.importKey = importKey; +exports.importKeyFromPath = importKeyFromPath; function deleteKey(keyFingerprint) { return __awaiter(this, void 0, void 0, function* () { yield exec.exec('gpg', ['--batch', '--yes', '--delete-secret-keys', keyFingerprint], { silent: true }); diff --git a/dist/setup/index.js b/dist/setup/index.js index 3beeeece..f12cdf00 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -25663,8 +25663,10 @@ exports.INPUT_SERVER_ID = 'server-id'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; exports.INPUT_SETTINGS_PATH = 'settings-path'; +exports.INPUT_GPG_PRIVATE_KEY_PATH = 'gpg-private-key-path'; exports.INPUT_GPG_PRIVATE_KEY = 'gpg-private-key'; exports.INPUT_GPG_PASSPHRASE = 'gpg-passphrase'; +exports.INPUT_DEFAULT_GPG_PRIVATE_KEY_PATH = undefined; exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined; exports.INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE'; exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = 'gpg-private-key-fingerprint'; @@ -28699,18 +28701,26 @@ function run() { const password = core.getInput(constants.INPUT_SERVER_PASSWORD, { required: false }); + const gpgPrivateKeyPath = core.getInput(constants.INPUT_GPG_PRIVATE_KEY_PATH, { required: false }) || + constants.INPUT_DEFAULT_GPG_PRIVATE_KEY_PATH; const gpgPrivateKey = core.getInput(constants.INPUT_GPG_PRIVATE_KEY, { required: false }) || constants.INPUT_DEFAULT_GPG_PRIVATE_KEY; const gpgPassphrase = core.getInput(constants.INPUT_GPG_PASSPHRASE, { required: false }) || - (gpgPrivateKey ? constants.INPUT_DEFAULT_GPG_PASSPHRASE : undefined); + (gpgPrivateKey || gpgPrivateKeyPath + ? constants.INPUT_DEFAULT_GPG_PASSPHRASE + : undefined); if (gpgPrivateKey) { core.setSecret(gpgPrivateKey); } yield auth.configAuthentication(id, username, password, gpgPassphrase); - if (gpgPrivateKey) { + if (gpgPrivateKey || gpgPrivateKeyPath) { core.info('importing private key'); - const keyFingerprint = (yield gpg.importKey(gpgPrivateKey)) || ''; - core.saveState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, keyFingerprint); + const keyFingerprint = gpgPrivateKey + ? yield gpg.importKey(gpgPrivateKey) + : gpgPrivateKeyPath + ? yield gpg.importKeyFromPath(gpgPrivateKeyPath) + : null; + core.saveState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, keyFingerprint || ''); } } catch (error) { @@ -32612,6 +32622,15 @@ function importKey(privateKey) { encoding: 'utf-8', flag: 'w' }); + const keyFingerprint = yield importKeyFromPath(exports.PRIVATE_KEY_FILE); + yield io.rmRF(exports.PRIVATE_KEY_FILE); + return keyFingerprint; + }); +} +exports.importKey = importKey; +function importKeyFromPath(privateKeyPath) { + return __awaiter(this, void 0, void 0, function* () { + console.log(`from path: ${privateKeyPath}`); let output = ''; const options = { silent: true, @@ -32621,19 +32640,12 @@ function importKey(privateKey) { } } }; - yield exec.exec('gpg', [ - '--batch', - '--import-options', - 'import-show', - '--import', - exports.PRIVATE_KEY_FILE - ], options); - yield io.rmRF(exports.PRIVATE_KEY_FILE); + yield exec.exec('gpg', ['--batch', '--import-options', 'import-show', '--import', privateKeyPath], options); const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX); return match && match[0]; }); } -exports.importKey = importKey; +exports.importKeyFromPath = importKeyFromPath; function deleteKey(keyFingerprint) { return __awaiter(this, void 0, void 0, function* () { yield exec.exec('gpg', ['--batch', '--yes', '--delete-secret-keys', keyFingerprint], { silent: true }); diff --git a/src/constants.ts b/src/constants.ts index 2e885cff..363ae1a1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -7,9 +7,11 @@ export const INPUT_SERVER_ID = 'server-id'; export const INPUT_SERVER_USERNAME = 'server-username'; export const INPUT_SERVER_PASSWORD = 'server-password'; export const INPUT_SETTINGS_PATH = 'settings-path'; +export const INPUT_GPG_PRIVATE_KEY_PATH = 'gpg-private-key-path'; export const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key'; export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase'; +export const INPUT_DEFAULT_GPG_PRIVATE_KEY_PATH = undefined; export const INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined; export const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE'; diff --git a/src/gpg.ts b/src/gpg.ts index c8e5d7b0..72eefc9f 100644 --- a/src/gpg.ts +++ b/src/gpg.ts @@ -15,6 +15,15 @@ export async function importKey(privateKey: string) { flag: 'w' }); + const keyFingerprint = await importKeyFromPath(PRIVATE_KEY_FILE); + + await io.rmRF(PRIVATE_KEY_FILE); + + return keyFingerprint; +} + +export async function importKeyFromPath(privateKeyPath: string) { + console.log(`from path: ${privateKeyPath}`); let output = ''; const options: ExecOptions = { @@ -28,18 +37,10 @@ export async function importKey(privateKey: string) { await exec.exec( 'gpg', - [ - '--batch', - '--import-options', - 'import-show', - '--import', - PRIVATE_KEY_FILE - ], + ['--batch', '--import-options', 'import-show', '--import', privateKeyPath], options ); - await io.rmRF(PRIVATE_KEY_FILE); - const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX); return match && match[0]; } diff --git a/src/setup-java.ts b/src/setup-java.ts index db169f29..296a8c1d 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -29,12 +29,17 @@ async function run() { const password = core.getInput(constants.INPUT_SERVER_PASSWORD, { required: false }); + const gpgPrivateKeyPath = + core.getInput(constants.INPUT_GPG_PRIVATE_KEY_PATH, {required: false}) || + constants.INPUT_DEFAULT_GPG_PRIVATE_KEY_PATH; const gpgPrivateKey = core.getInput(constants.INPUT_GPG_PRIVATE_KEY, {required: false}) || constants.INPUT_DEFAULT_GPG_PRIVATE_KEY; const gpgPassphrase = core.getInput(constants.INPUT_GPG_PASSPHRASE, {required: false}) || - (gpgPrivateKey ? constants.INPUT_DEFAULT_GPG_PASSPHRASE : undefined); + (gpgPrivateKey || gpgPrivateKeyPath + ? constants.INPUT_DEFAULT_GPG_PASSPHRASE + : undefined); if (gpgPrivateKey) { core.setSecret(gpgPrivateKey); @@ -42,12 +47,16 @@ async function run() { await auth.configAuthentication(id, username, password, gpgPassphrase); - if (gpgPrivateKey) { + if (gpgPrivateKey || gpgPrivateKeyPath) { core.info('importing private key'); - const keyFingerprint = (await gpg.importKey(gpgPrivateKey)) || ''; + const keyFingerprint = gpgPrivateKey + ? await gpg.importKey(gpgPrivateKey) + : gpgPrivateKeyPath + ? await gpg.importKeyFromPath(gpgPrivateKeyPath) + : null; core.saveState( constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, - keyFingerprint + keyFingerprint || '' ); } } catch (error) {