@nitra/cf-security 2.0.50 → 3.1.1
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/README.md +18 -2
- package/package.json +28 -7
- package/src/index.js +9 -20
- package/src/jwt.js +54 -0
- package/.github/workflows/npm-publish.yml +0 -41
- package/super-linter.log +0 -2217
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# cf-security
|
|
2
2
|
|
|
3
|
+
[](https://github.com/marketplace/actions/super-linter)
|
|
4
|
+
|
|
3
5
|
Check security header in Cloud Functions
|
|
4
6
|
|
|
5
|
-
```
|
|
7
|
+
```HTTP
|
|
6
8
|
X_NITRA_CF_KEY: secret
|
|
7
9
|
```
|
|
8
10
|
|
|
9
|
-
```
|
|
11
|
+
```JavaScript
|
|
10
12
|
const { cfSecurity } = require('@nitra/cf-security')
|
|
11
13
|
|
|
12
14
|
exports.function = async (req, res) => {
|
|
@@ -15,3 +17,17 @@ exports.function = async (req, res) => {
|
|
|
15
17
|
return
|
|
16
18
|
}
|
|
17
19
|
```
|
|
20
|
+
|
|
21
|
+
```HTTP
|
|
22
|
+
ALLOWED_ROLES: role1,role2
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```JavaScript
|
|
26
|
+
import runSecurity from '@nitra/cf-security'
|
|
27
|
+
|
|
28
|
+
exports.function = async (req, res) => {
|
|
29
|
+
if (!runSecurity(req)) {
|
|
30
|
+
res.send(`Nitra security not passed`)
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
```
|
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitra/cf-security",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "check header in cloud functions",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js",
|
|
8
|
+
"./jwt": "./src/jwt.js"
|
|
9
|
+
},
|
|
6
10
|
"scripts": {
|
|
7
|
-
"fix": "npx
|
|
11
|
+
"fix": "npx eslint --fix . && npx prettier --write . ",
|
|
12
|
+
"test": "env $(cat ./test/.env) npx coverage-node test/index.js"
|
|
8
13
|
},
|
|
9
14
|
"repository": {
|
|
10
15
|
"type": "git",
|
|
@@ -16,12 +21,28 @@
|
|
|
16
21
|
"url": "https://github.com/nitra/cf-security/issues"
|
|
17
22
|
},
|
|
18
23
|
"homepage": "https://github.com/nitra/cf-security#readme",
|
|
19
|
-
"prettier": "prettier-config
|
|
24
|
+
"prettier": "@nitra/prettier-config",
|
|
25
|
+
"eslintConfig": {
|
|
26
|
+
"extends": [
|
|
27
|
+
"@nitra/eslint-config/node"
|
|
28
|
+
],
|
|
29
|
+
"root": true
|
|
30
|
+
},
|
|
20
31
|
"devDependencies": {
|
|
21
|
-
"
|
|
32
|
+
"@nitra/eslint-config": "^1.0.9",
|
|
33
|
+
"@nitra/prettier-config": "^1.0.1",
|
|
34
|
+
"test-director": "^7.0.0"
|
|
22
35
|
},
|
|
23
36
|
"dependencies": {
|
|
24
|
-
"@
|
|
25
|
-
"
|
|
37
|
+
"@nitra/bunyan": "^1.1.1",
|
|
38
|
+
"@nitra/check-env": "^2.0.1",
|
|
39
|
+
"@nitra/isenv": "^2.0.1",
|
|
40
|
+
"@nitra/jwt": "^3.1.2"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"src"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=16.0.0"
|
|
26
47
|
}
|
|
27
48
|
}
|
package/src/index.js
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* @module @nitra/cf-security
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const consola = require('consola')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @const {Function}
|
|
11
|
-
*/
|
|
12
|
-
const checkEnv = require('@47ng/check-env').default
|
|
13
|
-
checkEnv({ required: ['X_NITRA_CF_KEY'] })
|
|
14
|
-
|
|
15
|
-
consola.debug('cfSecurity in DEBUG MODE')
|
|
1
|
+
import getLogger from '@nitra/bunyan/trace'
|
|
2
|
+
import checkEnv from '@nitra/check-env'
|
|
3
|
+
checkEnv(['X_NITRA_CF_KEY'])
|
|
16
4
|
|
|
17
5
|
/**
|
|
18
6
|
* Check request for Nitra security rules
|
|
@@ -20,25 +8,26 @@ consola.debug('cfSecurity in DEBUG MODE')
|
|
|
20
8
|
* @param {object} req - ApolloServer or Express Request for check
|
|
21
9
|
* @return {boolean} if check passed
|
|
22
10
|
*/
|
|
11
|
+
export const cfSecurity = req => {
|
|
12
|
+
const log = getLogger(req)
|
|
23
13
|
|
|
24
|
-
exports.cfSecurity = function (req) {
|
|
25
14
|
if (typeof req.headers === 'undefined') {
|
|
26
|
-
|
|
15
|
+
log.info('Request without headers')
|
|
27
16
|
return false
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
if (typeof req.headers['x-nitra-cf-key'] === 'undefined') {
|
|
31
|
-
|
|
20
|
+
log.info('Nitra key not exist in request')
|
|
32
21
|
return false
|
|
33
22
|
}
|
|
34
23
|
|
|
35
24
|
if (req.headers['x-nitra-cf-key'] === 0) {
|
|
36
|
-
|
|
25
|
+
log.info('Empty Nitra key in headers request')
|
|
37
26
|
return false
|
|
38
27
|
}
|
|
39
28
|
|
|
40
29
|
if (req.headers['x-nitra-cf-key'] !== process.env.X_NITRA_CF_KEY) {
|
|
41
|
-
|
|
30
|
+
log.info('Not equal Nitra key')
|
|
42
31
|
return false
|
|
43
32
|
}
|
|
44
33
|
|
package/src/jwt.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import getLogger from '@nitra/bunyan/trace'
|
|
2
|
+
import checkEnv from '@nitra/check-env'
|
|
3
|
+
import verify from '@nitra/jwt/verify'
|
|
4
|
+
import { isDev } from '@nitra/isenv'
|
|
5
|
+
|
|
6
|
+
checkEnv(['ALLOWED_ROLES'])
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Check request for Nitra security rules WI
|
|
10
|
+
*
|
|
11
|
+
* @param {object} req - Fastify Request for check
|
|
12
|
+
* @return {string} token if check passed
|
|
13
|
+
*/
|
|
14
|
+
export default async req => {
|
|
15
|
+
if (isDev) {
|
|
16
|
+
const token = {}
|
|
17
|
+
token['https://hasura.io/jwt/claims']['x-hasura-allowed-roles'] = process.env.ALLOWED_ROLES.split(',')
|
|
18
|
+
return token
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const log = getLogger(req)
|
|
22
|
+
|
|
23
|
+
// Перевіряємо токен тільки
|
|
24
|
+
if (!req.headers?.authorization) {
|
|
25
|
+
log.info('[verification] no authorization data')
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const authHeaders = req.headers.authorization.split(' ')
|
|
30
|
+
const token = await verify(authHeaders[1])
|
|
31
|
+
|
|
32
|
+
if (!token) {
|
|
33
|
+
log.info('[verification] invalid token')
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const roleArray = token.body['https://hasura.io/jwt/claims']['x-hasura-allowed-roles']
|
|
38
|
+
|
|
39
|
+
const allowedRoles = process.env.ALLOWED_ROLES.split(',')
|
|
40
|
+
|
|
41
|
+
const intersectRoles = intersection(roleArray, allowedRoles)
|
|
42
|
+
|
|
43
|
+
if (intersectRoles.length === 0) {
|
|
44
|
+
log.info('[verification] invalid all roles')
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return token.body
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function intersection(a, b) {
|
|
52
|
+
const setA = new Set(a)
|
|
53
|
+
return b.filter(value => setA.has(value))
|
|
54
|
+
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
name: Node.js Package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*.*.*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish-npm:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
- uses: actions/checkout@v2
|
|
13
|
-
with:
|
|
14
|
-
# Full git history is needed to get a proper list of changed files within `super-linter` and for Changelog
|
|
15
|
-
fetch-depth: 0
|
|
16
|
-
|
|
17
|
-
################################
|
|
18
|
-
# Run Linter against code base #
|
|
19
|
-
################################
|
|
20
|
-
- name: Lint Code Base
|
|
21
|
-
uses: docker://ghcr.io/github/super-linter:slim-v4
|
|
22
|
-
env:
|
|
23
|
-
VALIDATE_ALL_CODEBASE: false
|
|
24
|
-
DEFAULT_BRANCH: master
|
|
25
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
-
|
|
27
|
-
- uses: JS-DevTools/npm-publish@v1
|
|
28
|
-
with:
|
|
29
|
-
token: ${{ secrets.NPM_TOKEN }}
|
|
30
|
-
access: public
|
|
31
|
-
|
|
32
|
-
- uses: scottbrenner/generate-changelog-action@master
|
|
33
|
-
id: Changelog
|
|
34
|
-
|
|
35
|
-
- name: Create Release
|
|
36
|
-
uses: softprops/action-gh-release@v1
|
|
37
|
-
with:
|
|
38
|
-
body: |
|
|
39
|
-
${{ steps.Changelog.outputs.changelog }}
|
|
40
|
-
env:
|
|
41
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|