Chapter 5. Security realms
Security realms integrate Data Grid Server deployments with the network protocols and infrastructure in your environment that control access and verify user identities.
5.1. Creating security realms
Add security realms to Data Grid Server configuration to control access to deployments. You can add one or more security realm to your configuration.
When you add security realms to your configuration, Data Grid Server automatically enables the matching authentication mechanisms for the Hot Rod and REST endpoints.
Prerequisites
- Add socket bindings to your Data Grid Server configuration as required.
Create keystores, or have a PEM file, to configure the security realm with TLS/SSL encryption.
Data Grid Server can also generate keystores at startup.
-
Provision the resources or services that the security realm configuration relies on.
For example, if you add a token realm, you need to provision OAuth services.
This procedure demonstrates how to configure multiple property realms. Before you begin, you need to create properties files that add users and assign permissions with the Command Line Interface (CLI). Use the user create
commands as follows:
user create <username> -p <changeme> -g <role> \ --users-file=application-users.properties \ --groups-file=application-groups.properties user create <username> -p <changeme> -g <role> \ --users-file=management-users.properties \ --groups-file=management-groups.properties
Run user create --help
for examples and more information.
Adding credentials to a properties realm with the CLI creates the user only on the server instance to which you are connected. You must manually synchronize credentials in a properties realm to each node in the cluster.
Procedure
- Open your Data Grid Server configuration for editing.
-
Use the
security-realms
element in thesecurity
configuration to contain create multiple security realms. Add a security realm with the
security-realm
element and give it a unique name with thename
attribute.ImportantDo not add special characters, such as hyphens (
-
) or ampersands (&
), to security realm names. Data Grid Server endpoints can become unreachable if security realm names contain special characters.To follow the example, create one security realm named
ApplicationRealm
and another namedManagementRealm
.-
Provide the TLS/SSL identify for Data Grid Server with the
server-identities
element and configure a keystore as required. Specify the type of security realm by adding one the following elements or fields:
-
properties-realm
-
ldap-realm
-
token-realm
-
truststore-realm
-
Specify properties for the type of security realm you are configuring as appropriate.
To follow the example, specify the
*.properties
files you created with the CLI using thepath
attribute on theuser-properties
andgroup-properties
elements or fields.-
If you add multiple different types of security realm to your configuration, include the
distributed-realm
element or field so that Data Grid Server uses the realms in combination with each other. -
Configure Data Grid Server endpoints to use the security realm with the with the
security-realm
attribute. - Save the changes to your configuration.
Multiple property realms
The following configuration shows how you can configure multiple security realms in XML, JSON, or YAML format:
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="ApplicationRealm"> <properties-realm groups-attribute="Roles"> <user-properties path="application-users.properties"/> <group-properties path="application-groups.properties"/> </properties-realm> </security-realm> <security-realm name="ManagementRealm"> <properties-realm groups-attribute="Roles"> <user-properties path="management-users.properties"/> <group-properties path="management-groups.properties"/> </properties-realm> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "ManagementRealm", "properties-realm": { "groups-attribute": "Roles", "user-properties": { "digest-realm-name": "ManagementRealm", "path": "management-users.properties" }, "group-properties": { "path": "management-groups.properties" } } }, { "name": "ApplicationRealm", "properties-realm": { "groups-attribute": "Roles", "user-properties": { "digest-realm-name": "ApplicationRealm", "path": "application-users.properties" }, "group-properties": { "path": "application-groups.properties" } } }] } } }
YAML
server: security: securityRealms: - name: "ManagementRealm" propertiesRealm: groupsAttribute: "Roles" userProperties: digestRealmName: "ManagementRealm" path: "management-users.properties" groupProperties: path: "management-groups.properties" - name: "ApplicationRealm" propertiesRealm: groupsAttribute: "Roles" userProperties: digestRealmName: "ApplicationRealm" path: "application-users.properties" groupProperties: path: "application-groups.properties"
5.2. Setting up Kerberos identities
Add Kerberos identities to a security realm in your Data Grid Server configuration to use keytab files that contain service principal names and encrypted keys, derived from Kerberos passwords.
Prerequisites
- Have Kerberos service account principals.
keytab files can contain both user and service account principals. However, Data Grid Server uses service account principals only which means it can provide identity to clients and allow clients to authenticate with Kerberos servers.
In most cases, you create unique principals for the Hot Rod and REST endpoints. For example, if you have a "datagrid" server in the "INFINISPAN.ORG" domain you should create the following service principals:
-
hotrod/datagrid@INFINISPAN.ORG
identifies the Hot Rod service. -
HTTP/datagrid@INFINISPAN.ORG
identifies the REST service.
Procedure
Create keytab files for the Hot Rod and REST services.
- Linux
ktutil ktutil: addent -password -p datagrid@INFINISPAN.ORG -k 1 -e aes256-cts Password for datagrid@INFINISPAN.ORG: [enter your password] ktutil: wkt http.keytab ktutil: quit
- Microsoft Windows
ktpass -princ HTTP/datagrid@INFINISPAN.ORG -pass * -mapuser INFINISPAN\USER_NAME ktab -k http.keytab -a HTTP/datagrid@INFINISPAN.ORG
-
Copy the keytab files to the
server/conf
directory of your Data Grid Server installation. - Open your Data Grid Server configuration for editing.
-
Add a
server-identities
definition to the Data Grid server security realm. - Specify the location of keytab files that provide service principals to Hot Rod and REST connectors.
- Name the Kerberos service principals.
- Save the changes to your configuration.
Kerberos identity configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="kerberos-realm"> <server-identities> <!-- Specifies a keytab file that provides a Kerberos identity. --> <!-- Names the Kerberos service principal for the Hot Rod endpoint. --> <!-- The required="true" attribute specifies that the keytab file must be present when the server starts. --> <kerberos keytab-path="hotrod.keytab" principal="hotrod/datagrid@INFINISPAN.ORG" required="true"/> <!-- Specifies a keytab file and names the Kerberos service principal for the REST endpoint. --> <kerberos keytab-path="http.keytab" principal="HTTP/localhost@INFINISPAN.ORG" required="true"/> </server-identities> </security-realm> </security-realms> </security> <endpoints> <endpoint socket-binding="default" security-realm="KerberosRealm"> <hotrod-connector> <authentication> <sasl server-name="datagrid" server-principal="hotrod/datagrid@INFINISPAN.ORG"/> </authentication> </hotrod-connector> <rest-connector> <authentication server-principal="HTTP/localhost@INFINISPAN.ORG"/> </rest-connector> </endpoint> </endpoints> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "KerberosRealm", "server-identities": [{ "kerberos": { "principal": "hotrod/datagrid@INFINISPAN.ORG", "keytab-path": "hotrod.keytab", "required": true }, "kerberos": { "principal": "HTTP/localhost@INFINISPAN.ORG", "keytab-path": "http.keytab", "required": true } }] }] }, "endpoints": { "endpoint": { "socket-binding": "default", "security-realm": "KerberosRealm", "hotrod-connector": { "authentication": { "security-realm": "kerberos-realm", "sasl": { "server-name": "datagrid", "server-principal": "hotrod/datagrid@INFINISPAN.ORG" } } }, "rest-connector": { "authentication": { "server-principal": "HTTP/localhost@INFINISPAN.ORG" } } } } } }
YAML
server: security: securityRealms: - name: "KerberosRealm" serverIdentities: - kerberos: principal: "hotrod/datagrid@INFINISPAN.ORG" keytabPath: "hotrod.keytab" required: "true" - kerberos: principal: "HTTP/localhost@INFINISPAN.ORG" keytabPath: "http.keytab" required: "true" endpoints: endpoint: socketBinding: "default" securityRealm: "KerberosRealm" hotrodConnector: authentication: sasl: serverName: "datagrid" serverPrincipal: "hotrod/datagrid@INFINISPAN.ORG" restConnector: authentication: securityRealm: "KerberosRealm" serverPrincipal" : "HTTP/localhost@INFINISPAN.ORG"
5.3. Property realms
Property realms use property files to define users and groups.
-
users.properties
contains Data Grid user credentials. Passwords can be pre-digested with theDIGEST-MD5
andDIGEST
authentication mechanisms. -
groups.properties
associates users with roles and permissions.
Properties files contain headers that associate them with security realms in Data Grid Server configuration.
users.properties
myuser=a_password user2=another_password
groups.properties
myuser=supervisor,reader,writer user2=supervisor
Property realm configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="default"> <!-- groups-attribute configures the "groups.properties" file to contain security authorization roles. --> <properties-realm groups-attribute="Roles"> <user-properties path="users.properties" relative-to="infinispan.server.config.path" plain-text="true"/> <group-properties path="groups.properties" relative-to="infinispan.server.config.path"/> </properties-realm> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "default", "properties-realm": { "groups-attribute": "Roles", "user-properties": { "digest-realm-name": "default", "path": "users.properties", "relative-to": "infinispan.server.config.path", "plain-text": true }, "group-properties": { "path": "groups.properties", "relative-to": "infinispan.server.config.path" } } }] } } }
YAML
server: security: securityRealms: - name: "default" propertiesRealm: # groupsAttribute configures the "groups.properties" file # to contain security authorization roles. groupsAttribute: "Roles" userProperties: digestRealmName: "default" path: "users.properties" relative-to: 'infinispan.server.config.path' plainText: "true" groupProperties: path: "groups.properties" relative-to: 'infinispan.server.config.path'
5.4. LDAP realms
LDAP realms connect to LDAP servers, such as OpenLDAP, Red Hat Directory Server, Apache Directory Server, or Microsoft Active Directory, to authenticate users and obtain membership information.
LDAP servers can have different entry layouts, depending on the type of server and deployment. It is beyond the scope of this document to provide examples for all possible configurations.
The principal for LDAP connections must have necessary privileges to perform LDAP queries and access specific attributes.
As an alternative to verifying user credentials with the direct-verification
attribute, you can specify an LDAP attribute that validates passwords with the user-password-mapper
element.
You cannot use endpoint authentication mechanisms that perform hashing with the direct-verification
attribute.
Because Active Directory does not expose the password
attribute you can use the direct-verification
attribute only and not the user-password-mapper
element. As a result you must use the BASIC
authentication mechanism with the REST endpoint and PLAIN
with the Hot Rod endpoint to integrate with Active Directory Server. A more secure alternative is to use Kerberos, which allows the SPNEGO
, GSSAPI
, and GS2-KRB5
authentication mechanisms.
The rdn-identifier
attribute specifies an LDAP attribute that finds the user entry based on a provided identifier, which is typically a username; for example, the uid
or sAMAccountName
attribute. Add search-recursive="true"
to the configuration to search the directory recursively. By default, the search for the user entry uses the (rdn_identifier={0})
filter. Specify a different filter with the filter-name
attribute.
The attribute-mapping
element retrieves all the groups of which the user is a member. There are typically two ways in which membership information is stored:
-
Under group entries that usually have class
groupOfNames
in themember
attribute. In this case, you can use an attribute filter as in the preceding example configuration. This filter searches for entries that match the supplied filter, which locates groups with amember
attribute equal to the user’s DN. The filter then extracts the group entry’s CN as specified byfrom
, and adds it to the user’sRoles
. In the user entry in the
memberOf
attribute. In this case you should use an attribute reference such as the following:<attribute-reference reference="memberOf" from="cn" to="Roles" />
This reference gets all
memberOf
attributes from the user’s entry, extracts the CN as specified byfrom
, and adds them to the user’sRoles
.
LDAP realm configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="LdapRealm"> <!-- Specifies connection properties. --> <ldap-realm url="ldap://my-ldap-server:10389" principal="uid=admin,ou=People,dc=infinispan,dc=org" credential="strongPassword" connection-timeout="3000" read-timeout="30000" connection-pooling="true" referral-mode="ignore" page-size="30" direct-verification="true"> <!-- Defines how principals are mapped to LDAP entries. --> <identity-mapping rdn-identifier="uid" search-dn="ou=People,dc=infinispan,dc=org" search-recursive="false"> <!-- Retrieves all the groups of which the user is a member. --> <attribute-mapping> <attribute from="cn" to="Roles" filter="(&(objectClass=groupOfNames)(member={1}))" filter-dn="ou=Roles,dc=infinispan,dc=org"/> </attribute-mapping> </identity-mapping> </ldap-realm> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "LdapRealm", "ldap-realm": { "url": "ldap://my-ldap-server:10389", "principal": "uid=admin,ou=People,dc=infinispan,dc=org", "credential": "strongPassword", "connection-timeout": "3000", "read-timeout": "30000", "connection-pooling": "true", "referral-mode": "ignore", "page-size": "30", "direct-verification": "true", "identity-mapping": { "rdn-identifier": "uid", "search-dn": "ou=People,dc=infinispan,dc=org", "search-recursive": "false", "attribute-mapping": [{ "from": "cn", "to": "Roles", "filter": "(&(objectClass=groupOfNames)(member={1}))", "filter-dn": "ou=Roles,dc=infinispan,dc=org" }] } } }] } } }
YAML
server: security: securityRealms: - name: LdapRealm ldapRealm: url: 'ldap://my-ldap-server:10389' principal: 'uid=admin,ou=People,dc=infinispan,dc=org' credential: strongPassword connectionTimeout: '3000' readTimeout: '30000' connectionPooling: true referralMode: ignore pageSize: '30' directVerification: true identityMapping: rdnIdentifier: uid searchDn: 'ou=People,dc=infinispan,dc=org' searchRecursive: false attributeMapping: - filter: '(&(objectClass=groupOfNames)(member={1}))' filterDn: 'ou=Roles,dc=infinispan,dc=org' from: cn to: Roles
5.4.1. LDAP realm principal re-writing
SASL authentication mechanisms such as GSSAPI
, GS2-KRB5
and Negotiate
include a username that needs to be cleaned up before you can use it to search LDAP directories.
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="LdapRealm"> <ldap-realm url="ldap://${org.infinispan.test.host.address}:10389" principal="uid=admin,ou=People,dc=infinispan,dc=org" credential="strongPassword"> <name-rewriter> <!-- Defines a rewriter that extracts the username from the principal using a regular expression. --> <regex-principal-transformer name="domain-remover" pattern="(.*)@INFINISPAN\.ORG" replacement="$1"/> </name-rewriter> <identity-mapping rdn-identifier="uid" search-dn="ou=People,dc=infinispan,dc=org"> <attribute-mapping> <attribute from="cn" to="Roles" filter="(&(objectClass=groupOfNames)(member={1}))" filter-dn="ou=Roles,dc=infinispan,dc=org"/> </attribute-mapping> <user-password-mapper from="userPassword"/> </identity-mapping> </ldap-realm> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "LdapRealm", "ldap-realm": { "principal": "uid=admin,ou=People,dc=infinispan,dc=org", "url": "ldap://${org.infinispan.test.host.address}:10389", "credential": "strongPassword", "name-rewriter": { "regex-principal-transformer": { "pattern": "(.*)@INFINISPAN\\.ORG", "replacement": "$1" } }, "identity-mapping": { "rdn-identifier": "uid", "search-dn": "ou=People,dc=infinispan,dc=org", "attribute-mapping": { "attribute": { "filter": "(&(objectClass=groupOfNames)(member={1}))", "filter-dn": "ou=Roles,dc=infinispan,dc=org", "from": "cn", "to": "Roles" } }, "user-password-mapper": { "from": "userPassword" } } } }] } } }
YAML
server: security: securityRealms: - name: "LdapRealm" ldapRealm: principal: "uid=admin,ou=People,dc=infinispan,dc=org" url: "ldap://${org.infinispan.test.host.address}:10389" credential: "strongPassword" nameRewriter: regexPrincipalTransformer: pattern: (.*)@INFINISPAN\.ORG replacement: "$1" identityMapping: rdnIdentifier: "uid" searchDn: "ou=People,dc=infinispan,dc=org" attributeMapping: attribute: filter: "(&(objectClass=groupOfNames)(member={1}))" filterDn: "ou=Roles,dc=infinispan,dc=org" from: "cn" to: "Roles" userPasswordMapper: from: "userPassword"
5.5. Token realms
Token realms use external services to validate tokens and require providers that are compatible with RFC-7662 (OAuth2 Token Introspection), such as Red Hat SSO.
Token realm configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="TokenRealm"> <!-- Specifies the URL of the authentication server. --> <token-realm name="token" auth-server-url="https://oauth-server/auth/"> <!-- Specifies the URL of the token introspection endpoint. --> <oauth2-introspection introspection-url="https://oauth-server/auth/realms/infinispan/protocol/openid-connect/token/introspect" client-id="infinispan-server" client-secret="1fdca4ec-c416-47e0-867a-3d471af7050f"/> </token-realm> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "TokenRealm", "token-realm": { "auth-server-url": "https://oauth-server/auth/", "oauth2-introspection": { "client-id": "infinispan-server", "client-secret": "1fdca4ec-c416-47e0-867a-3d471af7050f", "introspection-url": "https://oauth-server/auth/realms/infinispan/protocol/openid-connect/token/introspect" } } }] } } }
YAML
server: security: securityRealms: - name: "TokenRealm" tokenRealm: authServerUrl: 'https://oauth-server/auth/' oauth2Introspection: clientId: infinispan-server clientSecret: '1fdca4ec-c416-47e0-867a-3d471af7050f' introspectionUrl: 'https://oauth-server/auth/realms/infinispan/protocol/openid-connect/token/introspect'
5.6. Trust store realms
Trust store realms use certificates, or certificates chains, that verify Data Grid Server and client identities when they negotiate connections.
- Keystores
- Contain server certificates that provide a Data Grid Server identity to clients. If you configure a keystore with server certificates, Data Grid Server encrypts traffic using industry standard SSL/TLS protocols.
- Trust stores
- Contain client certificates, or certificate chains, that clients present to Data Grid Server. Client trust stores are optional and allow Data Grid Server to perform client certificate authentication.
Client certificate authentication
You must add the require-ssl-client-auth="true"
attribute to the endpoint configuration if you want Data Grid Server to validate or authenticate client certificates.
Trust store realm configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="TrustStoreRealm"> <server-identities> <ssl> <!-- Provides an SSL/TLS identity with a keystore that contains server certificates. --> <keystore path="server.p12" relative-to="infinispan.server.config.path" keystore-password="secret" alias="server"/> <!-- Configures a trust store that contains client certificates or part of a certificate chain. --> <truststore path="trust.p12" relative-to="infinispan.server.config.path" password="secret"/> </ssl> </server-identities> <!-- Authenticates client certificates against the trust store. If you configure this, the trust store must contain the public certificates for all clients. --> <truststore-realm/> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "TrustStoreRealm", "server-identities": { "ssl": { "keystore": { "path": "server.p12", "relative-to": "infinispan.server.config.path", "keystore-password": "secret", "alias": "server" }, "truststore": { "path": "trust.p12", "relative-to": "infinispan.server.config.path", "password": "secret" } } }, "truststore-realm": {} }] } } }
YAML
server: security: securityRealms: - name: "TrustStoreRealm" serverIdentities: ssl: keystore: path: "server.p12" relative-to: "infinispan.server.config.path" keystore-password: "secret" alias: "server" truststore: path: "trust.p12" relative-to: "infinispan.server.config.path" password: "secret" truststoreRealm: ~
5.7. Distributed security realms
Distributed realms combine multiple different types of security realms. When users attempt to access the Hot Rod or REST endpoints, Data Grid Server uses each security realm in turn until it finds one that can perform the authentication.
Distributed realm configuration
XML
<server xmlns="urn:infinispan:server:13.0"> <security> <security-realms> <security-realm name="DistributedRealm"> <ldap-realm url="ldap://my-ldap-server:10389" principal="uid=admin,ou=People,dc=infinispan,dc=org" credential="strongPassword"> <identity-mapping rdn-identifier="uid" search-dn="ou=People,dc=infinispan,dc=org" search-recursive="false"> <attribute-mapping> <attribute from="cn" to="Roles" filter="(&(objectClass=groupOfNames)(member={1}))" filter-dn="ou=Roles,dc=infinispan,dc=org"/> </attribute-mapping> </identity-mapping> </ldap-realm> <properties-realm groups-attribute="Roles"> <user-properties path="users.properties" relative-to="infinispan.server.config.path"/> <group-properties path="groups.properties" relative-to="infinispan.server.config.path"/> </properties-realm> <distributed-realm/> </security-realm> </security-realms> </security> </server>
JSON
{ "server": { "security": { "security-realms": [{ "name": "DistributedRealm", "ldap-realm": { "principal": "uid=admin,ou=People,dc=infinispan,dc=org", "url": "ldap://my-ldap-server:10389", "credential": "strongPassword", "identity-mapping": { "rdn-identifier": "uid", "search-dn": "ou=People,dc=infinispan,dc=org", "search-recursive": false, "attribute-mapping": { "attribute": { "filter": "(&(objectClass=groupOfNames)(member={1}))", "filter-dn": "ou=Roles,dc=infinispan,dc=org", "from": "cn", "to": "Roles" } } } }, "properties-realm": { "groups-attribute": "Roles", "user-properties": { "digest-realm-name": "DistributedRealm", "path": "users.properties" }, "group-properties": { "path": "groups.properties" } }, "distributed-realm": {} }] } } }
YAML
server: security: securityRealms: - name: "DistributedRealm" ldapRealm: principal: "uid=admin,ou=People,dc=infinispan,dc=org" url: "ldap://my-ldap-server:10389" credential: "strongPassword" identityMapping: rdnIdentifier: "uid" searchDn: "ou=People,dc=infinispan,dc=org" searchRecursive: "false" attributeMapping: attribute: filter: "(&(objectClass=groupOfNames)(member={1}))" filterDn: "ou=Roles,dc=infinispan,dc=org" from: "cn" to: "Roles" propertiesRealm: groupsAttribute: "Roles" userProperties: digestRealmName: "DistributedRealm" path: "users.properties" groupProperties: path: "groups.properties" distributedRealm: ~