| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| === Security framework |
| |
| Karaf supports http://download.oracle.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html[JAAS] with |
| some enhancements to allow JAAS to work nicely in an OSGi environment. |
| |
| This framework also features an OSGi keystore manager with the ability to deploy new keystores or truststores at runtime. |
| |
| ==== Overview |
| |
| This feature allows runtime deployment of JAAS based configuration for use in various parts of the application. This |
| includes the remote console login, which uses the `karaf` realm, but which is configured with a dummy login module |
| by default. These realms can also be used by the NMR, JBI components or the JMX server to authenticate users logging in |
| or sending messages into the bus. |
| |
| In addition to JAAS realms, you can also deploy keystores and truststores to secure the remote shell console, setting |
| up HTTPS connectors or using certificates for WS-Security. |
| |
| A very simple XML schema for spring has been defined, allowing the deployment of a new realm or a new keystore very easily. |
| |
| ==== Schema |
| |
| To override or deploy a new realm, you can use the following XSD which is supported by a Spring namespace handler and |
| can thus be defined in a Spring xml configuration file. |
| |
| You can find the schema at the following http://karaf.apache.org/xmlns/jaas/v1.1.0 |
| |
| Here are two examples using this schema: |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0" |
| xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"> |
| |
| <!-- Bean to allow the $[karaf.base] property to be correctly resolved --> |
| <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/> |
| |
| <jaas:config name="myrealm"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| </jaas:module> |
| </jaas:config> |
| |
| </blueprint> |
| ---- |
| |
| ---- |
| <jaas:keystore xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0" |
| name="ks" |
| rank="1" |
| path="classpath:privatestore.jks" |
| keystorePassword="keyStorePassword" |
| keyPasswords="myalias=myAliasPassword"> |
| </jaas:keystore> |
| ---- |
| |
| The `id` attribute is the blueprint id of the bean, but it will be used by default as the name of the realm if no |
| `name` attribute is specified. Additional attributes on the `config` elements are a `rank`, which is an integer. |
| When the LoginContext looks for a realm for authenticating a given user, the realms registered in the OSGi registry are |
| matched against the required name. If more than one realm is found, the one with the highest rank will be used, thus |
| allowing the override of some realms with new values. The last attribute is `publish` which can be set to false to |
| not publish the realm in the OSGi registry, thereby disabling the use of this realm. |
| |
| Each realm can contain one or more module definitions. Each module identifies a LoginModule and the `className` |
| attribute must be set to the class name of the login module to use. Note that this login module must be available from |
| the bundle classloader, so either it has to be defined in the bundle itself, or the needed package needs to be correctly |
| imported. The `flags` attribute can take one of four values. |
| The content of the `module` element is parsed as a properties file and will be used to further configure the login module. |
| |
| Deploying such a code will lead to a JaasRealm object in the OSGi registry, which will then be used when using the JAAS login module. |
| |
| ===== Configuration override and use of the `rank` attribute |
| |
| The `rank` attribute on the `config` element is tied to the ranking of the underlying OSGi service. When the JAAS |
| framework performs an authentication, it will use the realm name to find a matching JAAS configuration. If multiple |
| configurations are used, the one with the highest `rank` attribute will be used. |
| So if you want to override the default security configuration in Karaf (which is used by the ssh shell, web console and |
| JMX layer), you need to deploy a JAAS configuration with the name `name="karaf"` and `rank="1"`. |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0" |
| xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"> |
| |
| <!-- Bean to allow the $[karaf.base] property to be correctly resolved --> |
| <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/> |
| |
| <jaas:config name="karaf" rank="1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| ... |
| </jaas:module> |
| </jaas:config> |
| |
| </blueprint> |
| ---- |
| |
| ==== Architecture |
| |
| Due to constraints in the JAAS specification, one class has to be available for all bundles. |
| This class is called ProxyLoginModule and is a LoginModule that acts as a proxy for an OSGi defined LoginModule. |
| If you plan to integrate this feature into another OSGi runtime, this class must be made available from the system |
| classloader and the related package be part of the boot delegation classpath (or be deployed as a fragment attached to |
| the system bundle). |
| |
| The xml schema defined above allows the use of a simple xml (leveraging spring xml extensibility) to configure and |
| register a JAAS configuration for a given realm. This configuration will be made available into the OSGi registry as a |
| JaasRealm and the OSGi specific Configuration will look for such services. |
| Then the proxy login module will be able to use the information provided by the realm to actually load the class from |
| the bundle containing the real login module. |
| |
| Karaf itself provides a set of login modules ready to use, depending of the authentication backend that you need. |
| |
| In addition to the login modules, Karaf also supports backend engines. The backend engine is coupled to a login module and |
| allows you to manipulate users and roles directly from Karaf (adding a new user, delete an existing user, etc). |
| The backend engine is constructed by a backend engine factory, registered as an OSGi service. |
| Some login modules (for security reasons for instance) don't provide backend engine. |
| |
| ==== Available realm and login modules |
| |
| Karaf comes with a default realm named "karaf" using login modules. |
| |
| Karaf also provides a set of login modules and backend engines to handle authentication needs for your environment. |
| |
| ===== PropertiesLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule |
| | org.apache.karaf.jaas.modules.properties.PropertiesBackendEngineFactory |
| |=== |
| |
| This login module is the one configured by default. It uses a properties text file to load the users, passwords and roles. |
| |
| |=== |
| |Name |Description |
| |
| |`users` |
| | location of the properties file |
| |=== |
| |
| This file uses the http://download.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader)[properties file format]. |
| The format of the properties is as follows, with each line defining a user, its password and associated roles: |
| |
| ---- |
| user=password[,role][,role]... |
| ---- |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = ${karaf.etc}/users.properties |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| The PropertiesLoginModule provides a backend engine allowing: |
| |
| * add a new user |
| * delete an existing user |
| * list the users, groups, and roles |
| * add a new role to an user |
| * delete a role from an user |
| * add an user into a group |
| * remove an user from a group |
| * add a role to a group |
| * delete a role from a group |
| |
| To enable the backend engine, you have to register the corresponding OSGi service. For instance, the following blueprint |
| shows how to register the PropertiesLoginModule and the corresponding backend engine: |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0" |
| xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"> |
| |
| <jaas:config name="karaf" rank="-1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = ${karaf.etc}/users.properties |
| </jaas:module> |
| </jaas:config> |
| |
| <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory"> |
| <bean class="org.apache.karaf.jaas.modules.properties.PropertiesBackingEngineFactory"/> |
| </service> |
| |
| </blueprint> |
| ---- |
| |
| ===== OsgiConfigLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.osgi.OsgiConfigLoginModule |
| |N/A |
| |=== |
| |
| The OsgiConfigLoginModule uses the OSGi ConfigurationAdmin service to provide the users, passwords and roles. |
| |
| |=== |
| |Name |Description |
| |
| |`pid` |
| |the PID of the configuration containing user definitions |
| |=== |
| |
| The format of the configuration is the same than for the `PropertiesLoginModule` with properties prefixed with `user.`. |
| |
| For instance, in the Karaf etc folder, we create a file `org.apache.karaf.authentication.cfg` containing: |
| |
| ---- |
| user.karaf=karaf,admin |
| user.user=password,role |
| ---- |
| |
| The following blueprint shows how to use this configuration: |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0"> |
| |
| <jaas:config name="karaf" rank="-1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.osgi.OsgiConfigLoginModule" |
| flags="required"> |
| pid = org.apache.karaf.authentication |
| </jaas:module> |
| </jaas:config> |
| |
| </blueprint> |
| ---- |
| |
| [NOTE] |
| ==== |
| The OsgiConfigLoginModule doesn't provide a backend engine. |
| ==== |
| |
| ===== JDBCLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule |
| |org.apache.karaf.jaas.modules.jdbc.JDBCBackendEngineFactory |
| |=== |
| |
| The JDBCLoginModule uses a database to load the users, passwords and roles from a provided data source (normal or XA). |
| The data source and the queries for password and role retrieval are configurable using the following parameters. |
| |
| |=== |
| |Name |Description |
| |
| |`datasource` |
| |The datasource as on OSGi ldap filter or as JDNI name |
| |
| |`query.password` |
| |The SQL query that retries the password of the user |
| |
| |`query.role` |
| |The SQL query that retries the roles of the user |
| |=== |
| |
| To use an OSGi ldap filter, the prefix osgi: needs to be provided, as shown below: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule" |
| flags="required"> |
| datasource = osgi:javax.sql.DataSource/(osgi.jndi.service.name=jdbc/karafdb) |
| query.password = SELECT PASSWORD FROM USERS WHERE USERNAME=? |
| query.role = SELECT ROLE FROM ROLES WHERE USERNAME=? |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| To use an JNDI name, the prefix jndi: needs to be provided. The example below assumes the use of Aries jndi to expose |
| services via JNDI. |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule" |
| flags="required"> |
| datasource = jndi:aries:services/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/karafdb) |
| query.password = SELECT PASSWORD FROM USERS WHERE USERNAME=? |
| query.role = SELECT ROLE FROM ROLES WHERE USERNAME=? |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| The JDBCLoginModule provides a backend engine allowing: |
| |
| * add a new user |
| * delete an user |
| * list users, roles |
| * add a new role to an user |
| * remove a role from an user |
| |
| [NOTE] |
| ==== |
| The groups are not fully supported by the JDBCBackingEngine. |
| ==== |
| |
| The following blueprint shows how to define the JDBCLoginModule with the corresponding backend engine: |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0"> |
| |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule" |
| flags="required"> |
| datasource = jndi:aries:services/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/karafdb) |
| query.password = SELECT PASSWORD FROM USERS WHERE USERNAME=? |
| query.role = SELECT ROLE FROM ROLES WHERE USERNAME=? |
| insert.user = INSERT INTO USERS(USERNAME,PASSWORD) VALUES(?,?) |
| insert.role = INSERT INTO ROLES(ROLE,USERNAME) VALUES(?,?) |
| delete.user = DELETE FROM USERS WHERE USERNAME=? |
| </jaas:module> |
| </jaas:config> |
| |
| <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory"> |
| <bean class="org.apache.karaf.jaas.modules.jdbc.JDBCBackingEngineFactory"/> |
| </service> |
| |
| </blueprint> |
| ---- |
| |
| ===== LDAPLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.ldap.LDAPLoginModule |
| |N/A |
| |=== |
| |
| The LDAPLoginModule uses LDAP to load the users and roles and bind the users on the LDAP to check passwords. |
| |
| The LDAPLoginModule supports the following parameters: |
| |
| |=== |
| |Name |Description |
| |
| |`connection.url` |
| |The LDAP connection URL, e.g. ldap://hostname |
| |
| |`connection.username` |
| |Admin username to connect to the LDAP. This parameter is optional, if it's not provided, the LDAP connection will be anonymous. |
| |
| |`connection.password` |
| |Admin password to connect to the LDAP. Only used if the `connection.username` is specified. |
| |
| |`user.base.dn` |
| |The LDAP base DN used to looking for user, e.g. ou=user,dc=apache,dc=org |
| |
| |`user.filter` |
| |The LDAP filter used to looking for user, e.g. (uid=%u) where %u will be replaced by the username. |
| |
| |`user.search.subtree` |
| |If "true", the user lookup will be recursive (SUBTREE). If "false", the user lookup will be performed only at the first level (ONELEVEL). |
| |
| |`role.base.dn` |
| |The LDAP base DN used to looking for roles, e.g. ou=role,dc=apache,dc=org |
| |
| |`role.filter` |
| |The LDAP filter used to looking for user's role, e.g. (member:=uid=%u) |
| |
| |`role.name.attribute` |
| |The LDAP role attribute containing the role string used by Karaf, e.g. cn |
| |
| |`role.search.subtree` |
| |If "true", the role lookup will be recursive (SUBTREE). If "false", the role lookup will be performed only at the first level (ONELEVEL). |
| |
| |`role.mapping` |
| |Define a mapping between roles defined in the LDAP directory for the user, and corresponding roles in Karaf. The format is ldapRole1=karafRole1,karafRole2;ldapRole2=karafRole3,karafRole4. |
| |
| |`authentication` |
| |Define the authentication backend used on the LDAP server. The default is simple. |
| |
| |`initial.context.factory` |
| |Define the initial context factory used to connect to the LDAP server. The default is com.sun.jndi.ldap.LdapCtxFactory |
| |
| |`ssl` |
| |If "true" or if the protocol on the `connection.url` is `ldaps`, an SSL connection will be used |
| |
| |`ssl.provider` |
| |The provider name to use for SSL |
| |
| |`ssl.protocol` |
| |The protocol name to use for SSL (SSL for example) |
| |
| |`ssl.algorithm` |
| |The algorithm to use for the KeyManagerFactory and TrustManagerFactory (PKIX for example) |
| |
| |`ssl.keystore` |
| |The key store name to use for SSL. The key store must be deployed using a `jaas:keystore` configuration. |
| |
| |`ssl.keyalias` |
| |The key alias to use for SSL |
| |
| |`ssl.truststore` |
| |The trust store name to use for SSL. The trust store must be deployed using a `jaas:keystore` configuration. |
| |
| |`ignorePartialResultException` |
| |Workaround for Active Directory servers not handling referrals correctly. When the `context.java.naming.referral` parameter is `false` (as it is by default), this will prevent `PartialResultException`s from being thrown during enumeration of search results. |
| |=== |
| |
| A example of LDAPLoginModule usage follows: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required"> |
| connection.url = ldap://localhost:389 |
| user.base.dn = ou=user,dc=apache,dc=org |
| user.filter = (cn=%u) |
| user.search.subtree = true |
| role.base.dn = ou=group,dc=apache,dc=org |
| role.filter = (member:=uid=%u) |
| role.name.attribute = cn |
| role.search.subtree = true |
| authentication = simple |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| If you wish to use an SSL connection, the following configuration can be used as an example: |
| |
| ---- |
| <ext:property-placeholder /> |
| |
| <jaas:config name="karaf" rank="1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required"> |
| connection.url = ldaps://localhost:10636 |
| user.base.dn = ou=users,ou=system |
| user.filter = (uid=%u) |
| user.search.subtree = true |
| role.base.dn = ou=groups,ou=system |
| role.filter = (uniqueMember=uid=%u) |
| role.name.attribute = cn |
| role.search.subtree = true |
| authentication = simple |
| ssl.protocol=SSL |
| ssl.truststore=ks |
| ssl.algorithm=PKIX |
| </jaas:module> |
| </jaas:config> |
| |
| <jaas:keystore name="ks" |
| path="file:///${karaf.home}/etc/trusted.ks" |
| keystorePassword="secret" /> |
| ---- |
| |
| The LDAPLoginModule supports the following patterns that you can use in the filter (user and role filters): |
| |
| * `%u` is replaced by the user |
| * `%dn` is replaced by the user DN |
| * `%fqdn` is replaced by the user full qualified DN (`userDNNamespace`). |
| |
| For instance, the following configuration will work properly with ActiveDirectory (adding the ActiveDirectory to the |
| default `karaf` realm): |
| |
| ---- |
| <jaas:config name="karaf" rank="2"> |
| <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required"> |
| initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory |
| connection.username=admin |
| connection.password=xxxxxxx |
| connection.protocol= |
| connection.url=ldap://activedirectory_host:389 |
| user.base.dn=ou=Users,ou=there,DC=local |
| user.filter=(sAMAccountName=%u) |
| user.search.subtree=true |
| role.base.dn=ou=Groups,ou=there,DC=local |
| role.name.attribute=cn |
| role.filter=(member=%fqdn) |
| role.search.subtree=true |
| authentication=simple |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| [NOTE] |
| ==== |
| The LDAPLoginModule doesn't provide backend engine. It means that the administration of the users and roles should be |
| performed directly on the LDAP backend. |
| ==== |
| |
| ===== KerberosLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.krb5.Krb5LoginModule |
| | |
| |=== |
| |
| The Kerberos login module uses the Oracle JVM Krb5 internal login module. |
| |
| Here is a simple configuration : |
| ---- |
| <jaas:config name="krb5" rank="1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.krb5.Krb5LoginModule"> |
| refreshKrb5Config = true |
| password-stacking = storePass |
| doNotPrompt = false |
| useTicketCache = true |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| You must specify a krb5 configuration file through the "java.security.krb5.conf" system property. |
| Here is a simple example of a krb5 configuration file : |
| ---- |
| [libdefaults] |
| default_realm = EXAMPLE.COM |
| dns_lookup_realm = false |
| dns_lookup_kdc = false |
| ticket_lifetime = 24h |
| renew_lifetime = 365d |
| forwardable = true |
| |
| [realms] |
| |
| EXAMPLE.COM = { |
| kdc = kdc.example.com |
| admin_server = kdc.example.com |
| default_domain = example.com |
| } |
| |
| [domain_realm] |
| .example.com = EXAMPLE.COM |
| example.com = EXAMPLE.COM |
| ---- |
| |
| ===== GSSAPILdapLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.ldap.GSSAPILdapLoginModule |
| | |
| |=== |
| |
| The GSSAPI module uses the GSSAPI mechanism to handle authentication to a LDAP server. |
| Typical use is using this and a Kerberos Login Module to connect to an ActiveDirectory Server, or any other LDAP server that needs a Kerberos tickets for authentication. |
| |
| Here is a simple configuration, that use as Kerberos login module as authentication backend : |
| ---- |
| <jaas:config name="ldap" rank="1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.ldap.GSSAPILdapLoginModule"flags="required"> |
| gssapiRealm=krb5 |
| initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory |
| connection.url=ldap://activedirectory_host:389 |
| user.base.dn=ou=Users,ou=there,DC=local |
| user.filter=(sAMAccountName=%u) |
| user.search.subtree=true |
| role.base.dn=ou=Groups,ou=there,DC=local |
| role.name.attribute=cn |
| role.filter=(member=%fqdn) |
| role.search.subtree=true |
| </jaas:module> |
| </jaas:config> |
| <jaas:config name="krb5" rank="1"> |
| <jaas:module className="org.apache.karaf.jaas.modules.krb5.Krb5LoginModule"> |
| refreshKrb5Config = true |
| password-stacking = storePass |
| doNotPrompt = false |
| useTicketCache = true |
| </jaas:module> |
| </jaas:config> |
| ---- |
| Note the 'gssapiRealm' property of the LDAP login module that match the name of the Kerberos Configuration. |
| |
| ===== SyncopeLoginModule |
| |
| |=== |
| |LoginModule |BackendEngineFactory |
| |
| |org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule |
| |org.apache.karaf.jaas.modules.syncope.SyncopeBackendEngineFactory |
| |=== |
| |
| The Syncope login module uses the Syncope REST API to authenticate users and retrieve the roles. |
| |
| The Syncope login module just requires one parameter: |
| |
| |=== |
| |Name |Description |
| |
| |`address` |
| |Location of the Syncope REST API |
| |
| |`version` |
| |Â Syncope backend version (could by "1.x" or "2.x" |
| |
| |`admin.user` |
| |Admin username to administrate Syncope (only required by the backend engine) |
| |
| |`admin.password` |
| |Admin password to administrate Syncope (only required by the backend engine) |
| |=== |
| |
| The following snippet shows how to use Syncope with the karaf realm: |
| |
| ---- |
| <jaas:config name="karaf" rank="2"> |
| <jaas:module className="org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule" flags="required"> |
| address=http://localhost:9080/syncope/cxf |
| version=1.x |
| admin.user=admin |
| admin.password=password |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| SyncopeLoginModule comes with a backend engine allowing to manipulate users and roles. You have to register the |
| SyncopeBackendEngineFactory service. |
| |
| For security reason, the SyncopeLoginModule backend engine allows only to list users and roles. You can't create or delete |
| users and roles directly from Karaf. To do it, you have to use the Syncope web console. |
| |
| For instance, the following blueprint descriptor enables the SyncopeLoginModule and the backend engine factory: |
| |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0" |
| xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"> |
| |
| <jaas:config name="karaf" rank="2"> |
| <jaas:module className="org.apache.karaf.jaas.modules.syncope.SyncopeLoginModule" |
| flags="required"> |
| address=http://localhost:9080/syncope/cxf |
| version=1.x |
| admin.user=admin |
| admin.password=password |
| </jaas:module> |
| </jaas:config> |
| |
| <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory"> |
| <bean class="org.apache.karaf.jaas.modules.syncope.SyncopeBackingEngineFactory"/> |
| </service> |
| |
| </blueprint> |
| ---- |
| |
| ==== Encryption service |
| |
| The EncryptionService is a service registered in the OSGi registry providing means to encrypt and check encrypted passwords. |
| This service acts as a factory for Encryption objects actually performing the encryption. |
| |
| This service is used in all Karaf login modules to support encrypted passwords. |
| |
| ===== Configuring properties |
| |
| Each login module supports the following additional set of properties: |
| |
| |=== |
| |Name |Description |
| |
| |`encryption.name` |
| |Name of the encryption service registered in OSGi (cf. Jasypt section) |
| |
| |`encryption.enabled` |
| |Boolean used to turn on encryption |
| |
| |`encryption.prefix` |
| |Prefix for encrypted passwords |
| |
| |`encryption.suffix` |
| |Suffix for encrypted passwords |
| |
| |`encryption.algorithm` |
| |Name of an algorithm to be used for hashing, like "MD5" or "SHA-1" |
| |
| |`encryption.encoding` |
| |Encrypted passwords encoding (can be `hexadecimal` or `base64`) |
| |
| |`role.policy` |
| |A policy for identifying roles (can be `prefix` or `group`) (see Role discovery policies section) |
| |
| |`role.discriminator` |
| |A discriminator value to be used by the role policy |
| |=== |
| |
| A simple example follows: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| encryption.enabled = true |
| encryption.algorithm = MD5 |
| encryption.encoding = hexadecimal |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| ===== Prefix and suffix |
| |
| The login modules have the ability to support both encrypted and plain passwords at the same time. |
| In some cases, some login modules may be able to encrypt the passwords on the fly and save them back in an encrypted form. |
| |
| ===== Jasypt |
| |
| Karaf default installation comes with a simple encryption service which usually fullfill simple needs. However, in some |
| cases, you may want to install the Jasypt (http://www.jasypt.org/) library which provides stronger encryption algorithms |
| and more control over them. |
| |
| To install the Jasypt library, the easiest way is to install the available feature: |
| |
| ---- |
| karaf@root> features:install jasypt-encryption |
| ---- |
| |
| It will download and install the required bundles and also register an `EncryptionService` for Jasypt in the OSGi registry. |
| |
| When configuring a login module to use Jasypt, you need to specify the `encryption.name` property and set it to a value of `jasypt` to make sure the Jasypt encryption service will be used. |
| |
| In addition to the standard properties above, the Jasypt service provides the following parameters: |
| |
| |=== |
| |Name |Description |
| |
| |`providerName` |
| |Name of the `java.security.Provider` name to use for obtaining the digest algorithm |
| |
| |`providerClassName` |
| |Class name for the security provider to be used for obtaining the digest algorithm |
| |
| |`iterations` |
| |Number of times the hash function will be applied recursively |
| |
| |`saltSizeBytes` |
| |Size of the salt to be used to compute the digest |
| |
| |`saltGeneratorClassName` |
| |Class name of the salt generator |
| |=== |
| |
| A typical realm definition using Jasypt encryption service would look like: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| encryption.enabled = true |
| encryption.name = jasypt |
| encryption.algorithm = SHA-256 |
| encryption.encoding = base64 |
| encryption.iterations = 100000 |
| encryption.saltSizeBytes = 16 |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| ===== Using encrypted property placeholders |
| |
| When using blueprint framework for OSGi for configuring devices that requires passwords like JDBC datasources, |
| it is undesirable to use plain text passwords in configuration files. To avoid this problem it is good to store database |
| passwords in encrypted format and use encrypted property placeholders when ever possible. |
| |
| Encrypted properties can be stored in plain properties files. The encrypted content is wrapped by an ENC() function. |
| |
| ---- |
| #db.cfg / db.properties |
| db.url=localhost:9999 |
| db.username=admin |
| db.password=ENC(zRM7Pb/NiKyCalroBz8CKw==) |
| ---- |
| |
| The encrypted property placeholders can be used either by defining Apache Aries ConfigAdmin `property-placeholder` |
| or by directly using the Apache Karaf `property-placeholder`. It has one child element `encryptor` that contains |
| the actual Jasypt configuration. For detailed information on how to configure the different Jasypt encryptors, see the |
| Jasypt documentation (http://www.jasypt.org/general-usage.html). |
| |
| A typical definition using Jasypt encryption would look like: |
| |
| ---- |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" |
| xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0" |
| xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0" |
| xmlns:enc="http://karaf.apache.org/xmlns/jasypt/v1.0.0"> |
| |
| <!-- Configuration via ConfigAdmin property-placeholder --> |
| <!-- the etc/*.cfg can contain encrypted values with ENC() function --> |
| <cm:property-placeholder persistent-id="db" update-strategy="reload"> |
| <cm:default-properties> |
| <cm:property name="encoded" value="ENC(${foo})"/> |
| </cm:default-properties> |
| </cm:property-placeholder> |
| |
| <!-- Configuration via properties file --> |
| <!-- Instead of ConfigAdmin, we can load "regular" properties file from a location --> |
| <!-- Again, the db.properties file can contain encrypted values with ENC() function --> |
| <ext:property-placeholder> |
| <ext:location>file:etc/db.properties</ext:location> |
| </ext:property-placeholder> |
| |
| <enc:property-placeholder> |
| <enc:encryptor class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> |
| <property name="config"> |
| <bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig"> |
| <property name="algorithm" value="PBEWithMD5AndDES"/> |
| <property name="passwordEnvName" value="ENCRYPTION_PASSWORD"/> |
| </bean> |
| </property> |
| </enc:encryptor> |
| </enc:property-placeholder> |
| |
| <!-- ... --> |
| |
| </blueprint> |
| ---- |
| |
| Don't forget to install the jasypt feature to add the support of the enc namespace: |
| |
| ---- |
| karaf@root()> feature:install jasypt-encryption |
| ---- |
| |
| ==== Role discovery policies |
| |
| The JAAS specification does not provide means to distinguish between User and Role Principals without referring to the |
| specification classes. In order to provide means to the application developer to decouple the application from Karaf |
| JAAS implementation role policies have been created. |
| |
| A role policy is a convention that can be adopted by the application in order to identify Roles, without depending on the implementation. |
| Each role policy can be cofigured by setting a "role.policy" and "role.discriminator" property to the login module configuration. |
| Currently, Karaf provides two policies that can be applied to all Karaf Login Modules. |
| |
| . Prefixed Roles |
| . Grouped Roles |
| |
| When the prefixed role policy is used the login module applies a configurable prefix _(property role.discriminator)_ to |
| the role, so that the application can identify the role's principals by its prefix. Example: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| role.policy = prefix |
| role.discriminator = ROLE_ |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| The application can identify the role principals using a snippet like this: |
| |
| ---- |
| LoginContext ctx = new LoginContext("karaf", handler); |
| ctx.login(); |
| authenticated = true; |
| subject = ctx.getSubject(); |
| for (Principal p : subject.getPrincipals()) { |
| if (p.getName().startsWith("ROLE_")) { |
| roles.add((p.getName().substring("ROLE_".length()))); |
| } |
| } |
| ---- |
| |
| When the group role policy is used the login module provides all roles as members of a group with a configurable name _(property role.discriminator)_. Example: |
| |
| ---- |
| <jaas:config name="karaf"> |
| <jaas:module className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule" |
| flags="required"> |
| users = $[karaf.base]/etc/users.properties |
| role.policy = group |
| role.discriminator = ROLES |
| </jaas:module> |
| </jaas:config> |
| ---- |
| |
| ---- |
| LoginContext ctx = new LoginContext("karaf", handler); |
| ctx.login(); |
| authenticated = true; |
| subject = ctx.getSubject(); |
| for (Principal p : subject.getPrincipals()) { |
| if ((p instanceof Group) && ("ROLES".equalsIgnoreCase(p.getName()))) { |
| Group g = (Group) p; |
| Enumeration<? extends Principal> members = g.members(); |
| while (members.hasMoreElements()) { |
| Principal member = members.nextElement(); |
| roles.add(member.getName()); |
| } |
| } |
| } |
| ---- |
| |
| ==== Default role policies |
| |
| The previous section describes how to leverage role policies. However, Karaf provides a default role policy, based on the following class names: |
| |
| * org.apache.karaf.jaas.modules.UserPrincipal |
| * org.apache.karaf.jaas.modules.RolePrincipal |
| * org.apache.karaf.jaas.modules.GroupPrincipal |
| |
| It allows you to directly handling the role class: |
| |
| ---- |
| String rolePrincipalClass = "org.apache.karaf.jaas.modules.RolePrincipal"; |
| |
| for (Principal p : subject.getPrincipals()) { |
| if (p.getClass().getName().equals(rolePrincipalClass)) { |
| roles.add(p.getName()); |
| } |
| } |
| ---- |