diff --git a/.changelog/10604.txt b/.changelog/10604.txt
new file mode 100644
index 0000000000..0fd8f1b50b
--- /dev/null
+++ b/.changelog/10604.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Show ACLs disabled page at Tokens page instead of 403 error when ACLs are disabled
+```
diff --git a/ui/packages/consul-ui/app/abilities/acl.js b/ui/packages/consul-ui/app/abilities/acl.js
index 4e6f8ae162..9a411567e8 100644
--- a/ui/packages/consul-ui/app/abilities/acl.js
+++ b/ui/packages/consul-ui/app/abilities/acl.js
@@ -6,6 +6,12 @@ export default class ACLAbility extends BaseAbility {
resource = 'acl';
segmented = false;
+ // Access is very similar to read, but when ACLs are disabled you still need
+ // access to ACLs in order to see the ACLs disabled page, which is accessing
+ // the ACLs area, but without read
+ get canAccess() {
+ return this.env.var('CONSUL_ACLS_ENABLED') ? this.canRead : true;
+ }
get canRead() {
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
diff --git a/ui/packages/consul-ui/app/components/app-view/index.hbs b/ui/packages/consul-ui/app/components/app-view/index.hbs
index 6197f1b69b..4985e5afe0 100644
--- a/ui/packages/consul-ui/app/components/app-view/index.hbs
+++ b/ui/packages/consul-ui/app/components/app-view/index.hbs
@@ -88,7 +88,7 @@
{{#if (not enabled) }}
-
+
Welcome to ACLs
diff --git a/ui/packages/consul-ui/app/router.js b/ui/packages/consul-ui/app/router.js
index 349dca47f5..3f7af1d039 100644
--- a/ui/packages/consul-ui/app/router.js
+++ b/ui/packages/consul-ui/app/router.js
@@ -130,7 +130,7 @@ export const routes = {
acls: {
_options: {
path: '/acls',
- abilities: ['read acls'],
+ abilities: ['access acls'],
},
edit: {
_options: { path: '/:id' },
diff --git a/ui/packages/consul-ui/tests/acceptance/dc/acls/access.feature b/ui/packages/consul-ui/tests/acceptance/dc/acls/access.feature
new file mode 100644
index 0000000000..e6623b2513
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/dc/acls/access.feature
@@ -0,0 +1,11 @@
+@setupApplicationTest
+Feature: dc / acls / access: ACLs Access
+ Scenario: ACLs are disabled
+ Given ACLs are disabled
+ And 1 datacenter model with the value "dc-1"
+ When I visit the tokens page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/acls/tokens
+ And I see the "[data-test-acls-disabled]" element
diff --git a/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/access-steps.js b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/access-steps.js
new file mode 100644
index 0000000000..ba1093295f
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/access-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui/packages/consul-ui/tests/helpers/set-cookies.js b/ui/packages/consul-ui/tests/helpers/set-cookies.js
index 772b8fe439..b3805cb600 100644
--- a/ui/packages/consul-ui/tests/helpers/set-cookies.js
+++ b/ui/packages/consul-ui/tests/helpers/set-cookies.js
@@ -1,8 +1,10 @@
-export default function(type, value) {
+export default function(type, value, doc = document) {
const obj = {};
if (type !== '*') {
let key = '';
- obj['CONSUL_ACLS_ENABLE'] = 1;
+ if (!doc.cookie.includes('CONSUL_ACLS_ENABLE=0')) {
+ obj['CONSUL_ACLS_ENABLE'] = 1;
+ }
switch (type) {
case 'dc':
key = 'CONSUL_DATACENTER_COUNT';
@@ -22,7 +24,6 @@ export default function(type, value) {
break;
case 'acl':
key = 'CONSUL_ACL_COUNT';
- obj['CONSUL_ACLS_ENABLE'] = 1;
break;
case 'session':
key = 'CONSUL_SESSION_COUNT';
@@ -32,19 +33,15 @@ export default function(type, value) {
break;
case 'policy':
key = 'CONSUL_POLICY_COUNT';
- obj['CONSUL_ACLS_ENABLE'] = 1;
break;
case 'role':
key = 'CONSUL_ROLE_COUNT';
- obj['CONSUL_ACLS_ENABLE'] = 1;
break;
case 'token':
key = 'CONSUL_TOKEN_COUNT';
- obj['CONSUL_ACLS_ENABLE'] = 1;
break;
case 'authMethod':
key = 'CONSUL_AUTH_METHOD_COUNT';
- obj['CONSUL_ACLS_ENABLE'] = 1;
break;
case 'nspace':
key = 'CONSUL_NSPACE_COUNT';
diff --git a/ui/packages/consul-ui/tests/steps/doubles/model.js b/ui/packages/consul-ui/tests/steps/doubles/model.js
index 0fc33b6b50..44f3d98ce7 100644
--- a/ui/packages/consul-ui/tests/steps/doubles/model.js
+++ b/ui/packages/consul-ui/tests/steps/doubles/model.js
@@ -29,6 +29,9 @@ export default function(scenario, create, set, win = window, doc = document) {
.given(['the local datacenter is "$value"'], function(value) {
doc.cookie = `CONSUL_DATACENTER_LOCAL=${value}`;
})
+ .given(['ACLs are disabled'], function() {
+ doc.cookie = `CONSUL_ACLS_ENABLE=0`;
+ })
.given(['permissions from yaml\n$yaml'], function(data) {
Object.entries(data).forEach(([key, value]) => {
const resource = `CONSUL_RESOURCE_${key.toUpperCase()}`;