2.2. Role-Based Access Control
Abstract
This section describes the role-based access control (RBAC) feature, which is enabled by default in the JBoss Fuse container. You can immediately start taking advantage of the RBAC feature, simply by adding one of the standard roles (such as
Deployer
or Administrator
) to a user's credentials. For more advanced usage, you have the option of customizing the access control lists, in order to control exactly what each role can do. Finally, you have the option of applying custom ACLs to your own OSGi services.
2.2.1. Overview of Role-Based Access Control
Overview
By default, the JBoss Fuse role-based access control protects access through the Fuse Management Console, JMX connections, and the Karaf command console. To use the default levels of access control, simply add any of the standard roles to your user authentication data (for example, by editing the
users.properties
file). You also have the option of customizing access control, by editing the relevant Access Control List (ACL) files.
Mechanisms
Role-based access control in JBoss Fuse is based on the following mechanisms:
- JMX Guard
- The JBoss Fuse container is configured with a JMX guard, which intercepts every incoming JMX invocation and filters the invocation through the configured JMX access control lists. The JMX guard is configured at the JVM level, so it intercepts every JMX invocation, without exception.
- OSGi Service Guard
- For any OSGi service, it is possible to configure an OSGi service guard. The OSGi service guard is implemented as a proxy object, which interposes itself between the client and the original OSGi service. An OSGi service guard must be explicitly configured for each OSGi service: it is not installed by default (except for the OSGi services that represent Karaf console commands, which are preconfigured for you).
Types of protection
The JBoss Fuse implementation of role-based access control is capable of providing the following types of protection:
- Fuse Management Console (Hawtio)
- Container access through the Fuse Management Console (Hawtio) is controlled by the JMX ACL files. The REST/HTTP service that provides the Fuse Management Console is implemented using Jolokia technology, which is layered above JMX. Hence, ultimately, all Fuse Management Console invocations pass through JMX and are regulated by JMX ACLs.
- JMX
- Direct access to the container's JMX port is regulated by the JMX ACLs. Moreover, any additional JMX ports opened by an application running in the container would also be regulated by the JMX ACLs, because the JMX guard is set at the JVM level.
- Karaf command console
- Access to the Karaf command console is regulated by the command console ACL files. Access control is applied no matter how the Karaf console is accessed. Whether accessing the command console through the Fuse Management Console or through the SSH protocol, access control is applied in both cases.NoteIn the special case where you start up the container directly at the command line (for example, using the
./bin/fuse
script) and no user authentication is performed, you automatically get the roles specified by thekaraf.local.roles
property in theetc/system.properties
file. - OSGi services
- For any OSGi service deployed in the container, you can optionally enable an ACL file, which restricts method invocations to specific roles.
Adding roles to users
In the system of role-based access control, you can give users permissions by adding roles to their user authentication data. For example, the following entry in the
etc/users.properties
file defines the admin
user and grants the Administrator
and SuperUser roles.
admin = secretpass,Administrator,SuperUser
You also have the option of defining user groups and then assigning users to a particular user group. For example, you could define and use an
admingroup
user group as follows:
admin = secretpass, _g_:admingroup _g_\:admingroup = Administrator, SuperUser
Note
User groups are not supported by every type of JAAS login module.
Standard roles
Table 2.2, “Standard Roles for Access Control” lists and describes the standard roles that are used throughout the JMX ACLs and the command console ACLs.
Roles | Description |
---|---|
Monitor , Operator , Maintainer | Grants read-only access to the container. |
Deployer , Auditor | Grants read-write access at the appropriate level for ordinary users, who want to deploy and run applications. But blocks access to sensitive container configuration settings. |
Administrator , SuperUser | Grants unrestricted access to the container. |
ACL files
The standard set of ACL files are located under the
etc/auth/
directory of the JBoss Fuse installation, as follows:
etc/auth/jmx.acl[.*].cfg
- JMX ACL files.
etc/auth/org.apache.karaf.command.acl.*.cfg
- Command console ACL files.
Customizing role-based access control
A complete set of JMX ACL files and command console ACL files are provided by default. You are free to customize these ACLs as required to suit the requirements of your system. Details of how to do this are given in the following sections.
Additional properties for controlling access
The
system.properties
file under the etc
directory provides the following additional properties for controlling access through the Karaf command console and the Fuse Management Console (Hawtio):
karaf.local.roles
- Specifies the roles that apply when a user starts up the container console locally (for example, by running the
./bin/fuse
script). hawtio.roles
- Specifies the roles that are allowed to access the container through the Fuse Management Console. This constraint is applied in addition to the access control defined by the JMX ACL files.
karaf.secured.command.compulsory.roles
- Specifies the default roles required to invoke a Karaf console command, in case the console command is not configured explicitly by a command ACL file,
etc/auth/org.apache.karaf.command.acl.*.cfg
. A user must be configured with at least one of the roles from the list in order to invoke the command. The value is specified as a comma-separated list of roles.
2.2.2. Customizing the JMX ACLs
Overview
The JMX ACLs are stored in the OSGi Config Admin Service and are normally accessible as the files,
etc/auth/jmx.acl.*.cfg
. This section explains how you can customize the JMX ACLs by editing these files yourself.
Architecture
Figure 2.1, “Access Control Mechanism for JMX” shows an overview of the role-based access control mechanism for JMX connections to the JBoss Fuse container.
Figure 2.1. Access Control Mechanism for JMX
How it works
JMX access control works by inserting a JMX Guard, which is configured through a JVM-wide
MBeanServerBuilder
object. The Apache Karaf launching scripts have been modified to include the following setting:
-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
JMX access control is now applied as follows:
- For every non-local JMX invocation, the JVM-wide
MBeanServerBuilder
calls into an OSGi bundle that contains the JMX Guard. - The JMX Guard looks up the relevant ACL for the MBean the user is trying to access (where the ACLs are stored in the OSGi Config Admin service).
- The ACL returns the list of roles that are allowed to make this particular invocation on the MBean.
- The JMX Guard checks the list of roles against the current security subject (the user that is making the JMX invocation), to see whether the current user has any of the required roles.
- If no matching role is found, the JMX invocation is blocked and a
SecurityException
is raised.
Location of JMX ACL files
The JMX ACL files are located in the
InstallDir/etc/auth
directory, where the ACL file names obey the following convention:
etc/auth/jmx.acl[.*].cfg
Technically, the ACLs are mapped to OSGi persistent IDs (PIDs), matching the pattern,
jmx.acl[.*]
. It just so happens that the standalone container stores OSGi PIDs as files, PID.cfg
, under the etc/
directory by default.
Mapping MBeans to ACL file names
The JMX Guard applies access control to every MBean class that is accessed through JMX (including any MBeans you define in your own application code). The ACL file for a specific MBean class is derived from the MBean's Object Name, by prefixing it with
jmx.acl
. For example, given the MBean whose Object Name is given by org.apache.activemq:type=Broker
, the corresponding PID would be:
jmx.acl.org.apache.activemq.Broker
In the case of a standalone container, the OSGi Config Admin service stores this PID data in the following file:
etc/auth/jmx.acl.org.apache.activemq.Broker.cfg
ACL file format
Each line of a JMX ACL file is an entry in the following format:
Pattern = Role1[,Role2][,Role3]...
Where
Pattern
is a pattern that matches a method invocation on an MBean, and the right-hand side of the equals sign is a comma-separated list of roles that give a user permission to make that invocation. In the simplest cases, the Pattern
is simply a method name. For example, as in the following settings for the org.apache.activemq.Broker
MBean (from the jmx.acl.org.apache.activemq.Broker.cfg
file):
addConnector = Deployer, Auditor, Administrator, SuperUser removeConnector = Deployer, Auditor, Administrator, SuperUser enableStatistics = Deployer, Auditor, Administrator, SuperUser addNetworkConnector = Deployer, Auditor, Administrator, SuperUser
It is also possible to use the wildcard character,
*
, to match multiple method names. For example, the following entry gives permission to invoke all method names starting with set
:
set* = Deployer, Auditor, Administrator, SuperUser
But the ACL syntax is also capable of defining much more fine-grained control of method invocations. You can define patterns to match methods invoked with specific arguments or even arguments that match a regular expression. For example, the ACL for the
org.apache.karaf.config
MBean package exploits this capability to prevent ordinary users from modifying sensitive configuration settings. The create
method from this package is restricted, as follows:
create(java.lang.String)[/jmx[.]acl.*/] = Administrator, SuperUser create(java.lang.String)[/org[.]apache[.]karaf[.]command[.]acl.+/] = Administrator, SuperUser create(java.lang.String)[/org[.]apache[.]karaf[.]service[.]acl.+/] = Administrator, SuperUser create(java.lang.String) = Deployer, Auditor, Administrator, SuperUser
In this case, the
Deployer
and Auditor
roles generally have permission to invoke the create
method, but only the Administrator
and SuperUser
roles have permission to invoke create
with a PID argument matching jmx.acl.*
, org.apache.karaf.command.acl.*
, or org.apache.karaf.service.*
.
For complete details of the ACL file format, please see the comments in the
etc/auth/jmx.acl.cfg
file.
ACL file hierarchy
Because it is often impractical to provide an ACL file for every single MBean, you have the option of specifying an ACL file at the level of a Java package, which provides default settings for all of the MBeans in that package. For example, the
org.apache.activemq.Broker
MBean could be affected by ACL settings at any of the following PID levels:
jmx.acl.org.apache.activemq.Broker jmx.acl.org.apache.activemq jmx.acl.org.apache jmx.acl.org jmx.acl
Where the most specific PID (top of the list) takes precedence over the least specific PID (bottom of the list).
Root ACL definitions
The root ACL file,
jmx.acl.cfg
, is a special case, because it supplies the default ACL settings for all MBeans. The root ACL has the following settings by default:
list* = viewer, Monitor, Operator, Maintainer,Deployer, Auditor, Administrator, SuperUser get* = viewer, Monitor, Operator, Maintainer,Deployer, Auditor, Administrator, SuperUser is* = viewer, Monitor, Operator, Maintainer,Deployer, Auditor, Administrator, SuperUser set* = admin, Administrator, SuperUser * = admin, Administrator, SuperUser
This implies that the typical read method patterns (
list*
, get*
, is*
) are accessible to all standard roles, but the typical write method patterns and other methods (set*
and *
) are accessible only to the administrator roles, admin
, Administrator
, SuperUser
.
Package ACL definitions
Many of the standard JMX ACL files provided in
etc/auth/jmx.acl[.*].cfg
apply to MBean packages. For example, the ACL for the org.apache.camel.endpoints
MBean package is defined with the following permissions:
is* = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser get* = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser set* = Deployer, Auditor, Administrator, SuperUser
ACL for custom MBeans
If you define custom MBeans in your own application, these custom MBeans are automatically integrated with the ACL mechanism and protected by the JMX Guard when you deploy them into the container. By default, however, your MBeans are typically protected only by the default root ACL file,
jmx.acl.cfg
. If you want to define a more fine-grained ACL for your MBean, create a new ACL file under etc/auth
, using the standard JMX ACL file naming convention.
For example, if your custom MBean class has the JMX Object Name,
org.example:type=MyMBean
, create a new ACL file under the etc/auth
directory called:
jmx.acl.org.example.MyMBean.cfg
Dynamic configuration at run time
Because the OSGi Config Admin service is dynamic, you can change ACL settings while the system is running, and even while a particular user is logged on. Hence, if you discover a security breach while the system is running, you can immediately restrict access to certain parts of the system by editing the relevant ACL file, without having to restart the container.
2.2.3. Customizing the Command Console ACLs
Overview
The command console ACLs are stored in the OSGi Config Admin Service and are normally accessible as the files,
etc/auth/org.apache.karaf.command.acl.*.cfg
. This section explains how you can customize the command console ACLs by editing these files yourself.
Architecture
Figure 2.2, “Access Control Mechanism for OSGi Services” shows an overview of the role-based access control mechanism for OSGi services in the JBoss Fuse container.
Figure 2.2. Access Control Mechanism for OSGi Services
How it works
The mechanism for command console access control is, in fact, based on the generic access control mechanism for OSGi services. It so happens that console commands are implemented and exposed as OSGi services. The Karaf console itself discovers the available commands through the OSGi service registry and accesses the commands as OSGi services. Hence, the access control mechanism for OSGi services can be used to control access to console commands.
The mechanism for securing OSGi services is based on OSGi Service Registry Hooks. This is an advanced OSGi feature that makes it possible to hide OSGi services from certain consumers and to replace an OSGi service with a proxy service.
When a service guard is in place for a particular OSGi service, a client invocation on the OSGi service proceeds as follows:
- The invocation does not go directly to the requested OSGi service. Instead, the request is routed to a replacement proxy service, which has the same service properties as the original service (and some extra ones).
- The service guard looks up the relevant ACL for the target OSGi service (where the ACLs are stored in the OSGi Config Admin service).
- The ACL returns the list of roles that are allowed to make this particular method invocation on the service.
- If no ACL is found for this command, the service guard defaults to the list of roles specified in the
karaf.secured.command.compulsory.roles
property in theetc/system.properties
file. - The service guard checks the list of roles against the current security subject (the user that is making the method invocation), to see whether the current user has any of the required roles.
- If no matching role is found, the method invocation is blocked and a
SecurityException
is raised. - Alternatively, if a matching role is found, the method invocation is delegated to the original OSGi service.
Configuring default security roles
For any commands that do not have a corresponding ACL file, you specify a default list of security roles by setting the
karaf.secured.command.compulsory.roles
property in the etc/system.properties
file (specified as a comma-separated list of roles).
Location of command console ACL files
The command console ACL files are located in the
InstallDir/etc/auth
directory, with the prefix, org.apache.karaf.command.acl
.
Mapping command scopes to ACL file names
The command console ACL file names obey the following convention:
etc/auth/org.apache.karaf.command.acl.CommandScope.cfg
Where the
CommandScope
corresponds to the prefix for a particular group of Karaf console commands. For example, the features:install
and features:uninstall
commands belong to the features
command scope, which has the corresponding ACL file, org.apache.karaf.command.acl.features.cfg
.
ACL file format
Each line of a command console ACL file is an entry in the following format:
Pattern = Role1[,Role2][,Role3]...
Where
Pattern
is a pattern that matches a Karaf console command from the current command scope, and the right-hand side of the equals sign is a comma-separated list of roles that give a user permission to make that invocation. In the simplest cases, the Pattern
is simply an unscoped command name. For example, the org.apache.karaf.command.acl.features.cfg
ACL file includes the following rules for the features
commands:
list = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser listRepositories = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser listUrl = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser info = Monitor, Operator, Maintainer, Deployer, Auditor, Administrator, SuperUser install = Administrator,SuperUser uninstall = Administrator,SuperUser
Important
If no match is found for a specific command name, it is assumed that no role is required for this command and it can be invoked by any user.
You can also define patterns to match commands invoked with specific arguments or even arguments that match a regular expression. For example, the
org.apache.karaf.command.acl.osgi.cfg
ACL file exploits this capability to prevent ordinary users from invoking the osgi:start
and osgi:stop
commands with the -f
(force) flag (which must be specified to manage system bundles). This restriction is coded as follows in the ACL file:
start[/.*[-][f].*/] = Administrator, SuperUser start = Deployer, Auditor, Administrator, SuperUser stop[/.*[-][f].*/] = Administrator, SuperUser stop = Deployer, Auditor, Administrator, SuperUser
In this case, the
Deployer
and Auditor
roles generally have permission to invoke the osgi:start
and osgi:stop
commands, but only the Administrator
and SuperUser
roles have permission to invoke these commands with the force option, -f
.
For complete details of the ACL file format, please see the comments in the
etc/auth/org.apache.karaf.command.acl.osgi.cfg
file.
Dynamic configuration at run time
The command console ACL settings are fully dynamic, which means you can change the ACL settings while the system is running and the changes will take effect within a few seconds, even for users that are already logged on.
2.2.4. Defining ACLs for OSGi Services
Overview
It is possible to define a custom ACL for any OSGi service (whether system level or application level). By default, OSGi services do not have access control enabled (with the exception of the OSGi services that expose Karaf console commands, which are pre-configured with command console ACL files). This section explains how to define a custom ACL for an OSGi service and how to invoke methods on that service using a specified role.
ACL file format
An OSGi service ACL file has one special entry, which identifies the OSGi service to which this ACL applies, as follows:
service.guard = (objectClass=InterfaceName)
Where the value of
service.guard
is an LDAP search filter that is applied to the registry of OSGi service properties in order to pick out the matching OSGi service. The simplest type of filter, (objectClass=InterfaceName)
, picks out an OSGi service with the specified Java interface name, InterfaceName
.
The remaining entries in the ACL file are of the following form:
Pattern = Role1[,Role2][,Role3]...
Where
Pattern
is a pattern that matches a service method, and the right-hand side of the equals sign is a comma-separated list of roles that give a user permission to make that invocation. The syntax of these entries is essentially the same as the entries in a JMX ACL file—see the section called “ACL file format”.
How to define an ACL for a custom OSGi service
To define an ACL for a custom OSGi service, perform the following steps:
- It is customary to define an OSGi service using a Java interface (you could use a regular Java class, but this is not recommended). For example, consider the Java interface,
MyService
, which we intend to expose as an OSGi service:package org.example; public interface MyService { void doit(String s); }
- To expose the Java interface as an OSGi service, you would typically add a
service
element to an OSGi Blueprint XML file (where the Blueprint XML file is typically stored under thesrc/main/resources/OSGI-INF/blueprint
directory in a Maven project). For example, assuming thatMyServiceImpl
is the class that implements theMyService
interface, you could expose theMyService
OSGi service as follows:<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" default-activation="lazy"> <bean id="myserviceimpl" class="org.example.MyServiceImpl"/> <service id="myservice" ref="myserviceimpl" interface="org.example.MyService"/> </blueprint>
- To define an ACL for the the OSGi service, you must create an OSGi Config Admin PID with the prefix,
org.apache.karaf.service.acl
.For example, in the case of a standalone container (where the OSGi Config Admin PIDs are stored as.cfg
files under theetc/auth/
directory), you can create the following ACL file for theMyService
OSGi service:etc/auth/org.apache.karaf.service.acl.myservice.cfg
NoteIt does not matter exactly how you name this file, as long as it starts with the required prefix,org.apache.karaf.service.acl
. The corresponding OSGi service for this ACL file is actually specified by a property setting in this file (as you will see in the next step). - Specify the contents of the ACL file in a format like the following:
service.guard = (objectClass=InterfaceName) Pattern = Role1[,Role2][,Role3]...
Theservice.guard
setting specifies theInterfaceName
of the OSGi service (using the syntax of an LDAP search filter, which is applied to the OSGi service properties). The other entries in the ACL file consist of a methodPattern
, which associates a matching method to the specified roles. For example, you could define a simple ACL for theMyService
OSGi service with the following settings in theorg.apache.karaf.service.acl.myservice.cfg
file:service.guard = (objectClass=org.example.MyService) doit = Deployer, Auditor, Administrator, SuperUser
- Finally, in order to enable the ACL for this OSGi service, you must edit the
karaf.secured.services
property in theetc/system.properties
file. The value of thekaraf.secured.services
property has the syntax of an LDAP search filter (which gets applied to the OSGi service properties). In general, to enable ACLs for an OSGi service,ServiceInterface
, you must modify this property as follows:karaf.secured.services=(|(objectClass=ServiceInterface)(...ExistingPropValue...))
For example, to enable theMyService
OSGi service:karaf.secured.services=(|(objectClass=org.example.MyService)(&(osgi.command.scope=*)(osgi.command.function=*)))
CautionThe initial value of thekaraf.secured.services
property has the settings to enable the command console ACLs. If you delete or corrupt these entries, the command console ACLs might stop working.
How to invoke an OSGi service secured with RBAC
If you are writing Java code to invoke methods an a custom OSGi service (that is, implementing a client of the OSGi service), you must use the Java security API to specify the role you are using to invoke the service. For example, to invoke the
MyService
OSGi service using the Deployer
role, you could use code like the following:
// Java import javax.security.auth.Subject; import org.apache.karaf.jaas.boot.principal.RolePrincipal; // ... Subject s = new Subject(); s.getPrincipals().add(new RolePrincipal("Deployer")); Subject.doAs(s, new PrivilegedAction() { public Object run() { svc.doit("foo"); // invoke the service } }
Note
This example uses the Karaf role type,
org.apache.karaf.jaas.boot.principal.RolePrincipal
. If necessary, you could use your own custom role class instead, but in that case you would have to specify your roles using the syntax className:roleName
in the OSGi service's ACL file.
How to discover the roles required by an OSGi service
When you are writing code against an OSGi service secured by an ACL, it can sometimes be useful to check what roles are allowed to invoke the service. For this purpose, the proxy service exports an additional OSGi property,
org.apache.karaf.service.guard.roles
. The value of this property is a java.util.Collection
object, which contains a list of all the roles that could possibly invoke a method on that service.