Skip to content

Commit f4bc03e

Browse files
committed
mgr/dashboard: fix access control permissions for roles
Since prometheus is being used in the dashboard page we need to make sure every role has prometheus read only access so that the dashboard page can load the utilization metrics. I also saw permission issue with the osd settings endpoint when its trying to get the nearfull/full ratio. so instead of failing the entire page i am proceeding with a chart that doesn't have those details when the user doesn't have permission to access the config opt. Multisite page was not accessible in the case of rgw-manager or read-only user because its trying to show the status of rgw module. This si also now gracefully handled to show the alert only when the user has sufficient permission. Fixes: https://tracker.ceph.com/issues/70331 Signed-off-by: Nizamudeen A <[email protected]>
1 parent 224a0e7 commit f4bc03e

File tree

8 files changed

+50
-42
lines changed

8 files changed

+50
-42
lines changed

src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-pie/dashboard-pie.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ export class DashboardPieComponent implements OnChanges, OnInit {
1515
@Input()
1616
data: any;
1717
@Input()
18-
highThreshold: number;
18+
highThreshold = 0;
1919
@Input()
20-
lowThreshold: number;
20+
lowThreshold = 0;
2121

2222
color: string;
2323

@@ -162,15 +162,15 @@ export class DashboardPieComponent implements OnChanges, OnInit {
162162
const percentAvailable = this.calcPercentage(max - current, max);
163163
const percentUsed = this.calcPercentage(current, max);
164164

165-
if (fullRatioPercent >= 0 && percentUsed >= fullRatioPercent) {
165+
if (fullRatioPercent > 0 && percentUsed >= fullRatioPercent) {
166166
this.color = 'chart-color-red';
167-
} else if (nearFullRatioPercent >= 0 && percentUsed >= nearFullRatioPercent) {
167+
} else if (nearFullRatioPercent > 0 && percentUsed >= nearFullRatioPercent) {
168168
this.color = 'chart-color-yellow';
169169
} else {
170170
this.color = 'chart-color-blue';
171171
}
172172

173-
if (fullRatioPercent >= 0 && nearFullRatioPercent >= 0) {
173+
if (fullRatioPercent > 0 && nearFullRatioPercent > 0) {
174174
chart.dataset[0].data = [
175175
Math.round(nearFullRatioPercent),
176176
Math.round(Math.abs(nearFullRatioPercent - fullRatioPercent)),

src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@
227227
[fullHeight]="true"
228228
aria-label="Capacity card">
229229
<ng-container class="ms-4 me-4"
230-
*ngIf="capacity && osdSettings">
230+
*ngIf="capacity">
231231
<cd-dashboard-pie [data]="{max: capacity.total_bytes, current: capacity.total_used_raw_bytes}"
232232
[lowThreshold]="osdSettings.nearfull_ratio"
233233
[highThreshold]="osdSettings.full_ratio">

src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
2626
import { AlertClass } from '~/app/shared/enum/health-icon.enum';
2727
import { HardwareService } from '~/app/shared/api/hardware.service';
2828
import { SettingsService } from '~/app/shared/api/settings.service';
29+
import { OsdSettings } from '~/app/shared/models/osd-settings';
2930

3031
@Component({
3132
selector: 'cd-dashboard-v3',
@@ -35,7 +36,7 @@ import { SettingsService } from '~/app/shared/api/settings.service';
3536
export class DashboardV3Component extends PrometheusListHelper implements OnInit, OnDestroy {
3637
detailsCardData: DashboardDetails = {};
3738
osdSettingsService: any;
38-
osdSettings: any;
39+
osdSettings = new OsdSettings();
3940
interval = new Subscription();
4041
permissions: Permissions;
4142
enabledFeature$: FeatureTogglesMap$;
@@ -117,7 +118,8 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
117118
}
118119
this.interval = this.refreshIntervalService.intervalData$.subscribe(() => {
119120
this.getHealth();
120-
this.getCapacityCardData();
121+
this.getCapacity();
122+
if (this.permissions.configOpt.read) this.getOsdSettings();
121123
if (this.hardwareEnabled) this.hardwareSubject.next([]);
122124
});
123125
this.getPrometheusData(this.prometheusService.lastHourDateObject);
@@ -165,16 +167,19 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
165167
);
166168
}
167169

168-
getCapacityCardData() {
170+
private getCapacity() {
171+
this.capacityService = this.healthService.getClusterCapacity().subscribe((data: any) => {
172+
this.capacity = data;
173+
});
174+
}
175+
176+
private getOsdSettings() {
169177
this.osdSettingsService = this.osdService
170178
.getOsdSettings()
171179
.pipe(take(1))
172-
.subscribe((data: any) => {
180+
.subscribe((data: OsdSettings) => {
173181
this.osdSettings = data;
174182
});
175-
this.capacityService = this.healthService.getClusterCapacity().subscribe((data: any) => {
176-
this.capacity = data;
177-
});
178183
}
179184

180185
public getPrometheusData(selectedTime: any) {

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<cd-rgw-multisite-tabs></cd-rgw-multisite-tabs>
22
<div>
3-
<cd-alert-panel *ngIf="!rgwModuleStatus"
3+
<!-- Show the alert only when the user has the permission to configure -->
4+
<cd-alert-panel *ngIf="permissions.configOpt.create && !rgwModuleStatus"
45
type="info"
56
spacingClass="mb-3"
67
class="d-flex align-items-center"
@@ -18,32 +19,32 @@
1819
Cluster->Services</a>
1920
</cd-alert-panel>
2021
<cd-table-actions class="btn-group mb-4 me-2"
21-
[permission]="permission"
22+
[permission]="permissions.rgw"
2223
[selection]="selection"
2324
[tableActions]="multisiteReplicationActions">
2425
</cd-table-actions>
2526
<cd-table-actions *ngIf="showMigrateAndReplicationActions"
2627
class="btn-group mb-4 me-2 secondary"
27-
[permission]="permission"
28+
[permission]="permissions.rgw"
2829
[btnColor]="'light'"
2930
[selection]="selection"
3031
[tableActions]="migrateTableAction">
3132
</cd-table-actions>
3233
<cd-table-actions *ngIf="!showMigrateAndReplicationActions"
3334
class="btn-group mb-4 me-2"
34-
[permission]="permission"
35+
[permission]="permissions.rgw"
3536
[selection]="selection"
3637
[tableActions]="createTableActions"
3738
[primaryDropDown]="true">
3839
</cd-table-actions>
3940
<cd-table-actions class="btn-group mb-4 me-2"
40-
[permission]="permission"
41+
[permission]="permissions.rgw"
4142
[btnColor]="'light'"
4243
[selection]="selection"
4344
[tableActions]="importAction">
4445
</cd-table-actions>
4546
<cd-table-actions class="btn-group mb-4 me-2"
46-
[permission]="permission"
47+
[permission]="permissions.rgw"
4748
[btnColor]="'light'"
4849
[selection]="selection"
4950
[tableActions]="exportAction">

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { Icons } from '~/app/shared/enum/icons.enum';
2121
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
2222
import { CdTableAction } from '~/app/shared/models/cd-table-action';
2323
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
24-
import { Permission } from '~/app/shared/models/permissions';
24+
import { Permissions } from '~/app/shared/models/permissions';
2525
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
2626
import { ModalService } from '~/app/shared/services/modal.service';
2727
import { NotificationService } from '~/app/shared/services/notification.service';
@@ -68,7 +68,7 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
6868
blockUI: NgBlockUI;
6969

7070
icons = Icons;
71-
permission: Permission;
71+
permissions: Permissions;
7272
selection = new CdTableSelection();
7373
createTableActions: CdTableAction[];
7474
migrateTableAction: CdTableAction[];
@@ -144,7 +144,7 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
144144
private rgwMultisiteService: RgwMultisiteService,
145145
private changeDetectionRef: ChangeDetectorRef
146146
) {
147-
this.permission = this.authStorageService.getPermissions().rgw;
147+
this.permissions = this.authStorageService.getPermissions();
148148
}
149149

150150
openModal(entity: any | string, edit = false) {
@@ -305,22 +305,17 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
305305
},
306306
(_error) => {}
307307
);
308-
this.mgrModuleService.list().subscribe((moduleData: any) => {
309-
this.rgwModuleData = moduleData.filter((module: object) => module['name'] === 'rgw');
310-
if (this.rgwModuleData.length > 0) {
311-
this.rgwModuleStatus = this.rgwModuleData[0].enabled;
312-
}
313-
});
308+
309+
// Only get the module status if you can read from configOpt
310+
if (this.permissions.configOpt.read) {
311+
this.mgrModuleService.list().subscribe((moduleData: any) => {
312+
this.rgwModuleData = moduleData.filter((module: object) => module['name'] === 'rgw');
313+
if (this.rgwModuleData.length > 0) {
314+
this.rgwModuleStatus = this.rgwModuleData[0].enabled;
315+
}
316+
});
317+
}
314318
}
315-
/* setConfigValues() {
316-
this.rgwDaemonService
317-
.setMultisiteConfig(
318-
this.defaultsInfo['defaultRealmName'],
319-
this.defaultsInfo['defaultZonegroupName'],
320-
this.defaultsInfo['defaultZoneName']
321-
)
322-
.subscribe(() => {});
323-
}*/
324319

325320
ngOnDestroy() {
326321
this.sub.unsubscribe();

src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<cds-overflow-menu [customTrigger]="customTrigger"
22
[flip]="true">
3-
<li class="cds--overflow-menu-options__option mb-2"
4-
*ngIf="userPermission.read">
3+
<li class="cds--overflow-menu-options__option mb-2">
54
<button routerLink="/user-management"
65
class="cds--overflow-menu-options__btn"
76
i18n>User management</button>

src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
<div class="cds--btn cds--btn--icon-only cds--header__action">
4040
<cd-dashboard-help></cd-dashboard-help>
4141
</div>
42-
<div class="cds--btn cds--btn--icon-only cds--header__action">
42+
<div class="cds--btn cds--btn--icon-only cds--header__action"
43+
*ngIf="permissions.user.read">
4344
<cd-administration></cd-administration>
4445
</div>
4546
<div class="cds--btn cds--btn--icon-only cds--header__action">
@@ -93,6 +94,7 @@
9394
</cds-sidenav-item>
9495
<!-- Multi-cluster Dashboard -->
9596
<cds-sidenav-menu title="Multi-Cluster"
97+
*ngIf="permissions.configOpt.read"
9698
i18n-title>
9799
<svg cdsIcon="edge-cluster"
98100
icon

src/pybind/mgr/dashboard/services/access_control.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ def map_to_system_roles(cls, roles) -> List['Role']:
232232
Scope.RBD_MIRRORING: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
233233
Scope.GRAFANA: [_P.READ],
234234
Scope.NVME_OF: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
235+
Scope.PROMETHEUS: [_P.READ]
235236
})
236237

237238

@@ -240,6 +241,7 @@ def map_to_system_roles(cls, roles) -> List['Role']:
240241
'rgw-manager', 'allows full permissions for the rgw scope', {
241242
Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
242243
Scope.GRAFANA: [_P.READ],
244+
Scope.PROMETHEUS: [_P.READ]
243245
})
244246

245247

@@ -263,13 +265,15 @@ def map_to_system_roles(cls, roles) -> List['Role']:
263265
'pool-manager', 'allows full permissions for the pool scope', {
264266
Scope.POOL: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
265267
Scope.GRAFANA: [_P.READ],
268+
Scope.PROMETHEUS: [_P.READ]
266269
})
267270

268271
# CephFS manager role provides all permissions for CephFS related scopes
269272
CEPHFS_MGR_ROLE = Role(
270273
'cephfs-manager', 'allows full permissions for the cephfs scope', {
271274
Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
272275
Scope.GRAFANA: [_P.READ],
276+
Scope.PROMETHEUS: [_P.READ]
273277
})
274278

275279
GANESHA_MGR_ROLE = Role(
@@ -278,7 +282,8 @@ def map_to_system_roles(cls, roles) -> List['Role']:
278282
Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
279283
Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
280284
Scope.GRAFANA: [_P.READ],
281-
Scope.SMB: [_P.READ]
285+
Scope.SMB: [_P.READ],
286+
Scope.PROMETHEUS: [_P.READ]
282287
})
283288

284289
SMB_MGR_ROLE = Role(
@@ -287,7 +292,8 @@ def map_to_system_roles(cls, roles) -> List['Role']:
287292
Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
288293
Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
289294
Scope.GRAFANA: [_P.READ],
290-
Scope.NFS_GANESHA: [_P.READ]
295+
Scope.NFS_GANESHA: [_P.READ],
296+
Scope.PROMETHEUS: [_P.READ]
291297
})
292298

293299

0 commit comments

Comments
 (0)