diff --git a/qa/pom.xml b/qa/pom.xml
index a2e3b1d0dbf..7bff7f17887 100644
--- a/qa/pom.xml
+++ b/qa/pom.xml
@@ -322,6 +322,7 @@
shield-example-realm
shield-tribe-node-tests
shield-client-tests
+ shield-audit-tests
diff --git a/qa/shield-audit-tests/integration-tests.xml b/qa/shield-audit-tests/integration-tests.xml
new file mode 100644
index 00000000000..24ee45c2cdc
--- /dev/null
+++ b/qa/shield-audit-tests/integration-tests.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Waiting for elasticsearch to become available on port @{port}...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Adding shield users...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Checking we can connect with basic auth on port ${integ.http.port}...
+
+
+
+
+
diff --git a/qa/shield-audit-tests/pom.xml b/qa/shield-audit-tests/pom.xml
new file mode 100644
index 00000000000..359a9858755
--- /dev/null
+++ b/qa/shield-audit-tests/pom.xml
@@ -0,0 +1,145 @@
+
+
+
+ x-plugins-qa
+ org.elasticsearch.qa
+ 3.0.0-SNAPSHOT
+
+ 4.0.0
+
+ shield-audit-tests
+ QA: Shield index audit tests
+ Tests the Shield Index Audit that works in a cluster properly
+
+
+
+ true
+ false
+ ${project.basedir}/integration-tests.xml
+ license,shield
+
+
+
+
+ org.elasticsearch.plugin
+ shield
+ ${elasticsearch.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ integ-setup-dependencies
+ pre-integration-test
+
+ copy
+
+
+ ${skip.integ.tests}
+ true
+ ${integ.deps}/plugins
+
+
+
+
+ org.elasticsearch.distribution.zip
+ elasticsearch
+ ${elasticsearch.version}
+ zip
+ true
+ ${integ.deps}
+
+
+
+
+ org.elasticsearch.plugin
+ license
+ ${elasticsearch.version}
+ zip
+ true
+
+
+
+ org.elasticsearch.plugin
+ shield
+ ${elasticsearch.version}
+ zip
+ true
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+
+ integ-setup
+ pre-integration-test
+
+ run
+
+
+
+
+
+
+
+
+
+ ${skip.integ.tests}
+
+
+
+
+ integ-teardown
+ post-integration-test
+
+ run
+
+
+
+
+
+ ${skip.integ.tests}
+
+
+
+
+
+ ant-contrib
+ ant-contrib
+ 1.0b3
+
+
+ ant
+ ant
+
+
+
+
+ org.apache.ant
+ ant-nodeps
+ 1.8.1
+
+
+
+
+
+
diff --git a/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java b/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java
new file mode 100644
index 00000000000..e76d3e01fbb
--- /dev/null
+++ b/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+package org.elasticsearch.shield.audit;
+
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.shield.ShieldPlugin;
+import org.elasticsearch.shield.authc.support.SecuredString;
+import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
+import org.elasticsearch.test.ESIntegTestCase;
+import org.elasticsearch.test.rest.client.http.HttpResponse;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+
+public class IndexAuditIT extends ESIntegTestCase {
+
+ private static final String USER = "test_user";
+ private static final String PASS = "changeme";
+
+ @Test
+ public void testShieldIndexAuditTrailWorking() throws Exception {
+ HttpResponse response = httpClient().path("/_cluster/health")
+ .addHeader("Authorization", UsernamePasswordToken.basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray())))
+ .execute();
+ assertThat(response.getStatusCode(), is(200));
+
+ boolean found = awaitBusy(() -> {
+ if (client().admin().cluster().prepareState().get().getState().getMetaData().getIndices().size() < 1) {
+ return false;
+ }
+ client().admin().indices().prepareRefresh().get();
+ return client().prepareSearch(".shield_audit_log*").setQuery(QueryBuilders.matchQuery("principal", USER)).get().getHits().totalHits() > 0;
+ }, 5L, TimeUnit.SECONDS);
+
+ assertThat(found, is(true));
+
+ SearchResponse searchResponse = client().prepareSearch(".shield_audit_log*").setQuery(QueryBuilders.matchQuery("principal", USER)).addField("principal").get();
+ assertThat(searchResponse.getHits().getHits().length, greaterThan(0));
+ assertThat((String) searchResponse.getHits().getAt(0).field("principal").getValue(), is(USER));
+
+ }
+
+ @Override
+ protected Settings externalClusterClientSettings() {
+ return Settings.builder()
+ .put("shield.user", USER + ":" + PASS)
+ .build();
+ }
+
+ @Override
+ protected Collection> transportClientPlugins() {
+ return Collections.>singleton(ShieldPlugin.class);
+ }
+}