Compare commits

...

7 Commits

Author SHA1 Message Date
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
20 changed files with 3727 additions and 2527 deletions
+68 -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,37 @@ 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: 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
+49 -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 the K/V backend of vault.
Expects [Version 2](https://www.vaultproject.io/docs/secrets/kv/kv-v2/) of the KV Secrets Engine by default.
## Example Usage
@@ -22,6 +24,26 @@ jobs:
# ...
```
## Authentication method
The `method` parameter can have these value :
- **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 +95,33 @@ 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 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`.
### Namespace
This action could be use with namespace Vault Enterprise feature. You can specify namespace in request :
This action could be use with namespace Vault Enterprise feature. You can specify namespace in request :
```yaml
steps:
@@ -84,6 +130,7 @@ steps:
uses: RichiCoder1/vault-action
with:
url: https://vault-enterprise.mycompany.com:8200
method: token
token: ${{ secrets.VaultToken }}
namespace: ns1
secrets: |
+88 -11
View File
@@ -2,31 +2,84 @@ const core = require('@actions/core');
const command = require('@actions/core/lib/command');
const got = require('got');
const AUTH_METHODS = ['approle', 'token'];
async function exportSecrets() {
const vaultUrl = core.getInput('url', { required: true });
const vaultToken = core.getInput('token', { required: true });
const vaultNamespace = core.getInput('namespace', { required: false });
let enginePath = core.getInput('path', { required: false });
let kvVersion = core.getInput('kv-version', { required: false });
const secretsInput = core.getInput('secrets', { required: true });
const secrets = 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';
}
if (kvVersion !== '1' && kvVersion !== '2') {
throw Error(`You must provide a valid K/V version (1 or 2). Input: "${kvVersion}"`);
}
kvVersion = parseInt(kvVersion);
for (const secret of secrets) {
const { secretPath, outputName, secretKey } = secret;
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);
const requestPath = (kvVersion === 1)
? `${vaultUrl}/v1/${enginePath}/${secretPath}`
: `${vaultUrl}/v1/${enginePath}/data/${secretPath}`;
const result = await got(requestPath, requestOptions);
const parsedResponse = JSON.parse(result.body);
const vaultKeyData = parsedResponse.data;
const versionData = vaultKeyData.data;
const value = versionData[secretKey];
const secretData = parseResponse(result.body, kvVersion);
const value = secretData[secretKey];
command.issue('add-mask', value);
core.exportVariable(outputName, `${value}`);
core.debug(`${secretPath} => ${outputName}`);
@@ -35,7 +88,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
@@ -86,7 +139,30 @@ function parseSecretsInput(secretsInput) {
}
/**
* Replaces any forward-slash characters to
* Parses a JSON response and returns the secret data
* @param {string} responseBody
* @param {number} kvVersion
*/
function parseResponse(responseBody, kvVersion) {
const parsedResponse = JSON.parse(responseBody);
let secretData;
switch(kvVersion) {
case 1: {
secretData = parsedResponse.data;
} break;
case 2: {
const vaultKeyData = parsedResponse.data;
secretData = vaultKeyData.data;
} break;
}
return secretData;
}
/**
* Replaces any forward-slash characters to
* @param {string} dataKey
*/
function normalizeOutputKey(dataKey) {
@@ -96,5 +172,6 @@ function normalizeOutputKey(dataKey) {
module.exports = {
exportSecrets,
parseSecretsInput,
parseResponse,
normalizeOutputKey
};
+76 -12
View File
@@ -7,6 +7,7 @@ const got = require('got');
const {
exportSecrets,
parseSecretsInput,
parseResponse
} = require('./action');
const { when } = require('jest-when');
@@ -82,6 +83,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 +122,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 +183,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');
});
});
+2658 -2029
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
-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');
});
});
+174
View File
@@ -0,0 +1,174 @@
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');
});
});
+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.
@@ -3,5 +3,8 @@ describe('e2e', () => {
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");
});
});
});
+71
View File
@@ -0,0 +1,71 @@
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',
},
});
} 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",