Skip to content

Commit fc17416

Browse files
authored
Merge branch 'stable' into monthlyupdate
2 parents d09e7c9 + f03fc8c commit fc17416

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

src/mas/devops/mas/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
getMasChannel,
1515
updateIBMEntitlementKey,
1616
getMasPublicClusterIssuer,
17+
getPermissionMode,
1718
)

src/mas/devops/mas/suite.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,93 @@ def getMasPublicClusterIssuer(dynClient: DynamicClient, instanceId: str) -> str
357357
except UnauthorizedError as e:
358358
logger.error(f"Error: Unable to retrieve MAS instance due to failed authorization: {e}")
359359
return None
360+
361+
362+
def getPermissionMode(dynClient: DynamicClient, instanceId: str) -> str | None:
363+
"""
364+
Detect the current RBAC permission mode for a MAS instance.
365+
366+
This function determines whether MAS is installed with cluster-level permissions,
367+
namespace-scoped permissions (essential + non-essential), or minimal essential-only
368+
permissions by checking for the existence of RBAC resources in the cluster.
369+
370+
RBAC Resource Distribution:
371+
- Cluster mode: ClusterRoles + Essential Roles
372+
- Namespaced mode: Essential Roles + Non-essential Roles
373+
- Minimal mode: Essential Roles ONLY
374+
375+
Detection Logic:
376+
1. Check for ClusterRoles → cluster mode
377+
2. Check for non-essential openshift-marketplace Role → namespaced mode
378+
3. No ClusterRole and no openshift-marketplace Role → minimal mode
379+
380+
Args:
381+
dynClient (DynamicClient): OpenShift dynamic client for cluster API interactions.
382+
instanceId (str): The MAS instance identifier.
383+
384+
Returns:
385+
str: Permission mode - "cluster", "namespaced", or "minimal"
386+
Returns None if unable to determine (e.g., no RBAC resources found)
387+
"""
388+
try:
389+
# Step 1: Check for ClusterRoles (indicates cluster mode)
390+
clusterRoleAPI = dynClient.resources.get(api_version="rbac.authorization.k8s.io/v1", kind="ClusterRole")
391+
392+
# Look for MAS ClusterRoles with the instance ID pattern
393+
clusterRoleName = f"mas:{instanceId}:core:coreapi"
394+
try:
395+
clusterRoleAPI.get(name=clusterRoleName)
396+
logger.info(f"Found ClusterRole '{clusterRoleName}' - permission mode is 'cluster'")
397+
return "cluster"
398+
except NotFoundError:
399+
logger.debug(f"ClusterRole '{clusterRoleName}' not found, checking for non-essential Roles")
400+
401+
# Step 2: Check for non-essential openshift-marketplace Role (only exists in namespaced mode)
402+
roleAPI = dynClient.resources.get(api_version="rbac.authorization.k8s.io/v1", kind="Role")
403+
404+
# This role only exists in namespaced mode (applied via role-non-essential-core-coreapi-openshift-marketplace.yaml)
405+
marketplaceRoleName = f"mas:{instanceId}:core:coreapi:openshift-marketplace"
406+
marketplaceNamespace = "openshift-marketplace"
407+
408+
try:
409+
roleAPI.get(name=marketplaceRoleName, namespace=marketplaceNamespace)
410+
logger.info(f"Found non-essential Role '{marketplaceRoleName}' in namespace '{marketplaceNamespace}' - permission mode is 'namespaced'")
411+
return "namespaced"
412+
except NotFoundError:
413+
logger.debug("Non-essential openshift-marketplace Role not found, checking for essential roles")
414+
415+
# Step 3: Verify minimal mode by checking for essential roles in mas-{instanceId}-core namespace
416+
# Essential roles have pattern: mas:{instanceId}:core:suite:{app}:essential
417+
coreNamespace = f"mas-{instanceId}-core"
418+
419+
# Try to find at least one essential role to confirm minimal mode
420+
# Check common apps that might be installed
421+
essentialRolePatterns = [
422+
f"mas:{instanceId}:core:suite:manage:essential",
423+
f"mas:{instanceId}:core:suite:iot:essential",
424+
f"mas:{instanceId}:core:suite:monitor:essential",
425+
f"mas:{instanceId}:core:suite:predict:essential",
426+
f"mas:{instanceId}:core:suite:arcgis:essential",
427+
f"mas:{instanceId}:core:suite:facilities:essential",
428+
f"mas:{instanceId}:core:suite:optimizer:essential",
429+
f"mas:{instanceId}:core:suite:visualinspection:essential"
430+
]
431+
432+
for essentialRoleName in essentialRolePatterns:
433+
try:
434+
roleAPI.get(name=essentialRoleName, namespace=coreNamespace)
435+
logger.info(f"Found essential Role '{essentialRoleName}' in namespace '{coreNamespace}' with no non-essential roles - permission mode is 'minimal'")
436+
return "minimal"
437+
except NotFoundError:
438+
continue
439+
440+
# If we couldn't find any RBAC resources, return None
441+
logger.warning(f"Unable to determine permission mode for instance '{instanceId}' ")
442+
return None
443+
444+
except ResourceNotFoundError:
445+
logger.warning("Required API resources not found in the cluster")
446+
return None
447+
except UnauthorizedError as e:
448+
logger.error(f"Error: Unable to check permissions due to failed authorization: {e}")
449+
return None

0 commit comments

Comments
 (0)