You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by om...@apache.org on 2014/08/14 22:50:53 UTC
[42/44] ARGUS-1. Initial code commit (Selvamohan Neethiraj via
omalley)
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/ConfigWatcher.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/ConfigWatcher.java b/agents-impl/src/main/java/com/xasecure/pdp/config/ConfigWatcher.java
new file mode 100644
index 0000000..449db16
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/ConfigWatcher.java
@@ -0,0 +1,532 @@
+/**
+ * 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 com.xasecure.pdp.config;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+import com.xasecure.authorization.hadoop.config.XaSecureConfiguration;
+import com.xasecure.pdp.config.gson.PolicyExclusionStrategy;
+import com.xasecure.pdp.constants.XaSecureConstants;
+import com.xasecure.pdp.model.PolicyContainer;
+import com.xasecure.authorization.hadoop.utils.XaSecureCredentialProvider;
+
+public abstract class ConfigWatcher extends Thread {
+
+ private static final Log LOG = LogFactory.getLog(ConfigWatcher.class);
+
+ public static final String EXPECTED_MIME_TYPE = "application/json" ;
+
+ // public static final String EXPECTED_MIME_TYPE = "application/octet-stream";
+
+ private static final String LASTUPDATED_PARAM = "epoch";
+ private static final String POLICY_COUNT_PARAM = "policyCount";
+ private static final String AGENT_NAME_PARAM = "agentId" ;
+
+ private static final int MAX_AGENT_NAME_LEN = 255 ;
+
+
+ private String url;
+
+ private long intervalInMilliSeconds;
+
+ private long lastModifiedTime = 0;
+
+ private boolean shutdownFlag = false;
+
+ private String lastStoredFileName = null;
+
+ protected PolicyContainer policyContainer = null;
+
+ private static PolicyExclusionStrategy policyExclusionStrategy = new PolicyExclusionStrategy();
+
+ private static XaSecureCredentialProvider xasecurecp = null;
+
+ public abstract void doOnChange();
+
+ private String keyStoreFile = null ;
+ private String keyStoreFilepwd = null;
+ private String keyStoreURL = null;
+ private String keyStoreAlias = null;
+ private String trustStoreFile = null ;
+ private String trustStoreFilepwd = null ;
+ private String trustStoreURL = null;
+ private String trustStoreAlias = null;
+ private String keyStoreType = null ;
+ private String trustStoreType = null ;
+ private SSLContext sslContext = null ;
+ private HostnameVerifier hv = null ;
+ private String agentName = "unknown" ;
+
+ private String sslConfigFileName = null ;
+
+ boolean policyCacheLoadedOnce = false;
+
+ public ConfigWatcher(String url, long aIntervalInMilliSeconds,String sslConfigFileName,String lastStoredFileName) {
+ super("XaSecureConfigURLWatcher");
+ setDaemon(true);
+ this.url = url;
+ intervalInMilliSeconds = aIntervalInMilliSeconds;
+ this.sslConfigFileName = sslConfigFileName ;
+ this.agentName = getAgentName(this.url) ;
+ this.lastStoredFileName = lastStoredFileName;
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Creating PolicyRefreshser with url: " + url +
+ ", refreshInterval(milliSeconds): " + aIntervalInMilliSeconds +
+ ", sslConfigFileName: " + sslConfigFileName +
+ ", lastStoredFileName: " + lastStoredFileName);
+ }
+ init();
+ validateAndRun();
+ LOG.debug("Created new ConfigWatcher for URL [" + url + "]");
+ }
+
+
+ public void init() {
+ if (sslConfigFileName != null) {
+ LOG.debug("Loading SSL Configuration from [" + sslConfigFileName + "]");
+ InputStream in = null ;
+ try {
+ Configuration conf = new Configuration() ;
+ in = getFileInputStream(sslConfigFileName) ;
+ if (in != null) {
+ conf.addResource(in);
+ }
+
+ xasecurecp = XaSecureCredentialProvider.getInstance();
+
+ keyStoreFile = conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE);
+
+ keyStoreURL=conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL);
+ keyStoreAlias=XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL_ALIAS;
+
+ char[] v_keyStoreFilePwd = getCredential(keyStoreURL,keyStoreAlias);
+ if ( v_keyStoreFilePwd == null ) {
+ keyStoreFilepwd = null;
+ } else {
+ keyStoreFilepwd = new String(v_keyStoreFilePwd);
+ }
+
+ trustStoreFile = conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE);
+
+ trustStoreURL=conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL);
+ trustStoreAlias=XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL_ALIAS;
+
+ char[] v_TrustStoreFilePwd = getCredential(trustStoreURL,trustStoreAlias);
+ if ( v_TrustStoreFilePwd == null ) {
+ trustStoreFilepwd = null;
+ } else {
+ trustStoreFilepwd = new String(v_TrustStoreFilePwd);
+ }
+
+
+ keyStoreType = conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE, XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE_DEFAULT);
+ trustStoreType = conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE, XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE_DEFAULT);
+ }
+ catch(IOException ioe) {
+ LOG.error("Unable to load SSL Config FileName: [" + sslConfigFileName + "]", ioe);
+ }
+ finally {
+ if (in != null) {
+ try {
+ in.close() ;
+ } catch (IOException e) {
+ LOG.error("Unable to close SSL Config FileName: [" + sslConfigFileName + "]", e) ;
+ }
+ }
+ }
+
+ LOG.debug("Keystore filename:[" + keyStoreFile + "]");
+ LOG.debug("TrustStore filename:[" + trustStoreFile + "]");
+
+ }
+ }
+
+ public String getURL() {
+ return url;
+ }
+
+ public long getIntervalInMilliSeconds() {
+ return intervalInMilliSeconds;
+ }
+
+ public long getLastModifiedTime() {
+ return lastModifiedTime;
+ }
+
+ public void run() {
+ while (!shutdownFlag) {
+ validateAndRun();
+ try {
+ Thread.sleep(intervalInMilliSeconds);
+ } catch (InterruptedException e) {
+ LOG.error("Unable to complete sleep for [" + intervalInMilliSeconds + "]", e);
+ }
+ }
+ }
+
+ private void validateAndRun() {
+ if (isFileChanged()) {
+ LOG.debug("Policy has been changed from " + url + " ... RELOADING");
+ try {
+ doOnChange();
+ } catch (Exception e) {
+ LOG.error("Unable to complete doOnChange() method on file change [" + url + "]", e);
+ }
+ } else {
+ LOG.debug("No Change found in the policy from " + url);
+ }
+ }
+
+ private boolean isFileChanged() {
+ boolean isChanged = false;
+
+
+ try {
+
+ Client client = null;
+ ClientResponse response = null;
+
+ try {
+
+ int policyCount = getPolicyCount(policyContainer);
+
+ if (url.contains("https")) {
+ // build SSL Client
+ client = buildSSLClient();
+ }
+
+ if (client == null) {
+ client = Client.create();
+ }
+
+ WebResource webResource = client.resource(url)
+ .queryParam(LASTUPDATED_PARAM, String.valueOf(lastModifiedTime))
+ .queryParam(POLICY_COUNT_PARAM, String.valueOf(policyCount))
+ .queryParam(AGENT_NAME_PARAM, agentName);
+
+ response = webResource.accept(EXPECTED_MIME_TYPE).get(ClientResponse.class);
+
+
+ if (response != null) {
+
+ Boolean responsePresent = true;
+ int responseStatus = response.getStatus();
+
+ if ( fetchPolicyfromCahce(responsePresent,responseStatus,lastStoredFileName) ) {
+ /* If the response is other than 200 and 304 load the policy from the cache */
+ isChanged = true;
+
+ } else {
+ /* If Policy Manager is available fetch the policy from it */
+ if (response.getStatus() == 200) {
+ String jsonString = response.getEntity(String.class);
+ Gson gson = new GsonBuilder().setPrettyPrinting().addDeserializationExclusionStrategy(policyExclusionStrategy).create();
+ PolicyContainer newPolicyContainer = gson.fromJson(jsonString, PolicyContainer.class);
+ if ((newPolicyContainer.getLastUpdatedTimeInEpoc() > lastModifiedTime) || (getPolicyCount(newPolicyContainer) != policyCount)) {
+ policyContainer = newPolicyContainer;
+ lastModifiedTime = policyContainer.getLastUpdatedTimeInEpoc();
+ isChanged = true;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 200 with {change in lastupdatedTime}\n" + gson.toJson(newPolicyContainer));
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 200 with {no-change in lastupdatedTime}\n" + gson.toJson(newPolicyContainer));
+ }
+ isChanged = false;
+ }
+ } else if (response.getStatus() == 304) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 304 ");
+ }
+ isChanged = false; // No Change has been there since our
+ // earlier request
+ } else {
+ LOG.error("Unable to get a valid response for isFileChanged() call for [" + url + "] = response code found [" + response.getStatus() + "]");
+ }
+ }
+
+ } else {
+ LOG.error("Unable to get a valid response for isFileChanged() call for [" + url + "] - got null response.");
+ // force the policy update to get fresh copy
+ lastModifiedTime = 0;
+ }
+
+ } finally {
+ if (response != null) {
+ response.close();
+ }
+ if (client != null) {
+ client.destroy();
+ }
+ }
+ } catch (Throwable t) {
+
+ Boolean responsePresent = false;
+ int responseStatus = -1;
+
+ if ( fetchPolicyfromCahce(responsePresent,responseStatus,lastStoredFileName) ) {
+ /* Successfully found the Policy Cache file and loaded */
+ isChanged = true;
+ } else {
+ LOG.error("Unable to complete isFileChanged() call for [" + url + "]", t);
+ // force the policy update to get fresh copy
+ lastModifiedTime = 0;
+ LOG.error("Policy file Cache not found..");
+ throw new RuntimeException("Unable to find Enterprise Policy Storage");
+ }
+
+ } finally {
+ if (isChanged) {
+ LOG.info("URL: [" + url + "], isModified: " + isChanged + ", lastModifiedTime:" + lastModifiedTime);
+ } else if (LOG.isDebugEnabled()) {
+ LOG.debug("URL: [" + url + "], isModified: " + isChanged + ", lastModifiedTime:" + lastModifiedTime);
+ }
+ }
+ return isChanged;
+ }
+
+ public PolicyContainer getPolicyContainer() {
+ return policyContainer;
+ }
+
+ private int getPolicyCount(PolicyContainer aPolicyContainer) {
+ return (aPolicyContainer == null ? 0 : (aPolicyContainer.getAcl() == null ? 0 : aPolicyContainer.getAcl().size()));
+ }
+
+
+ public synchronized Client buildSSLClient() {
+ Client client = null;
+ try {
+
+ ClientConfig config = new DefaultClientConfig();
+
+ if (sslContext == null) {
+
+ KeyManager[] kmList = null;
+ TrustManager[] tmList = null;
+
+ if (keyStoreFile != null && keyStoreFilepwd != null) {
+
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ InputStream in = null ;
+ try {
+ in = getFileInputStream(keyStoreFile) ;
+ if (in == null) {
+ LOG.error("Unable to obtain keystore from file [" + keyStoreFile + "]");
+ return client ;
+ }
+ keyStore.load(in, keyStoreFilepwd.toCharArray());
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(XaSecureConstants.XASECURE_SSL_KEYMANAGER_ALGO_TYPE);
+ keyManagerFactory.init(keyStore, keyStoreFilepwd.toCharArray());
+ kmList = keyManagerFactory.getKeyManagers();
+ }
+ finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+
+ }
+
+ if (trustStoreFile != null && trustStoreFilepwd != null) {
+
+ KeyStore trustStore = KeyStore.getInstance(trustStoreType);
+ InputStream in = null ;
+ try {
+ in = getFileInputStream(trustStoreFile) ;
+ if (in == null) {
+ LOG.error("Unable to obtain keystore from file [" + trustStoreFile + "]");
+ return client ;
+ }
+ trustStore.load(in, trustStoreFilepwd.toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(XaSecureConstants.XASECURE_SSL_TRUSTMANAGER_ALGO_TYPE);
+ trustManagerFactory.init(trustStore);
+ tmList = trustManagerFactory.getTrustManagers();
+ }
+ finally {
+ if (in != null) {
+ in.close() ;
+ }
+ }
+ }
+
+ sslContext = SSLContext.getInstance(XaSecureConstants.XASECURE_SSL_CONTEXT_ALGO_TYPE);
+
+ sslContext.init(kmList, tmList, new SecureRandom());
+
+ hv = new HostnameVerifier() {
+ public boolean verify(String urlHostName, SSLSession session) {
+ return session.getPeerHost().equals(urlHostName);
+ }
+ };
+
+ }
+
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hv, sslContext));
+
+ client = Client.create(config);
+
+ } catch (KeyStoreException e) {
+ LOG.error("Unable to obtain from KeyStore", e);
+ } catch (NoSuchAlgorithmException e) {
+ LOG.error("SSL algorithm is available in the environment", e);
+ } catch (CertificateException e) {
+ LOG.error("Unable to obtain the requested certification ", e);
+ } catch (FileNotFoundException e) {
+ LOG.error("Unable to find the necessary SSL Keystore and TrustStore Files", e);
+ } catch (IOException e) {
+ LOG.error("Unable to read the necessary SSL Keystore and TrustStore Files", e);
+ } catch (KeyManagementException e) {
+ LOG.error("Unable to initials the SSLContext", e);
+ } catch (UnrecoverableKeyException e) {
+ LOG.error("Unable to recover the key from keystore", e);
+ }
+ return client;
+ }
+
+ private InputStream getFileInputStream(String fileName) throws IOException {
+ InputStream in = null ;
+
+ File f = new File(fileName) ;
+
+ if (f.exists()) {
+ in = new FileInputStream(f) ;
+ }
+ else {
+ in = ClassLoader.getSystemResourceAsStream(fileName) ;
+ }
+ return in ;
+ }
+
+ public static String getAgentName(String aUrl) {
+ String hostName = null ;
+ String repoName = null ;
+ try {
+ hostName = InetAddress.getLocalHost().getHostName() ;
+ } catch (UnknownHostException e) {
+ LOG.error("ERROR: Unable to find hostname for the agent ", e);
+ hostName = "unknownHost" ;
+ }
+
+ String[] tokens = aUrl.split("/") ;
+
+ if ( tokens.length > 0 ) {
+ repoName = tokens[tokens.length-1] ;
+ }
+ else {
+ repoName = "unknownRepo" ;
+ }
+
+ String agentName = hostName + "-" + repoName ;
+
+ if (agentName.length() > MAX_AGENT_NAME_LEN ) {
+ agentName = agentName.substring(0,MAX_AGENT_NAME_LEN) ;
+ }
+
+ return agentName ;
+ }
+
+ private boolean fetchPolicyfromCahce( Boolean responsePresent, int responseStatus, String lastStoredFileName){
+
+ boolean cacheFound = false;
+
+ if ( ( responsePresent == false ) || ( responseStatus != 200 && responseStatus != 304) ) {
+
+ /* Policy Manager not available read the policy from the last enforced one */
+
+ if (policyCacheLoadedOnce) {
+ cacheFound = true;
+ return cacheFound;
+ }
+
+ try {
+ /* read the last stored policy file and load the PolicyContainer */
+ LOG.info("Policy Manager not available, using the last stored Policy File" + this.lastStoredFileName );
+ LOG.debug("LastStoredFileName when policymgr was available" + this.lastStoredFileName);
+
+ BufferedReader jsonString = new BufferedReader(new FileReader(this.lastStoredFileName));
+ Gson gson = new GsonBuilder().setPrettyPrinting().addDeserializationExclusionStrategy(policyExclusionStrategy).create();
+ PolicyContainer newPolicyContainer = gson.fromJson(jsonString, PolicyContainer.class);
+ policyContainer = newPolicyContainer;
+ lastModifiedTime = policyContainer.getLastUpdatedTimeInEpoc();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Policy Manager not available.Got response =" + responseStatus +"\n" + gson.toJson(newPolicyContainer));
+ }
+
+ cacheFound = true;
+ policyCacheLoadedOnce = true;
+
+ } catch( FileNotFoundException fe ){
+
+ /* unable to get the last stored policy, raise warning for unavailability of policy cache file and continue...*/
+ if ( this.lastStoredFileName == null ) {
+ LOG.info("Policy cache file not found...XAagent authorization not enabled");
+ }
+ else {
+ LOG.info("Unable to access Policy cache file...XAagent authorization not enabled");
+ }
+ }
+
+ }
+
+ return cacheFound;
+ }
+
+ private char[] getCredential(String url, String alias) {
+ char[] credStr=xasecurecp.getCredentialString(url,alias);
+ return credStr;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2ConfigWatcher.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2ConfigWatcher.java b/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2ConfigWatcher.java
new file mode 100644
index 0000000..7ef504a
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2ConfigWatcher.java
@@ -0,0 +1,554 @@
+/**
+ * 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 com.xasecure.pdp.config;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.glassfish.jersey.client.ClientConfig;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+import com.xasecure.authorization.hadoop.utils.XaSecureCredentialProvider;
+import com.xasecure.pdp.config.gson.PolicyExclusionStrategy;
+import com.xasecure.pdp.constants.XaSecureConstants;
+import com.xasecure.pdp.model.PolicyContainer;
+
+public abstract class Jersey2ConfigWatcher extends Thread {
+
+ private static final Log LOG = LogFactory.getLog(Jersey2ConfigWatcher.class);
+
+ public static final String EXPECTED_MIME_TYPE = "application/json" ;
+
+ // public static final String EXPECTED_MIME_TYPE = "application/octet-stream";
+
+ private static final String LASTUPDATED_PARAM = "epoch";
+ private static final String POLICY_COUNT_PARAM = "policyCount";
+ private static final String AGENT_NAME_PARAM = "agentId" ;
+
+ private static final int MAX_AGENT_NAME_LEN = 255 ;
+
+
+ private String url;
+
+ private long intervalInMilliSeconds;
+
+ private long lastModifiedTime = 0;
+
+ private boolean shutdownFlag = false;
+
+ private String lastStoredFileName = null;
+
+ protected PolicyContainer policyContainer = null;
+
+ private static PolicyExclusionStrategy policyExclusionStrategy = new PolicyExclusionStrategy();
+
+ private static XaSecureCredentialProvider xasecurecp = null;
+
+ public abstract void doOnChange();
+
+ private String keyStoreFile = null ;
+ private String keyStoreFilepwd = null;
+ private String keyStoreURL = null;
+ private String keyStoreAlias = null;
+ private String trustStoreFile = null ;
+ private String trustStoreFilepwd = null ;
+ private String trustStoreURL = null;
+ private String trustStoreAlias = null;
+ private String keyStoreType = null ;
+ private String trustStoreType = null ;
+ private SSLContext sslContext = null ;
+ private HostnameVerifier hv = null ;
+ private String agentName = "unknown" ;
+
+ private String sslConfigFileName = null ;
+
+ boolean policyCacheLoadedOnce = false;
+
+ public Jersey2ConfigWatcher(String url, long aIntervalInMilliSeconds,String sslConfigFileName,String lastStoredFileName) {
+ super("XaSecureConfigURLWatcher");
+ setDaemon(true);
+ this.url = url;
+ intervalInMilliSeconds = aIntervalInMilliSeconds;
+ this.sslConfigFileName = sslConfigFileName ;
+ this.agentName = getAgentName(this.url) ;
+ this.lastStoredFileName = lastStoredFileName;
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Creating PolicyRefreshser with url: " + url +
+ ", refreshInterval(milliSeconds): " + aIntervalInMilliSeconds +
+ ", sslConfigFileName: " + sslConfigFileName +
+ ", lastStoredFileName: " + lastStoredFileName);
+ }
+ init();
+ validateAndRun();
+ LOG.debug("Created new ConfigWatcher for URL [" + url + "]");
+ }
+
+
+ public void init() {
+ if (sslConfigFileName != null) {
+ LOG.debug("Loading SSL Configuration from [" + sslConfigFileName + "]");
+ InputStream in = null ;
+ try {
+ Configuration conf = new Configuration() ;
+ in = getFileInputStream(sslConfigFileName) ;
+ if (in != null) {
+ conf.addResource(in);
+ }
+
+ xasecurecp = XaSecureCredentialProvider.getInstance();
+
+ keyStoreFile = conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE);
+
+ keyStoreURL=conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL);
+ keyStoreAlias=XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL_ALIAS;
+
+ char[] v_keyStoreFilePwd = getCredential(keyStoreURL,keyStoreAlias);
+ if ( v_keyStoreFilePwd == null ) {
+ keyStoreFilepwd = null;
+ } else {
+ keyStoreFilepwd = new String(v_keyStoreFilePwd);
+ }
+
+ trustStoreFile = conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE);
+
+ trustStoreURL=conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL);
+ trustStoreAlias=XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL_ALIAS;
+
+ char[] v_TrustStoreFilePwd = getCredential(trustStoreURL,trustStoreAlias);
+ if ( v_TrustStoreFilePwd == null ) {
+ trustStoreFilepwd = null;
+ } else {
+ trustStoreFilepwd = new String(v_TrustStoreFilePwd);
+ }
+
+
+ keyStoreType = conf.get(XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE, XaSecureConstants.XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE_DEFAULT);
+ trustStoreType = conf.get(XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE, XaSecureConstants.XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE_DEFAULT);
+ }
+ catch(IOException ioe) {
+ LOG.error("Unable to load SSL Config FileName: [" + sslConfigFileName + "]", ioe);
+ }
+ finally {
+ if (in != null) {
+ try {
+ in.close() ;
+ } catch (IOException e) {
+ LOG.error("Unable to close SSL Config FileName: [" + sslConfigFileName + "]", e) ;
+ }
+ }
+ }
+
+ LOG.debug("Keystore filename:[" + keyStoreFile + "]");
+ LOG.debug("TrustStore filename:[" + trustStoreFile + "]");
+
+ }
+ }
+
+ public String getURL() {
+ return url;
+ }
+
+ public long getIntervalInMilliSeconds() {
+ return intervalInMilliSeconds;
+ }
+
+ public long getLastModifiedTime() {
+ return lastModifiedTime;
+ }
+
+ public void run() {
+ while (!shutdownFlag) {
+ validateAndRun();
+ try {
+ Thread.sleep(intervalInMilliSeconds);
+ } catch (InterruptedException e) {
+ LOG.error("Unable to complete sleep for [" + intervalInMilliSeconds + "]", e);
+ }
+ }
+ }
+
+ private void validateAndRun() {
+ if (isFileChanged()) {
+ LOG.debug("Policy has been changed from " + url + " ... RELOADING");
+ try {
+ doOnChange();
+ } catch (Exception e) {
+ LOG.error("Unable to complete doOnChange() method on file change [" + url + "]", e);
+ }
+ } else {
+ LOG.debug("No Change found in the policy from " + url);
+ }
+ }
+
+ private boolean isFileChanged() {
+ boolean isChanged = false;
+
+
+ try {
+
+ Client client = null;
+ Response response = null;
+
+ try {
+
+ int policyCount = getPolicyCount(policyContainer);
+
+ if (url.contains("https")) {
+ // build SSL Client
+ client = buildSSLClient();
+ }
+
+ if (client == null) {
+ client = ClientBuilder.newClient();
+ }
+
+ WebTarget webTarget = client.target(url)
+ .queryParam(LASTUPDATED_PARAM, String.valueOf(lastModifiedTime))
+ .queryParam(POLICY_COUNT_PARAM, String.valueOf(policyCount))
+ .queryParam(AGENT_NAME_PARAM, agentName);
+
+ response = webTarget.request().accept(EXPECTED_MIME_TYPE).get();
+
+
+ if (response != null) {
+
+ Boolean responsePresent = true;
+ int responseStatus = response.getStatus();
+
+ if ( fetchPolicyfromCahce(responsePresent,responseStatus,lastStoredFileName) ) {
+ /* If the response is other than 200 and 304 load the policy from the cache */
+ isChanged = true;
+
+ } else {
+ /*
+ * If Policy Manager is available fetch the policy from
+ * it
+ */
+ if (response.getStatus() == 200) {
+
+ String entityString = response
+ .readEntity(String.class);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("JSON response from server: "
+ + entityString);
+ }
+
+ Gson gson = new GsonBuilder()
+ .setPrettyPrinting()
+ .addDeserializationExclusionStrategy(
+ policyExclusionStrategy).create();
+ PolicyContainer newPolicyContainer = gson.fromJson(
+ entityString, PolicyContainer.class);
+ if ((newPolicyContainer.getLastUpdatedTimeInEpoc() > lastModifiedTime)
+ || (getPolicyCount(newPolicyContainer) != policyCount)) {
+ policyContainer = newPolicyContainer;
+ lastModifiedTime = policyContainer
+ .getLastUpdatedTimeInEpoc();
+ isChanged = true;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 200 with {change in lastupdatedTime}\n"
+ + gson.toJson(newPolicyContainer));
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 200 with {no-change in lastupdatedTime}\n"
+ + gson.toJson(newPolicyContainer));
+ }
+ isChanged = false;
+ }
+ } else if (response.getStatus() == 304) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Got response: 304 ");
+ }
+ isChanged = false; // No Change has been there since
+ // our
+ // earlier request
+ } else {
+ LOG.error("Unable to get a valid response for isFileChanged() call for ["
+ + url
+ + "] = response code found ["
+ + response.getStatus() + "]");
+ }
+ }
+
+ } else {
+ LOG.error("Unable to get a valid response for isFileChanged() call for [" + url + "] - got null response.");
+ // force the policy update to get fresh copy
+ lastModifiedTime = 0;
+ }
+
+ } finally {
+ if (response != null) {
+ response.close();
+ }
+ if (client != null) {
+ client.close();
+ }
+ }
+ } catch (Throwable t) {
+
+ Boolean responsePresent = false;
+ int responseStatus = -1;
+
+ if ( fetchPolicyfromCahce(responsePresent,responseStatus,lastStoredFileName) ) {
+ /* Successfully found the Policy Cache file and loaded */
+ isChanged = true;
+ } else {
+ LOG.error("Unable to complete isFileChanged() call for [" + url + "]", t);
+ // force the policy update to get fresh copy
+ lastModifiedTime = 0;
+ LOG.error("Policy file Cache not found..");
+ throw new RuntimeException("Unable to find Enterprise Policy Storage");
+ }
+
+ } finally {
+ if (isChanged) {
+ LOG.info("URL: [" + url + "], isModified: " + isChanged + ", lastModifiedTime:" + lastModifiedTime);
+ } else if (LOG.isDebugEnabled()) {
+ LOG.debug("URL: [" + url + "], isModified: " + isChanged + ", lastModifiedTime:" + lastModifiedTime);
+ }
+ }
+ return isChanged;
+ }
+
+ public PolicyContainer getPolicyContainer() {
+ return policyContainer;
+ }
+
+ private int getPolicyCount(PolicyContainer aPolicyContainer) {
+ return (aPolicyContainer == null ? 0 : (aPolicyContainer.getAcl() == null ? 0 : aPolicyContainer.getAcl().size()));
+ }
+
+
+ public synchronized Client buildSSLClient() {
+ Client client = null;
+ try {
+
+ ClientConfig config = new ClientConfig();
+
+ if (sslContext == null) {
+
+ KeyManager[] kmList = null;
+ TrustManager[] tmList = null;
+
+ if (keyStoreFile != null && keyStoreFilepwd != null) {
+
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ InputStream in = null ;
+ try {
+ in = getFileInputStream(keyStoreFile) ;
+ if (in == null) {
+ LOG.error("Unable to obtain keystore from file [" + keyStoreFile + "]");
+ return client ;
+ }
+ keyStore.load(in, keyStoreFilepwd.toCharArray());
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(XaSecureConstants.XASECURE_SSL_KEYMANAGER_ALGO_TYPE);
+ keyManagerFactory.init(keyStore, keyStoreFilepwd.toCharArray());
+ kmList = keyManagerFactory.getKeyManagers();
+ }
+ finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+
+ }
+
+ if (trustStoreFile != null && trustStoreFilepwd != null) {
+
+ KeyStore trustStore = KeyStore.getInstance(trustStoreType);
+ InputStream in = null ;
+ try {
+ in = getFileInputStream(trustStoreFile) ;
+ if (in == null) {
+ LOG.error("Unable to obtain keystore from file [" + trustStoreFile + "]");
+ return client ;
+ }
+ trustStore.load(in, trustStoreFilepwd.toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(XaSecureConstants.XASECURE_SSL_TRUSTMANAGER_ALGO_TYPE);
+ trustManagerFactory.init(trustStore);
+ tmList = trustManagerFactory.getTrustManagers();
+ }
+ finally {
+ if (in != null) {
+ in.close() ;
+ }
+ }
+ }
+
+ sslContext = SSLContext.getInstance(XaSecureConstants.XASECURE_SSL_CONTEXT_ALGO_TYPE);
+
+ sslContext.init(kmList, tmList, new SecureRandom());
+
+ hv = new HostnameVerifier() {
+ public boolean verify(String urlHostName, SSLSession session) {
+ return session.getPeerHost().equals(urlHostName);
+ }
+ };
+
+ }
+
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hv, sslContext));
+
+ client = ClientBuilder.newClient(config);
+
+ } catch (KeyStoreException e) {
+ LOG.error("Unable to obtain from KeyStore", e);
+ } catch (NoSuchAlgorithmException e) {
+ LOG.error("SSL algorithm is available in the environment", e);
+ } catch (CertificateException e) {
+ LOG.error("Unable to obtain the requested certification ", e);
+ } catch (FileNotFoundException e) {
+ LOG.error("Unable to find the necessary SSL Keystore and TrustStore Files", e);
+ } catch (IOException e) {
+ LOG.error("Unable to read the necessary SSL Keystore and TrustStore Files", e);
+ } catch (KeyManagementException e) {
+ LOG.error("Unable to initials the SSLContext", e);
+ } catch (UnrecoverableKeyException e) {
+ LOG.error("Unable to recover the key from keystore", e);
+ }
+ return client;
+ }
+
+ private InputStream getFileInputStream(String fileName) throws IOException {
+ InputStream in = null ;
+
+ File f = new File(fileName) ;
+
+ if (f.exists()) {
+ in = new FileInputStream(f) ;
+ }
+ else {
+ in = ClassLoader.getSystemResourceAsStream(fileName) ;
+ }
+ return in ;
+ }
+
+ public static String getAgentName(String aUrl) {
+ String hostName = null ;
+ String repoName = null ;
+ try {
+ hostName = InetAddress.getLocalHost().getHostName() ;
+ } catch (UnknownHostException e) {
+ LOG.error("ERROR: Unable to find hostname for the agent ", e);
+ hostName = "unknownHost" ;
+ }
+
+ String[] tokens = aUrl.split("/") ;
+
+ if ( tokens.length > 0 ) {
+ repoName = tokens[tokens.length-1] ;
+ }
+ else {
+ repoName = "unknownRepo" ;
+ }
+
+ String agentName = hostName + "-" + repoName ;
+
+ if (agentName.length() > MAX_AGENT_NAME_LEN ) {
+ agentName = agentName.substring(0,MAX_AGENT_NAME_LEN) ;
+ }
+
+ return agentName ;
+ }
+
+ private boolean fetchPolicyfromCahce( Boolean responsePresent, int responseStatus, String lastStoredFileName){
+
+ boolean cacheFound = false;
+
+ if ( ( responsePresent == false ) || ( responseStatus != 200 && responseStatus != 304) ) {
+
+ /* Policy Manager not available read the policy from the last enforced one */
+
+ if (policyCacheLoadedOnce) {
+ cacheFound = true;
+ return cacheFound;
+ }
+
+ try {
+ /* read the last stored policy file and load the PolicyContainer */
+ LOG.info("Policy Manager not available, using the last stored Policy File" + this.lastStoredFileName );
+ LOG.debug("LastStoredFileName when policymgr was available" + this.lastStoredFileName);
+
+ BufferedReader jsonString = new BufferedReader(new FileReader(this.lastStoredFileName));
+ Gson gson = new GsonBuilder().setPrettyPrinting().addDeserializationExclusionStrategy(policyExclusionStrategy).create();
+ PolicyContainer newPolicyContainer = gson.fromJson(jsonString, PolicyContainer.class);
+ policyContainer = newPolicyContainer;
+ lastModifiedTime = policyContainer.getLastUpdatedTimeInEpoc();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Policy Manager not available.Got response =" + responseStatus +"\n" + gson.toJson(newPolicyContainer));
+ }
+
+ cacheFound = true;
+ policyCacheLoadedOnce = true;
+
+ } catch( FileNotFoundException fe ){
+
+ /* unable to get the last stored policy, raise warning for unavailability of policy cache file and continue...*/
+ if ( this.lastStoredFileName == null ) {
+ LOG.info("Policy cache file not found...XAagent authorization not enabled");
+ }
+ else {
+ LOG.info("Unable to access Policy cache file...XAagent authorization not enabled");
+ }
+ }
+
+ }
+
+ return cacheFound;
+ }
+
+ private char[] getCredential(String url, String alias) {
+ char[] credStr=xasecurecp.getCredentialString(url,alias);
+ return credStr;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2PolicyRefresher.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2PolicyRefresher.java b/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2PolicyRefresher.java
new file mode 100644
index 0000000..6521f63
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/Jersey2PolicyRefresher.java
@@ -0,0 +1,206 @@
+/**************************************************************************
+ * *
+ * The information in this document is proprietary to XASecure Inc., *
+ * It may not be used, reproduced or disclosed without the written *
+ * approval from the XASecure Inc., *
+ * *
+ * PRIVILEGED AND CONFIDENTIAL XASECURE PROPRIETARY INFORMATION *
+ * *
+ * Copyright (c) 2013 XASecure, Inc. All rights reserved. *
+ * *
+ *************************************************************************/
+
+ /**
+ *
+ * @version: 1.0.004
+ *
+ */
+
+package com.xasecure.pdp.config;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.xasecure.pdp.config.gson.PolicyExclusionStrategy;
+import com.xasecure.pdp.model.PolicyContainer;
+
+public class Jersey2PolicyRefresher {
+
+ private static final Log LOG = LogFactory.getLog(Jersey2PolicyRefresher.class);
+
+ private String url ;
+ private long refreshInterval ;
+
+ private Jersey2ConfigWatcher watcherDaemon = null;
+
+ protected PolicyContainer policyContainer = null ;
+
+ private PolicyChangeListener policyChangeListener = null ;
+
+ private String saveAsFileName = null ;
+
+ private String sslConfigFileName = null ;
+
+ private String lastStoredFileName = null;
+
+ private PolicyExclusionStrategy policyExclusionStrategy = new PolicyExclusionStrategy() ;
+
+ public Jersey2PolicyRefresher(String url, long refreshInterval, String sslConfigFileName, String lastStoredFileName) {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Creating PolicyRefreshser with url: " + url +
+ ", refreshInterval: " + refreshInterval +
+ ", sslConfigFileName: " + sslConfigFileName +
+ ", lastStoredFileName: " + lastStoredFileName);
+ }
+ this.url = url ;
+ this.refreshInterval = refreshInterval ;
+ this.sslConfigFileName = sslConfigFileName ;
+ this.lastStoredFileName = lastStoredFileName;
+ checkFileWatchDogThread();
+ }
+
+ public PolicyChangeListener getPolicyChangeListener() {
+ return policyChangeListener;
+ }
+
+ public synchronized void setPolicyChangeListener(PolicyChangeListener policyChangeListener) {
+ this.policyChangeListener = policyChangeListener;
+ if (this.policyContainer != null) {
+ savePolicyToFile() ;
+ notifyPolicyChange() ;
+ }
+ }
+
+ private void setPolicyContainer(PolicyContainer aPolicyContainer) {
+ this.policyContainer = aPolicyContainer ;
+ }
+
+ public PolicyContainer getPolicyContainer() {
+ return policyContainer ;
+ }
+
+ public String getSaveAsFileName() {
+ return saveAsFileName;
+ }
+
+ public void setSaveAsFileName(String saveAsFileName) {
+ this.saveAsFileName = saveAsFileName;
+ }
+
+ public String getSslConfigFileName() {
+ return sslConfigFileName;
+ }
+
+ public String getLastStoredFileName() {
+ return lastStoredFileName;
+ }
+
+ public void setLastStoredFileName(String lastStoredFileName) {
+ this.lastStoredFileName = lastStoredFileName;
+ }
+
+ public void setSslConfigFileName(String sslConfigFileName) {
+ this.sslConfigFileName = sslConfigFileName;
+ }
+
+
+ private synchronized void checkFileWatchDogThread() {
+ if (watcherDaemon == null) {
+ try {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Starting WatchDog for the Path [" + url + "] ....");
+ }
+ watcherDaemon = new Jersey2ConfigWatcher(url, refreshInterval,sslConfigFileName,this.getLastStoredFileName()) {
+ public void doOnChange() {
+ PolicyContainer newPolicyContainer = getPolicyContainer() ;
+ setPolicyContainer(newPolicyContainer) ;
+ savePolicyToFile() ;
+ notifyPolicyChange();
+ };
+ };
+ watcherDaemon.start();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Completed kick-off of FileWatchDog for the Path [" + url + "] interval in millisecond:" + refreshInterval);
+ }
+ } catch (Throwable t) {
+ LOG.error("Unable to start the FileWatchDog for path [" + url + "]", t);
+ }
+ }
+ }
+
+ private void notifyPolicyChange() {
+ if (policyChangeListener != null) {
+ try {
+ policyChangeListener.OnPolicyChange(policyContainer);
+ }
+ catch(Throwable t) {
+ LOG.error("Error during notification of policy changes to listener [" + policyChangeListener + "]", t) ;
+ }
+ finally {
+ LOG.debug("Completed notification of policy changes to listener [" + policyChangeListener + "]") ;
+ }
+ }
+ }
+
+
+ private void savePolicyToFile() {
+
+ LOG.debug("savePolicyToFile() is called with [" + saveAsFileName + "] - START") ;
+ String fileName = null;
+ if (saveAsFileName != null) {
+ String currentDateTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) ;
+ fileName = saveAsFileName + "." + currentDateTime ;
+ File saveFile = new File(fileName) ;
+ Gson gson = new GsonBuilder().setPrettyPrinting().setExclusionStrategies(policyExclusionStrategy).create() ;
+ String policyAsJson = gson.toJson(policyContainer) ;
+ PrintWriter writer = null ;
+ try {
+ writer = new PrintWriter(new FileWriter(saveFile)) ;
+ writer.println(policyAsJson) ;
+ }
+ catch(IOException ioe) {
+ LOG.error("Unable to save policy into file: [" + saveFile.getAbsolutePath() + "]", ioe);
+ }
+ finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ if (lastStoredFileName != null) {
+ File lastSaveFileName = new File(lastStoredFileName);
+
+ try {
+ writer = new PrintWriter(new FileWriter(lastSaveFileName));
+ writer.println(policyAsJson);
+
+ }
+ catch(IOException ioe){
+ LOG.error("Unable to save the policy into Last Stored Policy File [" + lastSaveFileName.getAbsolutePath() + "]", ioe );
+ }
+ finally {
+ //make the policy file cache to be 600 permission when it gets created and updated
+ lastSaveFileName.setReadable(false,false);
+ lastSaveFileName.setReadable(true,true);
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ }
+ }
+
+ LOG.debug("savePolicyToFile() is called with [" + fileName + "] - END") ;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyChangeListener.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyChangeListener.java b/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyChangeListener.java
new file mode 100644
index 0000000..3d1df55
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyChangeListener.java
@@ -0,0 +1,7 @@
+package com.xasecure.pdp.config;
+
+import com.xasecure.pdp.model.PolicyContainer;
+
+public interface PolicyChangeListener {
+ public void OnPolicyChange(PolicyContainer aPolicyContainer) ;
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyRefresher.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyRefresher.java b/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyRefresher.java
new file mode 100644
index 0000000..0b1f38e
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/PolicyRefresher.java
@@ -0,0 +1,206 @@
+/**************************************************************************
+ * *
+ * The information in this document is proprietary to XASecure Inc., *
+ * It may not be used, reproduced or disclosed without the written *
+ * approval from the XASecure Inc., *
+ * *
+ * PRIVILEGED AND CONFIDENTIAL XASECURE PROPRIETARY INFORMATION *
+ * *
+ * Copyright (c) 2013 XASecure, Inc. All rights reserved. *
+ * *
+ *************************************************************************/
+
+ /**
+ *
+ * @version: 1.0.004
+ *
+ */
+
+package com.xasecure.pdp.config;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.xasecure.pdp.config.gson.PolicyExclusionStrategy;
+import com.xasecure.pdp.model.PolicyContainer;
+
+public class PolicyRefresher {
+
+ private static final Log LOG = LogFactory.getLog(PolicyRefresher.class);
+
+ private String url ;
+ private long refreshInterval ;
+
+ private ConfigWatcher watcherDaemon = null;
+
+ protected PolicyContainer policyContainer = null ;
+
+ private PolicyChangeListener policyChangeListener = null ;
+
+ private String saveAsFileName = null ;
+
+ private String sslConfigFileName = null ;
+
+ private String lastStoredFileName = null;
+
+ private PolicyExclusionStrategy policyExclusionStrategy = new PolicyExclusionStrategy() ;
+
+ public PolicyRefresher(String url, long refreshInterval, String sslConfigFileName, String lastStoredFileName) {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Creating PolicyRefreshser with url: " + url +
+ ", refreshInterval: " + refreshInterval +
+ ", sslConfigFileName: " + sslConfigFileName +
+ ", lastStoredFileName: " + lastStoredFileName);
+ }
+ this.url = url ;
+ this.refreshInterval = refreshInterval ;
+ this.sslConfigFileName = sslConfigFileName ;
+ this.lastStoredFileName = lastStoredFileName;
+ checkFileWatchDogThread();
+ }
+
+ public PolicyChangeListener getPolicyChangeListener() {
+ return policyChangeListener;
+ }
+
+ public synchronized void setPolicyChangeListener(PolicyChangeListener policyChangeListener) {
+ this.policyChangeListener = policyChangeListener;
+ if (this.policyContainer != null) {
+ savePolicyToFile() ;
+ notifyPolicyChange() ;
+ }
+ }
+
+ private void setPolicyContainer(PolicyContainer aPolicyContainer) {
+ this.policyContainer = aPolicyContainer ;
+ }
+
+ public PolicyContainer getPolicyContainer() {
+ return policyContainer ;
+ }
+
+ public String getSaveAsFileName() {
+ return saveAsFileName;
+ }
+
+ public void setSaveAsFileName(String saveAsFileName) {
+ this.saveAsFileName = saveAsFileName;
+ }
+
+ public String getSslConfigFileName() {
+ return sslConfigFileName;
+ }
+
+ public String getLastStoredFileName() {
+ return lastStoredFileName;
+ }
+
+ public void setLastStoredFileName(String lastStoredFileName) {
+ this.lastStoredFileName = lastStoredFileName;
+ }
+
+ public void setSslConfigFileName(String sslConfigFileName) {
+ this.sslConfigFileName = sslConfigFileName;
+ }
+
+
+ private synchronized void checkFileWatchDogThread() {
+ if (watcherDaemon == null) {
+ try {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Starting WatchDog for the Path [" + url + "] ....");
+ }
+ watcherDaemon = new ConfigWatcher(url, refreshInterval,sslConfigFileName,this.getLastStoredFileName()) {
+ public void doOnChange() {
+ PolicyContainer newPolicyContainer = getPolicyContainer() ;
+ setPolicyContainer(newPolicyContainer) ;
+ savePolicyToFile() ;
+ notifyPolicyChange();
+ };
+ };
+ watcherDaemon.start();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Completed kick-off of FileWatchDog for the Path [" + url + "] interval in millisecond:" + refreshInterval);
+ }
+ } catch (Throwable t) {
+ LOG.error("Unable to start the FileWatchDog for path [" + url + "]", t);
+ }
+ }
+ }
+
+ private void notifyPolicyChange() {
+ if (policyChangeListener != null) {
+ try {
+ policyChangeListener.OnPolicyChange(policyContainer);
+ }
+ catch(Throwable t) {
+ LOG.error("Error during notification of policy changes to listener [" + policyChangeListener + "]", t) ;
+ }
+ finally {
+ LOG.debug("Completed notification of policy changes to listener [" + policyChangeListener + "]") ;
+ }
+ }
+ }
+
+
+ private void savePolicyToFile() {
+
+ LOG.debug("savePolicyToFile() is called with [" + saveAsFileName + "] - START") ;
+ String fileName = null;
+ if (saveAsFileName != null) {
+ String currentDateTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) ;
+ fileName = saveAsFileName + "." + currentDateTime ;
+ File saveFile = new File(fileName) ;
+ Gson gson = new GsonBuilder().setPrettyPrinting().setExclusionStrategies(policyExclusionStrategy).create() ;
+ String policyAsJson = gson.toJson(policyContainer) ;
+ PrintWriter writer = null ;
+ try {
+ writer = new PrintWriter(new FileWriter(saveFile)) ;
+ writer.println(policyAsJson) ;
+ }
+ catch(IOException ioe) {
+ LOG.error("Unable to save policy into file: [" + saveFile.getAbsolutePath() + "]", ioe);
+ }
+ finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ if (lastStoredFileName != null) {
+ File lastSaveFileName = new File(lastStoredFileName);
+
+ try {
+ writer = new PrintWriter(new FileWriter(lastSaveFileName));
+ writer.println(policyAsJson);
+
+ }
+ catch(IOException ioe){
+ LOG.error("Unable to save the policy into Last Stored Policy File [" + lastSaveFileName.getAbsolutePath() + "]", ioe );
+ }
+ finally {
+ //make the policy file cache to be 600 permission when it gets created and updated
+ lastSaveFileName.setReadable(false,false);
+ lastSaveFileName.setReadable(true,true);
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ }
+ }
+
+ LOG.debug("savePolicyToFile() is called with [" + fileName + "] - END") ;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/gson/ExcludeSerialization.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/gson/ExcludeSerialization.java b/agents-impl/src/main/java/com/xasecure/pdp/config/gson/ExcludeSerialization.java
new file mode 100644
index 0000000..0bb91fc
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/gson/ExcludeSerialization.java
@@ -0,0 +1,13 @@
+package com.xasecure.pdp.config.gson;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+
+public @interface ExcludeSerialization {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/config/gson/PolicyExclusionStrategy.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/config/gson/PolicyExclusionStrategy.java b/agents-impl/src/main/java/com/xasecure/pdp/config/gson/PolicyExclusionStrategy.java
new file mode 100644
index 0000000..82eee9e
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/config/gson/PolicyExclusionStrategy.java
@@ -0,0 +1,18 @@
+package com.xasecure.pdp.config.gson;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+
+public class PolicyExclusionStrategy implements ExclusionStrategy {
+
+ @Override
+ public boolean shouldSkipClass(Class<?> objectClass) {
+ return (objectClass.getAnnotation(ExcludeSerialization.class) != null) ;
+ }
+
+ @Override
+ public boolean shouldSkipField(FieldAttributes aFieldAttributes) {
+ return (aFieldAttributes.getAnnotation(ExcludeSerialization.class) != null) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/constants/XaSecureConstants.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/constants/XaSecureConstants.java b/agents-impl/src/main/java/com/xasecure/pdp/constants/XaSecureConstants.java
new file mode 100644
index 0000000..b652c83
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/constants/XaSecureConstants.java
@@ -0,0 +1,60 @@
+package com.xasecure.pdp.constants;
+
+public class XaSecureConstants {
+ public static final String PUBLIC_ACCESS_ROLE = "public" ;
+
+ public static final String XASECURE_HBASE_POLICYMGR_URL_PROP = "xasecure.hbase.policymgr.url";
+ public static final String XASECURE_HBASE_POLICYMGR_URL_SAVE_FILE_PROP = "xasecure.hbase.policymgr.url.saveAsFile";
+ public static final String XASECURE_HBASE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP = "xasecure.hbase.policymgr.url.reloadIntervalInMillis";
+ public static final String XASECURE_HBASE_POLICYMGR_SSL_CONFIG_FILE_PROP = "xasecure.hbase.policymgr.ssl.config";
+ public static final long XASECURE_HBASE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT = 60000L ;
+ public static final String XASECURE_HBASE_LAST_SAVED_POLICY_FILE_PROP = "xasecure.hbase.policymgr.url.laststoredfile";
+
+ public static final String XASECURE_HDFS_POLICYMGR_URL_PROP = "xasecure.hdfs.policymgr.url";
+ public static final String XASECURE_HDFS_POLICYMGR_URL_SAVE_FILE_PROP = "xasecure.hdfs.policymgr.url.saveAsFile";
+ public static final String XASECURE_HDFS_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP = "xasecure.hdfs.policymgr.url.reloadIntervalInMillis";
+ public static final String XASECURE_HDFS_POLICYMGR_SSL_CONFIG_FILE_PROP = "xasecure.hdfs.policymgr.ssl.config";
+ public static final long XASECURE_HDFS_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT = 60000L ;
+ public static final String XASECURE_HDFS_LAST_SAVED_POLICY_FILE_PROP = "xasecure.hdfs.policymgr.url.laststoredfile";
+
+
+ public static final String XASECURE_KNOX_POLICYMGR_URL_PROP = "xasecure.knox.policymgr.url";
+ public static final String XASECURE_KNOX_POLICYMGR_URL_SAVE_FILE_PROP = "xasecure.knox.policymgr.url.saveAsFile";
+ public static final String XASECURE_KNOX_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP = "xasecure.knox.policymgr.url.reloadIntervalInMillis";
+ public static final String XASECURE_KNOX_POLICYMGR_SSL_CONFIG_FILE_PROP = "xasecure.knox.policymgr.ssl.config";
+ public static final long XASECURE_KNOX_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT = 60000L ;
+ public static final String XASECURE_KNOX_LAST_SAVED_POLICY_FILE_PROP = "xasecure.knox.policymgr.url.laststoredfile";
+
+
+ public static final String XASECURE_HIVE_POLICYMGR_URL_PROP = "xasecure.hive.policymgr.url";
+ public static final String XASECURE_HIVE_POLICYMGR_URL_SAVE_FILE_PROP = "xasecure.hive.policymgr.url.saveAsFile";
+ public static final String XASECURE_HIVE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP = "xasecure.hive.policymgr.url.reloadIntervalInMillis";
+ public static final String XASECURE_HIVE_POLICYMGR_SSL_CONFIG_FILE_PROP = "xasecure.hive.policymgr.ssl.config";
+ public static final long XASECURE_HIVE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT = 60000L ;
+ public static final String XASECURE_HIVE_LAST_SAVED_POLICY_FILE_PROP = "xasecure.hive.policymgr.url.laststoredfile";
+
+
+ // xasecure 2-way ssl configuration
+
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE = "xasecure.policymgr.clientssl.keystore";
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE_PASSWORD = "xasecure.policymgr.clientssl.keystore.password";
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE = "xasecure.policymgr.clientssl.keystore.type";
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL = "xasecure.policymgr.clientssl.keystore.credential.file";
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE_CREDENTIAL_ALIAS = "sslKeyStore";
+
+ public static final String XASECURE_POLICYMGR_CLIENT_KEY_FILE_TYPE_DEFAULT = "jks";
+
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE = "xasecure.policymgr.clientssl.truststore";
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE_PASSWORD = "xasecure.policymgr.clientssl.truststore.password";
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE = "xasecure.policymgr.clientssl.truststore.type";
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL = "xasecure.policymgr.clientssl.truststore.credential.file";
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL_ALIAS = "sslTrustStore";
+
+ public static final String XASECURE_POLICYMGR_TRUSTSTORE_FILE_TYPE_DEFAULT = "jks";
+
+
+ public static final String XASECURE_SSL_KEYMANAGER_ALGO_TYPE = "SunX509" ;
+ public static final String XASECURE_SSL_TRUSTMANAGER_ALGO_TYPE = "SunX509" ;
+ public static final String XASECURE_SSL_CONTEXT_ALGO_TYPE = "SSL" ;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthDB.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthDB.java b/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthDB.java
new file mode 100644
index 0000000..e859796
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthDB.java
@@ -0,0 +1,488 @@
+/**************************************************************************
+ * *
+ * The information in this document is proprietary to XASecure Inc., *
+ * It may not be used, reproduced or disclosed without the written *
+ * approval from the XASecure Inc., *
+ * *
+ * PRIVILEGED AND CONFIDENTIAL XASECURE PROPRIETARY INFORMATION *
+ * *
+ * Copyright (c) 2013 XASecure, Inc. All rights reserved. *
+ * *
+ *************************************************************************/
+
+ /**
+ *
+ * @version: 1.0.004
+ *
+ */
+
+package com.xasecure.pdp.hbase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.security.access.UserPermission;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.util.StringUtils;
+
+import com.xasecure.authorization.hbase.HBaseAccessController;
+import com.xasecure.pdp.constants.XaSecureConstants;
+
+public class HBaseAuthDB implements HBaseAccessController {
+
+ private static final long MAX_CACHE_AUDIT_ENTRIES = 1000L ;
+ private static final long MAX_CACHE_ENCRYPT_ENTRIES = 1000L ;
+
+ private static final Log LOG = LogFactory.getLog(HBaseAuthDB.class) ;
+
+ private ArrayList<HBaseAuthRules> ruleList = null;
+ private ArrayList<HBaseAuthRules> globalList = null;
+ private ArrayList<HBaseAuthRules> tableList = null;
+
+ private ArrayList<String> auditList = null ;
+ private HashMap<byte[],Boolean> cachedAuditTable = new HashMap<byte[],Boolean>() ;
+
+ private ArrayList<String> encryptList = null ;
+
+ private HashSet<String> encryptTableList = null ;
+ private HashMap<byte[],Boolean> cachedEncryptedTable = new HashMap<byte[],Boolean>() ;
+
+
+ public HBaseAuthDB(ArrayList<HBaseAuthRules> ruleList, ArrayList<String> auditList, ArrayList<String> encryptList) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("+Creating HBaseAuthDB is creating with ruleList [" + (ruleList == null ? 0 : ruleList.size()) + "]" );
+ }
+
+ this.auditList = auditList;
+ this.encryptList = encryptList;
+
+
+ this.ruleList = new ArrayList<HBaseAuthRules>() ;
+ this.globalList = new ArrayList<HBaseAuthRules>() ;
+ this.tableList = new ArrayList<HBaseAuthRules>() ;
+
+ for(HBaseAuthRules rule : ruleList ) {
+ if (rule.isGlobalRule()) {
+ this.globalList.add(rule) ;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RULE:[" + rule + "] is being added as GLOBAL Policy");
+ }
+ }
+ else if (rule.isTableRule()) {
+ this.tableList.add(rule) ;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RULE:[" + rule + "] is being added as Table Policy");
+ }
+ }
+ else {
+ this.ruleList.add(rule) ;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RULE:[" + rule + "] is being added as non-global, non-table Policy");
+ }
+ }
+ }
+
+ this.encryptTableList = new HashSet<String>() ;
+
+ if (encryptList != null && encryptList.size() > 0) {
+ for(String encryptKey : encryptList) {
+ String[] objKeys = encryptKey.split("/") ;
+ String tableName = objKeys[0] ;
+ if (! encryptTableList.contains(tableName)) {
+ encryptTableList.add(tableName) ;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("EncryptionList:[" + tableName + "] is being added encrypted table.");
+ }
+ }
+ }
+ }
+
+
+ }
+
+
+ public boolean isAccessAllowed(User user, Action accessAction) {
+
+
+ String access = accessAction.toString().toLowerCase() ;
+
+ if (user == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(GLOBAL," + access + ") => [FALSE] as user passed for check was null.");
+ }
+ return false ;
+ }
+
+
+ String username = user.getShortName() ;
+
+ String[] groups = user.getGroupNames() ;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Init of Global access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "]");
+ }
+
+ for (HBaseAuthRules rule : globalList) {
+
+ if (rule.getAccessType().equals(access)) {
+
+ String authorizedUser = rule.getUser() ;
+ String authorizedGroup = rule.getGroup();
+
+ if (authorizedGroup != null) {
+ if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true ;
+ }
+
+ for (String group : groups) {
+ if (group.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+
+ if (authorizedUser != null) {
+ if (username.equals(authorizedUser)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(GLOBAL," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
+ }
+
+ return false;
+ }
+
+ public boolean isAccessAllowed(User user, byte[] tableName, Action accessAction) {
+
+
+ if ( isAccessAllowed(user,accessAction)) { // Check Global Action
+ return true ;
+ }
+
+ String tableNameStr = Bytes.toString(tableName) ;
+
+ String access = accessAction.toString().toLowerCase() ;
+
+ if (user == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + tableNameStr + "," + access + ") => [FALSE] as user passed for check was null.");
+ }
+ return false ;
+ }
+
+ String username = user.getShortName() ;
+
+ String[] groups = user.getGroupNames() ;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Init of Table access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "], tableName: [" + tableNameStr + "]");
+ }
+
+ for (HBaseAuthRules rule : tableList) {
+
+ if (rule.isTableNameMatched(tableNameStr)) {
+ if (rule.getAccessType().equals(access)) {
+
+ String authorizedUser = rule.getUser() ;
+
+ String authorizedGroup = rule.getGroup();
+
+ if (authorizedGroup != null) {
+ if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true ;
+ }
+
+ for (String group : groups) {
+ if (group.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+ if (authorizedUser != null && username.equals(authorizedUser)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + tableNameStr + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
+ }
+
+ return false;
+ }
+
+
+
+
+
+
+ public boolean isAccessAllowed(User user, byte[] tableName, byte[] columnFamily, byte[] qualifier, Action accessAction) {
+
+ String FQColName = getFullyQualifiedColumnName(tableName, columnFamily, qualifier) ;
+
+ String access = accessAction.toString().toLowerCase() ;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("isAccessAllowed on HBaseAuthDB: for FQColName [" + FQColName + "]");
+ }
+
+
+ if (user == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + FQColName + "," + access + ") => [FALSE] as as user passed for check was null.");
+ }
+ return false ;
+ }
+
+
+ if (isAccessAllowed(user, accessAction)) { // Check Global Action
+ return true ;
+ }
+
+ if (isAccessAllowed(user,tableName, accessAction)) { // Check Table Action
+ return true;
+ }
+
+
+ String username = user.getShortName() ;
+
+ String[] groups = user.getGroupNames() ;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Init of Table access Verification - [" + access + "] for user [" + username + "], groups: [" + Arrays.toString(groups) + "], FQColumnFamily: [" + FQColName + "]");
+ }
+
+ for (HBaseAuthRules rule : ruleList) {
+
+ if (rule.isMatched(FQColName)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Rule [" + rule + "] matched [" + FQColName + "]");
+ }
+ if (rule.getAccessType().equals(access)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Access [" + rule.getAccessType() + "] matched [" + access + "]");
+ }
+ String authorizedUser = rule.getUser() ;
+
+ String authorizedGroup = rule.getGroup();
+
+ if (authorizedGroup != null) {
+ if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true ;
+ }
+ for (String group : groups) {
+ if (group.equals(authorizedGroup)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+
+ if (authorizedUser != null) {
+ if (username.equals(authorizedUser)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [TRUE] as matched for rule: " + rule);
+ }
+ return true;
+ }
+ }
+ }
+ else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Access [" + rule.getAccessType() + "] DID NOT match [" + access + "]");
+ }
+ }
+ }
+ else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Rule [" + rule + "] not matched [" + FQColName + "]");
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("rulecheck(" + FQColName + "," + access + "," + username + "," + StringUtils.arrayToString(groups) + ") => [FALSE] as it did not match any rules.");
+ }
+
+ return false;
+
+ }
+
+ public boolean isEncrypted(byte[] tableName, byte[] columnFamily, byte[] qualifier) {
+ String colName = getFullyQualifiedColumnName(tableName, columnFamily, qualifier) ;
+ for(String encryptable : encryptList) {
+ if (FilenameUtils.wildcardMatch(colName,encryptable)) {
+ return true ;
+ }
+ }
+ return false;
+ }
+
+ public boolean isAudited(byte[] tableName) {
+ Boolean ret = cachedAuditTable.get(tableName) ;
+ if (ret == null) {
+ ret = isAuditedFromTableList(tableName) ;
+ synchronized(cachedAuditTable) {
+ if (cachedAuditTable.size() > MAX_CACHE_AUDIT_ENTRIES) {
+ cachedAuditTable.clear();
+ }
+ cachedAuditTable.put(tableName,ret) ;
+ }
+ }
+ return ret.booleanValue();
+ }
+
+ private boolean isAuditedFromTableList(byte[] tableName) {
+ boolean ret = false ;
+ String tableNameStr = Bytes.toString(tableName) ;
+ for(String auditable : auditList) {
+ if (FilenameUtils.wildcardMatch(tableNameStr,auditable)) {
+ ret = true ;
+ break ;
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("isAudited(" + tableNameStr + "):" + ret) ;
+ }
+
+ return ret;
+ }
+
+
+ public boolean isTableHasEncryptedColumn(byte[] tableName) {
+ Boolean ret = cachedEncryptedTable.get(tableName) ;
+ if (ret == null) {
+ ret = isTableHasEncryptedColumnFromTableList(tableName) ;
+ synchronized(cachedEncryptedTable) {
+ if (cachedEncryptedTable.size() > MAX_CACHE_ENCRYPT_ENTRIES) {
+ cachedEncryptedTable.clear();
+ }
+ cachedEncryptedTable.put(tableName, ret) ;
+ }
+ }
+ return ret.booleanValue() ;
+ }
+
+
+ private boolean isTableHasEncryptedColumnFromTableList(byte[] tableName)
+ {
+ boolean ret = false ;
+
+ String tableNameStr = Bytes.toString(tableName) ;
+
+ for(String encryptTable : encryptTableList) {
+ ret = FilenameUtils.wildcardMatch(tableNameStr, encryptTable) ;
+ if (ret) {
+ break ;
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("isTableHasEncryptedColumn(" + tableNameStr + "):" + ret);
+ }
+
+ return ret ;
+ }
+
+
+
+ public static String getFullyQualifiedColumnName(byte[] tableName, byte[] columnFamily, byte[] qualifier) {
+ StringBuilder sb = new StringBuilder() ;
+
+ sb.append(((tableName != null && tableName.length > 0) ? Bytes.toString(tableName) : "*"))
+ .append("/")
+ .append(((columnFamily != null && columnFamily.length > 0) ? Bytes.toString(columnFamily) : "*"))
+ .append("/")
+ .append(((qualifier != null && qualifier.length > 0) ? Bytes.toString(qualifier) : "*")) ;
+
+ return sb.toString() ;
+ }
+
+ public List<UserPermission> getUserPermissions(User user) {
+ List<UserPermission> ret = new ArrayList<UserPermission>() ;
+
+ if (user != null) {
+ ArrayList<ArrayList<HBaseAuthRules>> allList = new ArrayList<ArrayList<HBaseAuthRules>>();
+ allList.add(globalList) ;
+ allList.add(tableList) ;
+ allList.add(ruleList) ;
+ for(ArrayList<HBaseAuthRules> rList : allList) {
+ for(HBaseAuthRules rule : rList) {
+ UserPermission perm = rule.getUserPermission(user) ;
+ if (perm != null) {
+ ret.add(perm) ;
+ }
+ }
+ }
+ }
+
+ return ret ;
+ }
+
+ public List<UserPermission> getUserPermissions(User user, byte[] tableName) {
+
+ String tableNameStr = Bytes.toString(tableName) ;
+
+ List<UserPermission> ret = new ArrayList<UserPermission>() ;
+
+ if (user != null) {
+ ArrayList<ArrayList<HBaseAuthRules>> allList = new ArrayList<ArrayList<HBaseAuthRules>>();
+ allList.add(globalList) ;
+ allList.add(tableList) ;
+ allList.add(ruleList) ;
+ for(ArrayList<HBaseAuthRules> rList : allList) {
+ for(HBaseAuthRules rule : rList) {
+ if (rule.isTableNameMatched(tableNameStr)) {
+ UserPermission perm = rule.getUserPermission(user) ;
+ if (perm != null) {
+ ret.add(perm) ;
+ }
+ }
+ }
+ }
+ }
+
+ return ret ;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthRules.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthRules.java b/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthRules.java
new file mode 100644
index 0000000..c2e0761
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/hbase/HBaseAuthRules.java
@@ -0,0 +1,134 @@
+/**************************************************************************
+ * *
+ * The information in this document is proprietary to XASecure Inc., *
+ * It may not be used, reproduced or disclosed without the written *
+ * approval from the XASecure Inc., *
+ * *
+ * PRIVILEGED AND CONFIDENTIAL XASECURE PROPRIETARY INFORMATION *
+ * *
+ * Copyright (c) 2013 XASecure, Inc. All rights reserved. *
+ * *
+ *************************************************************************/
+
+ /**
+ *
+ * @version: 1.0.004
+ *
+ */
+
+package com.xasecure.pdp.hbase;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.Permission;
+import org.apache.hadoop.hbase.security.access.UserPermission;
+
+import com.xasecure.pdp.constants.XaSecureConstants;
+
+public class HBaseAuthRules {
+ private String tableName ;
+ private String columnGroupName;
+ private String columnName ;
+ private String accessType ;
+ private String group ;
+ private String user ;
+ private String fullyQualifiedColumnName ;
+
+ private static final Log LOG = LogFactory.getLog(HBaseAuthRules.class) ;
+
+ public HBaseAuthRules(String tableName, String columnGroupName, String columnName, String accessType, String user, String group) {
+ this.tableName = tableName;
+ this.columnGroupName = columnGroupName;
+ this.columnName = columnName;
+ if (accessType != null) {
+ this.accessType = accessType.toLowerCase() ;
+ }
+ this.user = user ;
+ this.group = group;
+ this.fullyQualifiedColumnName = tableName + "/" + columnGroupName + "/" + columnName ;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+ public String getColumnGroupName() {
+ return columnGroupName;
+ }
+ public String getColumnName() {
+ return columnName;
+ }
+ public String getAccessType() {
+ return accessType;
+ }
+ public String getGroup() {
+ return group;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public String toString() {
+ return "table: " + tableName + ", columnGroup:" + columnGroupName + ", columnName: " + columnName + ", accessType: " + accessType + ", user:" + user + ", group: " + group ;
+ }
+
+ public boolean isMatched(String FQColName) {
+ return FQColName.equals(fullyQualifiedColumnName) || FilenameUtils.wildcardMatch(FQColName,fullyQualifiedColumnName) ;
+ }
+
+ public boolean isGlobalRule() {
+ return ("*".equals(tableName) && "*".equals(columnGroupName) && "*".equals(columnName)) ;
+ }
+
+ public boolean isTableRule() {
+ return ( ("*".equals(columnGroupName) && "*".equals(columnName)) || ("admin".equals(accessType) || "control".equals(accessType)) ) ;
+ }
+
+ public boolean isTableNameMatched(String tableNameStr) {
+ boolean ret = (tableNameStr == null) || (tableNameStr.equals(tableName)) || FilenameUtils.wildcardMatch(tableNameStr,tableName) ;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("TableMatched returns (" + tableNameStr + ", rule:" + tableName + ") returns: " + ret );
+ }
+ return ret ;
+ }
+
+ public UserPermission getUserPermission(User aUser) {
+
+ if (user == null) {
+ return null ;
+ }
+
+ Permission.Action action = null ;
+
+ try {
+ action = Permission.Action.valueOf(accessType.toUpperCase()) ;
+ } catch (Throwable e) {
+ return null ;
+ }
+
+ if (XaSecureConstants.PUBLIC_ACCESS_ROLE.equals(group)) {
+ return new UserPermission("public".getBytes(), TableName.valueOf ( tableName ) , columnGroupName.getBytes(), columnName.getBytes(), action) ;
+ }
+
+ if (user != null) {
+ if (aUser.getShortName().equals(user)) {
+ return new UserPermission(("user:(" + aUser.getShortName() + ")").getBytes(), TableName.valueOf( tableName ) , columnGroupName.getBytes(), columnName.getBytes(), action) ;
+ }
+ }
+
+ if (group != null) {
+ for (String ugroups : aUser.getGroupNames()) {
+ if (ugroups.equals(group)) {
+ return new UserPermission(("group:(" + ugroups + ")").getBytes(), TableName.valueOf( tableName ) , columnGroupName.getBytes(), columnName.getBytes(), action) ;
+ }
+ }
+ }
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-argus/blob/7defc061/agents-impl/src/main/java/com/xasecure/pdp/hbase/URLBasedAuthDB.java
----------------------------------------------------------------------
diff --git a/agents-impl/src/main/java/com/xasecure/pdp/hbase/URLBasedAuthDB.java b/agents-impl/src/main/java/com/xasecure/pdp/hbase/URLBasedAuthDB.java
new file mode 100644
index 0000000..160fe62
--- /dev/null
+++ b/agents-impl/src/main/java/com/xasecure/pdp/hbase/URLBasedAuthDB.java
@@ -0,0 +1,233 @@
+/**************************************************************************
+ * *
+ * The information in this document is proprietary to XASecure Inc., *
+ * It may not be used, reproduced or disclosed without the written *
+ * approval from the XASecure Inc., *
+ * *
+ * PRIVILEGED AND CONFIDENTIAL XASECURE PROPRIETARY INFORMATION *
+ * *
+ * Copyright (c) 2013 XASecure, Inc. All rights reserved. *
+ * *
+ *************************************************************************/
+
+ /**
+ *
+ * @version: 1.0.004
+ *
+ */
+
+package com.xasecure.pdp.hbase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.security.access.UserPermission;
+
+import com.xasecure.authorization.hadoop.config.XaSecureConfiguration;
+import com.xasecure.authorization.hbase.HBaseAccessController;
+import com.xasecure.pdp.config.PolicyChangeListener;
+import com.xasecure.pdp.config.PolicyRefresher;
+import com.xasecure.pdp.constants.XaSecureConstants;
+import com.xasecure.pdp.model.Policy;
+import com.xasecure.pdp.model.PolicyContainer;
+import com.xasecure.pdp.model.RolePermission;
+
+public class URLBasedAuthDB implements HBaseAccessController, PolicyChangeListener {
+
+ private static final Log LOG = LogFactory.getLog(URLBasedAuthDB.class);
+
+ private HBaseAuthDB authDB = null;
+
+ private static URLBasedAuthDB me = null ;
+
+ private PolicyRefresher refresher = null ;
+
+ public static URLBasedAuthDB getInstance() {
+ if (me == null) {
+ synchronized(URLBasedAuthDB.class) {
+ URLBasedAuthDB temp = me ;
+ if (temp == null) {
+ me = new URLBasedAuthDB() ;
+ me.init() ;
+ }
+ }
+ }
+ return me ;
+ }
+
+
+ private URLBasedAuthDB() {
+ String url = XaSecureConfiguration.getInstance().get(XaSecureConstants.XASECURE_HBASE_POLICYMGR_URL_PROP);
+ long refreshInMilli = XaSecureConfiguration.getInstance().getLong(
+ XaSecureConstants.XASECURE_HBASE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP,
+ XaSecureConstants.XASECURE_HBASE_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT);
+
+ String lastStoredFileName = XaSecureConfiguration.getInstance().get(XaSecureConstants.XASECURE_HBASE_LAST_SAVED_POLICY_FILE_PROP) ;
+
+ String sslConfigFileName = XaSecureConfiguration.getInstance().get(XaSecureConstants.XASECURE_HBASE_POLICYMGR_SSL_CONFIG_FILE_PROP) ;
+ refresher = new PolicyRefresher(url, refreshInMilli,sslConfigFileName,lastStoredFileName) ;
+
+ String saveAsFileName = XaSecureConfiguration.getInstance().get(XaSecureConstants.XASECURE_HBASE_POLICYMGR_URL_SAVE_FILE_PROP) ;
+ if (saveAsFileName != null) {
+ refresher.setSaveAsFileName(saveAsFileName) ;
+ }
+
+ if (lastStoredFileName != null) {
+ refresher.setLastStoredFileName(lastStoredFileName);
+ }
+ }
+
+ private void init() {
+ refresher.setPolicyChangeListener(this);
+ }
+
+ public boolean isAccessAllowed(User user, Action accessAction) {
+ if (authDB != null) {
+ return authDB.isAccessAllowed(user, accessAction);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isAccessAllowed(User user, byte[] tableName, Action accessAction) {
+ if (authDB != null) {
+ return authDB.isAccessAllowed(user, tableName, accessAction);
+ } else {
+ return false;
+ }
+ }
+
+
+ public boolean isAccessAllowed(User user, byte[] tableName, byte[] columnFamily, byte[] qualifier, Action accessAction) {
+ if (authDB != null) {
+ return authDB.isAccessAllowed(user, tableName, columnFamily, qualifier, accessAction);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isEncrypted(byte[] tableName, byte[] columnFamily, byte[] qualifier) {
+ if (authDB != null) {
+ return authDB.isEncrypted(tableName, columnFamily, qualifier);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isTableHasEncryptedColumn(byte[] tableName) {
+ if (authDB != null) {
+ return authDB.isTableHasEncryptedColumn(tableName);
+ } else {
+ return false;
+ }
+ }
+
+
+ public boolean isAudited(byte[] tableName) {
+ if (authDB != null) {
+ return authDB.isAudited(tableName);
+ } else {
+ return false;
+ }
+ }
+
+ public List<UserPermission> getUserPermissions(User aUser) {
+ if (authDB != null) {
+ return authDB.getUserPermissions(aUser) ;
+ } else {
+ return null;
+ }
+ }
+
+ public List<UserPermission> getUserPermissions(User aUser, byte[] aTableName) {
+ if (authDB != null) {
+ return authDB.getUserPermissions(aUser, aTableName) ;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void OnPolicyChange(PolicyContainer aPolicyContainer) {
+
+ if (aPolicyContainer == null) {
+ return ;
+ }
+
+ ArrayList<HBaseAuthRules> ruleListTemp = new ArrayList<HBaseAuthRules>();
+
+ HBaseAuthRules globalRule = new HBaseAuthRules(".META.", "*", "*", "read", null, XaSecureConstants.PUBLIC_ACCESS_ROLE) ;
+ ruleListTemp.add(globalRule) ;
+ globalRule = new HBaseAuthRules("-ROOT-", "*", "*", "read", null, XaSecureConstants.PUBLIC_ACCESS_ROLE) ;
+ ruleListTemp.add(globalRule) ;
+
+ ArrayList<String> auditListTemp = new ArrayList<String>();
+
+ ArrayList<String> encryptList = new ArrayList<String>();
+
+ for(Policy acl : aPolicyContainer.getAcl()) {
+
+ if (! acl.isEnabled()) {
+ LOG.debug("Diabled acl found [" + acl + "]. Skipping this acl ...") ;
+ continue ;
+ }
+
+ for(String table : acl.getTableList()) {
+ for(String colfamily : acl.getColumnFamilyList()) {
+ for(String col : acl.getColumnList()) {
+ if (table == null || table.isEmpty()) {
+ table = "*" ;
+ }
+ if (colfamily == null || colfamily.isEmpty()) {
+ colfamily = "*" ;
+ }
+ if (col == null || col.isEmpty()) {
+ col = "*" ;
+ }
+
+ if (acl.getAuditInd() == 1) {
+ if (!auditListTemp.contains(table)) {
+ LOG.debug("Adding [" + table + "] to audit list");
+ auditListTemp.add(table);
+ }
+ }
+
+ if (acl.getEncryptInd() == 1) {
+ String fqn = table + "/" + colfamily + "/" + col ;
+ if (!encryptList.contains(fqn)) {
+ LOG.debug("Adding [" + fqn + "] to encrypt list");
+ encryptList.add(fqn);
+ }
+ }
+
+ for(RolePermission rp : acl.getPermissions()) {
+ for (String accessLevel : rp.getAccess() ) {
+ if (rp.getGroups() != null && rp.getGroups().size() > 0) {
+ for (String group : rp.getGroups()) {
+ HBaseAuthRules rule = new HBaseAuthRules(table, colfamily, col, accessLevel, null, group);
+ LOG.debug("Adding (group) rule: [" + rule + "]") ;
+ ruleListTemp.add(rule);
+ }
+ }
+ if (rp.getUsers() != null && rp.getUsers().size() > 0) {
+ for (String user : rp.getUsers()) {
+ HBaseAuthRules rule = new HBaseAuthRules(table, colfamily, col, accessLevel, user, null);
+ LOG.debug("Adding (user) rule: [" + rule + "]") ;
+ ruleListTemp.add(rule);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ HBaseAuthDB authDBTemp = new HBaseAuthDB(ruleListTemp, auditListTemp, encryptList);
+ authDB = authDBTemp;
+ }
+
+}