You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by pr...@apache.org on 2021/12/08 03:12:55 UTC

[ranger] branch master updated: RANGER-2967: Add support for Amazon CloudWatch Logs as an Audit Store

This is an automated email from the ASF dual-hosted git repository.

pradeep pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 25def39  RANGER-2967: Add support for Amazon CloudWatch Logs as an Audit Store
25def39 is described below

commit 25def39b1c833b4e18ff657929656be3c37bcd8f
Author: Yao Zhou <zh...@gmail.com>
AuthorDate: Tue Aug 25 10:53:50 2020 +0530

    RANGER-2967: Add support for Amazon CloudWatch Logs as an Audit Store
    
    Signed-off-by: pradeep <pr...@apache.org>
---
 agents-audit/pom.xml                               |  15 ++
 .../AmazonCloudWatchAuditDestination.java          | 182 +++++++++++++++++++++
 .../audit/provider/AuditProviderFactory.java       |   2 +
 hbase-agent/conf/ranger-hbase-audit-changes.cfg    |   5 +
 hbase-agent/scripts/install.properties             |  12 ++
 hdfs-agent/conf/ranger-hdfs-audit-changes.cfg      |   5 +
 hdfs-agent/scripts/install.properties              |  12 ++
 hive-agent/conf/ranger-hive-audit-changes.cfg      |   5 +
 hive-agent/scripts/install.properties              |  12 ++
 kms/scripts/install.properties                     |  12 ++
 knox-agent/conf/ranger-knox-audit-changes.cfg      |   5 +
 knox-agent/scripts/install.properties              |  12 ++
 plugin-atlas/conf/ranger-atlas-audit-changes.cfg   |   6 +
 plugin-atlas/scripts/install.properties            |  12 ++
 .../conf/ranger-elasticsearch-audit-changes.cfg    |   5 +
 plugin-elasticsearch/scripts/install.properties    |  12 ++
 plugin-kafka/conf/ranger-kafka-audit-changes.cfg   |   5 +
 plugin-kafka/scripts/install.properties            |  12 ++
 plugin-kms/conf/ranger-kms-audit-changes.cfg       |   5 +
 plugin-kylin/conf/ranger-kylin-audit-changes.cfg   |   5 +
 plugin-kylin/scripts/install.properties            |  12 ++
 plugin-ozone/conf/ranger-ozone-audit-changes.cfg   |   5 +
 plugin-ozone/scripts/install.properties            |  12 ++
 plugin-presto/conf/ranger-presto-audit-changes.cfg |   5 +
 plugin-presto/scripts/install.properties           |  12 ++
 plugin-solr/conf/ranger-solr-audit-changes.cfg     |   5 +
 plugin-solr/scripts/install.properties             |  12 ++
 plugin-sqoop/conf/ranger-sqoop-audit-changes.cfg   |   5 +
 plugin-sqoop/scripts/install.properties            |  12 ++
 plugin-yarn/conf/ranger-yarn-audit-changes.cfg     |   5 +
 plugin-yarn/scripts/install.properties             |  12 ++
 .../AmazonCloudWatchAuditDestinationTest.java      |  79 +++++++++
 storm-agent/conf/ranger-storm-audit-changes.cfg    |   5 +
 storm-agent/scripts/install.properties             |  12 ++
 34 files changed, 534 insertions(+)

diff --git a/agents-audit/pom.xml b/agents-audit/pom.xml
index 5607242..33fa256 100644
--- a/agents-audit/pom.xml
+++ b/agents-audit/pom.xml
@@ -31,6 +31,17 @@
         <version>3.0.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.amazonaws</groupId>
+                <artifactId>aws-java-sdk-bom</artifactId>
+                <version>1.11.327</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.apache.ranger</groupId>
@@ -334,5 +345,9 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>com.amazonaws</groupId>
+            <artifactId>aws-java-sdk-logs</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestination.java b/agents-audit/src/main/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestination.java
new file mode 100644
index 0000000..b236a26
--- /dev/null
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestination.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.destination;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+import com.amazonaws.services.logs.AWSLogs;
+import com.amazonaws.services.logs.AWSLogsClientBuilder;
+import com.amazonaws.services.logs.model.CreateLogStreamRequest;
+import com.amazonaws.services.logs.model.InputLogEvent;
+import com.amazonaws.services.logs.model.InvalidSequenceTokenException;
+import com.amazonaws.services.logs.model.PutLogEventsRequest;
+import com.amazonaws.services.logs.model.PutLogEventsResult;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.audit.model.AuditEventBase;
+import org.apache.ranger.audit.provider.MiscUtil;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Writes audit events to Amazon CloudWatch Logs.
+ * <p>
+ * Two properties are required: LogGroupName and LogStreamPrefix
+ * <p>
+ * Thread-safety is ensured by making the log method synchronized.
+ * This is to avoid possible race condition on {@link #sequenceToken} which is required in PutLogEvents API.
+ * @see <a href="https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html">PutLogEvents API Reference</a>
+ * <p>
+ * Note: Amazon CloudWatch has limits on the payload size and request rate.
+ * Based on the traffic, adjust the batch size and flush interval accordingly.
+ * <p>
+ *
+ * @see <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html">Amazon CloudWatch Logs Service Limits</a>
+ */
+@ThreadSafe
+public class AmazonCloudWatchAuditDestination extends AuditDestination {
+
+    private static Log LOG = LogFactory.getLog(AmazonCloudWatchAuditDestination.class);
+
+    public static final String PROP_LOG_GROUP_NAME = "log_group";
+    public static final String PROP_LOG_STREAM_PREFIX = "log_stream_prefix";
+    public static final String CONFIG_PREFIX = "ranger.audit.amazon_cloudwatch";
+
+    private String logGroupName;
+    private String logStreamName;
+    private AWSLogs logsClient;
+    private String sequenceToken;
+
+    @Override
+    public void init(Properties props, String propPrefix) {
+        LOG.info("init() called for CloudWatchAuditDestination");
+        super.init(props, propPrefix);
+
+        this.logGroupName = MiscUtil.getStringProperty(props, propPrefix + "."
+                + PROP_LOG_GROUP_NAME);
+        this.logStreamName = MiscUtil.getStringProperty(props, propPrefix + "."
+                + PROP_LOG_STREAM_PREFIX) + MiscUtil.generateUniqueId();
+
+        logsClient = getClient(); // Initialize client
+        createLogStream();
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        logStatus();
+    }
+
+    @Override
+    synchronized public boolean log(Collection<AuditEventBase> collection) {
+        boolean ret = false;
+        AWSLogs client = getClient();
+
+        PutLogEventsRequest req = new PutLogEventsRequest()
+                .withLogEvents(toInputLogEvent(collection))
+                .withLogGroupName(logGroupName)
+                .withLogStreamName(logStreamName)
+                .withSequenceToken(sequenceToken);
+
+        try {
+            sequenceToken = pushLogEvents(req, false, client);
+            addSuccessCount(collection.size());
+            ret = true;
+        } catch (Throwable e) {
+            addFailedCount(collection.size());
+            LOG.error("Failed to send audit events", e);
+        }
+
+        return ret;
+    }
+
+    private String pushLogEvents(PutLogEventsRequest req,
+                                  boolean retryingOnInvalidSeqToken,
+                                  AWSLogs client) {
+        String sequenceToken;
+        try {
+            PutLogEventsResult re = client.putLogEvents(req);
+            sequenceToken = re.getNextSequenceToken();
+        } catch (InvalidSequenceTokenException ex) {
+            if (retryingOnInvalidSeqToken) {
+                LOG.error("Unexpected invalid sequence token. Possible race condition occurred");
+                throw ex;
+            }
+
+            // LogStream may exist before first push attempt, re-obtain the sequence token
+            LOG.info("Invalid sequence token. Plugin possibly restarted. " +
+                    "Updating the sequence token and retrying");
+            sequenceToken = ex.getExpectedSequenceToken();
+            req.setSequenceToken(sequenceToken);
+            return pushLogEvents(req, true, client);
+        }
+
+        return sequenceToken;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.ranger.audit.provider.AuditProvider#flush()
+     */
+    @Override
+    public void flush() {
+
+    }
+
+    static Collection<InputLogEvent> toInputLogEvent(Collection<AuditEventBase> collection) {
+        return collection.stream()
+                .map(e -> new InputLogEvent()
+                        .withMessage(MiscUtil.stringify(e))
+                        .withTimestamp(e.getEventTime().getTime()))
+                .sorted(Comparator.comparingLong(InputLogEvent::getTimestamp))
+                .collect(Collectors.toList());
+    }
+
+    private void createLogStream() {
+        AWSLogs client = getClient();
+        CreateLogStreamRequest req = new CreateLogStreamRequest()
+                .withLogGroupName(logGroupName)
+                .withLogStreamName(logStreamName);
+
+        LOG.info(String.format("Creating Log Stream `%s` in Log Group `%s`",
+                logStreamName, logGroupName));
+        client.createLogStream(req);
+    }
+
+    private AWSLogs getClient() {
+        if (logsClient == null) {
+            synchronized (AmazonCloudWatchAuditDestination.class) {
+                if (logsClient == null) {
+                    logsClient = newClient();
+                }
+            }
+        }
+
+        return logsClient;
+    }
+
+    private AWSLogs newClient() {
+        return AWSLogsClientBuilder.standard().build();
+    }
+}
diff --git a/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java b/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
index 7a3c7f6..7846879 100644
--- a/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
+++ b/agents-audit/src/main/java/org/apache/ranger/audit/provider/AuditProviderFactory.java
@@ -421,6 +421,8 @@ public class AuditProviderFactory {
 				provider = new SolrAuditDestination();
 			} else if (providerName.equalsIgnoreCase("elasticsearch")) {
 				provider = new ElasticSearchAuditDestination();
+			} else if (providerName.equalsIgnoreCase("amazon_cloudwatch")) {
+				provider = new AmazonCloudWatchAuditDestination();
 			} else if (providerName.equalsIgnoreCase("kafka")) {
 				provider = new KafkaAuditProvider();
 			} else if (providerName.equalsIgnoreCase("log4j")) {
diff --git a/hbase-agent/conf/ranger-hbase-audit-changes.cfg b/hbase-agent/conf/ranger-hbase-audit-changes.cfg
index 26bd2fa..a6c7ffd 100644
--- a/hbase-agent/conf/ranger-hbase-audit-changes.cfg
+++ b/hbase-agent/conf/ranger-hbase-audit-changes.cfg
@@ -56,6 +56,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/hbase-agent/scripts/install.properties b/hbase-agent/scripts/install.properties
index 2ce8822..87a2481 100644
--- a/hbase-agent/scripts/install.properties
+++ b/hbase-agent/scripts/install.properties
@@ -99,6 +99,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/hdfs-agent/conf/ranger-hdfs-audit-changes.cfg b/hdfs-agent/conf/ranger-hdfs-audit-changes.cfg
index 9e099e6..92d2a4b 100644
--- a/hdfs-agent/conf/ranger-hdfs-audit-changes.cfg
+++ b/hdfs-agent/conf/ranger-hdfs-audit-changes.cfg
@@ -53,6 +53,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/hdfs-agent/scripts/install.properties b/hdfs-agent/scripts/install.properties
index 4c5e0fb..323b878 100644
--- a/hdfs-agent/scripts/install.properties
+++ b/hdfs-agent/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/hive-agent/conf/ranger-hive-audit-changes.cfg b/hive-agent/conf/ranger-hive-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/hive-agent/conf/ranger-hive-audit-changes.cfg
+++ b/hive-agent/conf/ranger-hive-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/hive-agent/scripts/install.properties b/hive-agent/scripts/install.properties
index b88d642..3720b66 100644
--- a/hive-agent/scripts/install.properties
+++ b/hive-agent/scripts/install.properties
@@ -96,6 +96,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/kms/scripts/install.properties b/kms/scripts/install.properties
index 4935536..6b6b662 100755
--- a/kms/scripts/install.properties
+++ b/kms/scripts/install.properties
@@ -216,6 +216,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/knox-agent/conf/ranger-knox-audit-changes.cfg b/knox-agent/conf/ranger-knox-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/knox-agent/conf/ranger-knox-audit-changes.cfg
+++ b/knox-agent/conf/ranger-knox-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/knox-agent/scripts/install.properties b/knox-agent/scripts/install.properties
index 939fd88..4704004 100644
--- a/knox-agent/scripts/install.properties
+++ b/knox-agent/scripts/install.properties
@@ -91,6 +91,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/plugin-atlas/conf/ranger-atlas-audit-changes.cfg b/plugin-atlas/conf/ranger-atlas-audit-changes.cfg
index 39d1d10..2d8251b 100644
--- a/plugin-atlas/conf/ranger-atlas-audit-changes.cfg
+++ b/plugin-atlas/conf/ranger-atlas-audit-changes.cfg
@@ -33,6 +33,12 @@ xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARC
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
 
+#Amazon CloudWatch configuration
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 #log4j configuration
 xasecure.audit.log4j.is.enabled                %XAAUDIT.LOG4J.ENABLE%                      mod create-if-not-exists
 xasecure.audit.log4j.is.async                %XAAUDIT.LOG4J.IS_ASYNC%                      mod create-if-not-exists
diff --git a/plugin-atlas/scripts/install.properties b/plugin-atlas/scripts/install.properties
index 94a8023..3b777bd 100644
--- a/plugin-atlas/scripts/install.properties
+++ b/plugin-atlas/scripts/install.properties
@@ -94,6 +94,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg b/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg
+++ b/plugin-elasticsearch/conf/ranger-elasticsearch-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-elasticsearch/scripts/install.properties b/plugin-elasticsearch/scripts/install.properties
index 7e752c3..4111afe 100644
--- a/plugin-elasticsearch/scripts/install.properties
+++ b/plugin-elasticsearch/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/plugin-kafka/conf/ranger-kafka-audit-changes.cfg b/plugin-kafka/conf/ranger-kafka-audit-changes.cfg
index dfd27f3..bc5a089 100644
--- a/plugin-kafka/conf/ranger-kafka-audit-changes.cfg
+++ b/plugin-kafka/conf/ranger-kafka-audit-changes.cfg
@@ -47,6 +47,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-kafka/scripts/install.properties b/plugin-kafka/scripts/install.properties
index facbc79..1e325e0 100644
--- a/plugin-kafka/scripts/install.properties
+++ b/plugin-kafka/scripts/install.properties
@@ -94,6 +94,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/plugin-kms/conf/ranger-kms-audit-changes.cfg b/plugin-kms/conf/ranger-kms-audit-changes.cfg
index 8d5ca34..e5e9ae4 100644
--- a/plugin-kms/conf/ranger-kms-audit-changes.cfg
+++ b/plugin-kms/conf/ranger-kms-audit-changes.cfg
@@ -56,6 +56,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-kylin/conf/ranger-kylin-audit-changes.cfg b/plugin-kylin/conf/ranger-kylin-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/plugin-kylin/conf/ranger-kylin-audit-changes.cfg
+++ b/plugin-kylin/conf/ranger-kylin-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-kylin/scripts/install.properties b/plugin-kylin/scripts/install.properties
index b08f0ed..0134338 100644
--- a/plugin-kylin/scripts/install.properties
+++ b/plugin-kylin/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/plugin-ozone/conf/ranger-ozone-audit-changes.cfg b/plugin-ozone/conf/ranger-ozone-audit-changes.cfg
index 8cd5e39..0eace6d 100644
--- a/plugin-ozone/conf/ranger-ozone-audit-changes.cfg
+++ b/plugin-ozone/conf/ranger-ozone-audit-changes.cfg
@@ -47,6 +47,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir             		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-ozone/scripts/install.properties b/plugin-ozone/scripts/install.properties
index a160ec1..1891d56 100644
--- a/plugin-ozone/scripts/install.properties
+++ b/plugin-ozone/scripts/install.properties
@@ -94,6 +94,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/plugin-presto/conf/ranger-presto-audit-changes.cfg b/plugin-presto/conf/ranger-presto-audit-changes.cfg
index dfd27f3..bc5a089 100644
--- a/plugin-presto/conf/ranger-presto-audit-changes.cfg
+++ b/plugin-presto/conf/ranger-presto-audit-changes.cfg
@@ -47,6 +47,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-presto/scripts/install.properties b/plugin-presto/scripts/install.properties
index 9565335..ce162a2 100644
--- a/plugin-presto/scripts/install.properties
+++ b/plugin-presto/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/plugin-solr/conf/ranger-solr-audit-changes.cfg b/plugin-solr/conf/ranger-solr-audit-changes.cfg
index d4588ff..ffa0a76 100644
--- a/plugin-solr/conf/ranger-solr-audit-changes.cfg
+++ b/plugin-solr/conf/ranger-solr-audit-changes.cfg
@@ -48,6 +48,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-solr/scripts/install.properties b/plugin-solr/scripts/install.properties
index 88e8056..d1852e6 100644
--- a/plugin-solr/scripts/install.properties
+++ b/plugin-solr/scripts/install.properties
@@ -94,6 +94,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 #
diff --git a/plugin-sqoop/conf/ranger-sqoop-audit-changes.cfg b/plugin-sqoop/conf/ranger-sqoop-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/plugin-sqoop/conf/ranger-sqoop-audit-changes.cfg
+++ b/plugin-sqoop/conf/ranger-sqoop-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-sqoop/scripts/install.properties b/plugin-sqoop/scripts/install.properties
index b7b1187..81b4526 100644
--- a/plugin-sqoop/scripts/install.properties
+++ b/plugin-sqoop/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/plugin-yarn/conf/ranger-yarn-audit-changes.cfg b/plugin-yarn/conf/ranger-yarn-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/plugin-yarn/conf/ranger-yarn-audit-changes.cfg
+++ b/plugin-yarn/conf/ranger-yarn-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/plugin-yarn/scripts/install.properties b/plugin-yarn/scripts/install.properties
index 71bab49..e73ab8b 100644
--- a/plugin-yarn/scripts/install.properties
+++ b/plugin-yarn/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties
 
 
diff --git a/security-admin/src/test/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestinationTest.java b/security-admin/src/test/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestinationTest.java
new file mode 100644
index 0000000..dde8bb5
--- /dev/null
+++ b/security-admin/src/test/java/org/apache/ranger/audit/destination/AmazonCloudWatchAuditDestinationTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.destination;
+
+import org.apache.ranger.audit.model.AuthzAuditEvent;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Properties;
+
+import static org.apache.ranger.audit.destination.AmazonCloudWatchAuditDestination.CONFIG_PREFIX;
+
+public class AmazonCloudWatchAuditDestinationTest {
+
+    @Test
+    @Ignore // For manual execution only
+    public void testWrite() {
+        AmazonCloudWatchAuditDestination amazonCloudWatchAuditDestination = new AmazonCloudWatchAuditDestination();
+        Properties properties = new Properties();
+        properties.put(CONFIG_PREFIX + "." + AmazonCloudWatchAuditDestination.PROP_LOG_GROUP_NAME, "test-log-group");
+        properties.put(CONFIG_PREFIX + "." + AmazonCloudWatchAuditDestination.PROP_LOG_STREAM_PREFIX, "test-log-stream");
+
+        amazonCloudWatchAuditDestination.init(properties, CONFIG_PREFIX);
+
+        assert amazonCloudWatchAuditDestination.log(Arrays.asList(getAuthzAuditEvent()));
+    }
+
+    private AuthzAuditEvent getAuthzAuditEvent() {
+        AuthzAuditEvent event = new AuthzAuditEvent();
+        event.setAccessResult((short) 1);
+        event.setAccessType("");
+        event.setAclEnforcer("");
+        event.setAction("");
+        event.setAdditionalInfo("");
+        event.setAgentHostname("");
+        event.setAgentId("");
+        event.setClientIP("");
+        event.setClusterName("");
+        event.setClientType("");
+        event.setEventCount(1);
+        event.setEventDurationMS(1);
+        event.setEventId("");
+        event.setEventTime(new Date());
+        event.setLogType("");
+        event.setPolicyId(1);
+        event.setPolicyVersion(1l);
+        event.setRepositoryName("");
+        event.setRequestData("");
+        event.setRepositoryType(1);
+        event.setResourcePath("");
+        event.setResultReason("");
+        event.setSeqNum(1);
+        event.setSessionId("");
+        event.setTags(new HashSet<>());
+        event.setUser("");
+        event.setZoneName("");
+        return event;
+    }
+}
diff --git a/storm-agent/conf/ranger-storm-audit-changes.cfg b/storm-agent/conf/ranger-storm-audit-changes.cfg
index c396d5d..52c715e 100644
--- a/storm-agent/conf/ranger-storm-audit-changes.cfg
+++ b/storm-agent/conf/ranger-storm-audit-changes.cfg
@@ -54,6 +54,11 @@ xasecure.audit.destination.elasticsearch.index 						   %XAAUDIT.ELASTICSEARCH.I
 xasecure.audit.destination.elasticsearch.port 						   %XAAUDIT.ELASTICSEARCH.PORT% 							  mod create-if-not-exists
 xasecure.audit.destination.elasticsearch.protocol 						   %XAAUDIT.ELASTICSEARCH.PROTOCOL% 							  mod create-if-not-exists
 
+xasecure.audit.destination.amazon_cloudwatch                                    %XAAUDIT.AMAZON_CLOUDWATCH.ENABLE%                              mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_group                          %XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP%                           mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.log_stream_prefix                  %XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX%                   mod create-if-not-exists
+xasecure.audit.destination.amazon_cloudwatch.batch.filespool.dir                %XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR%                      mod create-if-not-exists
+
 xasecure.audit.destination.hdfs					   %XAAUDIT.HDFS.ENABLE%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.batch.filespool.dir                %XAAUDIT.HDFS.FILE_SPOOL_DIR%                      mod create-if-not-exists
 xasecure.audit.destination.hdfs.dir                		   %XAAUDIT.HDFS.HDFS_DIR%                      mod create-if-not-exists
diff --git a/storm-agent/scripts/install.properties b/storm-agent/scripts/install.properties
index 109300f..d219abf 100644
--- a/storm-agent/scripts/install.properties
+++ b/storm-agent/scripts/install.properties
@@ -93,6 +93,18 @@ XAAUDIT.LOG4J.ASYNC.MAX.FLUSH.INTERVAL.MS=30000
 XAAUDIT.LOG4J.DESTINATION.LOG4J=true
 XAAUDIT.LOG4J.DESTINATION.LOG4J.LOGGER=xaaudit
 
+# Enable audit logs to Amazon CloudWatch Logs
+#Example
+#XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=true
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=ranger_audits
+#XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM={instance_id}
+#XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=/var/log/hive/audit/amazon_cloudwatch/spool
+
+XAAUDIT.AMAZON_CLOUDWATCH.ENABLE=false
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_GROUP=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.LOG_STREAM_PREFIX=NONE
+XAAUDIT.AMAZON_CLOUDWATCH.FILE_SPOOL_DIR=NONE
+
 # End of V3 properties