summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2019-07-12 09:37:31 +0200
committerMartin Polden <mpolden@mpolden.no>2019-07-16 09:46:54 +0200
commit67e2766163bf1dba13c8cce56e2bbb3af7198ea3 (patch)
tree3efc494f2f9b14e26bf74f39bee972e9679e1f44
parent86f9f85848f7ff5ae34cd33c50a18e52f064fb87 (diff)
Audit log /flags/v1 on controller
-rw-r--r--controller-server/pom.xml7
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsHandler.java30
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java57
5 files changed, 100 insertions, 1 deletions
diff --git a/controller-server/pom.xml b/controller-server/pom.xml
index c6c6acafe15..ae756eae1fb 100644
--- a/controller-server/pom.xml
+++ b/controller-server/pom.xml
@@ -107,6 +107,13 @@
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>configserver-flags</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- compile -->
<dependency>
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsHandler.java
new file mode 100644
index 00000000000..31058a71816
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsHandler.java
@@ -0,0 +1,30 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.restapi.flags;
+
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.vespa.configserver.flags.FlagsDb;
+import com.yahoo.vespa.configserver.flags.http.FlagsHandler;
+import com.yahoo.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.auditlog.AuditLogger;
+
+/**
+ * An extension of {@link FlagsHandler} which logs requests to the audit log.
+ *
+ * @author mpolden
+ */
+public class AuditedFlagsHandler extends FlagsHandler {
+
+ private final AuditLogger auditLogger;
+
+ public AuditedFlagsHandler(Context context, Controller controller, FlagsDb flagsDb) {
+ super(context, flagsDb);
+ auditLogger = controller.auditLogger();
+ }
+
+ @Override
+ public HttpResponse handle(HttpRequest request) {
+ return super.handle(auditLogger.log(request));
+ }
+
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
index c7be543dd00..b32cbbcb926 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
@@ -7,7 +7,6 @@ import com.yahoo.application.container.handler.Response;
import com.yahoo.component.ComponentSpecification;
import com.yahoo.component.Version;
import com.yahoo.config.provision.zone.ZoneApi;
-import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.container.http.filter.FilterChainRepository;
import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
import com.yahoo.jdisc.http.filter.SecurityRequestFilterChain;
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
index 11aa132b478..83a43287880 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
@@ -60,6 +60,8 @@ public class ControllerContainerTest {
" </rotations>\n" +
" </config>\n" +
" <component id='com.yahoo.vespa.flags.InMemoryFlagSource'/>\n" +
+ " <component id='com.yahoo.vespa.configserver.flags.db.FlagsDbImpl'/>\n" +
+ " <component id='com.yahoo.vespa.curator.mock.MockCurator'/>\n" +
" <component id='com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb'/>\n" +
" <component id='com.yahoo.vespa.hosted.controller.athenz.mock.AthenzClientFactoryMock'/>\n" +
" <component id='com.yahoo.vespa.hosted.controller.api.integration.dns.MemoryNameService'/>\n" +
@@ -112,6 +114,10 @@ public class ControllerContainerTest {
" <binding>http://*/zone/v2</binding>\n" +
" <binding>http://*/zone/v2/*</binding>\n" +
" </handler>\n" +
+ " <handler id='com.yahoo.vespa.hosted.controller.restapi.flags.AuditedFlagsHandler'>\n" +
+ " <binding>http://*/flags/v1</binding>\n" +
+ " <binding>http://*/flags/v1/*</binding>\n" +
+ " </handler>\n" +
variablePartXml() +
"</container>";
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java
new file mode 100644
index 00000000000..b4ef98cc7f6
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java
@@ -0,0 +1,57 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.restapi.flags;
+
+import com.yahoo.application.container.handler.Request;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzUser;
+import com.yahoo.vespa.hosted.controller.auditlog.AuditLog;
+import com.yahoo.vespa.hosted.controller.restapi.ContainerControllerTester;
+import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author mpolden
+ */
+public class AuditedFlagsApiTest extends ControllerContainerTest {
+
+ private static final String responses = "src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/responses/";
+ private static final AthenzIdentity operator = AthenzUser.fromUserId("operatorUser");
+
+ private ContainerControllerTester tester;
+
+ @Before
+ public void before() {
+ addUserToHostedOperatorRole(operator);
+ tester = new ContainerControllerTester(container, responses);
+ }
+
+ @Test
+ public void test_audit_logging() {
+ var body = "{\n" +
+ " \"id\": \"id1\",\n" +
+ " \"rules\": [\n" +
+ " {\n" +
+ " \"value\": true\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ assertResponse(new Request("http://localhost:8080/flags/v1/data/id1?force=true", body, Request.Method.PUT),
+ "", 200);
+ var log = tester.controller().auditLogger().readLog();
+ assertEquals(1, log.entries().size());
+ var entry = log.entries().get(0);
+ assertEquals(operator.getFullName(), entry.principal());
+ assertEquals(AuditLog.Entry.Method.PUT, entry.method());
+ assertEquals("/flags/v1/data/id1?force=true", entry.resource());
+ assertEquals(body, log.entries().get(0).data().get());
+ }
+
+ private void assertResponse(Request request, String body, int statusCode) {
+ addIdentityToRequest(request, operator);
+ tester.assertResponse(request, body, statusCode);
+ }
+
+}