v1.16.0: OpenBao as central secrets store + vault broker + UI rework
- Boot: bao-conf.init('sso-manager') replaces conf_manager; deep-merges
secret/sso-manager/conf over file config (fail-soft). Scoped VAULT_TOKEN
(policy sso-broker), never root.
- /api/vault reworked: middleware.auth -> scopeGuard -> token-injecting
proxy. vault_broker.js mints Redis-cached per-user (user-<uid>) /
per-admin (sso-admin) tokens via the sso-broker role; scopeGuard enforces
path prefix on top of the OpenBao policy. Client auth-token stripped.
- vault UI renamed (vaultwarden.ejs -> vault.ejs), /vault route auth-gated,
role-scoped: users see only secret/users/<uid>/, admins get free-form +
Apps mint tab (secret/apps/<name>/*, token shown once).
- api_conf.js writes via bao-conf.set('sso-manager', ...).
- Remediation: config/*-secrets.js untracked+gitignored, test_plugins.js
deleted, proxy-secrets.js.example placeholder added. Secrets remain in
git history; provider-side rotation is the real fix.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+19
-3
@@ -11,6 +11,8 @@ const {Tos} = require('../models/tos');
|
||||
const conf = require('@simpleworkjs/conf');
|
||||
const buildInfo = require('../utils/build_info');
|
||||
const { mountStaticModules } = require('@simpleworkjs/app-stack');
|
||||
const middleware = require('../middleware/auth');
|
||||
const permission = require('../utils/permission');
|
||||
|
||||
const values ={
|
||||
title: conf.environment !== 'production' ? `dev` : '',
|
||||
@@ -65,7 +67,6 @@ router.get('/dashboard', (req, res) => res.redirect(301, '/overview'));
|
||||
router.get('/executive', (req, res) => res.redirect(301, '/overview'));
|
||||
|
||||
router.get('/conf', async function(req, res, next) {
|
||||
const permission = require('../utils/permission');
|
||||
try {
|
||||
await permission.byGroup(req.user, ['app_sso_admin']);
|
||||
res.render('conf', {...values});
|
||||
@@ -86,8 +87,23 @@ router.get('/plugins', function(req, res, next) {
|
||||
res.redirect('/directory');
|
||||
});
|
||||
|
||||
router.get('/vault', function(req, res, next) {
|
||||
res.render('vaultwarden', {...values});
|
||||
router.get('/vault', middleware.auth, async function(req, res, next) {
|
||||
// Personal per-user secrets (secret/users/<uid>/*) for everyone; admins get
|
||||
// free-form access across all of secret/ plus an Apps tab to mint scoped
|
||||
// tokens for external apps. The /api/vault proxy enforces the same scoping
|
||||
// server-side (scopeGuard + the token's own OpenBao policy).
|
||||
let isAdmin = false;
|
||||
try {
|
||||
await permission.byGroup(req.user, ['app_sso_admin']);
|
||||
isAdmin = true;
|
||||
} catch (e) { /* non-admin: personal namespace only */ }
|
||||
res.render('vault', {
|
||||
...values,
|
||||
vaultUid: req.user.uid,
|
||||
vaultIsAdmin: isAdmin,
|
||||
vaultBase: isAdmin ? '' : `users/${req.user.uid}/`,
|
||||
vaultAddr: process.env.VAULT_ADDR || 'http://openbao:8200',
|
||||
});
|
||||
});
|
||||
|
||||
// Linkable deep-link to a single resource's modal, e.g. from the resource
|
||||
|
||||
Reference in New Issue
Block a user