package com.sequenceiq.cloudbreak.service.stack.resource.definition.credential; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.jasypt.encryption.pbe.PBEStringCleanablePasswordEncryptor; import org.springframework.stereotype.Service; import com.sequenceiq.cloudbreak.cloud.model.Platform; import com.sequenceiq.cloudbreak.service.stack.resource.definition.MissingParameterException; import com.sequenceiq.cloudbreak.service.stack.resource.definition.ResourceDefinitionService; import com.sequenceiq.cloudbreak.util.JsonUtil; @Service public class CredentialDefinitionService { private static final String SELECTOR = "selector"; private static final String RESOURCE_TYPE = "credential"; @Inject private ResourceDefinitionService definitionService; @Inject private PBEStringCleanablePasswordEncryptor encryptor; public Map<String, Object> processProperties(Platform cloudPlatform, Map<String, Object> properties) { return processValues(getDefinition(cloudPlatform), properties, false); } public Map<String, Object> revertProperties(Platform cloudPlatform, Map<String, Object> properties) { return processValues(getDefinition(cloudPlatform), properties, true); } private Definition getDefinition(Platform cloudPlatform) { String json = definitionService.getResourceDefinition(cloudPlatform.value(), RESOURCE_TYPE); try { return JsonUtil.readValue(json, Definition.class); } catch (IOException e) { throw new RuntimeException(e); } } private Map<String, Object> processValues(Definition definition, Map<String, Object> properties, boolean revert) { Map<String, Object> processed = new HashMap<>(); processed.putAll(processValues(properties, definition.getDefaultValues(), revert)); Object selector = properties.get(SELECTOR); if (selector != null) { processed.put(SELECTOR, selector); processed.putAll(processValues(properties, collectSelectorValues(definition, String.valueOf(selector)), revert)); } return processed; } private List<Value> collectSelectorValues(Definition definition, String selectorName) { List<Value> values = new ArrayList<>(); List<Selector> selectors = definition.getSelectors(); String currentSelector = selectorName; Selector element; while ((element = findSelector(selectors, currentSelector)) != null) { values.addAll(element.getValues()); currentSelector = element.getParent(); } return values; } private Selector findSelector(List<Selector> selectors, String selector) { for (Selector s : selectors) { if (s.getName().equals(selector)) { return s; } } return null; } private Map<String, Object> processValues(Map<String, Object> properties, List<Value> values, boolean revert) { Map<String, Object> processed = new HashMap<>(); for (Value value : values) { String key = value.getName(); String property = getProperty(properties, key, isOptional(value)); if (property != null && !property.isEmpty() && isEncrypted(value)) { property = revert ? encryptor.decrypt(property) : encryptor.encrypt(property); } processed.put(key, property); } return processed; } private boolean isEncrypted(Value value) { Boolean encrypted = value.getEncrypted(); return isNotNull(encrypted) && encrypted; } private boolean isOptional(Value value) { Boolean optional = value.getOptional(); return isNotNull(optional) && optional; } private boolean isNotNull(Object object) { return null != object; } private String getProperty(Map<String, Object> properties, String key, boolean optional) { Object value = properties.get(key); if (value == null && !optional) { throw new MissingParameterException(String.format("Missing '%s' property!", key)); } return value == null ? null : String.valueOf(value); } }