diff options
author | Martin Polden <mpolden@mpolden.no> | 2019-07-12 09:37:31 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2019-07-16 09:46:54 +0200 |
commit | 67e2766163bf1dba13c8cce56e2bbb3af7198ea3 (patch) | |
tree | 3efc494f2f9b14e26bf74f39bee972e9679e1f44 | |
parent | 86f9f85848f7ff5ae34cd33c50a18e52f064fb87 (diff) |
Audit log /flags/v1 on controller
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); + } + +} |