このコンテンツは選択した言語では利用できません。
20.7. Securing Interfaces
While the Hot Rod interface may be secured programmatically, both the memcached and REST interfaces must be secured declaratively. Instructions for securing these interfaces are located in the JBoss Data Grid Administration and Configuration Guide.
20.7.1. Hot Rod Interface Security
20.7.1.1. Encryption of communication between Hot Rod Server and Hot Rod client
Hot Rod can be encrypted using TLS/SSL, and has the option to require certificate-based client authentication.
Use the following procedure to secure the Hot Rod connector using SSL.
Example 20.4. Secure Hot Rod Using SSL/TLS
import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.infinispan.client.hotrod.impl.ConfigurationProperties; [...] public class SslConfiguration { public static final String ISPN_IP = "127.0.0.1"; public static final String SERVER_NAME = "node0"; public static final String SASL_MECH = "EXTERNAL"; private static final String KEYSTORE_PATH = "./keystore_client.jks"; private static final String KEYSTORE_PASSWORD = "secret"; private static final String TRUSTSTORE_PATH = "./truststore_client.jks"; private static final String TRUSTSTORE_PASSWORD = "secret"; SslConfiguration(boolean enabled, String keyStoreFileName, char[] keyStorePassword, SSLContext sslContext, String trustStoreFileName, char[] trustStorePassword) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.addServer() .host(ISPN_IP) .port(ConfigurationProperties.DEFAULT_HOTROD_PORT); //setup auth builder.security() .authentication() .serverName(SERVER_NAME) .saslMechanism(SASL_MECH) .enable() .callbackHandler(new VoidCallbackHandler()); //setup encrypt builder.security() .ssl() .enable() .keyStoreFileName(KEYSTORE_PATH) .keyStorePassword(KEYSTORE_PASSWORD.toCharArray()) .trustStoreFileName(TRUSTSTORE_PATH) .trustStorePassword(TRUSTSTORE_PASSWORD.toCharArray()); RemoteCacheManager cacheManager = new RemoteCacheManager(builder.build()); RemoteCache<Object, Object> cache = cacheManager.getCache(RemoteCacheManager.DEFAULT_CACHE_NAME); } private static class VoidCallbackHandler implements CallbackHandler { @Override public void handle(Callback[] clbcks) throws IOException, UnsupportedCallbackException { } } }
Important
To prevent plain text passwords from appearing in configurations or source codes, plain text passwords should be changed to Vault passwords. For more information about how to set up Vault passwords, see the Red Hat Enterprise Application Platform Security Guide.
20.7.1.2. Securing Hot Rod to LDAP Server using SSL
When connecting to an LDAP server with SSL enabled it may be necessary to specify a trust store or key store containing the appropriate certificates.
PLAIN
authentication over SSL may be used for Hot Rod client authentication against an LDAP server. The Hot Rod client sends plain text credentials to the JBoss Data Grid server over SSL, and the server subsequently verifies the provided credentials against the specified LDAP server. In addition, a secure connection must be configured between the JBoss Data Grid server and the LDAP server. Refer to the JBoss Data Grid Administration and Configuration Guide for additional information on configuring the server to communicate to an LDAP backend. The example below demonstrates configuring PLAIN
authentication over SSL on the Hot Rod client side:
Example 20.5. Hot Rod Client Authentication to LDAP Server
import static org.infinispan.demo.util.CacheOps.dumpCache; import static org.infinispan.demo.util.CacheOps.onCache; import static org.infinispan.demo.util.CacheOps.putTestKV; import static org.infinispan.demo.util.CmdArgs.LOGIN_KEY; import static org.infinispan.demo.util.CmdArgs.PASS_KEY; import static org.infinispan.demo.util.CmdArgs.getCredentials; import java.util.Map; import javax.net.ssl.SSLContext; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.infinispan.client.hotrod.impl.ConfigurationProperties; import org.infinispan.commons.util.SslContextFactory; import org.infinispan.demo.util.SaslUtils.SimpleLoginHandler; public class HotRodPlainAuthOverSSL { public static final String ISPN_IP = "127.0.0.1"; public static final String SERVER_NAME = "node0"; public static final String SASL_MECH = "PLAIN"; private static final String SECURITY_REALM = "ApplicationRealm"; private static final String TRUSTSTORE_PATH = "./truststore_client.jks"; private static final String TRUSTSTORE_PASSWORD = "secret"; public static void main(String[] args) { Map<String, String> userArgs = null; try { userArgs = getCredentials(args); } catch (IllegalArgumentException e) { System.err.println(e.getMessage()); System.err.println( "Invalid credentials format, plase provide credentials (and optionally cache name) with --cache=<cache> --user=<user> --password=<password>"); System.exit(1); } ConfigurationBuilder builder = new ConfigurationBuilder(); builder.addServer().host(ISPN_IP).port(ConfigurationProperties.DEFAULT_HOTROD_PORT); //set up PLAIN auth builder.security().authentication().serverName(SERVER_NAME).saslMechanism(SASL_MECH).enable().callbackHandler( new SimpleLoginHandler(userArgs.get(LOGIN_KEY), userArgs.get(PASS_KEY), SECURITY_REALM)); //set up SSL SSLContext cont = SslContextFactory.getContext(null, null, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD.toCharArray()); builder.security().ssl().sslContext(cont).enable(); RemoteCacheManager cacheManager = new RemoteCacheManager(builder.build()); RemoteCache<Object, Object> cache = cacheManager.getCache(RemoteCacheManager.DEFAULT_CACHE_NAME); onCache(cache, putTestKV.andThen(dumpCache)); cacheManager.stop(); System.exit(0); } }
Important
To prevent plain text passwords from appearing in configurations or source codes, plain text passwords should be changed to Vault passwords. For more information about how to set up Vault passwords, see the Red Hat Enterprise Application Platform Security Guide.
20.7.1.3. User Authentication over Hot Rod Using SASL
User authentication over Hot Rod can be implemented using the following Simple Authentication and Security Layer (SASL) mechanisms:
PLAIN
is the least secure mechanism because credentials are transported in plain text format. However, it is also the simplest mechanism to implement. This mechanism can be used in conjunction with encryption (SSL) for additional security.DIGEST-MD5
is a mechanism than hashes the credentials before transporting them. As a result, it is more secure than thePLAIN
mechanism.GSSAPI
is a mechanism that uses Kerberos tickets. As a result, it requires a correctly configured Kerberos Domain Controller (for example, Microsoft Active Directory).EXTERNAL
is a mechanism that obtains the required credentials from the underlying transport (for example, from aX.509
client certificate) and therefore requires client certificate encryption to work correctly.
20.7.1.3.1. Configure Hot Rod Authentication (GSSAPI/Kerberos)
Use the following steps to set up Hot Rod Authentication using the SASL GSSAPI/Kerberos mechanism:
Procedure 20.1. Configure SASL GSSAPI/Kerberos Authentication - Client-side Configuration
- Ensure that the Server-Side configuration has been completed. As this is configured declaratively this configuration is found in the JBoss Data Grid Administration and Configuration Guide.
- Define a login module in a login configuration file (
gss.conf
) on the client side:GssExample { com.sun.security.auth.module.Krb5LoginModule required client=TRUE; };
- Set up the following system properties:
java.security.auth.login.config=gss.conf java.security.krb5.conf=/etc/krb5.conf
Note
Thekrb5.conf
file is dependent on the environment and must point to the Kerberos Key Distribution Center. - Implement the
CallbackHandler
:public class MyCallbackHandler implements CallbackHandler { final private String username; final private char[] password; final private String realm; public MyCallbackHandler() { } public MyCallbackHandler (String username, String realm, char[] password) { this.username = username; this.password = password; this.realm = realm; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callback; nameCallback.setName(username); } else if (callback instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callback; passwordCallback.setPassword(password); } else if (callback instanceof AuthorizeCallback) { AuthorizeCallback authorizeCallback = (AuthorizeCallback) callback; authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals( authorizeCallback.getAuthorizationID())); } else if (callback instanceof RealmCallback) { RealmCallback realmCallback = (RealmCallback) callback; realmCallback.setText(realm); } else { throw new UnsupportedCallbackException(callback); } } } }
- Configure the Hot Rod Client, as seen in the below snippet:
LoginContext lc = new LoginContext("GssExample", new MyCallbackHandler("krb_user", "krb_password".toCharArra())); lc.login(); Subject clientSubject = lc.getSubject(); ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); clientBuilder.addServer() .host("127.0.0.1") .port(11222) .socketTimeout(1200000) .security() .authentication() .enable() .serverName("infinispan-server") .saslMechanism("GSSAPI") .clientSubject(clientSubject) .callbackHandler(new MyCallbackHandler()); remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");
20.7.1.3.2. Configure Hot Rod Authentication (MD5)
Use the following steps to set up Hot Rod Authentication using the SASL using the MD5 mechanism:
- Ensure that the server has been configured for MD5 Authentication. Instructions for performing this configuration on the server are found in JBoss Data Grid's Administration and Configuration Guide.
- Implement the
CallbackHandler
:public class MyCallbackHandler implements CallbackHandler { final private String username; final private char[] password; final private String realm; public MyCallbackHandler (String username, String realm, char[] password) { this.username = username; this.password = password; this.realm = realm; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callback; nameCallback.setName(username); } else if (callback instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callback; passwordCallback.setPassword(password); } else if (callback instanceof AuthorizeCallback) { AuthorizeCallback authorizeCallback = (AuthorizeCallback) callback; authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals( authorizeCallback.getAuthorizationID())); } else if (callback instanceof RealmCallback) { RealmCallback realmCallback = (RealmCallback) callback; realmCallback.setText(realm); } else { throw new UnsupportedCallbackException(callback); } } } }
- Connect the client to the configured Hot Rod connector as seen below:
ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); clientBuilder.addServer() .host("127.0.0.1") .port(11222) .socketTimeout(1200000) .security() .authentication() .enable() .serverName("myhotrodserver") .saslMechanism("DIGEST-MD5") .callbackHandler(new MyCallbackHandler("myuser", "ApplicationRealm", "qwer1234!".toCharArray())); remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");
20.7.2. Hot Rod C++ Client Encryption
By default all communication with the remote server is unencrypted; however, TLS encryption may be enabled by defining the server's key via the
serverCAFile
method on the SslConfigurationBuilder
. Additionally, the client's certificate may be defined with the clientCertificateFile
, allowing for client authentication.
Important
TLS Encryption is a Technology Preview feature of the Hot Rod C++ Client in JBoss Data Grid 7.0.0.
The following example demonstrates defining a server key with an optional client certificate:
Example 20.6. Hot Rod C++ TLS Example
#include "infinispan/hotrod/ConfigurationBuilder.h" #include "infinispan/hotrod/RemoteCacheManager.h" #include "infinispan/hotrod/RemoteCache.h" #include "infinispan/hotrod/Version.h" #include "infinispan/hotrod/JBasicMarshaller.h" #include <stdlib.h> #include <iostream> #include <memory> #include <typeinfo> using namespace infinispan::hotrod; int main(int argc, char** argv) { std::cout << "TLS Test" << std::endl; if (argc < 2) { std::cerr << "Usage: " << argv[0] << " server_ca_file [client_ca_file]" << std::endl; return 1; } { ConfigurationBuilder builder; builder.addServer().host("127.0.0.1").port(11222).protocolVersion(Configuration::PROTOCOL_VERSION_24); // Enable the TLS layer and install the server public key // this ensure that the server is authenticated builder.ssl().enable().serverCAFile(argv[1]); if (argc > 2) { // Send a client certificate for authentication (optional) // without this the socket will only be encrypted std::cout << "Using supplied client certificate for authentication against the server" << std::endl; builder.ssl().clientCertificateFile(argv[2]); } // That's all. Now do business as usual RemoteCacheManager cacheManager(builder.build(), false); BasicMarshaller<std::string> *km = new BasicMarshaller<std::string>(); BasicMarshaller<std::string> *vm = new BasicMarshaller<std::string>(); RemoteCache<std::string, std::string> cache = cacheManager.getCache<std::string, std::string>(km, &Marshaller<std::string>::destroy, vm, &Marshaller<std::string>::destroy ); cacheManager.start(); cache.clear(); std::string k1("key13"); std::string v1("boron"); cache.put(k1, v1); std::unique_ptr<std::string> rv(cache.get(k1)); if (rv->compare(v1)) { std::cerr << "get/put fail for " << k1 << " got " << *rv << " expected " << v1 << std::endl; return 1; } cacheManager.stop(); } return 0; }
20.7.3. Hot Rod C# Client Encryption
By default all communication with the remote server is unencrypted; however, TLS encryption may be enabled by defining the server's key via the
ServerCAFile
method on the SslConfigurationBuilder
. Additionally, the client's certificate may be defined with the ClientCertificateFile
, allowing for client authentication.
Important
TLS Encryption is a Technology Preview feature of the Hot Rod C# Client in JBoss Data Grid 7.0.0.
The following example demonstrates defining a server key with an optional client certificate:
Example 20.7. Hot Rod C# TLS Example
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Infinispan.HotRod; using Infinispan.HotRod.Config; namespace TLS { /// <summary> /// This sample code shows how to perform operations over TLS using the C# client /// </summary> class TLS { static void Main(string[] args) { // Cache manager setup RemoteCacheManager remoteManager; ConfigurationBuilder conf = new ConfigurationBuilder(); conf.AddServer().Host("127.0.0.1").Port(11222).ConnectionTimeout(90000).SocketTimeout(900); SslConfigurationBuilder sslConfB = conf.Ssl(); // Retrieve the server public certificate, needed to do server authentication. Mandatory if (!System.IO.File.Exists("resources/infinispan-ca.pem")) { Console.WriteLine("File not found: resources/infinispan-ca.pem."); Environment.Exit(-1); } sslConfB.Enable().ServerCAFile("resources/infinispan-ca.pem"); // Retrieve the client public certificate, needed if the server requires client authentication. Optional if (!System.IO.File.Exists("resources/client-ca.pem")) { Console.WriteLine("File not found: resources/client-ca.pem."); Environment.Exit(-1); } sslConfB.ClientCertificateFile("resources/client-ca.pem"); // Usual business now conf.Marshaller(new JBasicMarshaller()); remoteManager = new RemoteCacheManager(conf.Build(), true); IRemoteCache<string, string> testCache = remoteManager.GetCache<string, string>(); testCache.Clear(); string k1 = "key13"; string v1 = "boron"; testCache.Put(k1, v1); } } }