Skip to content

Commit cb19fda

Browse files
Merge pull request #104 from CruGlobal/jh/auditFix
Updates to securily harden our running service.
2 parents 4da8ecd + a061f55 commit cb19fda

22 files changed

+8678
-13824
lines changed

.dockerignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Dependencies (reinstalled in image)
2+
node_modules
3+
**/node_modules
4+
5+
# Version control and CI
6+
.git
7+
.gitignore
8+
.github
9+
10+
# Local and sensitive files
11+
.env
12+
.env.*
13+
!.env.example
14+
*.log
15+
npm-debug.log*
16+
# Our services actually DO want to include this file.
17+
#config/local.js
18+
19+
# Test and dev
20+
test
21+
*.test.js
22+
.mocharc.js
23+
coverage
24+
.nyc_output
25+
.eslintrc*
26+
eslint.config.mjs
27+
.prettier*
28+
29+
# IDE and OS
30+
.vscode
31+
.idea
32+
*.swp
33+
.DS_Store
34+
35+
# Docs and misc (optional: remove if you need these in image)
36+
README.md
37+
Makefile
38+
*.md
39+
!AppBuilder/**/*.md

.eslintrc.js

Lines changed: 0 additions & 51 deletions
This file was deleted.

Dockerfile

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,46 @@
33
##
44
## This is our microservice for the users in an AB managed site.
55
##
6+
## Security: image runs as non-root user (node). For production, prefer
7+
## pinning the base image by digest and overriding CMD to remove --inspect.
8+
##
69
## Docker Commands:
710
## ---------------
811
## $ docker build -t digiserve/ab-user-manager:master .
912
## $ docker push digiserve/ab-user-manager:master
1013
##
14+
## Multi-platform (M1/M2/M3 Mac → amd64 + arm64):
15+
## $ docker buildx create --use # once, if no builder
16+
## $ docker buildx build --provenance=true --sbom=true --platform linux/amd64,linux/arm64 -t digiserve/ab-user-manager:master --push .
17+
## Or use: $ DOCKER_ARGS="--platform linux/amd64,linux/arm64 --push" ./build.sh
18+
## Supply chain: use --provenance=true --sbom=true when pushing to a registry for Docker Hub attestations and license visibility.
19+
##
1120

1221
ARG BRANCH=master
1322

1423
FROM digiserve/service-cli:${BRANCH}
1524

25+
# OCI labels for Docker Hub / Scout (license, description)
26+
LABEL org.opencontainers.image.title="User Manager" \
27+
org.opencontainers.image.description="Microservice for managing users in an AB managed site" \
28+
org.opencontainers.image.licenses="MIT"
29+
1630
COPY . /app
1731

1832
WORKDIR /app
1933

20-
RUN npm i -f
34+
# Reproducible install; use npm i -f only if npm ci fails (e.g. peer deps, git deps)
35+
RUN npm ci && npm cache clean --force
2136

2237
WORKDIR /app/AppBuilder
2338

24-
RUN npm i -f
39+
RUN npm ci && npm cache clean --force
2540

2641
WORKDIR /app
2742

43+
# Security: run as non-root (base image should provide node user)
44+
RUN chown -R node:node /app
45+
USER node
46+
47+
# --inspect=0.0.0.0:9229 exposes debugger to the network; omit in production or bind to 127.0.0.1
2848
CMD [ "node", "--inspect=0.0.0.0:9229", "app.js" ]

app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ if (AB.defaults.env("TELEMETRY_PROVIDER", "sentry") == "sentry") {
99
AB.telemetry.init("sentry", {
1010
dsn: AB.defaults.env(
1111
"SENTRY_DSN",
12-
"https://74d87e0653ba19e70a16e38945dc847d@o144358.ingest.sentry.io/4506143933202432"
12+
"https://74d87e0653ba19e70a16e38945dc847d@o144358.ingest.sentry.io/4506143933202432",
1313
),
1414
release: version,
1515
});

build.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env bash
2+
# Supply chain: --provenance and --sbom are required for Docker Hub attestations; they are preserved when using --push.
3+
24
git submodule update --init --recursive
35

4-
docker buildx build $DOCKER_ARGS \
5-
.
6+
docker buildx build --provenance=true --sbom=true $DOCKER_ARGS .

eslint.config.mjs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// ╔═╗╔═╗╦ ╦╔╗╔╔╦╗┬─┐┌─┐
2+
// ║╣ ╚═╗║ ║║║║ ║ ├┬┘│
3+
// o╚═╝╚═╝╩═╝╩╝╚╝ ╩ ┴└─└─┘
4+
// Flat config for ESLint v9+. Replaces .eslintrc.js and test/.eslintrc.js.
5+
import js from "@eslint/js";
6+
import globals from "globals";
7+
import eslintConfigPrettier from "eslint-config-prettier/flat";
8+
import eslintPluginPrettier from "eslint-plugin-prettier";
9+
10+
export default [
11+
js.configs.recommended,
12+
13+
// Main project: Node + ES2022, Prettier, custom rules
14+
{
15+
files: ["**/*.js"],
16+
languageOptions: {
17+
ecmaVersion: 2022,
18+
globals: { ...globals.node },
19+
},
20+
plugins: { prettier: eslintPluginPrettier },
21+
rules: {
22+
"prettier/prettier": [
23+
"error",
24+
{
25+
arrowParens: "always",
26+
endOfLine: "lf",
27+
printWidth: 80,
28+
tabWidth: 3,
29+
trailingComma: "all",
30+
},
31+
],
32+
"no-console": "off", // allow console.log() in our services
33+
},
34+
},
35+
36+
// Test files: Mocha globals + no-unused-vars ignore for should/expect
37+
{
38+
files: ["test/**/*.js"],
39+
languageOptions: {
40+
globals: { ...globals.node, ...globals.mocha },
41+
},
42+
rules: {
43+
"no-unused-vars": ["error", { varsIgnorePattern: "should|expect" }],
44+
},
45+
},
46+
47+
// Prettier disables conflicting rules — must be last
48+
eslintConfigPrettier,
49+
];

handlers/config-user-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function hashCode(str) {
2020
.reduce(
2121
(prevHash, currVal) =>
2222
((prevHash << 5) - prevHash + currVal.charCodeAt(0)) | 0,
23-
0
23+
0,
2424
);
2525
}
2626

handlers/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ module.exports = {
6262
req.log(
6363
`user[${user.username}] with roles:[${list
6464
.map((l) => l.uuid)
65-
.join(", ")}]`
65+
.join(", ")}]`,
6666
);
6767
cb(null, user);
6868
})

handlers/password-reset.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ module.exports = {
9696
})
9797
.catch((err) => {
9898
req.notify.developer(err, {
99-
context: "Service:user_manager.password-reset: Error initializing ABFactory",
99+
context:
100+
"Service:user_manager.password-reset: Error initializing ABFactory",
100101
});
101102
cb(err);
102103
});

handlers/user-find-password.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module.exports = {
8484
if (user && user.failedLogins > config.maxFailedLogins) {
8585
req.log("Too many failed attempts");
8686
var errorFailedAttempts = new Error(
87-
"Too many failed attempts. Please contact an admin."
87+
"Too many failed attempts. Please contact an admin.",
8888
);
8989
errorFailedAttempts.code = "EFAILEDATTEMPTS";
9090
cb(errorFailedAttempts);
@@ -99,7 +99,7 @@ module.exports = {
9999
} else {
100100
req.log("invalid password.");
101101
var pwError = new Error(
102-
"invalid username/password"
102+
"invalid username/password",
103103
);
104104
pwError.code = "EINVALIDLOGIN";
105105
cb(pwError);

0 commit comments

Comments
 (0)