| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You 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. |
| */ |
| package org.apache.geode.security.generator; |
| |
| import java.security.Principal; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import org.apache.logging.log4j.Logger; |
| |
| import org.apache.geode.internal.logging.LogService; |
| import org.apache.geode.security.AuthInitialize; |
| import org.apache.geode.security.Authenticator; |
| import org.apache.geode.security.templates.DummyAuthenticator; |
| import org.apache.geode.security.templates.LdapUserAuthenticator; |
| import org.apache.geode.security.templates.PKCSAuthenticator; |
| |
| /** |
| * Encapsulates obtaining valid and invalid credentials. Implementations will be for different kinds |
| * of authentication schemes. |
| * |
| * @since GemFire 5.5 |
| */ |
| public abstract class CredentialGenerator { |
| |
| private static final Logger logger = LogService.getLogger(); |
| |
| /** |
| * A set of properties that should be added to the Gemfire system properties before using the |
| * authentication module. |
| */ |
| private Properties systemProperties = null; |
| |
| /** |
| * A set of properties that should be added to the java system properties before using the |
| * authentication module. |
| */ |
| protected Properties javaProperties = null; |
| |
| /** |
| * A factory method to create a new instance of an {@link CredentialGenerator} for the given |
| * {@link ClassCode}. Caller is supposed to invoke {@link CredentialGenerator#init} immediately |
| * after obtaining the instance. |
| * |
| * @param classCode the {@code ClassCode} of the {@code CredentialGenerator} implementation |
| * |
| * @return an instance of {@code CredentialGenerator} for the given class code |
| */ |
| public static CredentialGenerator create(final ClassCode classCode) { |
| switch (classCode.classType) { |
| // Removing dummy one to reduce test run times |
| // case ClassCode.ID_DUMMY: |
| // return new DummyCredentialGenerator(); |
| case ClassCode.ID_LDAP: |
| return new LdapUserCredentialGenerator(); |
| // case ClassCode.ID_SSL:ΓΈ |
| // return new SSLCredentialGenerator(); |
| case ClassCode.ID_PKCS: |
| return new PKCSCredentialGenerator(); |
| default: |
| return null; |
| } |
| } |
| |
| /** |
| * Initialize the credential generator. |
| * |
| * @throws IllegalArgumentException when there is a problem during initialization |
| */ |
| public void init() throws IllegalArgumentException { |
| this.systemProperties = initialize(); |
| logger.info("Generating CredentialGenerator with {}", this.systemProperties); |
| } |
| |
| /** |
| * @return A set of extra properties that should be added to Gemfire system properties when not |
| * null. |
| */ |
| public Properties getSystemProperties() { |
| return this.systemProperties; |
| } |
| |
| /** |
| * @return A set of extra properties that should be added to Gemfire system properties when not |
| * null. |
| */ |
| public Properties getJavaProperties() { |
| return this.javaProperties; |
| } |
| |
| /** |
| * The {@link ClassCode} of this particular implementation. |
| * |
| * @return the {@code ClassCode} |
| */ |
| public abstract ClassCode classCode(); |
| |
| /** |
| * The name of the {@link AuthInitialize} factory function that should be used in conjunction with |
| * the credentials generated by this generator. |
| * |
| * @return name of the {@code AuthInitialize} factory function |
| */ |
| public abstract String getAuthInit(); |
| |
| /** |
| * The name of the {@link Authenticator} factory function that should be used in conjunction with |
| * the credentials generated by this generator. |
| * |
| * @return name of the {@code Authenticator} factory function |
| */ |
| public abstract String getAuthenticator(); |
| |
| /** |
| * Get a set of valid credentials generated using the given index. |
| */ |
| public abstract Properties getValidCredentials(final int index); |
| |
| /** |
| * Get a set of valid credentials for the given {@link Principal}. |
| * |
| * @return credentials for the given {@code Principal} or null if none possible. |
| */ |
| public abstract Properties getValidCredentials(final Principal principal); |
| |
| /** |
| * Get a set of invalid credentials generated using the given index. |
| */ |
| public abstract Properties getInvalidCredentials(final int index); |
| |
| /** |
| * Initialize the credential generator. This is provided separately from the {@link #init()} |
| * method for convenience of implementations so that they do not need to store in |
| * {@link #systemProperties}. The latter is convenient for the users who do not need to store |
| * these properties rather can obtain it later by invoking {@link #getSystemProperties()} |
| * |
| * <p> |
| * Required to be implemented by concrete classes that implement this abstract class. |
| * |
| * @return A set of extra properties that should be added to Gemfire system properties when not |
| * null. |
| * |
| * @throws IllegalArgumentException when there is a problem during initialization |
| */ |
| protected abstract Properties initialize() throws IllegalArgumentException; |
| |
| /** |
| * Enumeration for various {@link CredentialGenerator} implementations. |
| * |
| * <p> |
| * The following schemes are supported as of now: {@code DummyAuthenticator}, |
| * {@code LdapUserAuthenticator}, {@code PKCSAuthenticator}. In addition SSL socket mode with |
| * mutual authentication is also supported. |
| * |
| * <p> |
| * To add a new authentication scheme the following needs to be done: |
| * <ul> |
| * <li>Add implementations for {@link AuthInitialize} and {@link Authenticator} classes for |
| * clients/peers.</li> |
| * <li>Add a new enumeration value for the scheme in this class. Notice the size of {@code VALUES} |
| * array and increase that if it is getting overflowed. Note the methods and fields for existing |
| * schemes and add for the new one in a similar manner.</li> |
| * <li>Add an implementation for {@link CredentialGenerator}.</li> |
| * <li>Modify the CredentialGenerator.Factory#create [no such Factory exists] method to add |
| * creation of an instance of the new implementation for the {@code ClassCode} enumeration |
| * value.</li> |
| * </ul> |
| * |
| * <p> |
| * All security dunit tests will automagically start testing the new implementation after this. |
| * |
| * @since GemFire 5.5 |
| */ |
| public static class ClassCode { |
| |
| private static byte nextOrdinal = 0; |
| |
| private static final byte ID_DUMMY = 1; |
| private static final byte ID_LDAP = 2; |
| private static final byte ID_PKCS = 3; |
| private static final byte ID_SSL = 4; |
| |
| private static final ClassCode[] VALUES = new ClassCode[10]; |
| private static final Map CODE_NAME_MAP = new HashMap(); |
| |
| public static final ClassCode DUMMY = |
| new ClassCode(DummyAuthenticator.class.getName() + ".create", ID_DUMMY); |
| public static final ClassCode LDAP = |
| new ClassCode(LdapUserAuthenticator.class.getName() + ".create", ID_LDAP); |
| public static final ClassCode PKCS = |
| new ClassCode(PKCSAuthenticator.class.getName() + ".create", ID_PKCS); |
| public static final ClassCode SSL = new ClassCode("SSL", ID_SSL); |
| |
| /** The name of this class. */ |
| private final String name; |
| |
| /** byte used as ordinal to represent this class */ |
| private final byte ordinal; |
| |
| /** |
| * One of the following: ID_DUMMY, ID_LDAP, ID_PKCS |
| */ |
| private final byte classType; |
| |
| /** Creates a new instance of class code. */ |
| private ClassCode(final String name, final byte classType) { |
| this.name = name; |
| this.classType = classType; |
| this.ordinal = nextOrdinal++; |
| VALUES[this.ordinal] = this; |
| CODE_NAME_MAP.put(name, this); |
| } |
| |
| public boolean isDummy() { |
| return this.classType == ID_DUMMY; |
| } |
| |
| public boolean isLDAP() { |
| return this.classType == ID_LDAP; |
| } |
| |
| public boolean isPKCS() { |
| return this.classType == ID_PKCS; |
| } |
| |
| public boolean isSSL() { |
| return this.classType == ID_SSL; |
| } |
| |
| /** |
| * Returns the {@code ClassCode} represented by specified ordinal. |
| */ |
| public static ClassCode fromOrdinal(final byte ordinal) { |
| return VALUES[ordinal]; |
| } |
| |
| /** |
| * Returns the {@code ClassCode} represented by specified string. |
| */ |
| public static ClassCode parse(final String operationName) { |
| return (ClassCode) CODE_NAME_MAP.get(operationName); |
| } |
| |
| /** |
| * Returns all the possible values. |
| */ |
| public static List getAll() { |
| final List codes = new ArrayList(); |
| for (Iterator iter = CODE_NAME_MAP.values().iterator(); iter.hasNext();) { |
| codes.add(iter.next()); |
| } |
| return codes; |
| } |
| |
| /** |
| * Returns the ordinal for this operation code. |
| * |
| * @return the ordinal of this operation. |
| */ |
| public byte toOrdinal() { |
| return this.ordinal; |
| } |
| |
| /** |
| * Returns a string representation for this operation. |
| * |
| * @return the name of this operation. |
| */ |
| @Override |
| public String toString() { |
| return this.name; |
| } |
| |
| /** |
| * Indicates whether other object is same as this one. |
| * |
| * @return true if other object is same as this one. |
| */ |
| @Override |
| public boolean equals(final Object obj) { |
| if (obj == this) { |
| return true; |
| } |
| if (!(obj instanceof ClassCode)) { |
| return false; |
| } |
| final ClassCode other = (ClassCode) obj; |
| return other.ordinal == this.ordinal; |
| } |
| |
| /** |
| * Indicates whether other {@code ClassCode} is same as this one. |
| * |
| * @return true if other {@code ClassCode} is same as this one. |
| */ |
| public boolean equals(final ClassCode opCode) { |
| return opCode != null && opCode.ordinal == this.ordinal; |
| } |
| |
| /** |
| * Returns a hash code value for this {@code ClassCode} which is the same as its ordinal. |
| * |
| * @return the ordinal of this operation. |
| */ |
| @Override |
| public int hashCode() { |
| return this.ordinal; |
| } |
| } |
| } |