aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLoggerTest.java
blob: 5c5abea027655e6ff9eedb433fffbf99470c835e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.auditlog;

import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.jdisc.http.HttpRequest.Method;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.auditlog.AuditLog.Entry;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.function.Supplier;

import static java.time.temporal.ChronoUnit.MILLIS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * @author mpolden
 */
public class AuditLoggerTest {

    private final ControllerTester tester = new ControllerTester();
    private final Supplier<AuditLog> log = () -> tester.controller().auditLogger().readLog();

    @Test
    void test_logging() {
        { // GET request is ignored
            HttpRequest request = testRequest(Method.GET, URI.create("http://localhost:8080/os/v1/"), "");
            tester.controller().auditLogger().log(request);
            assertTrue(log.get().entries().isEmpty(), "Not logged");
        }

        { // PATCH request is logged in audit log
            URI url = URI.create("http://localhost:8080/os/v1/?foo=bar");
            String data = "{\"cloud\":\"cloud9\",\"version\":\"42.0\"}";
            HttpRequest request = testRequest(Method.PATCH, url, data);
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.PATCH, 1, "/os/v1/?foo=bar");
            assertEquals("user", log.get().entries().get(0).principal());
            assertEquals(data, log.get().entries().get(0).data().get());
        }

        { // Another PATCH request is logged
            tester.clock().advance(Duration.ofDays(1));
            HttpRequest request = testRequest(Method.PATCH, URI.create("http://localhost:8080/os/v1/"),
                    "{\"cloud\":\"cloud9\",\"version\":\"43.0\"}");
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.PATCH, 2, "/os/v1/");
        }

        { // PUT is logged
            tester.clock().advance(Duration.ofDays(1));
            HttpRequest request = testRequest(Method.PUT, URI.create("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/state/dirty/node1/"),
                    "");
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.PUT, 3, "/zone/v2/prod/us-north-1/nodes/v2/state/dirty/node1/");
        }

        { // DELETE is logged
            tester.clock().advance(Duration.ofDays(1));
            HttpRequest request = testRequest(Method.DELETE, URI.create("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/node/node1"),
                    "");
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.DELETE, 4, "/zone/v2/prod/us-north-1/nodes/v2/node/node1");
        }

        { // POST is logged
            tester.clock().advance(Duration.ofDays(1));
            HttpRequest request = testRequest(Method.POST, URI.create("http://localhost:8080/controller/v1/jobs/upgrader/confidence/6.42"),
                    "6.42");
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.POST, 5, "/controller/v1/jobs/upgrader/confidence/6.42");
        }

        { // 15 days pass and another PATCH request is logged. Older entries are removed due to expiry
            tester.clock().advance(Duration.ofDays(15));
            HttpRequest request = testRequest(Method.PATCH, URI.create("http://localhost:8080/os/v1/"),
                    "{\"cloud\":\"cloud9\",\"version\":\"44.0\"}");
            tester.controller().auditLogger().log(request);
            assertEntry(Entry.Method.PATCH, 1, "/os/v1/");
        }
    }

    private Instant instant() {
        return tester.clock().instant().truncatedTo(MILLIS);
    }

    private void assertEntry(Entry.Method method, int logSize, String resource) {
        assertEquals(logSize, log.get().entries().size());
        assertEquals(instant(), log.get().entries().get(0).at());
        assertEquals(method, log.get().entries().get(0).method());
        assertEquals(resource, log.get().entries().get(0).resource());
    }

    private static HttpRequest testRequest(Method method, URI url, String data) {
        HttpRequest request = HttpRequest.createTestRequest(
                url.toString(),
                method,
                new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))
        );
        request.getJDiscRequest().setUserPrincipal(() -> "user");
        return request;
    }

}