@wavo-cloud/aws-secrets-manager-helper 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +69 -0
- package/.prettierrc +9 -0
- package/CHANGELOG.md +66 -0
- package/Dockerfile +19 -0
- package/README.md +46 -0
- package/app/index.js +2 -0
- package/app/utils/awsSecretsManager.js +104 -0
- package/docker-compose.test.yml +17 -0
- package/package.json +44 -0
- package/test/aws.test.js +19 -0
- package/yarn.lock +5685 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
confiversion: 2
|
|
2
|
+
jobs:
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
test:
|
|
6
|
+
docker:
|
|
7
|
+
- image: circleci/node:10.15
|
|
8
|
+
|
|
9
|
+
steps:
|
|
10
|
+
- checkout
|
|
11
|
+
- setup_remote_docker
|
|
12
|
+
|
|
13
|
+
# Download and cache dependencies
|
|
14
|
+
- restore_cache: &restore_cache
|
|
15
|
+
keys:
|
|
16
|
+
- v1-dependencies-{{ checksum "package.json" }}
|
|
17
|
+
# fallback to using the latest cache if no exact match is found
|
|
18
|
+
- v1-dependencies-
|
|
19
|
+
|
|
20
|
+
- run: yarn install
|
|
21
|
+
|
|
22
|
+
- save_cache:
|
|
23
|
+
paths:
|
|
24
|
+
- node_modules
|
|
25
|
+
key: v1-dependencies-{{ checksum "package.json" }}
|
|
26
|
+
|
|
27
|
+
# run tests!
|
|
28
|
+
- run:
|
|
29
|
+
name: Run tests (if possible)
|
|
30
|
+
command: |
|
|
31
|
+
if ./node_modules/@wavo-cloud/generator-microservice/shared/util/test-checks.sh; then
|
|
32
|
+
yarn ci-test
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
module-push:
|
|
36
|
+
docker:
|
|
37
|
+
- image: circleci/node:10.15
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- checkout
|
|
41
|
+
|
|
42
|
+
- restore_cache: *restore_cache
|
|
43
|
+
|
|
44
|
+
- run:
|
|
45
|
+
name: Deploy (if possible)
|
|
46
|
+
command: |
|
|
47
|
+
if [ ! -z "${WAVO_CLOUD_WRITE_NPM_TOKEN}" ]; then
|
|
48
|
+
echo "//registry.npmjs.org/:_authToken=$WAVO_CLOUD_WRITE_NPM_TOKEN" > .npmrc
|
|
49
|
+
npm whoami
|
|
50
|
+
npm publish
|
|
51
|
+
else
|
|
52
|
+
echo "WAVO_CLOUD_WRITE_NPM_TOKEN not found. Skipping generator module push."
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
workflows:
|
|
57
|
+
version: 2
|
|
58
|
+
test-and-deploy:
|
|
59
|
+
jobs:
|
|
60
|
+
- test:
|
|
61
|
+
context: org-global
|
|
62
|
+
- module-push:
|
|
63
|
+
context: org-global
|
|
64
|
+
requires:
|
|
65
|
+
- test
|
|
66
|
+
|
|
67
|
+
filters:
|
|
68
|
+
branches:
|
|
69
|
+
only: master
|
package/.prettierrc
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
0.2.16
|
|
2
|
+
-----
|
|
3
|
+
- Removed logout on unauthorized hash error
|
|
4
|
+
- added isWavoUser() function
|
|
5
|
+
|
|
6
|
+
0.2.12
|
|
7
|
+
-----
|
|
8
|
+
- FIX: added base url to local storage listener logout
|
|
9
|
+
|
|
10
|
+
0.2.10
|
|
11
|
+
-----
|
|
12
|
+
- added infinite loop fix to auth cookies module
|
|
13
|
+
|
|
14
|
+
0.2.9
|
|
15
|
+
-----
|
|
16
|
+
- fix: fixed infinite loop for non @wavo.me emails
|
|
17
|
+
|
|
18
|
+
0.2.8
|
|
19
|
+
-----
|
|
20
|
+
- removed dev console logs
|
|
21
|
+
|
|
22
|
+
0.2.7
|
|
23
|
+
-----
|
|
24
|
+
- added get apps functionality
|
|
25
|
+
|
|
26
|
+
0.2.6
|
|
27
|
+
-----
|
|
28
|
+
- added get user function
|
|
29
|
+
|
|
30
|
+
0.2.5
|
|
31
|
+
-----
|
|
32
|
+
- added token renewal logic to silent checksession auth flow
|
|
33
|
+
|
|
34
|
+
0.2.4
|
|
35
|
+
-----
|
|
36
|
+
- added support for checkSession on not authenticated
|
|
37
|
+
|
|
38
|
+
0.2.3
|
|
39
|
+
-----
|
|
40
|
+
- added support for query strings
|
|
41
|
+
|
|
42
|
+
0.2.0
|
|
43
|
+
-----
|
|
44
|
+
- Added init() function that allows client side to set callback URL for particular service
|
|
45
|
+
|
|
46
|
+
0.1.5
|
|
47
|
+
-----
|
|
48
|
+
- Getting navbar name from email (since nickname is not always defined on social logins)
|
|
49
|
+
|
|
50
|
+
0.1.5
|
|
51
|
+
-----
|
|
52
|
+
- Added handling for dev/production config
|
|
53
|
+
|
|
54
|
+
0.1.1
|
|
55
|
+
-----
|
|
56
|
+
- Added getAccessToken() getter and refactored constants
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
0.1.0
|
|
60
|
+
-----
|
|
61
|
+
- First fully functional test commit with all basic necessary authentication functionality
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
0.0.0
|
|
65
|
+
-----
|
|
66
|
+
- Initial Commit.
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
FROM node:10.15-alpine
|
|
2
|
+
|
|
3
|
+
# Create app directory
|
|
4
|
+
RUN mkdir -p /usr/local/src/cloud-app
|
|
5
|
+
WORKDIR /usr/local/src/cloud-app
|
|
6
|
+
|
|
7
|
+
# Add .npmrc, package.json & yarn.lock
|
|
8
|
+
COPY .npmrc /usr/local/src/cloud-app/.npmrc
|
|
9
|
+
COPY package.json yarn.lock /usr/local/src/cloud-app/
|
|
10
|
+
|
|
11
|
+
# Install modules with yarn
|
|
12
|
+
RUN yarn
|
|
13
|
+
|
|
14
|
+
# Copy the code
|
|
15
|
+
COPY . /usr/local/src/cloud-app/
|
|
16
|
+
|
|
17
|
+
# Let's roll!
|
|
18
|
+
EXPOSE 3000
|
|
19
|
+
CMD [ "yarn", "start" ]
|
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# wavo-cloud.auth-ui-helper
|
|
2
|
+
|
|
3
|
+
> Wavo Cloud Infallible AWS Secrets Manager Helper
|
|
4
|
+
|
|
5
|
+
## Important Commands
|
|
6
|
+
|
|
7
|
+
### Building the Dockerfile image
|
|
8
|
+
$ yarn image-build
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Prettify the Source
|
|
12
|
+
$ yarn prettify
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Start the Microservice
|
|
16
|
+
When using this option, node is passed the `--inspect` flag so you can inspect your code with the debugger of your choice. If your microservice is a worker or if you need it to block and wait for the debugger to connect use the "debug mode" instead.
|
|
17
|
+
|
|
18
|
+
$ yarn start
|
|
19
|
+
|
|
20
|
+
Dockerized version (using `docker-compose`):
|
|
21
|
+
|
|
22
|
+
$ yarn docker-start
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Start the Microservice in Debug Mode
|
|
26
|
+
|
|
27
|
+
Important: when you run the microservice in debug mode, it is going to be started with node's `--inspect-brk` flag.
|
|
28
|
+
**This implies that the microservice will block and wait for a debugger to connect to port 5858 and resume code execution.**
|
|
29
|
+
|
|
30
|
+
$ yarn debug
|
|
31
|
+
|
|
32
|
+
Dockerized version (using `docker-compose`):
|
|
33
|
+
|
|
34
|
+
$ yarn docker-debug
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Running the Tests
|
|
38
|
+
|
|
39
|
+
Important: when you run the microservice in debug mode, it is going to be started with node's `--inspect-brk` flag.
|
|
40
|
+
**This implies that the microservice will block and wait for a debugger to connect to port 5858 and resume code execution.**
|
|
41
|
+
|
|
42
|
+
$ yarn test
|
|
43
|
+
|
|
44
|
+
Dockerized version (using `docker-compose`):
|
|
45
|
+
|
|
46
|
+
$ yarn docker-test
|
package/app/index.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const AWS = require('aws-sdk')
|
|
2
|
+
|
|
3
|
+
const region = 'us-east-1'
|
|
4
|
+
const clientIdsSecretId = 'wavo/self_serve/client_list'
|
|
5
|
+
const client = new AWS.SecretsManager({
|
|
6
|
+
region,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
// attempts to parse secret
|
|
10
|
+
async function parseSecret(secretString) {
|
|
11
|
+
let parsedSecret = {}
|
|
12
|
+
try {
|
|
13
|
+
parsedSecret = JSON.parse(secretString)
|
|
14
|
+
return parsedSecret
|
|
15
|
+
} catch (error) {
|
|
16
|
+
parsedSecret.error = 'Could not parse client secret'
|
|
17
|
+
return parsedSecret
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// gets a defined secret value from aws secrets manager
|
|
22
|
+
// returns JSON where JSON is the secret
|
|
23
|
+
async function getSecretValue(secretId) {
|
|
24
|
+
let promiseError
|
|
25
|
+
const data = await client
|
|
26
|
+
.getSecretValue({ SecretId: secretId })
|
|
27
|
+
.promise()
|
|
28
|
+
.catch(error => {
|
|
29
|
+
promiseError = error
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
if (promiseError) {
|
|
33
|
+
if (promiseError.code === 'DecryptionFailureException') {
|
|
34
|
+
promiseError.message =
|
|
35
|
+
"Secrets Manager can't decrypt the protected secret text using the provided KMS key."
|
|
36
|
+
throw promiseError
|
|
37
|
+
} else if (promiseError.code === 'InternalServiceErrorException') {
|
|
38
|
+
promiseError.message = 'An error occurred on the server side.'
|
|
39
|
+
throw promiseError
|
|
40
|
+
} else if (promiseError.code === 'InvalidParameterException') {
|
|
41
|
+
promiseError.message = 'You provided an invalid value for a parameter.'
|
|
42
|
+
throw promiseError
|
|
43
|
+
} else if (promiseError.code === 'InvalidRequestException') {
|
|
44
|
+
promiseError.message =
|
|
45
|
+
'You provided a parameter value that is not valid for the current state of the resource.'
|
|
46
|
+
throw promiseError
|
|
47
|
+
} else if (promiseError.code === 'ResourceNotFoundException') {
|
|
48
|
+
promiseError.message = "We can't find the resource that you asked for."
|
|
49
|
+
throw promiseError
|
|
50
|
+
}
|
|
51
|
+
} else if ('SecretString' in data) {
|
|
52
|
+
return parseSecret(data.SecretString)
|
|
53
|
+
} else {
|
|
54
|
+
const buff = Buffer.from(data.SecretBinary, 'base64')
|
|
55
|
+
return parseSecret(buff.toString('ascii'))
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// gets the secret keying where client secrets are stored
|
|
60
|
+
// returns JSON where JSON is the secret
|
|
61
|
+
async function getClientSecretIds() {
|
|
62
|
+
return getSecretValue(clientIdsSecretId)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// gets a specific client secret holding their API keys
|
|
66
|
+
// returns JSON where JSON is the secret
|
|
67
|
+
async function getClientSecret(clientId) {
|
|
68
|
+
const clientSecretIds = await getClientSecretIds()
|
|
69
|
+
return getSecretValue(clientSecretIds[clientId])
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// gets all client secrets holding their API keys
|
|
73
|
+
// returns [{ clientId: String, secretId: String, ...secret }]
|
|
74
|
+
// skips all that are missing a region or organization
|
|
75
|
+
async function getAllClientSecrets() {
|
|
76
|
+
const clientSecretIds = await getClientSecretIds()
|
|
77
|
+
if (!clientSecretIds) {
|
|
78
|
+
console.log('No clients found')
|
|
79
|
+
return []
|
|
80
|
+
}
|
|
81
|
+
const parsedClientSecrets = await Promise.all(
|
|
82
|
+
Object.keys(clientSecretIds).map(async clientId => {
|
|
83
|
+
const result = await getSecretValue(clientSecretIds[clientId])
|
|
84
|
+
result.id = clientId
|
|
85
|
+
result.secretId = clientSecretIds[clientId]
|
|
86
|
+
return result
|
|
87
|
+
})
|
|
88
|
+
)
|
|
89
|
+
return parsedClientSecrets.filter(clientSecret => {
|
|
90
|
+
if (clientSecret.organization && clientSecret.region && !clientSecret.error)
|
|
91
|
+
return true
|
|
92
|
+
console.log(
|
|
93
|
+
`Client secret at ${clientSecret.secretId} is missing organization or region`
|
|
94
|
+
)
|
|
95
|
+
return false
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
getClientSecretIds,
|
|
101
|
+
getClientSecret,
|
|
102
|
+
getAllClientSecrets,
|
|
103
|
+
getSecretValue,
|
|
104
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wavo-cloud/aws-secrets-manager-helper",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Wavo Cloud Infallible AWS Secrets Manager Helper",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/Wavo/wavo-cloud.aws-secrets-manager-helper.git"
|
|
9
|
+
},
|
|
10
|
+
"wavoCloud": {
|
|
11
|
+
"enableK8sDeployment": false,
|
|
12
|
+
"name": "wavo-cloud.aws-secrets-manager-helper"
|
|
13
|
+
},
|
|
14
|
+
"main": "app/index.js",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"image-build": "./node_modules/@wavo-cloud/generator-microservice/shared/util/image-build.sh",
|
|
17
|
+
"image-push": "./node_modules/@wavo-cloud/generator-microservice/shared/util/image-push.sh",
|
|
18
|
+
"k8s-deploy": "./node_modules/@wavo-cloud/generator-microservice/shared/util/k8s-deploy.sh",
|
|
19
|
+
"prettier": "node ./node_modules/prettier/bin-prettier.js --write --single-quote --print-width 120 --no-semi '**/*.js'",
|
|
20
|
+
"test": "NODE_ENV=${NODE_ENV-test} node ./node_modules/mocha/bin/mocha --recursive --require mock-local-storage",
|
|
21
|
+
"docker-dev-up": "docker-compose -f ./docker-compose.dev.yml up",
|
|
22
|
+
"docker-dev-down": "docker-compose -f ./docker-compose.dev.yml down",
|
|
23
|
+
"docker-test": "docker-compose -f ./docker-compose.test.yml down; docker-compose -f ./docker-compose.test.yml build && docker-compose -f ./docker-compose.test.yml run --rm app; R=$?; docker-compose -f ./docker-compose.test.yml down; [ $R -eq 0 ]",
|
|
24
|
+
"ci-test": "yarn docker-test"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@wavo-cloud/generator-microservice": "^2.5.0",
|
|
28
|
+
"chai": "^4.2.0",
|
|
29
|
+
"eslint": "^5.6.0",
|
|
30
|
+
"eslint-config-prettier": "^3.1.0",
|
|
31
|
+
"mocha": "^5.2.0",
|
|
32
|
+
"mock-local-storage": "^1.1.7",
|
|
33
|
+
"prettier": "^1.14.3",
|
|
34
|
+
"webpack": "^4.27.1",
|
|
35
|
+
"webpack-cli": "^3.1.2"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"auth0-js": "^9.8.0",
|
|
39
|
+
"aws-sdk": "^2.713.0",
|
|
40
|
+
"js-cookie": "^2.2.0",
|
|
41
|
+
"jsonwebtoken": "^8.5.1",
|
|
42
|
+
"jwt-decode": "^2.2.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/test/aws.test.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getAllClientSecrets,
|
|
3
|
+
} = require('../app/utils/awsSecretsManager')
|
|
4
|
+
const expect = require('chai').expect
|
|
5
|
+
|
|
6
|
+
const clientIdsSecretId = 'wavo/self_serve/client_list'
|
|
7
|
+
|
|
8
|
+
describe('Test Secrets Manager Helper', async () => {
|
|
9
|
+
/**
|
|
10
|
+
* This function call tests all of the helper functions
|
|
11
|
+
*/
|
|
12
|
+
it('should get all client secrets', async () => {
|
|
13
|
+
const clientSecrets = await getAllClientSecrets()
|
|
14
|
+
expect(Array.isArray(clientSecrets)).to.be.true
|
|
15
|
+
expect(clientSecrets.length).to.be.above(0)
|
|
16
|
+
expect(clientSecrets[0].clientId).to.not.be.null
|
|
17
|
+
expect(clientSecrets[0].secretId).to.not.be.null
|
|
18
|
+
})
|
|
19
|
+
})
|