Chapter 21. Security
Apache Karaf provides an advanced and flexible security system, powered by JAAS (Java Authentication and Authorization Service) in an OSGi compliant way.
It provides a dynamic security system.
The Apache Karaf security framework is used internally to control the access to:
- the OSGi services (described in the developer guide)
- the console commands
- the JMX layer
- the WebConsole
Your applications can also use the security framework (see the developer guide for details).
21.1. Realms Copy linkLink copied to clipboard!
Apache Karaf is able to manage multiple realms. A realm contains the definition of the login modules to use for the authentication and/or authorization on this realm. The login modules define the authentication and authorization for the realm.
The jaas:realm-list command list the current defined realms:
karaf@root()> jaas:realm-list Index | Realm Name | Login Module Class Name ----------------------------------------------------------------------------------- 1 | karaf | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule 2 | karaf | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1 | karaf | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2 | karaf | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
You can see that the Apache Karaf provides a default realm named karaf.
This realm has two login modules:
-
the
PropertiesLoginModuleuses theetc/users.propertiesfile as backend for users, groups, roles and password. This login module authenticates the users and returns the users' roles. -
the
PublickeyLoginModuleis especially used by the SSHd. It uses theetc/keys.propertiesfile. This file contains the users and a public key associated to each user.
Apache Karaf provides additional login modules (see the developer guide for details):
- JDBCLoginModule uses a database as backend
- LDAPLoginModule uses a LDAP server as backend
- SyncopeLoginModule uses Apache Syncope as backend
- OsgiConfigLoginModule uses a configuration as backend
- Krb5LoginModule uses a Kerberos Server as backend
- GSSAPILdapLoginModule uses a LDAP server as backend but delegate LDAP server authentication to an other backend (typically Krb5LoginModule)
You can manage an existing realm, login module, or create your own realm using the jaas:realm-manage command.
21.1.1. Users, groups, roles, and passwords Copy linkLink copied to clipboard!
As we saw, by default, Apache Karaf uses a PropertiesLoginModule.
This login module uses the etc/users.properties file as storage for the users, groups, roles and passwords.
The initial etc/users.properties file contains:
We can see in this file, that we have one user by default: karaf. The default password is karaf.
The karaf user is member of one group: the admingroup.
A group is always prefixed by g:. An entry without this prefix is an user.
A group defines a set of roles. By default, the admingroup defines group, admin, manager, and viewer roles.
It means that the karaf user will have the roles defined by the admingroup.
21.1.1.1. Commands Copy linkLink copied to clipboard!
The jaas:* commands manage the realms, users, groups, roles in the console.
21.1.1.1.1. jaas:realm-list Copy linkLink copied to clipboard!
We already used the jaas:realm-list previously in this section.
The jaas:realm-list command list the realm and the login modules for each realm:
karaf@root()> jaas:realm-list Index | Realm Name | Login Module Class Name ----------------------------------------------------------------------------------- 1 | karaf | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule 2 | karaf | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1 | karaf | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2 | karaf | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
We have here one realm (karaf) containing two login modules (PropertiesLoginModule and PublickeyLoginModule).
The index is used by the jaas:realm-manage command to easily identify the realm/login module that we want to manage.
21.1.1.1.2. jaas:realm-manage Copy linkLink copied to clipboard!
The jaas:realm-manage command switch in realm/login module edit mode, where you can manage the users, groups, and roles in the login module.
To identify the realm and login module that you want to manage, you can use the --index option. The indexes are displayed by the jaas:realm-list command:
karaf@root()> jaas:realm-manage --index 1
karaf@root()> jaas:realm-manage --index 1
Another way is to use the --realm and --module options. The --realm option expects the realm name, and the --module option expects the login module class name:
karaf@root()> jaas:realm-manage --realm karaf --module org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
karaf@root()> jaas:realm-manage --realm karaf --module org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
21.1.1.1.3. jaas:user-list Copy linkLink copied to clipboard!
When you are in edit mode, you can list the users in the login module using the jaas:user-list:
You can see the user name and the group by role.
21.1.1.1.4. jaas:user-add Copy linkLink copied to clipboard!
The jaas:user-add command adds a new user (and the password) in the currently edited login module:
karaf@root()> jaas:user-add foo bar
karaf@root()> jaas:user-add foo bar
To "commit" your change (here the user addition), you have to execute the jaas:update command:
On the other hand, if you want to rollback the user addition, you can use the jaas:cancel command.
21.1.1.1.5. jaas:user-delete Copy linkLink copied to clipboard!
The jaas:user-delete command deletes an user from the currently edited login module:
karaf@root()> jaas:user-delete foo
karaf@root()> jaas:user-delete foo
Like for the jaas:user-add command, you have to use the jaas:update to commit your change (or jaas:cancel to rollback):
21.1.1.1.6. jaas:group-add Copy linkLink copied to clipboard!
The jaas:group-add command assigns a group (and eventually creates the group) to an user in the currently edited login module:
karaf@root()> jaas:group-add karaf mygroup
karaf@root()> jaas:group-add karaf mygroup
21.1.1.1.7. jaas:group-delete Copy linkLink copied to clipboard!
The jaas:group-delete command removes an user from a group in the currently edited login module:
karaf@root()> jaas:group-delete karaf mygroup
karaf@root()> jaas:group-delete karaf mygroup
21.1.1.1.8. jaas:group-role-add Copy linkLink copied to clipboard!
The jaas:group-role-add command adds a role in a group in the currently edited login module:
karaf@root()> jaas:group-role-add mygroup myrole
karaf@root()> jaas:group-role-add mygroup myrole
21.1.1.1.9. jaas:group-role-delete Copy linkLink copied to clipboard!
The jaas:group-role-delete command removes a role from a group in the currently edited login module:
karaf@root()> jaas:group-role-delete mygroup myrole
karaf@root()> jaas:group-role-delete mygroup myrole
21.1.1.1.10. jaas:update Copy linkLink copied to clipboard!
The jaas:update command commits your changes in the login module backend. For instance, in the case of the PropertiesLoginModule, the etc/users.properties will be updated only after the execution of the jaas:update command.
21.1.1.1.11. jaas:cancel Copy linkLink copied to clipboard!
The jaas:cancel command rollback your changes and doesn’t update the login module backend.
21.1.2. Passwords encryption Copy linkLink copied to clipboard!
By default, the passwords are stored in clear form in the etc/users.properties file.
It’s possible to enable encryption in the etc/org.apache.karaf.jaas.cfg configuration file:
If the encryption.enabled y is set to true, the password encryption is enabled.
With encryption enabled, the password are encrypted at the first time an user logs in. The encrypted passwords are prefixed and suffixed with \{CRYPT\}. To re-encrypt the password, you can reset the password in clear (in etc/users.properties file), without the \{CRYPT\} prefix and suffix. Apache Karaf will detect that this password is in clear (because it’s not prefixed and suffixed with \{CRYPT\}) and encrypt it again.
The etc/org.apache.karaf.jaas.cfg configuration file allows you to define advanced encryption behaviours:
-
the
encryption.prefixproperty defines the prefix to "flag" a password as encrypted. The default is\{CRYPT\}. -
the
encryption.suffixproperty defines the suffix to "flag" a password as encrypted. The default is\{CRYPT\}. -
the
encryption.algorithmproperty defines the algorithm to use for encryption (digest). The possible values areMD2,MD5,SHA-1,SHA-256,SHA-384,SHA-512. The default isMD5. -
the
encryption.encodingproperty defines the encoding of the encrypted password. The possible values arehexadecimalorbase64. The default value ishexadecimal.
21.1.3. Managing authentication by key Copy linkLink copied to clipboard!
For the SSH layer, Karaf supports the authentication by key, allowing to login without providing the password.
The SSH client (so bin/client provided by Karaf itself, or any ssh client like OpenSSH) uses a public/private keys pair that will identify himself on Karaf SSHD (server side).
The keys allowed to connect are stored in etc/keys.properties file, following the format:
user=key,role
user=key,role
By default, Karaf allows a key for the karaf user:
karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,admin
# karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,admin
For security reason, this key is disabled. We encourage to create the keys pair per client and update the etc/keys.properties file.
The easiest way to create key pair is to use OpenSSH.
You can create a key pair using:
ssh-keygen -t dsa -f karaf.id_dsa -N karaf
ssh-keygen -t dsa -f karaf.id_dsa -N karaf
You have now the public and private keys:
-rw------- 1 jbonofre jbonofre 771 Jul 25 22:05 karaf.id_dsa -rw-r--r-- 1 jbonofre jbonofre 607 Jul 25 22:05 karaf.id_dsa.pub
-rw------- 1 jbonofre jbonofre 771 Jul 25 22:05 karaf.id_dsa
-rw-r--r-- 1 jbonofre jbonofre 607 Jul 25 22:05 karaf.id_dsa.pub
You can copy in the content of the karaf.id_dsa.pub file in the etc/keys.properties:
karaf=AAAAB3NzaC1kc3MAAACBAJLj9vnEhu3/Q9Cvym2jRDaNWkATgQiHZxmErCmiLRuD5Klfv+HT/+8WoYdnvj0YaXFP80phYhzZ7fbIO2LRFhYhPmGLa9nSeOsQlFuX5A9kY1120yB2kxSIZI0fU2hy1UCgmTxdTQPSYtdWBJyvO/vczoX/8I3FziEfss07Hj1NAAAAFQD1dKEzkt4e7rBPDokPOMZigBh4kwAAAIEAiLnpbGNbKm8SNLUEc/fJFswg4G4VjjngjbPZAjhkYe4+H2uYmynry6V+GOTS2kaFQGZRf9XhSpSwfdxKtx7vCCaoH9bZ6S5Pe0voWmeBhJXi/Sww8f2stpitW2Oq7V7lDdDG81+N/D7/rKDD5PjUyMsVqc1n9wCTmfqmi6XPEw8AAACAHAGwPn/Mv7P9Q9+JZRWtGq+i4pL1zs1OluiStCN9e/Ok96t3gRVKPheQ6IwLacNjC9KkSKrLtsVyepGA+V5j/N+Cmsl6csZilnLvMUTvL/cmHDEEhTIQnPNrDDv+tED2BFqkajQqYLgMWeGVqXsBU6IT66itZlYtrq4v6uDQG/o=,admin
karaf=AAAAB3NzaC1kc3MAAACBAJLj9vnEhu3/Q9Cvym2jRDaNWkATgQiHZxmErCmiLRuD5Klfv+HT/+8WoYdnvj0YaXFP80phYhzZ7fbIO2LRFhYhPmGLa9nSeOsQlFuX5A9kY1120yB2kxSIZI0fU2hy1UCgmTxdTQPSYtdWBJyvO/vczoX/8I3FziEfss07Hj1NAAAAFQD1dKEzkt4e7rBPDokPOMZigBh4kwAAAIEAiLnpbGNbKm8SNLUEc/fJFswg4G4VjjngjbPZAjhkYe4+H2uYmynry6V+GOTS2kaFQGZRf9XhSpSwfdxKtx7vCCaoH9bZ6S5Pe0voWmeBhJXi/Sww8f2stpitW2Oq7V7lDdDG81+N/D7/rKDD5PjUyMsVqc1n9wCTmfqmi6XPEw8AAACAHAGwPn/Mv7P9Q9+JZRWtGq+i4pL1zs1OluiStCN9e/Ok96t3gRVKPheQ6IwLacNjC9KkSKrLtsVyepGA+V5j/N+Cmsl6csZilnLvMUTvL/cmHDEEhTIQnPNrDDv+tED2BFqkajQqYLgMWeGVqXsBU6IT66itZlYtrq4v6uDQG/o=,admin
and specify to the client to use the karaf.id_dsa private key:
bin/client -k ~/karaf.id_dsa
bin/client -k ~/karaf.id_dsa
or to ssh
ssh -p 8101 -i ~/karaf.id_dsa karaf@localhost
ssh -p 8101 -i ~/karaf.id_dsa karaf@localhost
21.1.4. RBAC Copy linkLink copied to clipboard!
Apache Karaf uses the roles to control the access to the resources: it’s a RBAC (Role Based Access Control) system.
The roles are used to control:
- access to OSGi services
- access to the console (control the execution of the commands)
- access to JMX (MBeans and/or operations)
- access to the WebConsole
21.1.4.1. OSGi services Copy linkLink copied to clipboard!
The details about OSGi services RBAC support is explained in the developer guide.
21.1.4.2. Console Copy linkLink copied to clipboard!
Console RBAC supports is a specialization of the OSGi service RBAC. Actually, in Apache Karaf, all console commands are defined as OSGi services.
The console command name follows the scope:name format.
The ACL (Access Lists) are defined in etc/org.apache.karaf.command.acl.<scope>.cfg configuration files, where <scope> is the commands scope.
For instance, we can define the ACL to the feature:* commands by creating a etc/org.apache.karaf.command.acl.feature.cfg configuration file. In this etc/org.apache.karaf.command.acl.feature.cfg configuration file, we can set:
list = viewer info = viewer install = admin uninstall = admin
list = viewer
info = viewer
install = admin
uninstall = admin
Here, we define that feature:list and feature:info commands can be executed by users with viewer role, whereas the feature:install and feature:uninstall commands can only be executed by users with admin role. Note that users in the admin group will also have viewer role, so will be able to do everything.
Apache Karaf command ACLs can control access using (inside a given command scope):
-
the command name regex (e.g.
name = role) -
the command name and options or arguments values regex (e.g.
name[/.[0-9][0-9][0-9]+./] = roleto execute name only with argument value above 100)
Both command name and options/arguments support exact matching or regex matching.
By default, Apache Karaf defines the following commands ACLs:
-
etc/org.apache.karaf.command.acl.bundle.cfgconfiguration file defines the ACL forbundle:*commands. This ACL limits the execution ofbundle:*commands for system bundles only to the users withadminrole, whereasbundle:*commands for non-system bundles can be executed by the users withmanagerrole. -
etc/org.apache.karaf.command.acl.config.cfgconfiguration file defines the ACL forconfig:*commands. This ACL limits the execution ofconfig:*commands withjmx.acl.*,org.apache.karaf.command.acl.*, andorg.apache.karaf.service.acl.*configuration PID to the users withadminrole. For the other configuration PID, the users with themanagerrole can executeconfig:*commands. -
etc/org.apache.karaf.command.acl.feature.cfgconfiguration file defines the ACL forfeature:*commands. Only the users withadminrole can executefeature:installandfeature:uninstallcommands. The otherfeature:*commands can be executed by any user. -
etc/org.apache.karaf.command.acl.jaas.cfgconfiguration file defines the ACL forjaas:*commands. Only the users withadminrole can executejaas:updatecommand. The otherjaas:*commands can be executed by any user. -
etc/org.apache.karaf.command.acl.kar.cfgconfiguration file defines the ACL forkar:*commands. Only the users withadminrole can executekar:installandkar:uninstallcommands. The otherkar:*commands can be executed by any user. -
etc/org.apache.karaf.command.acl.shell.cfgconfiguration file defines the ACL forshell:*and "direct" commands. Only the users withadminrole can executeshell:edit,shell:exec,shell:new, andshell:javacommands. The othershell:*commands can be executed by any user.
You can change these default ACLs, and add your own ACLs for additional command scopes (for instance etc/org.apache.karaf.command.acl.cluster.cfg for Apache Karaf Cellar, etc/org.apache.karaf.command.acl.camel.cfg from Apache Camel, …).
You can fine tuned the command RBAC support by editing the karaf.secured.services property in etc/system.properties:
By default, only Karaf shell commands are secured, but additional services can be secured by expanding this filter
#
# By default, only Karaf shell commands are secured, but additional services can be
# secured by expanding this filter
#
karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))
21.1.4.3. JMX Copy linkLink copied to clipboard!
Like for the console commands, you can define ACL (AccessLists) to the JMX layer.
The JMX ACL are defined in etc/jmx.acl<ObjectName>.cfg configuration file, where <ObjectName> is a MBean object name (for instance org.apache.karaf.bundle represents org.apache.karaf;type=Bundle MBean).
The etc/jmx.acl.cfg is the most generic configuration file and is used when no specific ones are found. It contains the "global" ACL definition.
JMX ACLs can control access using (inside a JMX MBean):
-
the operation name regex (e.g.
operation* = role) -
the operation arguments value regex (e.g.
operation(java.lang.String, int)[/([1-4])?[0-9]/,/.*/] = role)
By default, Apache Karaf defines the following JMX ACLs:
-
etc/jmx.acl.org.apache.karaf.bundle.cfgconfiguration file defines the ACL for theorg.apache.karaf:type=bundleMBean. This ACL limits thesetStartLevel(),start(),stop(), andupdate()operations for system bundles for only users withadminrole. The other operations can be performed by users with themanagerrole. -
etc/jmx.acl.org.apache.karaf.config.cfgconfiguration file defines the ACL for theorg.apache.karaf:type=configMBean. This ACL limits the change onjmx.acl*,org.apache.karaf.command.acl*, andorg.apache.karaf.service.acl*configuration PIDs for only users withadminrole. The other operations can be performed by users with themanagerrole. -
etc/jmx.acl.org.apache.karaf.security.jmx.cfgconfiguration file defines the ACL for theorg.apache.karaf:type=security,area=jmxMBean. This ACL limits the invocation of thecanInvoke()operation for the users withviewerrole. -
etc/jmx.acl.osgi.compendium.cm.cfgconfiguration file defines the ACL for theosgi.compendium:type=cmMBean. This ACL limits the changes onjmx.acl*,org.apache.karaf.command.acl*, andorg.apache.karaf.service.acl*configuration PIDs for only users withadminrole. The other operations can be performed by users with themanagerrole. -
etc/jmx.acl.java.lang.Memory.cfgconfiguration file defines the ACL for the core JVM Memory MBean. This ACL limits the invocation of thegcoperation for only users with themanagerrole. -
etc/jmx.acl.cfgconfiguration file is the most generic file. The ACLs defined here are used when no other specific ACLs match (by specific ACL, it’s an ACL defined in another MBean specificetc/jmx.acl.*.cfgconfiguration file). Thelist*(),get*(),is*()operations can be performed by users with theviewerrole. Theset*()and all other*()operations can be performed by users with theadminrole.
21.1.4.4. WebConsole Copy linkLink copied to clipboard!
The Apache Karaf WebConsole is not available by default. To enable it, you have to install the webconsole feature:
karaf@root()> feature:install webconsole
karaf@root()> feature:install webconsole
The WebConsole doesn’t support fine grained RBAC like console or JMX for now.
All users with the admin role can logon the WebConsole and perform any operations.
21.1.5. SecurityMBean Copy linkLink copied to clipboard!
Apache Karaf provides a JMX MBean to check if the current user can invoke a given MBean and/or operation.
The canInvoke() operation gets the roles of the current user, and check if one the roles can invoke the MBean and/or the operation, eventually with a given argument value.
21.1.5.1. Operations Copy linkLink copied to clipboard!
-
canInvoke(objectName)returnstrueif the current user can invoke the MBean with theobjectName,falseelse. -
canInvoke(objectName, methodName)returnstrueif the current user can invoke the operationmethodNameon the MBean with theobjectName,falseelse. -
canInvoke(objectName, methodName, argumentTypes)returnstrueif the current user can invoke the operationmethodNamewith the array of arguments typesargumentTypeson the MBean withobjectName,falseelse. -
canInvoke(bulkQuery)returns a tabular data containing for each operation in thebulkQuerytabular data ifcanInvokeistrueorfalse.
21.1.6. Security providers Copy linkLink copied to clipboard!
Some applications require specific security providers to be available, such as [BouncyCastle|http://www.bouncycastle.org].
The JVM imposes some restrictions about the use of such jars: they have to be signed and be available on the boot classpath.
One way to deploy those providers is to put them in the JRE folder at $JAVA_HOME/jre/lib/ext and modify the security policy configuration ($JAVA_HOME/jre/lib/security/java.security) in order to register such providers.
While this approach works fine, it has a global effect and requires you to configure all your servers accordingly.
Apache Karaf offers a simple way to configure additional security providers: * put your provider jar in lib/ext * modify the etc/config.properties configuration file to add the following property
org.apache.karaf.security.providers = xxx,yyy
org.apache.karaf.security.providers = xxx,yyy
The value of this property is a comma separated list of the provider class names to register.
For instance, to add the bouncycastle security provider, you define:
org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider
org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider
In addition, you may want to provide access to the classes from those providers from the system bundle so that all bundles can access those.
It can be done by modifying the org.osgi.framework.bootdelegation property in the same configuration file:
org.osgi.framework.bootdelegation = ...,org.bouncycastle*
org.osgi.framework.bootdelegation = ...,org.bouncycastle*