mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
UI: handle reduced disclosure on replication endpoints (#24379)
* add replicationRedacted attribute to cluster model * disallow access to replication pages if repl endpoints are redacted * hide replicatio nav item * Hide replication card on dashboard
This commit is contained in:
@@ -61,6 +61,12 @@ export default ApplicationAdapter.extend({
|
||||
}
|
||||
if (replicationStatus && replicationStatus instanceof AdapterError === false) {
|
||||
ret = Object.assign(ret, replicationStatus.data);
|
||||
} else if (
|
||||
replicationStatus instanceof AdapterError &&
|
||||
replicationStatus?.errors.find((err) => err === 'disabled path')
|
||||
) {
|
||||
// set redacted if result is an error which only happens when redacted
|
||||
ret = Object.assign(ret, { replication_redacted: true });
|
||||
}
|
||||
return resolve(ret);
|
||||
});
|
||||
|
||||
@@ -52,7 +52,14 @@
|
||||
}}
|
||||
<Nav.Title data-test-sidebar-nav-heading="Monitoring">Monitoring</Nav.Title>
|
||||
{{/if}}
|
||||
{{#if (and this.version.isEnterprise this.namespace.inRootNamespace (has-permission "status" routeParams="replication"))}}
|
||||
{{#if
|
||||
(and
|
||||
this.version.isEnterprise
|
||||
this.namespace.inRootNamespace
|
||||
(not this.cluster.replicationRedacted)
|
||||
(has-permission "status" routeParams="replication")
|
||||
)
|
||||
}}
|
||||
<Nav.Link
|
||||
@route="vault.cluster.replication.index"
|
||||
@text="Replication"
|
||||
|
||||
@@ -16,8 +16,10 @@ export default class ClusterModel extends Model {
|
||||
@attr('boolean') standby;
|
||||
@attr('string') type;
|
||||
@attr('object') license;
|
||||
// manually set on response when sys/health failure
|
||||
|
||||
// manually set on response in cluster adapter
|
||||
@attr('boolean') hasChrootNamespace;
|
||||
@attr('boolean') replicationRedacted;
|
||||
|
||||
/* Licensing concerns */
|
||||
get licenseExpiry() {
|
||||
|
||||
@@ -30,12 +30,13 @@ export default class VaultClusterDashboardRoute extends Route.extend(ClusterRout
|
||||
model() {
|
||||
const clusterModel = this.modelFor('vault.cluster');
|
||||
const hasChroot = clusterModel?.hasChrootNamespace;
|
||||
const replication = hasChroot
|
||||
? null
|
||||
: {
|
||||
dr: clusterModel.dr,
|
||||
performance: clusterModel.performance,
|
||||
};
|
||||
const replication =
|
||||
hasChroot || clusterModel.replicationRedacted
|
||||
? null
|
||||
: {
|
||||
dr: clusterModel.dr,
|
||||
performance: clusterModel.performance,
|
||||
};
|
||||
return hash({
|
||||
replication,
|
||||
secretsEngines: this.store.query('secret-engine', {}),
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
{{#if @license}}
|
||||
<Dashboard::ClientCountCard @license={{@license}} />
|
||||
{{/if}}
|
||||
{{#if (and @isRootNamespace (has-permission "status" routeParams="replication"))}}
|
||||
{{#if
|
||||
(and @isRootNamespace (has-permission "status" routeParams="replication") (not (is-empty-value @replication)))
|
||||
}}
|
||||
<Dashboard::ReplicationCard
|
||||
@replication={{@replication}}
|
||||
@version={{@version}}
|
||||
|
||||
@@ -13,8 +13,13 @@ export default Route.extend(ClusterRoute, {
|
||||
version: service(),
|
||||
store: service(),
|
||||
auth: service(),
|
||||
router: service(),
|
||||
|
||||
beforeModel() {
|
||||
if (this.auth.activeCluster.replicationRedacted) {
|
||||
// disallow replication access if endpoints are redacted
|
||||
return this.router.transitionTo('vault.cluster');
|
||||
}
|
||||
return this.version.fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import modifyPassthroughResponse from '../helpers/modify-passthrough-response';
|
||||
import { Response } from 'miragejs';
|
||||
|
||||
export default function (server) {
|
||||
server.get('/sys/health', (schema, req) =>
|
||||
@@ -12,7 +13,10 @@ export default function (server) {
|
||||
server.get('/sys/seal-status', (schema, req) =>
|
||||
modifyPassthroughResponse(req, { version: '', cluster_name: '', build_date: '' })
|
||||
);
|
||||
server.get('sys/replication/status', () => new Response(404));
|
||||
server.get('sys/replication/dr/status', () => new Response(404));
|
||||
server.get('sys/replication/performance/status', () => new Response(404));
|
||||
server.get('sys/replication/status', () => new Response(404, {}, { errors: ['disabled path'] }));
|
||||
server.get('sys/replication/dr/status', () => new Response(404, {}, { errors: ['disabled path'] }));
|
||||
server.get(
|
||||
'sys/replication/performance/status',
|
||||
() => new Response(404, {}, { errors: ['disabled path'] })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -134,4 +134,17 @@ module('Acceptance | Enterprise | reduced disclosure test', function (hooks) {
|
||||
.dom('[data-test-footer-version]')
|
||||
.hasText(`Vault ${versionSvc.version}`, 'Version is shown after login');
|
||||
});
|
||||
|
||||
test('does not allow access to replication pages', async function (assert) {
|
||||
await authPage.login();
|
||||
assert.dom('[data-test-sidebar-nav-link="Replication"]').doesNotExist('hides replication nav item');
|
||||
|
||||
await visit(`/vault/replication/dr`);
|
||||
assert.strictEqual(
|
||||
currentRouteName(),
|
||||
'vault.cluster.dashboard',
|
||||
'redirects to dashboard if replication access attempted'
|
||||
);
|
||||
assert.dom('[data-test-card="replication"]').doesNotExist('hides replication card on dashboard');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user