Repository: ambari Updated Branches: refs/heads/trunk d853a99a8 -> 01e9e7607
AMBARI-6344. Views: Add <mask> optional attribute to <parameter> in view.xml. Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/01e9e760 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/01e9e760 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/01e9e760 Branch: refs/heads/trunk Commit: 01e9e76079f4fb5aeffa5ce059644f16296f5291 Parents: d853a99 Author: Siddharth Wagle <swa...@hortonworks.com> Authored: Tue Jul 1 13:20:37 2014 -0700 Committer: Siddharth Wagle <swa...@hortonworks.com> Committed: Tue Jul 1 13:39:17 2014 -0700 ---------------------------------------------------------------------- .../internal/ViewVersionResourceProvider.java | 15 ++-- .../ambari/server/orm/entities/ViewEntity.java | 27 +++++++ .../orm/entities/ViewParameterEntity.java | 24 ++++++ .../server/upgrade/UpgradeCatalog170.java | 6 ++ .../ambari/server/view/DefaultMasker.java | 48 ++++++++++++ .../ambari/server/view/ViewContextImpl.java | 82 +++++++++++++++----- .../apache/ambari/server/view/ViewRegistry.java | 48 +++++++++--- .../view/configuration/ParameterConfig.java | 14 ++++ .../server/view/configuration/ViewConfig.java | 45 ++++++++++- .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 4 +- .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 4 +- .../resources/Ambari-DDL-Postgres-CREATE.sql | 4 +- .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 4 +- .../server/upgrade/UpgradeCatalog170Test.java | 43 +++++++++- .../ambari/server/view/DefaultMaskerTest.java | 47 +++++++++++ .../ambari/server/view/ViewContextImplTest.java | 9 ++- .../view/configuration/ParameterConfigTest.java | 9 +++ .../view/configuration/ViewConfigTest.java | 8 ++ ambari-views/pom.xml | 21 ++--- .../org/apache/ambari/view/MaskException.java | 33 ++++++++ .../java/org/apache/ambari/view/Masker.java | 43 ++++++++++ .../ambari/view/PersistenceException.java | 2 +- .../org/apache/ambari/view/ViewDefinition.java | 7 ++ 23 files changed, 490 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java index 485eb04..5793a1b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java @@ -44,12 +44,13 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { /** * View property id constants. */ - public static final String VIEW_NAME_PROPERTY_ID = "ViewVersionInfo/view_name"; - public static final String VIEW_VERSION_PROPERTY_ID = "ViewVersionInfo/version"; - public static final String LABEL_PROPERTY_ID = "ViewVersionInfo/label"; - public static final String VERSION_PROPERTY_ID = "ViewVersionInfo/version"; - public static final String PARAMETERS_PROPERTY_ID = "ViewVersionInfo/parameters"; - public static final String ARCHIVE_PROPERTY_ID = "ViewVersionInfo/archive"; + public static final String VIEW_NAME_PROPERTY_ID = "ViewVersionInfo/view_name"; + public static final String VIEW_VERSION_PROPERTY_ID = "ViewVersionInfo/version"; + public static final String LABEL_PROPERTY_ID = "ViewVersionInfo/label"; + public static final String VERSION_PROPERTY_ID = "ViewVersionInfo/version"; + public static final String PARAMETERS_PROPERTY_ID = "ViewVersionInfo/parameters"; + public static final String ARCHIVE_PROPERTY_ID = "ViewVersionInfo/archive"; + public static final String MASKER_CLASS_PROPERTY_ID = "ViewVersionInfo/masker_class"; /** * The key property ids for a view resource. @@ -71,6 +72,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { propertyIds.add(VERSION_PROPERTY_ID); propertyIds.add(PARAMETERS_PROPERTY_ID); propertyIds.add(ARCHIVE_PROPERTY_ID); + propertyIds.add(MASKER_CLASS_PROPERTY_ID); } @@ -123,6 +125,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { setResourceProperty(resource, PARAMETERS_PROPERTY_ID, viewDefinition.getConfiguration().getParameters(), requestedIds); setResourceProperty(resource, ARCHIVE_PROPERTY_ID, viewDefinition.getArchive(), requestedIds); + setResourceProperty(resource, MASKER_CLASS_PROPERTY_ID, viewDefinition.getMask(), requestedIds); resources.add(resource); } http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java index eaf2589..a26e5e7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java @@ -94,6 +94,13 @@ public class ViewEntity implements ViewDefinition { private String archive; /** + * The masker class for parameters. + */ + @Column + @Basic + private String mask; + + /** * The list of view parameters. */ @OneToMany(cascade = CascadeType.ALL, mappedBy = "view") @@ -202,6 +209,8 @@ public class ViewEntity implements ViewDefinition { this.name = getViewName(configuration.getName(), version); this.label = configuration.getLabel(); this.version = version; + + this.mask = configuration.getMasker(); this.icon = configuration.getIcon(); this.icon64 = configuration.getIcon64(); @@ -580,6 +589,24 @@ public class ViewEntity implements ViewDefinition { return view; } + /** + * Set the mask class name. + * + * @param mask the mask class name + */ + public void setMask(String mask) { + this.mask = mask; + } + + /** + * Get the mask class name. + * + * @return the mask class name. + */ + public String getMask() { + return mask; + } + // ----- helper methods ---------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java index b3a7320..0c4c70f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java @@ -58,6 +58,13 @@ public class ViewParameterEntity { @Basic private char required; + /** + * Indicates whether or not the parameter is masked when persisted. + */ + @Column + @Basic + private char masked; + @ManyToOne @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false) private ViewEntity view; @@ -138,6 +145,23 @@ public class ViewParameterEntity { } /** + * Determine whether or not the parameter is masked. + * + * @return true if parameter is masked + */ + public boolean isMasked() { + return masked == 'y' || masked == 'Y'; + } + + /** + * Set the flag which indicate whether or not the parameter is masked + * @param masked the masked flag; true if the parameter is masked + */ + public void setMasked(boolean masked) { + this.masked = (masked ? 'Y' : 'N'); + } + + /** * Get the associated view entity. * * @return the view entity http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java index 029e98c..50087e5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java @@ -65,6 +65,12 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog { DBAccessor.DBColumnInfo clusterConfigAttributesColumn = new DBAccessor.DBColumnInfo( "config_attributes", String.class, 32000, null, true); dbAccessor.addColumn("clusterconfig", clusterConfigAttributesColumn); + + // Add columns + dbAccessor.addColumn("viewmain", new DBAccessor.DBColumnInfo("mask", + String.class, 255, null, true)); + dbAccessor.addColumn("viewparameter", new DBAccessor.DBColumnInfo("masked", + Character.class, 1, null, true)); } http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/view/DefaultMasker.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/DefaultMasker.java b/ambari-server/src/main/java/org/apache/ambari/server/view/DefaultMasker.java new file mode 100644 index 0000000..704ff7d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/DefaultMasker.java @@ -0,0 +1,48 @@ +/** + * 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.view; + +import java.io.UnsupportedEncodingException; + +import org.apache.ambari.view.MaskException; +import org.apache.ambari.view.Masker; +import org.apache.commons.codec.binary.Base64; + +/** + * Provides simple masking of view parameters. + */ +public class DefaultMasker implements Masker { + + @Override + public String mask(String value) throws MaskException { + try { + return Base64.encodeBase64String(value.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new MaskException("UTF-8 is not supported", e); + } + } + + @Override + public String unmask(String value) throws MaskException { + try { + return new String(Base64.decodeBase64(value), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new MaskException("UTF-8 is not supported", e); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java index e914c75..6426575 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java @@ -38,8 +38,6 @@ import org.apache.ambari.view.events.Listener; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.apache.velocity.exception.ParseErrorException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; @@ -51,6 +49,15 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; + +import org.apache.ambari.server.view.configuration.ParameterConfig; +import org.apache.ambari.server.view.configuration.ViewConfig; +import org.apache.ambari.view.MaskException; +import org.apache.ambari.view.Masker; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * View context implementation. @@ -58,6 +65,11 @@ import java.util.Map; public class ViewContextImpl implements ViewContext, ViewController { /** + * Logger. + */ + private static final Log LOG = LogFactory.getLog(ViewContextImpl.class); + + /** * The associated view definition. */ private final ViewEntity viewEntity; @@ -82,14 +94,12 @@ public class ViewContextImpl implements ViewContext, ViewController { */ private DataStore dataStore = null; - private final VelocityContext velocityContext; - - - // ----- Constants --------------------------------------------------------- - - protected final static Logger LOG = - LoggerFactory.getLogger(ViewContext.class); + /** + * Masker for properties. + */ + private Masker masker; + private final VelocityContext velocityContext; // ---- Constructors ------------------------------------------------------- @@ -118,6 +128,7 @@ public class ViewContextImpl implements ViewContext, ViewController { this.viewInstanceEntity = viewInstanceEntity; this.viewRegistry = viewRegistry; this.streamProvider = ViewURLStreamProvider.getProvider(); + this.masker = getMasker(viewEntity.getClassLoader(), viewEntity.getConfiguration()); this.velocityContext = initVelocityContext(); } @@ -147,18 +158,42 @@ public class ViewContextImpl implements ViewContext, ViewController { public Map<String, String> getProperties() { if (viewInstanceEntity == null) { return null; - } - Map<String, String> properties = viewInstanceEntity.getPropertyMap(); - String rawValue; - for (String key : properties.keySet()) { - rawValue = properties.get(key); - try { - properties.put(key, parameterize(rawValue)); - } catch (ParseErrorException ex) { - LOG.warn(String.format("Error during parsing '%s' parameter. Leaving original value.", key)); + } else { + Map<String, String> properties = viewInstanceEntity.getPropertyMap(); + + // unmasking + for (Entry<String, String> entry: properties.entrySet()) { + ParameterConfig parameterConfig = null; + for (ParameterConfig paramConfig : viewEntity.getConfiguration().getParameters()) { + if (StringUtils.equals(paramConfig.getName(), entry.getKey())) { + parameterConfig = paramConfig; + break; + } + } + if (parameterConfig == null || !parameterConfig.isMasked()) { + properties.put(entry.getKey(), entry.getValue()); + } else { + try { + properties.put(entry.getKey(), masker.unmask(entry.getValue())); + } catch (MaskException e) { + LOG.error("Failed to unmask view property", e); + } + } + } + + // parametrizing + + String rawValue; + for (String key : properties.keySet()) { + rawValue = properties.get(key); + try { + properties.put(key, parameterize(rawValue)); + } catch (ParseErrorException ex) { + LOG.warn(String.format("Error during parsing '%s' parameter. Leaving original value.", key)); + } } + return Collections.unmodifiableMap(properties); } - return Collections.unmodifiableMap(properties); } @Override @@ -270,6 +305,14 @@ public class ViewContextImpl implements ViewContext, ViewController { } } + private Masker getMasker(ClassLoader cl, ViewConfig viewConfig) { + try { + return viewConfig.getMaskerClass(cl).newInstance(); + } catch (Exception e) { + throw new InstantiationError("Could not create masker instance."); + } + } + /** * Parameterize string using VelocityContext instance * @@ -316,7 +359,6 @@ public class ViewContextImpl implements ViewContext, ViewController { return context; } - // ----- Inner class : ViewURLStreamProvider ------------------------------- /** http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java index 33485a0..849da64 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java @@ -21,6 +21,7 @@ package org.apache.ambari.server.view; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; + import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl; import org.apache.ambari.server.api.resources.SubResourceDefinition; import org.apache.ambari.server.api.resources.ViewExternalSubResourceDefinition; @@ -43,6 +44,8 @@ import org.apache.ambari.server.view.configuration.PersistenceConfig; import org.apache.ambari.server.view.configuration.PropertyConfig; import org.apache.ambari.server.view.configuration.ResourceConfig; import org.apache.ambari.server.view.configuration.ViewConfig; +import org.apache.ambari.view.MaskException; +import org.apache.ambari.view.Masker; import org.apache.ambari.view.SystemException; import org.apache.ambari.view.View; import org.apache.ambari.view.ViewContext; @@ -50,6 +53,7 @@ import org.apache.ambari.view.ViewDefinition; import org.apache.ambari.view.ViewResourceHandler; import org.apache.ambari.view.events.Event; import org.apache.ambari.view.events.Listener; +import org.apache.commons.lang.StringUtils; import org.eclipse.jetty.webapp.WebAppContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,6 +61,7 @@ import org.slf4j.LoggerFactory; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; + import java.beans.IntrospectionException; import java.io.File; import java.io.FileNotFoundException; @@ -203,7 +208,7 @@ public class ViewRegistry { } /** - * Get the instance definition for the given view nam,e and instance name. + * Get the instance definition for the given view name and instance name. * * @param viewName the view name * @param version the version @@ -338,7 +343,7 @@ public class ViewRegistry { for (InstanceConfig instanceConfig : viewConfig.getInstances()) { try { - instanceDefinitions.add(createViewInstanceDefinition(viewDefinition, instanceConfig)); + instanceDefinitions.add(createViewInstanceDefinition(viewConfig, viewDefinition, instanceConfig)); } catch (Exception e) { LOG.error("Caught exception adding view instance for view " + viewDefinition.getViewName(), e); @@ -603,6 +608,7 @@ public class ViewRegistry { viewParameterEntity.setName(parameterConfiguration.getName()); viewParameterEntity.setDescription(parameterConfiguration.getDescription()); viewParameterEntity.setRequired(parameterConfiguration.isRequired()); + viewParameterEntity.setMasked(parameterConfiguration.isMasked()); viewParameterEntity.setViewEntity(viewDefinition); parameters.add(viewParameterEntity); } @@ -658,18 +664,32 @@ public class ViewRegistry { view = getView(viewConfig.getViewClass(cl), new ViewContextImpl(viewDefinition, this)); } viewDefinition.setView(view); + viewDefinition.setMask(viewConfig.getMasker()); return viewDefinition; } // create a new view instance definition - protected ViewInstanceEntity createViewInstanceDefinition(ViewEntity viewDefinition, InstanceConfig instanceConfig) - throws ClassNotFoundException, IllegalStateException { + protected ViewInstanceEntity createViewInstanceDefinition(ViewConfig viewConfig, ViewEntity viewDefinition, InstanceConfig instanceConfig) + throws ClassNotFoundException, IllegalStateException, MaskException { ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig); + Masker masker = getMasker(viewConfig.getMaskerClass(viewDefinition.getClassLoader())); for (PropertyConfig propertyConfig : instanceConfig.getProperties()) { - viewInstanceDefinition.putProperty(propertyConfig.getKey(), propertyConfig.getValue()); + ParameterConfig parameterConfig = null; + for (ParameterConfig paramConfig : viewConfig.getParameters()) { + if (StringUtils.equals(paramConfig.getName(), propertyConfig.getKey())) { + parameterConfig = paramConfig; + break; + } + } + if (parameterConfig != null && parameterConfig.isMasked()) { + viewInstanceDefinition.putProperty(propertyConfig.getKey(), + masker.mask(propertyConfig.getValue())); + } else { + viewInstanceDefinition.putProperty(propertyConfig.getKey(), propertyConfig.getValue()); + } } viewInstanceDefinition.validate(viewDefinition); @@ -786,6 +806,16 @@ public class ViewRegistry { return viewInstanceInjector.getInstance(clazz); } + // create masker from given class; probably replace with injector later + private static Masker getMasker(Class<? extends Masker> clazz) { + try { + return clazz.newInstance(); + } catch (Exception e) { + LOG.error("Could not create masker instance", e); + } + return null; + } + // remove undeployed views from the ambari db private void removeUndeployedViews() { for (ViewEntity viewEntity : viewDAO.findAll()) { @@ -881,7 +911,7 @@ public class ViewRegistry { } // extract the given view archive to the given archive directory - private ClassLoader extractViewArchive(File viewArchive, File archiveDir) + private ClassLoader extractViewArchive(File viewArchive, File archiveDir) throws IOException { // Skip if the archive has already been extracted @@ -890,7 +920,7 @@ public class ViewRegistry { String archivePath = archiveDir.getAbsolutePath(); LOG.info("Creating archive folder " + archivePath + "."); - + if (archiveDir.mkdir()) { JarFile viewJarFile = helper.getJarFile(viewArchive); Enumeration enumeration = viewJarFile.entries(); @@ -933,7 +963,7 @@ public class ViewRegistry { } // get a class loader for the given archive directory - private ClassLoader getArchiveClassLoader(File archiveDir) + private ClassLoader getArchiveClassLoader(File archiveDir) throws MalformedURLException { String archivePath = archiveDir.getAbsolutePath(); @@ -960,7 +990,7 @@ public class ViewRegistry { } } - // include the archive directory + // include the archive directory urlList.add(archiveDir.toURI().toURL()); return URLClassLoader.newInstance(urlList.toArray(new URL[urlList.size()])); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java index 97c9e22..827b5e7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java @@ -42,6 +42,11 @@ public class ParameterConfig { private boolean required; /** + * Indicates whether or not the parameter is masked when persisted. + */ + private boolean masked; + + /** * Get the parameter name. * * @return the name @@ -67,4 +72,13 @@ public class ParameterConfig { public boolean isRequired() { return required; } + + /** + * Indicates whether or not the parameter is masked when persisted. + * + * @return true if the parameter is masked; false otherwise + */ + public boolean isMasked() { + return masked; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java index 1e29f5d..e084918 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java @@ -18,12 +18,16 @@ package org.apache.ambari.server.view.configuration; +import org.apache.ambari.server.view.DefaultMasker; +import org.apache.ambari.view.Masker; import org.apache.ambari.view.View; +import org.apache.commons.lang.StringUtils; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; + import java.util.Collections; import java.util.List; @@ -70,6 +74,17 @@ public class ViewConfig { private Class<? extends View> viewClass = null; /** + * The masker class name for parameters. + */ + @XmlElement(name="masker-class") + private String masker; + + /** + * The mask class. + */ + private Class<? extends Masker> maskerClass = null; + + /** * The list of view parameters. */ @XmlElement(name="parameter") @@ -150,7 +165,7 @@ public class ViewConfig { /** * Get the view class. * - * @param cl the class loader + * @param cl the class loader * * @return the view class * @@ -164,6 +179,34 @@ public class ViewConfig { } /** + * Get the masker class name. + * @return the masker class name + */ + public String getMasker() { + return masker; + } + + /** + * Get the masker class. + * + * @param cl the class loader + * + * @return the masker class + * + * @throws ClassNotFoundException if the class can not be loaded + */ + public Class<? extends Masker> getMaskerClass(ClassLoader cl) throws ClassNotFoundException { + if (maskerClass == null) { + if (StringUtils.isBlank(masker)) { + maskerClass = DefaultMasker.class; + } else { + maskerClass = cl.loadClass(masker).asSubclass(Masker.class); + } + } + return maskerClass; + } + + /** * Get the list of view parameters. * * @return the list of parameters http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index 8d73866..f12c5d1 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -62,11 +62,11 @@ CREATE TABLE hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255) CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name)); CREATE TABLE blueprint_configuration (blueprint_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data VARCHAR(32000) NOT NULL , PRIMARY KEY(blueprint_name, type_name)); CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name)); -CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name)); +CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name)); CREATE TABLE viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(VIEW_INSTANCE_ID, NAME, USER_NAME)); CREATE TABLE viewinstance (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name)); -CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name)); +CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name)); CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id)); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index c8b4ba7..3620788 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -52,11 +52,11 @@ CREATE TABLE hostgroup (blueprint_name VARCHAR2(255) NOT NULL, name VARCHAR2(255 CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name)); CREATE TABLE blueprint_configuration (blueprint_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL , PRIMARY KEY(blueprint_name, type_name)); CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name)); -CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name)); +CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name)); CREATE TABLE viewinstancedata (view_instance_id NUMBER(19), view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name)); CREATE TABLE viewinstance (view_instance_id NUMBER(19), view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name)); -CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name)); +CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), "resource" VARCHAR(255), PRIMARY KEY(view_name, name)); CREATE TABLE viewentity (id NUMBER(19) NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id)); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index c020a66..8c1cf3b 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -85,11 +85,11 @@ CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgrou CREATE TABLE blueprint_configuration (blueprint_name varchar(255) NOT NULL, type_name varchar(255) NOT NULL, config_data varchar(32000) NOT NULL , PRIMARY KEY(blueprint_name, type_name)); CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name)); -CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name)); +CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name)); CREATE TABLE viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name)); CREATE TABLE viewinstance (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name)); -CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name)); +CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name)); CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id)); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql index a8b1048..6ac6558 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql @@ -132,11 +132,11 @@ GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_configuration TO :username; -CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name)); +CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name)); CREATE TABLE ambari.viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name)); CREATE TABLE ambari.viewinstance (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name)); -CREATE TABLE ambari.viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name)); +CREATE TABLE ambari.viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); CREATE TABLE ambari.viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name)); CREATE TABLE ambari.viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id)); GRANT ALL PRIVILEGES ON TABLE ambari.viewmain TO :username; http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java index 7101ef9..dfda132 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java @@ -19,6 +19,7 @@ package org.apache.ambari.server.upgrade; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.capture; @@ -58,7 +59,11 @@ public class UpgradeCatalog170Test { expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes(); Capture<DBAccessor.DBColumnInfo> clusterConfigAttributesColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); + Capture<DBAccessor.DBColumnInfo> maskColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); + Capture<DBAccessor.DBColumnInfo> maskedColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); + setViewExpectations(dbAccessor, maskColumnCapture); + setViewParameterExpectations(dbAccessor, maskedColumnCapture); setClusterConfigExpectations(dbAccessor, clusterConfigAttributesColumnCapture); dbAccessor.executeSelect(anyObject(String.class)); expectLastCall().andReturn(resultSet).anyTimes(); @@ -78,6 +83,8 @@ public class UpgradeCatalog170Test { verify(dbAccessor, configuration, resultSet); assertClusterConfigColumns(clusterConfigAttributesColumnCapture); + assertViewColumns(maskColumnCapture); + assertViewParameterColumns(maskedColumnCapture); } @Test @@ -125,5 +132,39 @@ public class UpgradeCatalog170Test { final DBAccessor dbAccessor = createNiceMock(DBAccessor.class); UpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor); Assert.assertEquals("1.6.1", upgradeCatalog.getSourceVersion()); - } + } + + private void setViewExpectations(DBAccessor dbAccessor, + Capture<DBAccessor.DBColumnInfo> maskColumnCapture) + throws SQLException { + + dbAccessor.addColumn(eq("viewmain"), capture(maskColumnCapture)); + } + + private void setViewParameterExpectations(DBAccessor dbAccessor, + Capture<DBAccessor.DBColumnInfo> maskedColumnCapture) + throws SQLException { + + dbAccessor.addColumn(eq("viewparameter"), capture(maskedColumnCapture)); + } + + private void assertViewColumns( + Capture<DBAccessor.DBColumnInfo> maskColumnCapture) { + DBAccessor.DBColumnInfo column = maskColumnCapture.getValue(); + assertEquals("mask", column.getName()); + assertEquals(255, (int) column.getLength()); + assertEquals(String.class, column.getType()); + assertNull(column.getDefaultValue()); + assertTrue(column.isNullable()); + } + + private void assertViewParameterColumns( + Capture<DBAccessor.DBColumnInfo> maskedColumnCapture) { + DBAccessor.DBColumnInfo column = maskedColumnCapture.getValue(); + assertEquals("masked", column.getName()); + assertEquals(1, (int) column.getLength()); + assertEquals(Character.class, column.getType()); + assertNull(column.getDefaultValue()); + assertTrue(column.isNullable()); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/test/java/org/apache/ambari/server/view/DefaultMaskerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/DefaultMaskerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/DefaultMaskerTest.java new file mode 100644 index 0000000..7fde6b7 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/DefaultMaskerTest.java @@ -0,0 +1,47 @@ +/** + * 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.view; + +import junit.framework.Assert; + +import org.apache.ambari.server.view.DefaultMasker; +import org.junit.Test; + +/** + * DefaultMasker test. + */ +public class DefaultMaskerTest { + private DefaultMasker masker = new DefaultMasker(); + + @Test + public void testMask() throws Exception { + final String source = "unmasked"; + final String masked = masker.mask(source); + Assert.assertNotNull(masked); + Assert.assertTrue(masked.length() > 0); + } + + @Test + public void testMaskUnmask() throws Exception { + final String source = "unmasked"; + final String masked = masker.mask(source); + final String unmasked = masker.unmask(masked); + Assert.assertEquals(source, unmasked); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java index 5358162..6bddf08 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java @@ -25,6 +25,7 @@ import org.apache.ambari.server.orm.entities.ViewEntityTest; import org.apache.ambari.server.orm.entities.ViewInstanceEntity; import org.apache.ambari.server.view.configuration.InstanceConfig; import org.apache.ambari.server.view.configuration.InstanceConfigTest; +import org.apache.ambari.server.view.configuration.ViewConfigTest; import org.apache.ambari.view.ResourceProvider; import org.junit.Assert; import org.junit.Test; @@ -77,7 +78,7 @@ public class ViewContextImplTest { ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig); ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); viewInstanceDefinition.putProperty("p1", "v1"); - viewInstanceDefinition.putProperty("p2", "v2"); + viewInstanceDefinition.putProperty("p2", new DefaultMasker().mask("v2")); viewInstanceDefinition.putProperty("p3", "v3"); ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry); @@ -96,18 +97,22 @@ public class ViewContextImplTest { replay(instanceConfig); ViewEntity viewDefinition = createNiceMock(ViewEntity.class); expect(viewDefinition.getCommonName()).andReturn("View").times(2); + expect(viewDefinition.getClassLoader()).andReturn(ViewContextImplTest.class.getClassLoader()).anyTimes(); + expect(viewDefinition.getConfiguration()).andReturn(ViewConfigTest.getConfig()).anyTimes(); replay(viewDefinition); ViewInstanceEntity viewInstanceDefinition = createMockBuilder(ViewInstanceEntity.class) .addMockedMethod("getUsername") .addMockedMethod("getName") + .addMockedMethod("getViewEntity") .withConstructor(viewDefinition, instanceConfig).createMock(); expect(viewInstanceDefinition.getUsername()).andReturn("User").times(1); expect(viewInstanceDefinition.getUsername()).andReturn("User2").times(1); expect(viewInstanceDefinition.getName()).andReturn("Instance").times(3); + expect(viewInstanceDefinition.getViewEntity()).andReturn(viewDefinition).times(1); replay(viewInstanceDefinition); ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); viewInstanceDefinition.putProperty("p1", "/tmp/some/path/${username}"); - viewInstanceDefinition.putProperty("p2", "/tmp/path/$viewName"); + viewInstanceDefinition.putProperty("p2", new DefaultMasker().mask("/tmp/path/$viewName")); viewInstanceDefinition.putProperty("p3", "/path/$instanceName"); viewInstanceDefinition.putProperty("p4", "/path/to/${unspecified_parameter}"); viewInstanceDefinition.putProperty("p5", "/path/to/${incorrect_parameter"); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java index 7069d37..e3350bc 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java @@ -55,6 +55,15 @@ public class ParameterConfigTest { Assert.assertEquals(false, parameters.get(1).isRequired()); } + @Test + public void testIsMasked() throws Exception { + List<ParameterConfig> parameters = getParameterConfigs(); + + Assert.assertEquals(2, parameters.size()); + Assert.assertEquals(false, parameters.get(0).isMasked()); + Assert.assertEquals(true, parameters.get(1).isMasked()); + } + public static List<ParameterConfig> getParameterConfigs() throws JAXBException { ViewConfig viewConfig = ViewConfigTest.getConfig(); return viewConfig.getParameters (); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java index bb4ad0c..ba40027 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java @@ -48,6 +48,7 @@ public class ViewConfigTest { " <version>1.0.0</version>\n" + " <icon64>/this/is/the/icon/url/icon64.png</icon64>\n" + " <icon>/this/is/the/icon/url/icon.png</icon>\n" + + " <masker-class>org.apache.ambari.server.view.DefaultMasker</masker-class>" + " <parameter>\n" + " <name>p1</name>\n" + " <description>Parameter 1.</description>\n" + @@ -57,6 +58,7 @@ public class ViewConfigTest { " <name>p2</name>\n" + " <description>Parameter 2.</description>\n" + " <required>false</required>\n" + + " <masked>true</masked>" + " </parameter>\n" + " <resource>\n" + " <name>resource</name>\n" + @@ -145,6 +147,12 @@ public class ViewConfigTest { } @Test + public void testMasker() throws Exception { + ViewConfig config = getConfig(); + Assert.assertEquals("org.apache.ambari.server.view.DefaultMasker", config.getMasker()); + } + + @Test public void testGetView() throws Exception { ViewConfig config = getConfig(view_class_xml); Assert.assertEquals("ViewImpl", config.getView()); http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-views/pom.xml ---------------------------------------------------------------------- diff --git a/ambari-views/pom.xml b/ambari-views/pom.xml index e4fcb4a..23cb784 100644 --- a/ambari-views/pom.xml +++ b/ambari-views/pom.xml @@ -48,6 +48,10 @@ <artifactId>jersey-core</artifactId> <version>1.8</version> </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> </dependencies> <build> <plugins> @@ -126,14 +130,14 @@ <exclude>**/*.json</exclude> </excludes> </configuration> - <executions> - <execution> - <phase>test</phase> - <goals> - <goal>check</goal> - </goals> - </execution> - </executions> + <executions> + <execution> + <phase>test</phase> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> @@ -152,4 +156,3 @@ </build> </project> - http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-views/src/main/java/org/apache/ambari/view/MaskException.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/MaskException.java b/ambari-views/src/main/java/org/apache/ambari/view/MaskException.java new file mode 100644 index 0000000..b976d4a --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/MaskException.java @@ -0,0 +1,33 @@ +/** + * 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.view; + +/** + * Indicates that a mask exception occurred. + */ +public class MaskException extends Exception { + /** + * Constructor. + * + * @param msg message + * @param throwable root exception + */ + public MaskException(String msg, Throwable throwable) { + super(msg, throwable); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-views/src/main/java/org/apache/ambari/view/Masker.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/Masker.java b/ambari-views/src/main/java/org/apache/ambari/view/Masker.java new file mode 100644 index 0000000..31d22f1 --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/Masker.java @@ -0,0 +1,43 @@ +/** + * 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.view; + +/** + * Masker for view parameters. + */ +public interface Masker { + + /** + * Get a masked version of the given string. + * + * @param value the value to be masked + * @return the masked value + * @throws MaskException error happened during masking process + */ + public String mask(String value) throws MaskException; + + /** + * Get the original string from a masked string. + * + * @param value the value to be unmasked + * @return the unmasked value + * @throws MaskException error happened during unmasking process + */ + public String unmask(String value) throws MaskException; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java b/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java index 6e32940..e8959b4 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java @@ -19,7 +19,7 @@ package org.apache.ambari.view; /** - * View persistence exception. Indicates that an error occurred while + * View persistence exception. Indicates that an error occurred while * persisting a view or view data. */ public class PersistenceException extends Exception { http://git-wip-us.apache.org/repos/asf/ambari/blob/01e9e760/ambari-views/src/main/java/org/apache/ambari/view/ViewDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewDefinition.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewDefinition.java index 8389033..e519526 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/ViewDefinition.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewDefinition.java @@ -43,4 +43,11 @@ public interface ViewDefinition { * @return the version */ public String getVersion(); + + /** + * Get the mask class name. + * + * @return the mask class name. + */ + public String getMask(); }