selective generation of settings for GPG + isolated gpg homedir

This commit is contained in:
Jared Petersen 2020-05-12 01:11:43 -07:00
parent 5e3159d960
commit 8bc07f9980
7 changed files with 30386 additions and 95 deletions

View file

@ -66,7 +66,21 @@ describe('auth tests', () => {
await io.rmRF(altHome);
}, 100000);
it('creates settings.xml with all data', async () => {
it('creates settings.xml with minimal configuration', async () => {
const id = 'packages';
const username = 'UNAME';
const password = 'TOKEN';
await auth.configAuthentication(id, username, password);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
);
}, 100000);
it('creates settings.xml with gpg data', async () => {
const id = 'packages';
const username = 'UNAME';
const password = 'TOKEN';
@ -145,27 +159,41 @@ describe('auth tests', () => {
);
}, 100000);
it('escapes invalid XML inputs', () => {
it('generates valid settings.xml', () => {
const id = 'packages';
const username = 'USER';
const password = '&<>"\'\'"><&';
const gpgPassphrase = 'PASSPHRASE';
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(`
<settings>
<servers>
<server>
<id>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;&quot;&apos;&apos;&quot;&gt;&lt;&amp;}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${gpgPassphrase}}</passphrase>
</server>
</servers>
</settings>
`);
const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${gpgPassphrase}}</passphrase>
</server>
</servers>
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.homedir>${tempDir}</gpg.homedir>
</properties>
</profile>
</profiles>
</settings>`;
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
expectedSettings
);
});
it('imports gpg private key', async () => {

View file

@ -10,7 +10,7 @@ describe('util tests', () => {
describe('getTempDir', () => {
it('gets temp dir using env', () => {
process.env['RUNNER_TEMP'] = 'defaulttmp'
process.env['RUNNER_TEMP'] = 'defaulttmp';
const util = require('../src/util');
const tempDir = util.getTempDir();
@ -25,7 +25,9 @@ describe('util tests', () => {
const tempDir = util.getTempDir();
expect(tempDir).toEqual(path.join(process.env['USERPROFILE'], 'actions', 'temp'));
expect(tempDir).toEqual(
path.join(process.env['USERPROFILE'], 'actions', 'temp')
);
});
it('gets temp dir for windows using c drive', () => {

30248
dist/index.js generated vendored

File diff suppressed because it is too large Load diff

78
package-lock.json generated
View file

@ -430,6 +430,74 @@
"@types/yargs": "^13.0.0"
}
},
"@oozcitak/dom": {
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.5.tgz",
"integrity": "sha512-L6v3Mwb0TaYBYgeYlIeBaHnc+2ZEaDSbFiRm5KmqZQSoBlbPlf+l6aIH/sD5GUf2MYwULw00LT7+dOnEuAEC0A==",
"requires": {
"@oozcitak/infra": "1.0.5",
"@oozcitak/url": "1.0.0",
"@oozcitak/util": "8.0.0"
},
"dependencies": {
"@oozcitak/util": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz",
"integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw=="
}
}
},
"@oozcitak/infra": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.5.tgz",
"integrity": "sha512-o+zZH7M6l5e3FaAWy3ojaPIVN5eusaYPrKm6MZQt0DKNdgXa2wDYExjpP0t/zx+GoQgQKzLu7cfD8rHCLt8JrQ==",
"requires": {
"@oozcitak/util": "8.0.0"
},
"dependencies": {
"@oozcitak/util": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz",
"integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw=="
}
}
},
"@oozcitak/url": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.0.tgz",
"integrity": "sha512-LGrMeSxeLzsdaitxq3ZmBRVOrlRRQIgNNci6L0VRnOKlJFuRIkNm4B+BObXPCJA6JT5bEJtrrwjn30jueHJYZQ==",
"requires": {
"@oozcitak/infra": "1.0.3",
"@oozcitak/util": "1.0.2"
},
"dependencies": {
"@oozcitak/infra": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.3.tgz",
"integrity": "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag==",
"requires": {
"@oozcitak/util": "1.0.1"
},
"dependencies": {
"@oozcitak/util": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.1.tgz",
"integrity": "sha512-dFwFqcKrQnJ2SapOmRD1nQWEZUtbtIy9Y6TyJquzsalWNJsKIPxmTI0KG6Ypyl8j7v89L2wixH9fQDNrF78hKg=="
}
}
},
"@oozcitak/util": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz",
"integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA=="
}
}
},
"@oozcitak/util": {
"version": "8.3.3",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.3.tgz",
"integrity": "sha512-Ufpab7G5PfnEhQyy5kDg9C8ltWJjsVT1P/IYqacjstaqydG4Q21HAT2HUZQYBrC/a1ZLKCz87pfydlDvv8y97w=="
},
"@types/babel__core": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz",
@ -4955,6 +5023,16 @@
"integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
"dev": true
},
"xmlbuilder2": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.1.2.tgz",
"integrity": "sha512-PI710tmtVlQ5VmwzbRTuhmVhKnj9pM8Si+iOZCV2g2SNo3gCrpzR2Ka9wNzZtqfD+mnP+xkrqoNy0sjKZqP4Dg==",
"requires": {
"@oozcitak/dom": "1.15.5",
"@oozcitak/infra": "1.0.5",
"@oozcitak/util": "8.3.3"
}
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",

View file

@ -29,7 +29,8 @@
"@actions/http-client": "^1.0.6",
"@actions/io": "^1.0.0",
"@actions/tool-cache": "^1.3.1",
"semver": "^6.1.1"
"semver": "^6.1.1",
"xmlbuilder2": "^2.1.2"
},
"devDependencies": {
"@types/jest": "^24.0.13",

View file

@ -5,6 +5,7 @@ import * as core from '@actions/core';
import * as io from '@actions/io';
import * as exec from '@actions/exec';
import * as util from './util';
import {create as xmlCreate} from 'xmlbuilder2';
export const M2_DIR = '.m2';
export const TEMP_DIR = util.getTempDir();
@ -39,10 +40,11 @@ export async function configAuthentication(
);
await io.mkdirP(settingsDirectory);
core.debug(`created directory ${settingsDirectory}`);
const isGpgEnabled = gpgPrivateKey !== DEFAULT_GPG_PRIVATE_KEY;
await write(
settingsDirectory,
SETTINGS_FILE,
generate(id, username, password, gpgPassphrase)
generate(id, username, password, isGpgEnabled ? gpgPassphrase : null)
);
if (gpgPrivateKey !== DEFAULT_GPG_PRIVATE_KEY) {
@ -51,37 +53,53 @@ export async function configAuthentication(
}
}
function escapeXML(value: string) {
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
}
// only exported for testing purposes
export function generate(
id = DEFAULT_ID,
username = DEFAULT_USERNAME,
password = DEFAULT_PASSWORD,
gpgPassphrase = DEFAULT_GPG_PASSPHRASE
id: string,
username: string,
password: string,
gpgPassphrase: string | null = null
) {
return `
<settings>
<servers>
<server>
<id>${escapeXML(id)}</id>
<username>\${env.${escapeXML(username)}}</username>
<password>\${env.${escapeXML(password)}}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${escapeXML(gpgPassphrase)}}</passphrase>
</server>
</servers>
</settings>
`;
const xmlObj: any = {
settings: {
'@xmlns': 'http://maven.apache.org/SETTINGS/1.0.0',
'@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'@xsi:schemaLocation':
'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd',
servers: {
server: [
{
id: id,
username: `\${env.${username}}`,
password: `\${env.${password}}`
}
]
}
}
};
if (gpgPassphrase !== null) {
const gpgServer = {
id: 'gpg.passphrase',
passphrase: `\${env.${gpgPassphrase}}`
};
xmlObj.settings.servers.server.push(gpgServer);
xmlObj.settings.profiles = {
profile: [
{
activation: {
activeByDefault: true
},
properties: {
'gpg.homedir': TEMP_DIR
}
}
]
};
}
return xmlCreate(xmlObj).end({headless: true, prettyPrint: true, width: 80});
}
async function write(directory: string, file: string, contents: string) {

View file

@ -6,7 +6,9 @@ export function getTempDir() {
let baseLocation;
if (isWindows()) {
// On windows use the USERPROFILE env variable
baseLocation = (process.env['USERPROFILE']) ? process.env['USERPROFILE'] : 'C:\\';
baseLocation = process.env['USERPROFILE']
? process.env['USERPROFILE']
: 'C:\\';
} else {
if (process.platform === 'darwin') {
baseLocation = '/Users';
@ -20,5 +22,5 @@ export function getTempDir() {
}
export function isWindows() {
return (process.platform === 'win32');
return process.platform === 'win32';
}