/**
* 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 distribut
* ed 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.topology;
import java.util.Map;
import java.util.UUID;
import org.apache.ambari.server.orm.dao.KerberosDescriptorDAO;
import org.apache.ambari.server.orm.entities.KerberosDescriptorEntity;
import org.apache.ambari.server.state.SecurityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Enums;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.inject.Inject;
public class SecurityConfigurationFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfigurationFactory.class);
public static final String SECURITY_PROPERTY_ID = "security";
public static final String TYPE_PROPERTY_ID = "type";
public static final String KERBEROS_DESCRIPTOR_PROPERTY_ID = "kerberos_descriptor";
public static final String KERBEROS_DESCRIPTOR_REFERENCE_PROPERTY_ID = "kerberos_descriptor_reference";
@Inject
protected Gson jsonSerializer;
@Inject
private KerberosDescriptorDAO kerberosDescriptorDAO;
@Inject
private KerberosDescriptorFactory kerberosDescriptorFactory;
public SecurityConfigurationFactory() {
}
protected SecurityConfigurationFactory(Gson jsonSerializer, KerberosDescriptorDAO kerberosDescriptorDAO, KerberosDescriptorFactory kerberosDescriptorFactory) {
this.jsonSerializer = jsonSerializer;
this.kerberosDescriptorDAO = kerberosDescriptorDAO;
this.kerberosDescriptorFactory = kerberosDescriptorFactory;
}
/**
* Creates and also validates SecurityConfiguration based on properties parsed from request Json.
*
* @param properties Security properties from Json parsed into a Map
* @param persistEmbeddedDescriptor whether to save embedded descriptor or not
* @return
*/
public SecurityConfiguration createSecurityConfigurationFromRequest(Map<String, Object> properties, boolean
persistEmbeddedDescriptor) {
SecurityConfiguration securityConfiguration = null;
LOGGER.debug("Creating security configuration from properties: {}", properties);
Map<String, Object> securityProperties = (Map<String, Object>) properties.get(SECURITY_PROPERTY_ID);
if (securityProperties == null) {
LOGGER.debug("No security information properties provided, returning null");
return securityConfiguration;
}
String securityTypeString = Strings.emptyToNull((String) securityProperties.get(TYPE_PROPERTY_ID));
if (securityTypeString == null) {
LOGGER.error("Type is missing from security block.");
throw new IllegalArgumentException("Type missing from security block.");
}
SecurityType securityType = Enums.getIfPresent(SecurityType.class, securityTypeString).orNull();
if (securityType == null) {
LOGGER.error("Unsupported security type specified: {}", securityType);
throw new IllegalArgumentException("Invalid security type specified: " + securityTypeString);
}
if (securityType == SecurityType.KERBEROS) {
// get security information from the request propertie if any
String descriptorReference = Strings.emptyToNull((String)
securityProperties.get(KERBEROS_DESCRIPTOR_REFERENCE_PROPERTY_ID));
Object descriptorJsonMap = securityProperties.get(KERBEROS_DESCRIPTOR_PROPERTY_ID);
if (descriptorReference != null && descriptorJsonMap != null) {
LOGGER.error("Both kerberos descriptor and kerberos descriptor reference are set in the security configuration!");
throw new IllegalArgumentException("Usage of properties : " + KERBEROS_DESCRIPTOR_PROPERTY_ID + " and "
+ KERBEROS_DESCRIPTOR_REFERENCE_PROPERTY_ID + " at the same time, is not allowed.");
}
String descriptorText = null;
if (descriptorJsonMap != null) { // this means the reference is null
LOGGER.debug("Found embedded descriptor: {}", descriptorJsonMap);
descriptorText = jsonSerializer.<Map<String, Object>>toJson(descriptorJsonMap, Map.class);
if (persistEmbeddedDescriptor) {
descriptorReference = persistKerberosDescriptor(descriptorText);
}
securityConfiguration = new SecurityConfiguration(SecurityType.KERBEROS, descriptorReference, descriptorText);
} else if (descriptorReference != null) { // this means the reference is not null
LOGGER.debug("Found descriptor reference: {}", descriptorReference);
securityConfiguration = loadSecurityConfigurationByReference(descriptorReference);
} else {
LOGGER.debug("There is no security descriptor found in the request");
securityConfiguration = new SecurityConfiguration(SecurityType.KERBEROS);
}
} else {
LOGGER.debug("There is no security configuration found in the request");
securityConfiguration = new SecurityConfiguration(SecurityType.NONE);
}
return securityConfiguration;
}
public SecurityConfiguration loadSecurityConfigurationByReference(String reference) {
SecurityConfiguration securityConfiguration = null;
LOGGER.debug("Loading security configuration by reference: {}", reference);
if (reference == null) {
LOGGER.error("No security configuration reference provided!");
throw new IllegalArgumentException("No security configuration reference provided!");
}
KerberosDescriptorEntity descriptorEntity = kerberosDescriptorDAO.findByName(reference);
if (descriptorEntity == null) {
LOGGER.error("No security configuration found for the reference: {}", reference);
throw new IllegalArgumentException("No security configuration found for the reference: " + reference);
}
securityConfiguration = new SecurityConfiguration(SecurityType.KERBEROS, reference, descriptorEntity.getKerberosDescriptorText());
return securityConfiguration;
}
private String persistKerberosDescriptor(String descriptor) {
LOGGER.debug("Generating new kerberos descriptor reference ...");
String kdReference = generateKerberosDescriptorReference();
KerberosDescriptor kerberosDescriptor = kerberosDescriptorFactory.createKerberosDescriptor(kdReference, descriptor);
LOGGER.debug("Persisting kerberos descriptor ...");
kerberosDescriptorDAO.create(kerberosDescriptor.toEntity());
return kdReference;
}
// generates a unique name for the kerberos descriptor for further reference
private String generateKerberosDescriptorReference() {
String kdReference = UUID.randomUUID().toString();
LOGGER.debug("Generated new kerberos descriptor reference: {}", kdReference);
return kdReference;
}
}