/** * 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.ambari.server.state.kerberos; import java.util.Map; import org.apache.ambari.server.collections.Predicate; import org.apache.ambari.server.collections.PredicateUtils; import com.google.common.base.Optional; /** * KerberosIdentityDescriptor is an implementation of an AbstractKerberosDescriptor that * encapsulates data related to a Kerberos identity - including its principal and keytab file details. * <p/> * A KerberosIdentityDescriptor has the following properties: * <ul> * <li>name</li> * <li>principal</li> * <li>keytab</li> * <li>password</li> * </ul> * <p/> * The following (pseudo) JSON Schema will yield a valid KerberosIdentityDescriptor * <pre> * { * "$schema": "http://json-schema.org/draft-04/schema#", * "title": "KerberosIdentityDescriptor", * "description": "Describes a Kerberos identity", * "type": "object", * "properties": { * "name": { * "description": "An identifying name for this identity. The name may reference another * KerberosIdentityDescriptor by declaring the path to it", * "type": "string" * }, * "principal": { * "description": "Details about this identity's principal", * "type": "{@link org.apache.ambari.server.state.kerberos.KerberosPrincipalDescriptor}", * } * "keytab": { * "description": "Details about this identity's keytab", * "type": "{@link org.apache.ambari.server.state.kerberos.KerberosKeytabDescriptor}", * } * } * "password": { * "description": "The password to use for this identity. If not set a secure random * password will automatically be generated", * "type": "string" * } * } * } * </pre> * <p/> * In this implementation, * {@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptor#name} will hold the * KerberosIdentityDescriptor#name value */ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor { /** * The path to the Kerberos Identity definitions this {@link KerberosIdentityDescriptor} references */ private String reference = null; /** * The KerberosPrincipalDescriptor containing the principal details for this Kerberos identity */ private KerberosPrincipalDescriptor principal = null; /** * The KerberosKeytabDescriptor containing the keytab details for this Kerberos identity */ private KerberosKeytabDescriptor keytab = null; /** * A String containing the password for this Kerberos identity * <p/> * If this value is null or empty, a random password will be generated as necessary. */ private String password = null; /** * An expression used to determine when this {@link KerberosIdentityDescriptor} is relevant for the * cluster. If the process expression is not <code>null</code> and evaluates to <code>false</code> * then this {@link KerberosIdentityDescriptor} will be ignored when processing identities. */ private Predicate when = null; /** * Creates a new KerberosIdentityDescriptor * * @param name the name of this identity descriptor * @param reference an optional path to a referenced KerberosIdentityDescriptor * @param principal a KerberosPrincipalDescriptor * @param keytab a KerberosKeytabDescriptor * @param when a predicate */ public KerberosIdentityDescriptor(String name, String reference, KerberosPrincipalDescriptor principal, KerberosKeytabDescriptor keytab, Predicate when) { setName(name); setReference(reference); setPrincipalDescriptor(principal); setKeytabDescriptor(keytab); setWhen(when); } /** * Creates a new KerberosIdentityDescriptor * <p/> * See {@link org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor} for the JSON * Schema that may be used to generate this map. * * @param data a Map of values use to populate the data for the new instance * @see org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor */ public KerberosIdentityDescriptor(Map<?, ?> data) { // The name for this KerberosIdentityDescriptor is stored in the "name" entry in the map // This is not automatically set by the super classes. setName(getStringValue(data, "name")); setReference(getStringValue(data, "reference")); if (data != null) { Object item; setPassword(getStringValue(data, "password")); item = data.get(Type.PRINCIPAL.getDescriptorName()); if (item instanceof Map) { setPrincipalDescriptor(new KerberosPrincipalDescriptor((Map<?, ?>) item)); } item = data.get(Type.KEYTAB.getDescriptorName()); if (item instanceof Map) { setKeytabDescriptor(new KerberosKeytabDescriptor((Map<?, ?>) item)); } item = data.get("when"); if (item instanceof Map) { setWhen(PredicateUtils.fromMap((Map<?, ?>) item)); } } } /** * Gets the path to the referenced Kerberos identity definition * * @return the path to the referenced Kerberos identity definition or <code>null</code> if not set */ public String getReference() { return reference; } /** * Sets the path to the referenced Kerberos identity definition * * @param reference the path to the referenced Kerberos identity definition or <code>null</code> * to indicate no reference */ public void setReference(String reference) { this.reference = reference; } /** * Gets the KerberosPrincipalDescriptor related to this KerberosIdentityDescriptor * * @return the KerberosPrincipalDescriptor related to this KerberosIdentityDescriptor */ public KerberosPrincipalDescriptor getPrincipalDescriptor() { return principal; } /** * Sets the KerberosPrincipalDescriptor related to this KerberosIdentityDescriptor * * @param principal the KerberosPrincipalDescriptor related to this KerberosIdentityDescriptor */ public void setPrincipalDescriptor(KerberosPrincipalDescriptor principal) { this.principal = principal; if (this.principal != null) { this.principal.setParent(this); } } /** * Gets the KerberosKeytabDescriptor related to this KerberosIdentityDescriptor * * @return the KerberosKeytabDescriptor related to this KerberosIdentityDescriptor */ public KerberosKeytabDescriptor getKeytabDescriptor() { return keytab; } /** * Sets the KerberosKeytabDescriptor related to this KerberosIdentityDescriptor * * @param keytab the KerberosKeytabDescriptor related to this KerberosIdentityDescriptor */ public void setKeytabDescriptor(KerberosKeytabDescriptor keytab) { this.keytab = keytab; if (this.keytab != null) { this.keytab.setParent(this); } } /** * Gets the password for this this KerberosIdentityDescriptor * * @return A String containing the password for this this KerberosIdentityDescriptor * @see #password */ public String getPassword() { return password; } /** * Sets the password for this this KerberosIdentityDescriptor * * @param password A String containing the password for this this KerberosIdentityDescriptor * @see #password */ public void setPassword(String password) { this.password = password; } /** * Gets the expression (or {@link Predicate}) to use to determine when to include this Kerberos * identity while processing Kerberos identities. * <p> * <code>null</code> indicates there is nothing to evaluate and this Kerberos identity is to always * be included when processing Kerberos identities. * * @return a predicate */ public Predicate getWhen() { return when; } /** * Sets the expression (or {@link Predicate}) to use to determine when to include this Kerberos * identity while processing Kerberos identities. * <p> * <code>null</code> indicates there is nothing to evaluate and this Kerberos identity is to always * be included when processing Kerberos identities. * * @param when a predicate */ public void setWhen(Predicate when) { this.when = when; } /** * Processes the expression indicating when this {@link KerberosIdentityDescriptor} is to be included * in the set of Kerberos identities to process. * <p> * <code>True</code> will be returned if the expression is <code>null</code> or if it evaluates * as such. * * @param context A Map of context values, including at least the list of services and available configurations * @return true if this {@link KerberosIdentityDescriptor} is to be included when processing the * Kerberos identities; otherwise false. */ public boolean shouldInclude(Map<String, Object> context) { return (this.when == null) || this.when.evaluate(context); } /** * Updates this KerberosIdentityDescriptor with data from another KerberosIdentityDescriptor * <p/> * Properties will be updated if the relevant updated values are not null. * * @param updates the KerberosIdentityDescriptor containing the updated values */ public void update(KerberosIdentityDescriptor updates) { if (updates != null) { setName(updates.getName()); setReference(updates.getReference()); setPassword(updates.getPassword()); KerberosPrincipalDescriptor existingPrincipal = getPrincipalDescriptor(); if (existingPrincipal == null) { setPrincipalDescriptor(updates.getPrincipalDescriptor()); } else { existingPrincipal.update(updates.getPrincipalDescriptor()); } KerberosKeytabDescriptor existingKeytabDescriptor = getKeytabDescriptor(); if (existingKeytabDescriptor == null) { setKeytabDescriptor(updates.getKeytabDescriptor()); } else { existingKeytabDescriptor.update(updates.getKeytabDescriptor()); } Predicate updatedWhen = updates.getWhen(); if(updatedWhen != null) { setWhen(updatedWhen); } } } /** * Creates a Map of values that can be used to create a copy of this KerberosIdentityDescriptor * or generate the JSON structure described in * {@link org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor} * * @return a Map of values for this KerberosIdentityDescriptor * @see org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor */ @Override public Map<String, Object> toMap() { Map<String, Object> dataMap = super.toMap(); if (reference != null) { dataMap.put("reference", reference); } if (principal != null) { dataMap.put(Type.PRINCIPAL.getDescriptorName(), principal.toMap()); } if (keytab != null) { dataMap.put(Type.KEYTAB.getDescriptorName(), keytab.toMap()); } if (password != null) { dataMap.put("password", password); } if(when != null) { dataMap.put("when", PredicateUtils.toMap(when)); } return dataMap; } /*** * A name that refers to a service has a format like /[<service name>/[<component name>/]]<identity name> * @return an optional referenced service name */ public Optional<String> getReferencedServiceName() { return parseServiceName(reference).or(parseServiceName(getName())); } private Optional<String> parseServiceName(String name) { if (name != null && name.startsWith("/") && name.split("/").length > 2) { return Optional.of(name.split("/")[1]); } else { return Optional.absent(); } } @Override public int hashCode() { return super.hashCode() + ((getReference() == null) ? 0 : getReference().hashCode()) + ((getPrincipalDescriptor() == null) ? 0 : getPrincipalDescriptor().hashCode()) + ((getKeytabDescriptor() == null) ? 0 : getKeytabDescriptor().hashCode()) + ((getWhen() == null) ? 0 : getWhen().hashCode()); } @Override public boolean equals(Object object) { if (object == null) { return false; } else if (object == this) { return true; } else if (object.getClass() == KerberosIdentityDescriptor.class) { KerberosIdentityDescriptor descriptor = (KerberosIdentityDescriptor) object; return super.equals(object) && ( (getReference() == null) ? (descriptor.getReference() == null) : getReference().equals(descriptor.getReference()) ) && ( (getPrincipalDescriptor() == null) ? (descriptor.getPrincipalDescriptor() == null) : getPrincipalDescriptor().equals(descriptor.getPrincipalDescriptor()) ) && ( (getKeytabDescriptor() == null) ? (descriptor.getKeytabDescriptor() == null) : getKeytabDescriptor().equals(descriptor.getKeytabDescriptor()) ) && ( (getPassword() == null) ? (descriptor.getPassword() == null) : getPassword().equals(descriptor.getPassword()) ) && ( (getWhen() == null) ? (descriptor.getWhen() == null) : getWhen().equals(descriptor.getWhen()) ); } else { return false; } } }