Compare commits

...

8 Commits

Author SHA1 Message Date
Richard Simpson 0188d9d223 feat: add support for (nearly) any engine (#15)
* feat: add support for (nearly) any engine

* cache response and fixup data depth logic

* use starting slash as non-kv sentinel value

* add tests for custom engines

* improve docs and add descriptor of generic support

* update dist
2020-02-05 16:33:12 -06:00
Giancarlo França f229481670 feat: support for KV version 1 and custom-named engines (#12)
* feat: kv v1 and engine path

* doc: add custom version and engine path usage docs

Co-authored-by: Richard Simpson <richardsimpson@outlook.com>
2020-02-04 09:40:55 -06:00
Antoine Méausoone 3b9239de79 feat(authenticate): add approle auth method (#10)
* feat(authenticate): add approle auth method

* docs(readme): update readme

* fix: update index.js

* fix: update got to 10.2.2 to fix ncc

* chore: clean up code slightly

* chore: update tests to use got correctly

* chore(test): fix integration tests

* chore: streamline method logic

* chore: make role and secret required in approle

Co-authored-by: Sébastien FAUVART <sebastien.fauvart@gmail.com>
Co-authored-by: Richard Simpson <richardsimpson@outlook.com>
2020-01-28 19:10:19 -06:00
Richard Simpson 7a9634236c chore(build): re-enable builds on PR and restrict publish to master 2020-01-09 10:45:52 -06:00
Richard Simpson ab4dc55b2e fix: actually build namespace changes 2020-01-09 10:31:15 -06:00
dependabot[bot] e394527e23 chore(deps): bump handlebars from 4.2.1 to 4.5.3 (#9)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.2.1 to 4.5.3.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.2.1...v4.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-29 21:04:07 -06:00
dependabot[bot] 29150a8fd2 chore(deps): bump npm from 6.11.3 to 6.13.4 (#8)
Bumps [npm](https://github.com/npm/cli) from 6.11.3 to 6.13.4.
- [Release notes](https://github.com/npm/cli/releases)
- [Changelog](https://github.com/npm/cli/blob/latest/CHANGELOG.md)
- [Commits](https://github.com/npm/cli/compare/v6.11.3...v6.13.4)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-13 13:56:22 -06:00
Richard Simpson 38c189f087 chore(test): organize tests a bit better (#7)
* chore(test): organize tests a bit better

* add caching
2019-11-24 16:00:31 -06:00
21 changed files with 3915 additions and 2547 deletions
+76 -33
View File
@@ -1,44 +1,44 @@
on: [push]
on:
push:
branches:
- master
pull_request:
jobs:
test:
build:
runs-on: ubuntu-latest
services:
vault:
image: vault:1.2.3
ports:
- 8200/tcp
env:
VAULT_DEV_ROOT_TOKEN_ID: testtoken
options: --cap-add=IPC_LOCK
steps:
- uses: actions/checkout@v1
- name: Use Node.js 10.x
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: setup npm cache
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm install
run: npm ci
- name: npm build
run: npm run build
- name: npm run test
run: npm run test
env:
CI: true
- name: npm run test:integration
run: npm run test:integration
env:
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vault.ports[8200] }}
CI: true
test-ent:
integration:
runs-on: ubuntu-latest
services:
vault:
vaultBasic:
image: vault:1.2.3
ports:
- 8200/tcp
env:
VAULT_DEV_ROOT_TOKEN_ID: testtoken
options: --cap-add=IPC_LOCK
vaultEnterprise:
image: hashicorp/vault-enterprise:1.3.0_ent
ports:
- 8200/tcp
@@ -52,19 +52,28 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: setup npm cache
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm install
run: npm ci
- name: npm build
run: npm run build
- name: npm run test
run: npm run test
env:
CI: true
- name: npm run test:integration-ent
run: npm run test:integration-ent
- name: npm run test:integration:basic
run: npm run test:integration:basic
env:
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vault.ports[8200] }}
VAULT_PORT: ${{ job.services.vaultBasic.ports[8200] }}
CI: true
- name: npm run test:integration:enterprise
run: npm run test:integration:enterprise
env:
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vaultEnterprise.ports[8200] }}
CI: true
e2e:
@@ -72,7 +81,7 @@ jobs:
services:
vault:
image: vault:1.2.3
image: vault:1.3.0
ports:
- 8200/tcp
env:
@@ -85,16 +94,23 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: setup npm cache
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm install
run: npm ci
- name: npm build
run: npm run build
- name: setup vault
run: node ./e2e/setup.js
run: node ./integrationTests/e2e/setup.js
env:
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vault.ports[8200] }}
- name: use vault action
- name: use vault action (default K/V version 2)
uses: ./
with:
url: http://localhost:${{ job.services.vault.ports[8200] }}
@@ -103,18 +119,45 @@ jobs:
test secret ;
test secret | NAMED_SECRET ;
nested/test otherSecret ;
- name: use vault action (custom K/V version 1)
uses: ./
with:
url: http://localhost:${{ job.services.vault.ports[8200] }}
token: testtoken
path: my-secret
kv-version: 1
secrets: |
test altSecret ;
test altSecret | NAMED_ALTSECRET ;
nested/test otherAltSecret ;
- name: use vault action (using cubbyhole engine)
uses: ./
with:
url: http://localhost:${{ job.services.vault.ports[8200] }}
token: testtoken
secrets: |
/cubbyhole/test foo ;
/cubbyhole/test zip | NAMED_CUBBYSECRET ;
- name: verify
run: npm run test:e2e
publish:
if: github.event_name == 'push' && contains(github.ref, 'master')
runs-on: ubuntu-latest
needs: [test, e2e]
needs: [build, integration, e2e]
steps:
- uses: actions/checkout@v1
- name: Use Node.js 10.x
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: setup npm cache
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm install
run: npm ci
- name: release
+97 -2
View File
@@ -1,6 +1,8 @@
# vault-action
A helper action for easily pulling secrets from the default v2 K/V backend of vault.
A helper action for easily pulling secrets from HashiCorp Vault.
By default, this action pulls from [Version 2](https://www.vaultproject.io/docs/secrets/kv/kv-v2/) of the K/V Engine. See examples below for how to [use v1](#using-kv-version-1) as well as non-K/V engines.
## Example Usage
@@ -22,6 +24,27 @@ jobs:
# ...
```
## Authentication method
While most workflows will likely use a vault token, you can also use an `approle` to authenticate with vaule. You can configure which by using the `method` parameter:
- **token**: (by default) you must provide a token parameter
```yaml
...
with:
url: https://vault.mycompany.com:8200
token: ${{ secrets.VaultToken }}
```
- **approle**: you must provide a roleId & secretId parameter
```yaml
...
with:
url: https://vault.mycompany.com:8200
method: approle
roleId: ${{ secrets.roleId }}
secretId: ${{ secrets.secretId }}
```
## Key Syntax
The `secrets` parameter is a set of multiple secret requests separated by the `;` character.
@@ -73,9 +96,80 @@ with:
ci/aws secretKey | AWS_SECRET_ACCESS_KEY
```
### Using K/V version 1
By default, `vault-action` expects a K/V engine using [version 2](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html).
In order to work with a [v1 engine](https://www.vaultproject.io/docs/secrets/kv/kv-v1/), the `kv-version` parameter may be passed:
```yaml
with:
kv-version: 1
```
### Custom K/V Engine Path
When you enable the K/V Engine, by default it's placed at the path `secret`, so a secret named `ci` will be accessed from `secret/ci`. However, [if you enabled the secrets engine using a custom `path`](https://www.vaultproject.io/docs/commands/secrets/enable/#inlinecode--path-4), you
can pass it as follows:
```yaml
with:
path: my-secrets
secrets: ci npmToken
```
This way, the `ci` secret in the example above will be retrieved from `my-secrets/ci`.
### Other Secret Engines
While this action primarily supports the K/V engine, it is possible to request secrets from other engines in Vault.
To do so when specifying the `Secret Path`, just append a leading formard slash (`/`) and specify the path as described in the Vault API documentation.
For example, to retrieve a stored secret from the [`cubbyhole` engine](https://www.vaultproject.io/api-docs/secret/cubbyhole/), assuming you have a stored secret at the path `foo` with the contents:
```json
{
"foo": "bar",
"zip": "zap"
}
```
You could request the contents like so:
```yaml
with:
secrets: |
/cubbyhole/foo foo ;
/cubbyhole/foo zip | MY_KEY ;
```
Resulting in:
```bash
FOO=bar MY_KEY=zap
```
Secrets pulled from the same `Secret Path` are cached by default. So if you, for example, are using the `aws` engine and retrieve a key, only a single key for a given path is returned.
e.g.:
```yaml
with:
secrets: |
/aws/creds/ci access_key | AWS_ACCESS_KEY_ID ;
/aws/creds/ci secret_key | AWS_SECRET_ACCESS_KEY
```
would work fine.
NOTE: The `Secret Key` is pulled from the `data` property of the response.
## Vault Enterprise Features
### Namespace
This action could be use with namespace Vault Enterprise feature. You can specify namespace in request :
If you need to retrieve secrets from a specific vault namespace, all that's required is an additional parameter specifying the namespace.
```yaml
steps:
@@ -84,6 +178,7 @@ steps:
uses: RichiCoder1/vault-action
with:
url: https://vault-enterprise.mycompany.com:8200
method: token
token: ${{ secrets.VaultToken }}
namespace: ns1
secrets: |
+126 -18
View File
@@ -2,31 +2,103 @@ const core = require('@actions/core');
const command = require('@actions/core/lib/command');
const got = require('got');
const AUTH_METHODS = ['approle', 'token'];
const VALID_KV_VERSION = [-1, 1, 2];
async function exportSecrets() {
const vaultUrl = core.getInput('url', { required: true });
const vaultToken = core.getInput('token', { required: true });
const vaultNamespace = core.getInput('namespace', { required: false });
const secretsInput = core.getInput('secrets', { required: true });
const secrets = parseSecretsInput(secretsInput);
let enginePath = core.getInput('path', { required: false });
let kvVersion = core.getInput('kv-version', { required: false });
for (const secret of secrets) {
const { secretPath, outputName, secretKey } = secret;
const secretsInput = core.getInput('secrets', { required: true });
const secretRequests = parseSecretsInput(secretsInput);
const vaultMethod = core.getInput('method', { required: false }) || 'token';
if (!AUTH_METHODS.includes(vaultMethod)) {
throw Error(`Sorry, the authentication method ${vaultMethod} is not currently supported.`);
}
let vaultToken = null;
switch (vaultMethod) {
case 'approle':
const vaultRoleId = core.getInput('roleId', { required: true });
const vaultSecretId = core.getInput('secretId', { required: true });
core.debug('Try to retrieve Vault Token from approle');
var options = {
headers: {},
json: { role_id: vaultRoleId, secret_id: vaultSecretId },
responseType: 'json'
};
if (vaultNamespace != null) {
options.headers["X-Vault-Namespace"] = vaultNamespace;
}
const result = await got.post(`${vaultUrl}/v1/auth/approle/login`, options);
if (result && result.body && result.body.auth && result.body.auth.client_token) {
vaultToken = result.body.auth.client_token;
core.debug('✔ Vault Token has retrieved from approle');
} else {
throw Error(`No token was retrieved with the role_id and secret_id provided.`);
}
break;
default:
vaultToken = core.getInput('token', { required: true });
break;
}
if (!enginePath) {
enginePath = 'secret';
}
if (!kvVersion) {
kvVersion = 2;
}
kvVersion = +kvVersion;
if (Number.isNaN(kvVersion) || !VALID_KV_VERSION.includes(kvVersion)) {
throw Error(`You must provide a valid K/V version (${VALID_KV_VERSION.slice(1).join(', ')}). Input: "${kvVersion}"`);
}
const responseCache = new Map();
for (const secretRequest of secretRequests) {
const { secretPath, outputName, secretSelector, isJSONPath } = secretRequest;
const requestOptions = {
headers: {
'X-Vault-Token': vaultToken
}};
},
};
if (vaultNamespace != null){
requestOptions.headers["X-Vault-Namespace"] = vaultNamespace
if (vaultNamespace != null) {
requestOptions.headers["X-Vault-Namespace"] = vaultNamespace;
}
const result = await got(`${vaultUrl}/v1/secret/data/${secretPath}`, requestOptions);
let requestPath = `${vaultUrl}/v1`;
const kvRequest = !secretPath.startsWith('/')
if (!kvRequest) {
requestPath += secretPath;
} else {
requestPath += (kvVersion === 2)
? `/${enginePath}/data/${secretPath}`
: `/${enginePath}/${secretPath}`;
}
const parsedResponse = JSON.parse(result.body);
const vaultKeyData = parsedResponse.data;
const versionData = vaultKeyData.data;
const value = versionData[secretKey];
let body;
if (responseCache.has(requestPath)) {
body = responseCache.get(requestPath);
core.debug(' using cached response');
} else {
const result = await got(requestPath, requestOptions);
body = result.body;
responseCache.set(requestPath, body);
}
let dataDepth = isJSONPath === true ? 0 : kvRequest === false ? 1 : kvVersion;
const secretData = getResponseData(body, dataDepth);
const value = selectData(secretData, secretSelector);
command.issue('add-mask', value);
core.exportVariable(outputName, `${value}`);
core.debug(`${secretPath} => ${outputName}`);
@@ -35,7 +107,7 @@ async function exportSecrets() {
/**
* Parses a secrets input string into key paths and their resulting environment variable name.
* @param {string} secretsInput
* @param {string} secretsInput
*/
function parseSecretsInput(secretsInput) {
const secrets = secretsInput
@@ -69,32 +141,68 @@ function parseSecretsInput(secretsInput) {
throw Error(`You must provide a valid path and key. Input: "${secret}"`)
}
const [secretPath, secretKey] = pathParts;
const [secretPath, secretSelector] = pathParts;
// If we're not using a mapped name, normalize the key path into a variable name.
if (!outputName) {
outputName = normalizeOutputKey(secretKey);
outputName = normalizeOutputKey(secretSelector);
}
output.push({
secretPath,
outputName,
secretKey
secretSelector,
isJSONPath: secretSelector.startsWith('$')
});
}
return output;
}
/**
* Replaces any forward-slash characters to
* Parses a JSON response and returns the secret data
* @param {string} responseBody
* @param {number} kvVersion
*/
function getResponseData(responseBody, dataLevel) {
let secretData = JSON.parse(responseBody);
for (let i = 0; i < dataLevel; i++) {
secretData = secretData['data'];
}
return secretData;
}
/**
* Parses a JSON response and returns the secret data
* @param {Object} data
* @param {string} selector
*/
function selectData(data, selector, isJSONPath) {
if (!isJSONPath) {
return data[selector];
}
// TODO: JSONPath
}
/**
* Replaces any forward-slash characters to
* @param {string} dataKey
*/
function normalizeOutputKey(dataKey) {
return dataKey.replace('/', '__').replace(/[^\w-]/, '').toUpperCase();
}
function parseBoolInput(input) {
if (input === null || input === undefined || input.trim() === '') {
return null;
}
return Boolean(input);
}
module.exports = {
exportSecrets,
parseSecretsInput,
parseResponse: getResponseData,
normalizeOutputKey
};
+78 -13
View File
@@ -7,6 +7,7 @@ const got = require('got');
const {
exportSecrets,
parseSecretsInput,
parseResponse
} = require('./action');
const { when } = require('jest-when');
@@ -16,8 +17,9 @@ describe('parseSecretsInput', () => {
const output = parseSecretsInput('test key');
expect(output).toContainEqual({
secretPath: 'test',
secretKey: 'key',
secretSelector: 'key',
outputName: 'KEY',
isJSONPath: false
});
});
@@ -82,6 +84,38 @@ describe('parseSecretsInput', () => {
})
});
describe('parseResponse', () => {
// https://www.vaultproject.io/api/secret/kv/kv-v1.html#sample-response
it('parses K/V version 1 response', () => {
const response = JSON.stringify({
data: {
foo: 'bar'
}
})
const output = parseResponse(response, 1);
expect(output).toEqual({
foo: 'bar'
});
});
// https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version
it('parses K/V version 2 response', () => {
const response = JSON.stringify({
data: {
data: {
foo: 'bar'
}
}
})
const output = parseResponse(response, 2);
expect(output).toEqual({
foo: 'bar'
});
});
});
describe('exportSecrets', () => {
beforeEach(() => {
@@ -89,27 +123,44 @@ describe('exportSecrets', () => {
when(core.getInput)
.calledWith('url')
.mockReturnValue('http://vault:8200');
.mockReturnValueOnce('http://vault:8200');
when(core.getInput)
.calledWith('token')
.mockReturnValue('EXAMPLE');
.mockReturnValueOnce('EXAMPLE');
});
function mockInput(key) {
when(core.getInput)
.calledWith('secrets')
.mockReturnValue(key);
.mockReturnValueOnce(key);
}
function mockVaultData(data) {
got.mockResolvedValue({
body: JSON.stringify({
data: {
data
}
})
});
function mockVersion(version) {
when(core.getInput)
.calledWith('kv-version')
.mockReturnValueOnce(version);
}
function mockVaultData(data, version='2') {
switch(version) {
case '1':
got.mockResolvedValue({
body: JSON.stringify({
data
})
});
break;
case '2':
got.mockResolvedValue({
body: JSON.stringify({
data: {
data
}
})
});
break;
}
}
it('simple secret retrieval', async () => {
@@ -133,4 +184,18 @@ describe('exportSecrets', () => {
expect(core.exportVariable).toBeCalledWith('TEST_NAME', '1');
});
});
it('simple secret retrieval from K/V v1', async () => {
const version = '1';
mockInput('test key');
mockVersion(version);
mockVaultData({
key: 1
}, version);
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('KEY', '1');
});
});
+2695 -2035
View File
File diff suppressed because it is too large Load Diff
+9 -4
View File
@@ -1,12 +1,17 @@
# Start vault server locally
# You can run integration tests against server by running
# `VAULT_HOST=localhost VAULT_PORT=8200 CI=true npm run test:integration-ent`
# Start vault server locally for the purposes of integration tests.
version: "3.0"
services:
vault:
image: hashicorp/vault-enterprise:1.3.0_ent
image: vault:1.3.0
environment:
VAULT_DEV_ROOT_TOKEN_ID: testtoken
ports:
- 8200:8200
privileged: true
vault-enterprise:
image: hashicorp/vault-enterprise:1.3.0_ent
environment:
VAULT_DEV_ROOT_TOKEN_ID: testtoken
ports:
- 8201:8200
privileged: true
-7
View File
@@ -1,7 +0,0 @@
describe('e2e', () => {
it('verify', () => {
expect(process.env.SECRET).toBe("SUPERSECRET");
expect(process.env.NAMED_SECRET).toBe("SUPERSECRET");
expect(process.env.OTHERSECRET).toBe("OTHERSUPERSECRET");
});
});
-41
View File
@@ -1,41 +0,0 @@
const got = require('got');
(async () => {
try {
// Verify Connection
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
body: {
data: {
secret: "SUPERSECRET",
},
},
json: true,
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
body: {
data: {
otherSecret: "OTHERSUPERSECRET",
},
},
json: true,
});
} catch (error) {
console.log(error);
process.exit(1);
}
})();
-131
View File
@@ -1,131 +0,0 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const got = require('got');
const { when } = require('jest-when');
const { exportSecrets } = require('../action');
describe('integration', () => {
beforeAll(async () => {
// Verify Connection
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
// Create namespace
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/sys/namespaces/ns1`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: true,
});
// Enable secret engine
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/sys/mounts/secret`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns1',
},
body: {"path":"secret","type":"kv","config":{},"options":{"version":2},"generate_signing_key":true},
json: true,
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns1',
},
body: {
data: {
secret: "SUPERSECRET_IN_NAMESPACE",
},
},
json: true,
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns1',
},
body: {
data: {
otherSecret: "OTHERSUPERSECRET_IN_NAMESPACE",
},
},
json: true,
});
})
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('url')
.mockReturnValue(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`);
when(core.getInput)
.calledWith('token')
.mockReturnValue('testtoken');
when(core.getInput)
.calledWith('namespace')
.mockReturnValue('ns1');
});
function mockInput(secrets) {
when(core.getInput)
.calledWith('secrets')
.mockReturnValue(secrets);
}
it('get simple secret', async () => {
mockInput('test secret')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET_IN_NAMESPACE');
});
it('re-map secret', async () => {
mockInput('test secret | TEST_KEY')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('TEST_KEY', 'SUPERSECRET_IN_NAMESPACE');
});
it('get nested secret', async () => {
mockInput('nested/test otherSecret')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET_IN_NAMESPACE');
});
it('get multiple secrets', async () => {
mockInput(`
test secret ;
test secret | NAMED_SECRET ;
nested/test otherSecret ;`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(3);
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET_IN_NAMESPACE');
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET_IN_NAMESPACE');
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET_IN_NAMESPACE');
});
});
-103
View File
@@ -1,103 +0,0 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const got = require('got');
const { when } = require('jest-when');
const { exportSecrets } = require('../action');
describe('integration', () => {
beforeAll(async () => {
// Verify Connection
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
body: {
data: {
secret: "SUPERSECRET",
},
},
json: true,
});
await got(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
body: {
data: {
otherSecret: "OTHERSUPERSECRET",
},
},
json: true,
});
})
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('url')
.mockReturnValue(`http://${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`);
when(core.getInput)
.calledWith('token')
.mockReturnValue('testtoken');
});
function mockInput(secrets) {
when(core.getInput)
.calledWith('secrets')
.mockReturnValue(secrets);
}
it('get simple secret', async () => {
mockInput('test secret')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
});
it('re-map secret', async () => {
mockInput('test secret | TEST_KEY')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('TEST_KEY', 'SUPERSECRET');
});
it('get nested secret', async () => {
mockInput('nested/test otherSecret')
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET');
});
it('get multiple secrets', async () => {
mockInput(`
test secret ;
test secret | NAMED_SECRET ;
nested/test otherSecret ;`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(3);
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET');
});
});
+210
View File
@@ -0,0 +1,210 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const got = require('got');
const { when } = require('jest-when');
const { exportSecrets } = require('../../action');
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
describe('integration', () => {
beforeAll(async () => {
// Verify Connection
await got(`${vaultUrl}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
await got(`${vaultUrl}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
secret: 'SUPERSECRET',
},
},
});
await got(`${vaultUrl}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
otherSecret: 'OTHERSUPERSECRET',
},
}
});
// Enable custom secret engine
try {
await got(`${vaultUrl}/v1/sys/mounts/my-secret`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
type: 'kv'
}
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("path is already in use")) {
// Engine might already be enabled from previous test runs
} else {
throw error;
}
}
await got(`${vaultUrl}/v1/my-secret/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
secret: 'CUSTOMSECRET',
}
});
await got(`${vaultUrl}/v1/my-secret/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
otherSecret: 'OTHERCUSTOMSECRET',
},
});
});
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('url')
.mockReturnValueOnce(`${vaultUrl}`);
when(core.getInput)
.calledWith('token')
.mockReturnValueOnce('testtoken');
});
function mockInput(secrets) {
when(core.getInput)
.calledWith('secrets')
.mockReturnValueOnce(secrets);
}
function mockEngineName(name) {
when(core.getInput)
.calledWith('path')
.mockReturnValueOnce(name);
}
function mockVersion(version) {
when(core.getInput)
.calledWith('kv-version')
.mockReturnValueOnce(version);
}
it('get simple secret', async () => {
mockInput('test secret');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
});
it('re-map secret', async () => {
mockInput('test secret | TEST_KEY');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('TEST_KEY', 'SUPERSECRET');
});
it('get nested secret', async () => {
mockInput('nested/test otherSecret');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET');
});
it('get multiple secrets', async () => {
mockInput(`
test secret ;
test secret | NAMED_SECRET ;
nested/test otherSecret ;`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(3);
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET');
});
it('get secret from K/V v1', async () => {
mockInput('test secret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'CUSTOMSECRET');
});
it('get nested secret from K/V v1', async () => {
mockInput('nested/test otherSecret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERCUSTOMSECRET');
});
describe('generic engines', () => {
beforeAll(async () => {
await got(`${vaultUrl}/v1/cubbyhole/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
foo: "bar",
zip: "zap"
},
});
});
it('supports cubbyhole', async () => {
mockInput('/cubbyhole/test foo');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('FOO', 'bar');
});
it('caches responses', async () => {
mockInput(`
/cubbyhole/test foo ;
/cubbyhole/test zip`);
await exportSecrets();
expect(core.debug).toBeCalledWith(' using cached response');
expect(core.exportVariable).toBeCalledWith('FOO', 'bar');
expect(core.exportVariable).toBeCalledWith('ZIP', 'zap');
});
})
});
+4
View File
@@ -0,0 +1,4 @@
# e2e tests
This test suite runs `vault-action` as a GitHub Action in the context of a live build, and then verifies that the appropriate environmental variables are set.
These tests are intended to mostly be very simple smoke tests to verify that the action is being compiled and run correctly in context.
+12
View File
@@ -0,0 +1,12 @@
describe('e2e', () => {
it('verify', () => {
expect(process.env.SECRET).toBe("SUPERSECRET");
expect(process.env.NAMED_SECRET).toBe("SUPERSECRET");
expect(process.env.OTHERSECRET).toBe("OTHERSUPERSECRET");
expect(process.env.ALTSECRET).toBe("CUSTOMSECRET");
expect(process.env.NAMED_ALTSECRET).toBe("CUSTOMSECRET");
expect(process.env.OTHERALTSECRET).toBe("OTHERCUSTOMSECRET");
expect(process.env.FOO).toBe("bar");
expect(process.env.NAMED_CUBBYSECRET).toBe("zap");
});
});
+82
View File
@@ -0,0 +1,82 @@
const got = require('got');
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
(async () => {
try {
// Verify Connection
await got(`http://${vaultUrl}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
await got(`http://${vaultUrl}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
secret: 'SUPERSECRET',
},
},
});
await got(`http://${vaultUrl}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
otherSecret: 'OTHERSUPERSECRET',
},
}
});
await got(`http://${vaultUrl}/v1/sys/mounts/my-secret`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
type: 'kv'
}
});
await got(`http://${vaultUrl}/v1/my-secret/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
altSecret: 'CUSTOMSECRET',
}
});
await got(`http://${vaultUrl}/v1/my-secret/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
otherAltSecret: 'OTHERCUSTOMSECRET',
},
});
await got(`http://${vaultUrl}/v1/cubbyhole/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
foo: 'bar',
zip: 'zap',
},
});
} catch (error) {
console.log(error);
process.exit(1);
}
})();
@@ -0,0 +1,307 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const got = require('got');
const { when } = require('jest-when');
const { exportSecrets } = require('../../action');
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8201'}`;
describe('integration', () => {
beforeAll(async () => {
try {
// Verify Connection
await got(`${vaultUrl}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
// Create namespace
await enableNamespace('ns1');
// Enable K/V v2 secret engine at 'secret/'
await enableEngine('secret', 'ns1', 2);
await writeSecret('secret', 'test', 'ns1', 2, {secret: 'SUPERSECRET_IN_NAMESPACE'})
await writeSecret('secret', 'nested/test', 'ns1', 2, {otherSecret: 'OTHERSUPERSECRET_IN_NAMESPACE'})
// Enable K/V v1 secret engine at 'my-secret/'
await enableEngine('my-secret', 'ns1', 1);
await writeSecret('my-secret', 'test', 'ns1', 1, {secret: 'CUSTOMSECRET_IN_NAMESPACE'})
await writeSecret('my-secret', 'nested/test', 'ns1', 1, {otherSecret: 'OTHERCUSTOMSECRET_IN_NAMESPACE'})
} catch (e) {
console.error('Failed to setup test', e);
throw e;
}
});
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('url')
.mockReturnValueOnce(`${vaultUrl}`);
when(core.getInput)
.calledWith('token')
.mockReturnValueOnce('testtoken');
when(core.getInput)
.calledWith('namespace')
.mockReturnValueOnce('ns1');
});
it('get simple secret', async () => {
mockInput('test secret');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET_IN_NAMESPACE');
});
it('re-map secret', async () => {
mockInput('test secret | TEST_KEY');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('TEST_KEY', 'SUPERSECRET_IN_NAMESPACE');
});
it('get nested secret', async () => {
mockInput('nested/test otherSecret');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET_IN_NAMESPACE');
});
it('get multiple secrets', async () => {
mockInput(`
test secret ;
test secret | NAMED_SECRET ;
nested/test otherSecret ;`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(3);
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET_IN_NAMESPACE');
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET_IN_NAMESPACE');
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET_IN_NAMESPACE');
});
it('get secret from K/V v1', async () => {
mockInput('test secret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'CUSTOMSECRET_IN_NAMESPACE');
});
it('get nested secret from K/V v1', async () => {
mockInput('nested/test otherSecret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERCUSTOMSECRET_IN_NAMESPACE');
});
});
describe('authenticate with approle', () => {
let roleId;
let secretId;
beforeAll(async () => {
try {
// Verify Connection
await got(`${vaultUrl}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
// Create namespace
await enableNamespace("ns2");
// Enable K/V v2 secret engine at 'secret/'
await enableEngine("secret", "ns2", 2);
// Add secret
await writeSecret('secret', 'test', 'ns2', 2, {secret: 'SUPERSECRET_WITH_APPROLE'})
// Enable approle
try {
await got(`${vaultUrl}/v1/sys/auth/approle`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns2',
},
json: {
type: 'approle'
},
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("path is already in use")) {
// Approle might already be enabled from previous test runs
} else {
throw error;
}
}
// Create policies
await got(`${vaultUrl}/v1/sys/policies/acl/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns2',
},
json: {
"name":"test",
"policy":"path \"auth/approle/*\" {\n capabilities = [\"read\", \"list\"]\n}\npath \"auth/approle/role/my-role/role-id\"\n{\n capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\"]\n}\npath \"auth/approle/role/my-role/secret-id\"\n{\n capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\"]\n}\n\npath \"secret/data/*\" {\n capabilities = [\"list\"]\n}\npath \"secret/metadata/*\" {\n capabilities = [\"list\"]\n}\n\npath \"secret/data/test\" {\n capabilities = [\"read\", \"list\"]\n}\npath \"secret/metadata/test\" {\n capabilities = [\"read\", \"list\"]\n}\npath \"secret/data/test/*\" {\n capabilities = [\"read\", \"list\"]\n}\npath \"secret/metadata/test/*\" {\n capabilities = [\"read\", \"list\"]\n}\n"
},
});
// Create approle
await got(`${vaultUrl}/v1/auth/approle/role/my-role`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns2',
},
json: {
policies: 'test'
},
});
// Get role-id
const roldIdResponse = await got(`${vaultUrl}/v1/auth/approle/role/my-role/role-id`, {
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns2',
},
responseType: 'json',
});
roleId = roldIdResponse.body.data.role_id;
// Get secret-id
const secretIdResponse = await got(`${vaultUrl}/v1/auth/approle/role/my-role/secret-id`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': 'ns2',
},
responseType: 'json',
});
secretId = secretIdResponse.body.data.secret_id;
} catch(err) {
console.warn('Create approle', err.response.body);
throw err;
}
});
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('method')
.mockReturnValueOnce('approle');
when(core.getInput)
.calledWith('roleId')
.mockReturnValueOnce(roleId);
when(core.getInput)
.calledWith('secretId')
.mockReturnValueOnce(secretId);
when(core.getInput)
.calledWith('url')
.mockReturnValueOnce(`${vaultUrl}`);
when(core.getInput)
.calledWith('namespace')
.mockReturnValueOnce('ns2');
});
it('authenticate with approle', async()=> {
mockInput('test secret');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET_WITH_APPROLE');
})
});
async function enableNamespace(name) {
try {
await got(`${vaultUrl}/v1/sys/namespaces/${name}`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
}
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("already exists")) {
// Namespace might already be enabled from previous test runs
} else {
throw error;
}
}
}
async function enableEngine(path, namespace, version) {
try {
await got(`${vaultUrl}/v1/sys/mounts/${path}`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': namespace,
},
json: { type: 'kv', config: {}, options: { version }, generate_signing_key: true },
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("path is already in use")) {
// Engine might already be enabled from previous test runs
} else {
throw error;
}
}
}
async function writeSecret(engine, path, namespace, version, data) {
const secretPath = (version == 1) ? (`${engine}/${path}`) : (`${engine}/data/${path}`);
const secretPayload = (version == 1) ? (data) : ({data});
await got(`${vaultUrl}/v1/${secretPath}`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
'X-Vault-Namespace': namespace,
},
json: secretPayload
});
}
function mockInput(secrets) {
when(core.getInput)
.calledWith('secrets')
.mockReturnValueOnce(secrets);
}
function mockEngineName(name) {
when(core.getInput)
.calledWith('path')
.mockReturnValueOnce(name);
}
function mockVersion(version) {
when(core.getInput)
.calledWith('kv-version')
.mockReturnValueOnce(version);
}
+1 -1
View File
@@ -1,3 +1,3 @@
module.exports = {
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/integration/', '<rootDir>/e2e/','<rootDir>/integration-ent'],
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/integrationTests/'],
};
+214 -155
View File
@@ -810,16 +810,16 @@
}
},
"@sindresorhus/is": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
"integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ=="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-1.2.0.tgz",
"integrity": "sha512-mwhXGkRV5dlvQc4EgPDxDxO6WuMBVymGFd1CA+2Y+z5dG9MNspoQ+AWjl/Ld1MnpCL8AKbosZlDVohqcIwuWsw=="
},
"@szmarczak/http-timer": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
"integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.0.tgz",
"integrity": "sha512-3yoXv8OtGr/r3R5gaWWNQ3VUoQ5G3Gmo8DXX95V14ZVvE2b7Pj6Ide9uIDON8ym4D/ItyfL9ejohYUPqOyvRXw==",
"requires": {
"defer-to-connect": "^1.0.1"
"defer-to-connect": "^1.1.1"
}
},
"@types/babel__core": {
@@ -863,6 +863,17 @@
"@babel/types": "^7.3.0"
}
},
"@types/cacheable-request": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz",
"integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==",
"requires": {
"@types/http-cache-semantics": "*",
"@types/keyv": "*",
"@types/node": "*",
"@types/responselike": "*"
}
},
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -880,6 +891,11 @@
"@types/node": "*"
}
},
"@types/http-cache-semantics": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
"integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A=="
},
"@types/istanbul-lib-coverage": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
@@ -920,6 +936,14 @@
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
"dev": true
},
"@types/keyv": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz",
"integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==",
"requires": {
"@types/node": "*"
}
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -929,8 +953,7 @@
"@types/node": {
"version": "12.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz",
"integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==",
"dev": true
"integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w=="
},
"@types/normalize-package-data": {
"version": "2.4.0",
@@ -938,6 +961,14 @@
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
"dev": true
},
"@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
"requires": {
"@types/node": "*"
}
},
"@types/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
@@ -1463,10 +1494,18 @@
"unset-value": "^1.0.0"
}
},
"cacheable-lookup": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-0.2.1.tgz",
"integrity": "sha512-BQ8MRjxJASEq2q+w0SusPU3B054gS278K8sj58QCLMZIso5qG05+MdCdmXxuyVlfvI8h4bPsNOavVUauVCGxrg==",
"requires": {
"keyv": "^3.1.0"
}
},
"cacheable-request": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
"integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.0.tgz",
"integrity": "sha512-UVG4gMn3WjnAeFBBx7RFoprgOANIAkMwN5Dta6ONmfSwrCxfm0Ip7g0mIBxIRJZX9aDsoID0Ry3dU5Pr0csKKA==",
"requires": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
@@ -1474,7 +1513,7 @@
"keyv": "^3.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^4.1.0",
"responselike": "^1.0.2"
"responselike": "^2.0.0"
},
"dependencies": {
"get-stream": {
@@ -1484,11 +1523,6 @@
"requires": {
"pump": "^3.0.0"
}
},
"lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
}
}
},
@@ -1646,6 +1680,13 @@
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
"requires": {
"mimic-response": "^1.0.0"
},
"dependencies": {
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
}
}
},
"co": {
@@ -1952,11 +1993,11 @@
"dev": true
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz",
"integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==",
"requires": {
"mimic-response": "^1.0.0"
"mimic-response": "^2.0.0"
}
},
"deep-extend": {
@@ -1972,9 +2013,9 @@
"dev": true
},
"defer-to-connect": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz",
"integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw=="
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.1.tgz",
"integrity": "sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ=="
},
"define-properties": {
"version": "1.1.3",
@@ -3184,6 +3225,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
@@ -3282,21 +3324,39 @@
}
},
"got": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
"integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/got/-/got-10.2.2.tgz",
"integrity": "sha512-QibZN13xHH/mc7H5uuU2xq28xxs8moEPsJrW9AQQX0jAV4DkGdllHDVE9cxw1nntIPFk8xzzOrgJZBg194AWrg==",
"requires": {
"@sindresorhus/is": "^0.14.0",
"@szmarczak/http-timer": "^1.1.2",
"cacheable-request": "^6.0.0",
"decompress-response": "^3.3.0",
"@sindresorhus/is": "^1.0.0",
"@szmarczak/http-timer": "^4.0.0",
"@types/cacheable-request": "^6.0.1",
"cacheable-lookup": "^0.2.1",
"cacheable-request": "^7.0.0",
"decompress-response": "^5.0.0",
"duplexer3": "^0.1.4",
"get-stream": "^4.1.0",
"lowercase-keys": "^1.0.1",
"mimic-response": "^1.0.1",
"p-cancelable": "^1.0.0",
"to-readable-stream": "^1.0.0",
"url-parse-lax": "^3.0.0"
"get-stream": "^5.0.0",
"lowercase-keys": "^2.0.0",
"mimic-response": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0",
"to-readable-stream": "^2.0.0",
"type-fest": "^0.8.0"
},
"dependencies": {
"get-stream": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
"integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
"requires": {
"pump": "^3.0.0"
}
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
}
}
},
"graceful-fs": {
@@ -3312,9 +3372,9 @@
"dev": true
},
"handlebars": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.1.tgz",
"integrity": "sha512-bqPIlDk06UWbVEIFoYj+LVo42WhK96J+b25l7hbFDpxrOXMphFM3fNIm+cluwg4Pk2jiLjWU5nHQY7igGE75NQ==",
"version": "4.5.3",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",
@@ -4669,9 +4729,9 @@
}
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
},
"lru-cache": {
"version": "5.1.1",
@@ -4889,9 +4949,9 @@
"dev": true
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.0.0.tgz",
"integrity": "sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ=="
},
"minimatch": {
"version": "3.0.4",
@@ -5137,9 +5197,9 @@
"integrity": "sha512-rjH3yRt0Ssx19mUwS0hrDUOdG9VI+oRLpLHJ7tXRdjcuQ7v7wo6qPvOZppHRrqfslTKr0L2yBhjj4UXd7c3cQg=="
},
"npm": {
"version": "6.11.3",
"resolved": "https://registry.npmjs.org/npm/-/npm-6.11.3.tgz",
"integrity": "sha512-K2h+MPzZiY39Xf6eHEdECe/LKoJXam4UCflz5kIxoskN3LQFeYs5fqBGT5i4TtM/aBk+86Mcf+jgXs/WuWAutQ==",
"version": "6.13.4",
"resolved": "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz",
"integrity": "sha512-vTcUL4SCg3AzwInWTbqg1OIaOXlzKSS8Mb8kc5avwrJpcvevDA5J9BhYSuei+fNs3pwOp4lzA5x2FVDXACvoXA==",
"dev": true,
"requires": {
"JSONStream": "^1.3.5",
@@ -5148,12 +5208,12 @@
"ansistyles": "~0.1.3",
"aproba": "^2.0.0",
"archy": "~1.0.0",
"bin-links": "^1.1.3",
"bin-links": "^1.1.6",
"bluebird": "^3.5.5",
"byte-size": "^5.0.1",
"cacache": "^12.0.3",
"call-limit": "^1.1.1",
"chownr": "^1.1.2",
"chownr": "^1.1.3",
"ci-info": "^2.0.0",
"cli-columns": "^3.1.2",
"cli-table3": "^0.5.1",
@@ -5169,11 +5229,11 @@
"find-npm-prefix": "^1.0.2",
"fs-vacuum": "~1.2.10",
"fs-write-stream-atomic": "~1.0.10",
"gentle-fs": "^2.2.1",
"gentle-fs": "^2.3.0",
"glob": "^7.1.4",
"graceful-fs": "^4.2.2",
"graceful-fs": "^4.2.3",
"has-unicode": "~2.0.1",
"hosted-git-info": "^2.8.2",
"hosted-git-info": "^2.8.5",
"iferr": "^1.0.2",
"imurmurhash": "*",
"infer-owner": "^1.0.4",
@@ -5184,7 +5244,7 @@
"is-cidr": "^3.0.0",
"json-parse-better-errors": "^1.0.2",
"lazy-property": "~1.0.0",
"libcipm": "^4.0.3",
"libcipm": "^4.0.7",
"libnpm": "^3.0.1",
"libnpmaccess": "^3.0.2",
"libnpmhook": "^5.0.3",
@@ -5210,33 +5270,33 @@
"mississippi": "^3.0.0",
"mkdirp": "~0.5.1",
"move-concurrently": "^1.0.1",
"node-gyp": "^5.0.3",
"node-gyp": "^5.0.5",
"nopt": "~4.0.1",
"normalize-package-data": "^2.5.0",
"npm-audit-report": "^1.3.2",
"npm-cache-filename": "~1.0.2",
"npm-install-checks": "~3.0.0",
"npm-lifecycle": "^3.1.3",
"npm-install-checks": "^3.0.2",
"npm-lifecycle": "^3.1.4",
"npm-package-arg": "^6.1.1",
"npm-packlist": "^1.4.4",
"npm-packlist": "^1.4.7",
"npm-pick-manifest": "^3.0.2",
"npm-profile": "^4.0.2",
"npm-registry-fetch": "^4.0.0",
"npm-registry-fetch": "^4.0.2",
"npm-user-validate": "~1.0.0",
"npmlog": "~4.1.2",
"once": "~1.4.0",
"opener": "^1.5.1",
"osenv": "^0.1.5",
"pacote": "^9.5.8",
"pacote": "^9.5.11",
"path-is-inside": "~1.0.2",
"promise-inflight": "~1.0.1",
"qrcode-terminal": "^0.12.0",
"query-string": "^6.8.2",
"qw": "~1.0.1",
"read": "~1.0.7",
"read-cmd-shim": "^1.0.4",
"read-cmd-shim": "^1.0.5",
"read-installed": "~4.0.3",
"read-package-json": "^2.1.0",
"read-package-json": "^2.1.1",
"read-package-tree": "^5.3.1",
"readable-stream": "^3.4.0",
"readdir-scoped-modules": "^1.1.0",
@@ -5250,8 +5310,8 @@
"sorted-object": "~2.0.1",
"sorted-union-stream": "~2.1.3",
"ssri": "^6.0.1",
"stringify-package": "^1.0.0",
"tar": "^4.4.10",
"stringify-package": "^1.0.1",
"tar": "^4.4.13",
"text-table": "~0.2.0",
"tiny-relative-date": "^1.3.0",
"uid-number": "0.0.6",
@@ -5259,7 +5319,7 @@
"unique-filename": "^1.1.1",
"unpipe": "~1.0.0",
"update-notifier": "^2.5.0",
"uuid": "^3.3.2",
"uuid": "^3.3.3",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "~3.0.0",
"which": "^1.3.1",
@@ -5430,14 +5490,15 @@
}
},
"bin-links": {
"version": "1.1.3",
"version": "1.1.6",
"bundled": true,
"dev": true,
"requires": {
"bluebird": "^3.5.3",
"cmd-shim": "^3.0.0",
"gentle-fs": "^2.0.1",
"gentle-fs": "^2.3.0",
"graceful-fs": "^4.1.15",
"npm-normalize-package-bin": "^1.0.0",
"write-file-atomic": "^2.3.0"
}
},
@@ -5542,7 +5603,7 @@
}
},
"chownr": {
"version": "1.1.2",
"version": "1.1.3",
"bundled": true,
"dev": true
},
@@ -6180,11 +6241,22 @@
}
},
"fs-minipass": {
"version": "1.2.6",
"version": "1.2.7",
"bundled": true,
"dev": true,
"requires": {
"minipass": "^2.2.1"
"minipass": "^2.6.0"
},
"dependencies": {
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
}
}
},
"fs-vacuum": {
@@ -6285,12 +6357,13 @@
"dev": true
},
"gentle-fs": {
"version": "2.2.1",
"version": "2.3.0",
"bundled": true,
"dev": true,
"requires": {
"aproba": "^1.1.2",
"chownr": "^1.1.2",
"cmd-shim": "^3.0.3",
"fs-vacuum": "^1.2.10",
"graceful-fs": "^4.1.11",
"iferr": "^0.1.5",
@@ -6381,7 +6454,7 @@
}
},
"graceful-fs": {
"version": "4.2.2",
"version": "4.2.3",
"bundled": true,
"dev": true
},
@@ -6423,12 +6496,9 @@
"dev": true
},
"hosted-git-info": {
"version": "2.8.2",
"version": "2.8.5",
"bundled": true,
"dev": true,
"requires": {
"lru-cache": "^5.1.1"
}
"dev": true
},
"http-cache-semantics": {
"version": "3.8.1",
@@ -6455,7 +6525,7 @@
}
},
"https-proxy-agent": {
"version": "2.2.2",
"version": "2.2.4",
"bundled": true,
"dev": true,
"requires": {
@@ -6485,7 +6555,7 @@
"dev": true
},
"ignore-walk": {
"version": "3.0.1",
"version": "3.0.3",
"bundled": true,
"dev": true,
"requires": {
@@ -6739,7 +6809,7 @@
}
},
"libcipm": {
"version": "4.0.3",
"version": "4.0.7",
"bundled": true,
"dev": true,
"requires": {
@@ -7042,7 +7112,7 @@
}
},
"make-fetch-happen": {
"version": "5.0.0",
"version": "5.0.2",
"bundled": true,
"dev": true,
"requires": {
@@ -7050,7 +7120,7 @@
"cacache": "^12.0.0",
"http-cache-semantics": "^3.8.1",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.1",
"https-proxy-agent": "^2.2.3",
"lru-cache": "^5.1.1",
"mississippi": "^3.0.0",
"node-fetch-npm": "^2.0.2",
@@ -7103,30 +7173,25 @@
"bundled": true,
"dev": true
},
"minipass": {
"version": "2.3.3",
"minizlib": {
"version": "1.3.3",
"bundled": true,
"dev": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
"minipass": "^2.9.0"
},
"dependencies": {
"yallist": {
"version": "3.0.2",
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true
"dev": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
}
}
},
"minizlib": {
"version": "1.2.1",
"bundled": true,
"dev": true,
"requires": {
"minipass": "^2.2.1"
}
},
"mississippi": {
"version": "3.0.0",
"bundled": true,
@@ -7193,7 +7258,7 @@
}
},
"node-gyp": {
"version": "5.0.3",
"version": "5.0.5",
"bundled": true,
"dev": true,
"requires": {
@@ -7206,7 +7271,7 @@
"request": "^2.87.0",
"rimraf": "2",
"semver": "~5.3.0",
"tar": "^4.4.8",
"tar": "^4.4.12",
"which": "1"
},
"dependencies": {
@@ -7265,9 +7330,12 @@
}
},
"npm-bundled": {
"version": "1.0.6",
"version": "1.1.1",
"bundled": true,
"dev": true
"dev": true,
"requires": {
"npm-normalize-package-bin": "^1.0.1"
}
},
"npm-cache-filename": {
"version": "1.0.2",
@@ -7275,7 +7343,7 @@
"dev": true
},
"npm-install-checks": {
"version": "3.0.0",
"version": "3.0.2",
"bundled": true,
"dev": true,
"requires": {
@@ -7283,7 +7351,7 @@
}
},
"npm-lifecycle": {
"version": "3.1.3",
"version": "3.1.4",
"bundled": true,
"dev": true,
"requires": {
@@ -7302,6 +7370,11 @@
"bundled": true,
"dev": true
},
"npm-normalize-package-bin": {
"version": "1.0.1",
"bundled": true,
"dev": true
},
"npm-package-arg": {
"version": "6.1.1",
"bundled": true,
@@ -7314,7 +7387,7 @@
}
},
"npm-packlist": {
"version": "1.4.4",
"version": "1.4.7",
"bundled": true,
"dev": true,
"requires": {
@@ -7343,7 +7416,7 @@
}
},
"npm-registry-fetch": {
"version": "4.0.0",
"version": "4.0.2",
"bundled": true,
"dev": true,
"requires": {
@@ -7352,7 +7425,15 @@
"figgy-pudding": "^3.4.1",
"lru-cache": "^5.1.1",
"make-fetch-happen": "^5.0.0",
"npm-package-arg": "^6.1.0"
"npm-package-arg": "^6.1.0",
"safe-buffer": "^5.2.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.0",
"bundled": true,
"dev": true
}
}
},
"npm-run-path": {
@@ -7488,7 +7569,7 @@
}
},
"pacote": {
"version": "9.5.8",
"version": "9.5.11",
"bundled": true,
"dev": true,
"requires": {
@@ -7506,6 +7587,7 @@
"mississippi": "^3.0.0",
"mkdirp": "^0.5.1",
"normalize-package-data": "^2.4.0",
"npm-normalize-package-bin": "^1.0.0",
"npm-package-arg": "^6.1.0",
"npm-packlist": "^1.1.12",
"npm-pick-manifest": "^3.0.0",
@@ -7524,7 +7606,7 @@
},
"dependencies": {
"minipass": {
"version": "2.3.5",
"version": "2.9.0",
"bundled": true,
"dev": true,
"requires": {
@@ -7757,7 +7839,7 @@
}
},
"read-cmd-shim": {
"version": "1.0.4",
"version": "1.0.5",
"bundled": true,
"dev": true,
"requires": {
@@ -7779,7 +7861,7 @@
}
},
"read-package-json": {
"version": "2.1.0",
"version": "2.1.1",
"bundled": true,
"dev": true,
"requires": {
@@ -7787,7 +7869,7 @@
"graceful-fs": "^4.1.2",
"json-parse-better-errors": "^1.0.1",
"normalize-package-data": "^2.0.0",
"slash": "^1.0.0"
"npm-normalize-package-bin": "^1.0.0"
}
},
"read-package-tree": {
@@ -7962,28 +8044,23 @@
"bundled": true,
"dev": true
},
"slash": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"slide": {
"version": "1.1.6",
"bundled": true,
"dev": true
},
"smart-buffer": {
"version": "4.0.2",
"version": "4.1.0",
"bundled": true,
"dev": true
},
"socks": {
"version": "2.3.2",
"version": "2.3.3",
"bundled": true,
"dev": true,
"requires": {
"ip": "^1.1.5",
"smart-buffer": "4.0.2"
"ip": "1.1.5",
"smart-buffer": "^4.1.0"
}
},
"socks-proxy-agent": {
@@ -8198,7 +8275,7 @@
}
},
"stringify-package": {
"version": "1.0.0",
"version": "1.0.1",
"bundled": true,
"dev": true
},
@@ -8229,13 +8306,13 @@
}
},
"tar": {
"version": "4.4.10",
"version": "4.4.13",
"bundled": true,
"dev": true,
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.3.5",
"minipass": "^2.8.6",
"minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
@@ -8243,18 +8320,13 @@
},
"dependencies": {
"minipass": {
"version": "2.3.5",
"version": "2.9.0",
"bundled": true,
"dev": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
}
}
},
@@ -8435,7 +8507,7 @@
}
},
"uuid": {
"version": "3.3.2",
"version": "3.3.3",
"bundled": true,
"dev": true
},
@@ -8779,9 +8851,9 @@
}
},
"p-cancelable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
"integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw=="
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz",
"integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg=="
},
"p-each-series": {
"version": "1.0.0",
@@ -9029,11 +9101,6 @@
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
"dev": true
},
"prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
},
"pretty-format": {
"version": "24.9.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz",
@@ -9330,11 +9397,11 @@
"dev": true
},
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
"integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
"integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
"requires": {
"lowercase-keys": "^1.0.0"
"lowercase-keys": "^2.0.0"
}
},
"ret": {
@@ -10245,9 +10312,9 @@
}
},
"to-readable-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
"integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q=="
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz",
"integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w=="
},
"to-regex": {
"version": "3.0.2",
@@ -10443,14 +10510,6 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"dev": true
},
"url-parse-lax": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
"integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
"requires": {
"prepend-http": "^2.0.0"
}
},
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+4 -4
View File
@@ -6,9 +6,9 @@
"scripts": {
"build": "ncc build index.js -o dist",
"test": "jest",
"test:integration": "jest -c integration/jest.config.js",
"test:integration-ent": "jest -c integration-ent/jest.config.js",
"test:e2e": "jest -c e2e/jest.config.js"
"test:integration:basic": "jest -c integrationTests/basic/jest.config.js",
"test:integration:enterprise": "jest -c integrationTests/enterprise/jest.config.js",
"test:e2e": "jest -c integrationTests/e2e/jest.config.js"
},
"release": {
"branch": "master",
@@ -39,7 +39,7 @@
"homepage": "https://github.com/RichiCoder1/vault-action#readme",
"dependencies": {
"@actions/core": "^1.1.1",
"got": "^9.6.0"
"got": "^10.2.2"
},
"devDependencies": {
"@types/jest": "^24.0.18",