ATLAS-1896:Fix for adding Cross Origin [CORS] headers for Atlas

Signed-off-by: nixonrodrigues <nixon@apache.org>
diff --git a/common/src/main/java/org/apache/atlas/utils/MD5Utils.java b/common/src/main/java/org/apache/atlas/utils/SHA256Utils.java
similarity index 68%
rename from common/src/main/java/org/apache/atlas/utils/MD5Utils.java
rename to common/src/main/java/org/apache/atlas/utils/SHA256Utils.java
index 8529b3c..0b57068 100644
--- a/common/src/main/java/org/apache/atlas/utils/MD5Utils.java
+++ b/common/src/main/java/org/apache/atlas/utils/SHA256Utils.java
@@ -15,25 +15,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.atlas.utils;
 
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
-/**
- * Utilities for MD5 hash.
- */
-public final class MD5Utils {
+public class SHA256Utils{
 
-    private MD5Utils() {
-    }
 
     private static final ThreadLocal<MessageDigest> DIGESTER_FACTORY =
             new ThreadLocal<MessageDigest>() {
                 @Override
                 protected MessageDigest initialValue() {
                     try {
-                        return MessageDigest.getInstance("MD5");
+                        return MessageDigest.getInstance("SHA-256");
                     } catch (NoSuchAlgorithmException e) {
                         throw new RuntimeException(e);
                     }
@@ -41,26 +38,31 @@
             };
 
     /**
-     * Create a thread local MD5 digester.
+     * Create a thread local SHA256 digester.
      */
+
     public static MessageDigest getDigester() {
         MessageDigest digester = DIGESTER_FACTORY.get();
         digester.reset();
         return digester;
     }
 
-    private static final char[] HEX_DIGITS =
-    {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+    public static String toString(byte[] hash) {
+        try{
+            StringBuffer hexString = new StringBuffer();
 
-    public static String toString(byte[] digest) {
-        StringBuilder buf = new StringBuilder(MD5_LEN * 2);
-        for (int i = 0; i < MD5_LEN; i++) {
-            int b = digest[i];
-            buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
-            buf.append(HEX_DIGITS[b & 0xf]);
+            for (int i = 0; i < hash.length; i++) {
+                String hex = Integer.toHexString(0xff & hash[i]);
+                if(hex.length() == 1) hexString.append('0');
+                hexString.append(hex);
+            }
+
+            return hexString.toString();
+        } catch(Exception ex){
+            throw new RuntimeException(ex);
         }
-        return buf.toString();
     }
 
-    public static final int MD5_LEN = 16;
+
+
 }
diff --git a/distro/src/conf/atlas-application.properties b/distro/src/conf/atlas-application.properties
index 474f253..c3213df 100755
--- a/distro/src/conf/atlas-application.properties
+++ b/distro/src/conf/atlas-application.properties
@@ -251,3 +251,10 @@
 
 #Set to false to disable full text search.
 #atlas.search.fulltext.enable=true
+
+
+########## Add http headers ###########
+
+#atlas.headers.Access-Control-Allow-Origin=*
+#atlas.headers.Access-Control-Allow-Methods=GET,OPTIONS,HEAD,PUT,POST
+#atlas.headers.<headerName>=<headerValue>
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
index 4dac293..1fb4ee9 100644
--- a/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
@@ -39,7 +39,7 @@
 import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
 import org.apache.atlas.typesystem.types.utils.TypesUtil;
 import org.apache.atlas.util.AtlasRepositoryConfiguration;
-import org.apache.atlas.utils.MD5Utils;
+import org.apache.atlas.utils.SHA256Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -675,7 +675,7 @@
         }
 
         // Update attributes
-        final MessageDigest digester = MD5Utils.getDigester();
+        final MessageDigest digester = SHA256Utils.getDigester();
         String newSignature = newAttributeValue.getSignatureHash(digester);
         String curSignature = GraphHelper.getSingleValuedProperty(structInstanceVertex, SIGNATURE_HASH_PROPERTY_KEY, String.class);
 
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/Id.java b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/Id.java
index 101a1f3..ba05a45 100755
--- a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/Id.java
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/Id.java
@@ -24,7 +24,7 @@
 import org.apache.atlas.typesystem.IStruct;
 import org.apache.atlas.typesystem.ITypedReferenceableInstance;
 import org.apache.atlas.typesystem.types.FieldMapping;
-import org.apache.atlas.utils.MD5Utils;
+import org.apache.atlas.utils.SHA256Utils;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -290,7 +290,7 @@
         digester.update(id.getBytes(Charset.forName("UTF-8")));
         digester.update(typeName.getBytes(Charset.forName("UTF-8")));
         byte[] digest = digester.digest();
-        return MD5Utils.toString(digest);
+        return SHA256Utils.toString(digest);
     }
 
     private static long nextNegativeLong() {
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/ReferenceableInstance.java b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/ReferenceableInstance.java
index 11cbb26..be2634d 100755
--- a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/ReferenceableInstance.java
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/ReferenceableInstance.java
@@ -29,7 +29,7 @@
 import org.apache.atlas.typesystem.types.ClassType;
 import org.apache.atlas.typesystem.types.FieldMapping;
 import org.apache.atlas.typesystem.types.TypeSystem;
-import org.apache.atlas.utils.MD5Utils;
+import org.apache.atlas.utils.SHA256Utils;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -130,6 +130,6 @@
         ClassType classType = TypeSystem.getInstance().getDataType(ClassType.class, getTypeName());
         classType.updateSignatureHash(digester, this);
         byte[] digest = digester.digest();
-        return MD5Utils.toString(digest);
+        return SHA256Utils.toString(digest);
     }
 }
diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/StructInstance.java b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/StructInstance.java
index fc10d07..766d2d0 100755
--- a/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/StructInstance.java
+++ b/typesystem/src/main/java/org/apache/atlas/typesystem/persistence/StructInstance.java
@@ -32,7 +32,7 @@
 import org.apache.atlas.typesystem.types.StructType;
 import org.apache.atlas.typesystem.types.TypeSystem;
 import org.apache.atlas.typesystem.types.ValueConversionException;
-import org.apache.atlas.utils.MD5Utils;
+import org.apache.atlas.utils.SHA256Utils;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -774,7 +774,7 @@
         StructType structType = TypeSystem.getInstance().getDataType(StructType.class, getTypeName());
         structType.updateSignatureHash(digester, this);
         byte[] digest = digester.digest();
-        return MD5Utils.toString(digest);
+        return SHA256Utils.toString(digest);
     }
 
     @Override
diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java
index 25aede3..444b094 100644
--- a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java
+++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java
@@ -26,6 +26,7 @@
 import org.apache.atlas.web.util.Servlets;
 import org.apache.commons.collections.iterators.IteratorEnumeration;
 import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationConverter;
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.security.SecurityUtil;
 import org.apache.hadoop.security.UserGroupInformation;
@@ -74,6 +75,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+
 /**
  * This enforces authentication as part of the filter before processing the request.
  * todo: Subclass of {@link org.apache.hadoop.security.authentication.server.AuthenticationFilter}.
@@ -90,7 +92,8 @@
     private boolean isInitializedByTomcat;
     private Set<Pattern> browserUserAgents;
     private boolean supportKeyTabBrowserLogin = false;
-
+    private Configuration configuration;
+    private Properties headerProperties;
     public AtlasAuthenticationFilter() {
         try {
             LOG.info("AtlasAuthenticationFilter initialization started");
@@ -112,8 +115,16 @@
     public void init(FilterConfig filterConfig) throws ServletException {
         LOG.info("AtlasAuthenticationFilter initialization started");
         final FilterConfig globalConf = filterConfig;
-
         final Map<String, String> params = new HashMap<>();
+        try {
+            configuration = ApplicationProperties.get();
+        } catch (Exception e) {
+            throw new ServletException(e);
+        }
+
+        if (configuration != null) {
+            headerProperties = ConfigurationConverter.getProperties(configuration.subset("atlas.headers"));
+        }
 
         FilterConfig filterConfig1 = new FilterConfig() {
             @Override
@@ -147,7 +158,6 @@
         optionsServlet = new HttpServlet() {
         };
         optionsServlet.init();
-
     }
 
 
@@ -176,7 +186,6 @@
 
     @Override
     protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) throws ServletException {
-        Configuration configuration;
         try {
             configuration = ApplicationProperties.get();
         } catch (Exception e) {
@@ -308,10 +317,16 @@
         try {
             Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
             HttpServletResponse httpResponse = (HttpServletResponse) response;
-
             AtlasResponseRequestWrapper responseWrapper = new AtlasResponseRequestWrapper(httpResponse);
             responseWrapper.setHeader("X-Frame-Options", "DENY");
 
+            if (headerProperties != null) {
+                for (String headerKey : headerProperties.stringPropertyNames()) {
+                    String headerValue = headerProperties.getProperty(headerKey);
+                    responseWrapper.setHeader(headerKey, headerValue);
+                }
+            }
+
             if (existingAuth == null) {
                 String authHeader = httpRequest.getHeader("Authorization");
                 if (authHeader != null && authHeader.startsWith("Basic")) {