0

I am trying to implement TLS based authentication, basically SSL certificate based authentication, when two-way SSL is enabled in Geode cluster. Authentication is performed based on certificate DN. Lets say client/peer node configured with two-way ssl of certificate "cn=example.com,ou=org,location=us", authentication and authorization should only be successful if "example.com" is valid cert and authorize accordingly. I see that Geode authentication implementation is based on security-username/password and security Manager Geode implementation does not provide better way to access connection peer certificates. I was not able to find related documentation, any direction on this kind of requirement would be helpful.

Thanks.

NoName
  • 46
  • 4

1 Answers1

1

As you may already be familiar based on the comments in your question above, I encourage you to first re-review the section on SSL in the Security chapter of Apache Geode's documentation. SSL would be a prerequisite for everything I am about to suggest below.

Apache Geode's Security implementation of Authentication (as well as Authorization) is based on Apache Geode's SecurityManager interface as well as the AuthInitialize interface.

The SecurityManager is used on the server-side to authenticate clients (or additional peers joining the P2P cluster as a member). An implementation of the AuthInitialize interface is used by clients (or other peers joining the P2P cluster as a member) to supply the credentials.

The supplied SecurityManager implementation is configured with the [gemfire.]security-manager property. The AuthInitialize implementation is configured with the [gemfire.]security-client-auth-init property (or the [gemfire.]security-peer-auth-init property).

While Apache Geode's documentation commonly refers to username/password-based authentication for Geode nodes (clients and peers), the fact of the matter is, the Properties returned by the (client-side) AuthInitialize.getCredentials(..) (Javadoc) method and processed on the server-side, SecurityManager.authenticate(:Properties) (Javadoc) could contain the appropriate certificate and evidence as described (for example) here.

It is not uncommon for Password-based authentication to be used with Certificate-based authentication (both over SSL).

In which, case you could do the following. On the client-side:

package example.app.geode.security.client.auth;

import org.apache.geode.security.AuthInitialize;

class CertificateBasedAuthInitialize implements AuthInitialize {

  public static CertificateBasedAuthInitialize create() {
    new CertificateBasedAuthInitialize();
  }

  public Properties getCredentials(Properties securityProperties, DistributedMember member, boolean isServer) {

    Properties credentials = new Properties(securityProperties);

    // Load PrivateKey from KeyStore using java.security API.
    PrivateKey privateKey = ...

    Certificate clientCertificate = privateKey.getCertificate();

    // Sign the some randomly generated data with the PrivateKey.
    Object signedEvidence = ...

    credentials.put("certificate", clientCertificate);
    credentials.put("evidence", signedEvidence);
    // optional...
    credentials.put(AuthInitialize.SECURITY_USERNAME, username);
    credentials.put(AuthInitialize.SECURITY_PASSWORD, password);

    return credentials;

  }
}

Then configure your client with:

# Spring Boot application.properties

spring.data.gemfire.security.client.authentication-initializer=\
  example.app.geode.security.client.auth.CertificateBasedAuthInitialize.create

...

The server-side, custom SecurityManager implementation would then use the credentials to authenticate the client.

package example.app.geode.security.server.auth;

import org.apache.geode.security.SecurityManager;

class CertificateBasedSecurityManager implements SecurityManager {

  public Object authenticate(Properties securityProperties) {

    Certificate certificate = securityProperties.get("certificate");

    Objected signedEvidence = securityProperties.get("evidence");

    // verify the client's cert and use the PublicKey to verify the "evidence".
  } 
}

If the servers's in the Apache Geode cluster were configured and bootstrapped with Spring, then you would configure your custom SecurityManager implementation using:

# Spring Boot application.properties

spring.data.gemfire.security.manager.class-name=\
  example.app.geode.security.server.auth.CertificateBasedSecurityManager

If you used Gfsh to start the Locators and Servers in your cluster, then refer to Apache Geode's documentation to configure properties on startup.

As you may also be aware (based on your tags), Apache Geode integrates with Apache Shiro. Unfortunately, I did not find any support in Apache Shiro for Certificate-based Authentication (here), which introduces the concept of Realms for auth, where the available Realms provided by Apache Shiro are here (you can see support for ActiveDirectory, JDBC, JNDI, LDAP, and text-based Realms).

Of course, you could also devise an implementation of Apache Geode's SecurityManager interface along with the AuthInitialize interface, integrated with Spring Security and follow the general advice in Baeldung's blog post.

Hopefully this gives you enough to think about and some ideas on how to go about implementing Certificate-based Authentication between clients and servers (and peers?) in your [Spring] Apache Geode application/cluster.

John Blum
  • 7,381
  • 1
  • 20
  • 30
  • DISCLAIMER: I have not tried nor tested this configuration arrangement myself, so your mileage may vary. However, this would essentially be the basic setup and idea. – John Blum Aug 22 '22 at 21:34