Skip to content

Commit efe272d

Browse files
authored
[#5556] feat(iceberg) support audit framework for Iceberg REST server (#5580)
### What changes were proposed in this pull request? 1. expand `BaseEvent` to represent general event information, like `OperationType` `OperationStatus`, etc. 2. add `SimpleFormatterV2` to convert all `Event` (include GravitinoServerEvent and Iceberg REST Event) to an audit object ### Why are the changes needed? Fix: #5556 ### Does this PR introduce _any_ user-facing change? For Gravitino server: 1. If user use default audit configuration, will add `remoteAddr` and `eventSource` to the audit log 2. If user use custom audit writer or formatter, there is no affect. For Gravitino Iceberg REST server: new feature, add configuration. ### How was this patch tested? add `gravitino.audit.enabled = true`, check audit log content in Gravitino server and Gravitino IcebergRESTServer.
1 parent af259c3 commit efe272d

File tree

181 files changed

+2210
-23
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+2210
-23
lines changed

core/src/main/java/org/apache/gravitino/Configs.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import java.util.List;
2525
import org.apache.commons.lang3.StringUtils;
2626
import org.apache.gravitino.audit.FileAuditWriter;
27-
import org.apache.gravitino.audit.SimpleFormatter;
27+
import org.apache.gravitino.audit.v2.SimpleFormatterV2;
2828
import org.apache.gravitino.config.ConfigBuilder;
2929
import org.apache.gravitino.config.ConfigConstants;
3030
import org.apache.gravitino.config.ConfigEntry;
@@ -366,5 +366,5 @@ private Configs() {}
366366
.doc("Gravitino event log formatter class name")
367367
.version(ConfigConstants.VERSION_0_7_0)
368368
.stringConf()
369-
.createWithDefault(SimpleFormatter.class.getName());
369+
.createWithDefault(SimpleFormatterV2.class.getName());
370370
}

core/src/main/java/org/apache/gravitino/audit/AuditLog.java

+61-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.apache.gravitino.audit;
2121

22+
import com.google.common.collect.ImmutableMap;
23+
import java.util.Map;
2224
import org.apache.gravitino.listener.api.event.AlterCatalogEvent;
2325
import org.apache.gravitino.listener.api.event.AlterCatalogFailureEvent;
2426
import org.apache.gravitino.listener.api.event.AlterFilesetEvent;
@@ -56,6 +58,7 @@
5658
import org.apache.gravitino.listener.api.event.DropTopicEvent;
5759
import org.apache.gravitino.listener.api.event.DropTopicFailureEvent;
5860
import org.apache.gravitino.listener.api.event.Event;
61+
import org.apache.gravitino.listener.api.event.EventSource;
5962
import org.apache.gravitino.listener.api.event.GetFileLocationEvent;
6063
import org.apache.gravitino.listener.api.event.GetFileLocationFailureEvent;
6164
import org.apache.gravitino.listener.api.event.GetPartitionEvent;
@@ -86,6 +89,8 @@
8689
import org.apache.gravitino.listener.api.event.LoadTableFailureEvent;
8790
import org.apache.gravitino.listener.api.event.LoadTopicEvent;
8891
import org.apache.gravitino.listener.api.event.LoadTopicFailureEvent;
92+
import org.apache.gravitino.listener.api.event.OperationStatus;
93+
import org.apache.gravitino.listener.api.event.OperationType;
8994
import org.apache.gravitino.listener.api.event.PartitionExistsEvent;
9095
import org.apache.gravitino.listener.api.event.PartitionExistsFailureEvent;
9196
import org.apache.gravitino.listener.api.event.PurgePartitionEvent;
@@ -106,7 +111,9 @@ public interface AuditLog {
106111
* The operation name.
107112
*
108113
* @return operation name.
114+
* @deprecated use {@code #operationType()} instead.
109115
*/
116+
@Deprecated
110117
Operation operation();
111118

112119
/**
@@ -127,9 +134,61 @@ public interface AuditLog {
127134
* The status of the operation.
128135
*
129136
* @return operation status.
137+
* @deprecated use {@link #operationStatus()} instead.
130138
*/
139+
@Deprecated
131140
Status status();
132141

142+
/**
143+
* The remote address of the operation.
144+
*
145+
* @return The remote address string.
146+
* @since 0.8.0
147+
*/
148+
default String remoteAddress() {
149+
return "unknown";
150+
}
151+
152+
/**
153+
* The status of the operation.
154+
*
155+
* @return The operation status.
156+
* @since 0.8.0
157+
*/
158+
default OperationStatus operationStatus() {
159+
return OperationStatus.UNKNOWN;
160+
}
161+
162+
/**
163+
* The type of the operation.
164+
*
165+
* @return The operation status.
166+
* @since 0.8.0
167+
*/
168+
default OperationType operationType() {
169+
return OperationType.UNKNOWN;
170+
}
171+
172+
/**
173+
* The custom information.
174+
*
175+
* @return the custom information.
176+
* @since 0.8.0
177+
*/
178+
default Map<String, String> customInfo() {
179+
return ImmutableMap.of();
180+
}
181+
182+
/**
183+
* The event source.
184+
*
185+
* @return the event source.
186+
* @since 0.8.0
187+
*/
188+
default EventSource eventSource() {
189+
return EventSource.GRAVITINO_SERVER;
190+
}
191+
133192
/** Define user metadata operation. */
134193
enum Operation {
135194
CREATE_METALAKE,
@@ -294,6 +353,7 @@ public static Operation fromEvent(Event event) {
294353

295354
enum Status {
296355
SUCCESS,
297-
FAILURE
356+
FAILURE,
357+
UNKNOWN
298358
}
299359
}

core/src/main/java/org/apache/gravitino/audit/SimpleAuditLog.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@
2323
import javax.annotation.Nullable;
2424
import lombok.Builder;
2525

26-
/** The default implementation of the audit log. */
26+
/**
27+
* The first version of implementation of the audit log.
28+
*
29+
* @deprecated since 0.8.0
30+
*/
2731
@Builder
32+
@Deprecated
33+
@SuppressWarnings("deprecation")
2834
public class SimpleAuditLog implements AuditLog {
2935

3036
private String user;

core/src/main/java/org/apache/gravitino/audit/SimpleFormatter.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,16 @@
2323
import org.apache.gravitino.listener.api.event.Event;
2424
import org.apache.gravitino.listener.api.event.FailureEvent;
2525

26-
/** The default formatter implementation of the audit log. */
26+
/**
27+
* The first version of formatter implementation of the audit log.
28+
*
29+
* @deprecated since 0.8.0, please use {@link org.apache.gravitino.audit.v2.SimpleFormatterV2}
30+
*/
31+
@Deprecated
2732
public class SimpleFormatter implements Formatter {
2833

2934
@Override
35+
@SuppressWarnings("deprecation")
3036
public SimpleAuditLog format(Event event) {
3137
Status status = event instanceof FailureEvent ? Status.FAILURE : Status.SUCCESS;
3238
return SimpleAuditLog.builder()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.gravitino.audit.v2;
21+
22+
import com.google.common.collect.ImmutableMap;
23+
import org.apache.gravitino.audit.AuditLog.Operation;
24+
import org.apache.gravitino.audit.AuditLog.Status;
25+
import org.apache.gravitino.listener.api.event.OperationStatus;
26+
import org.apache.gravitino.listener.api.event.OperationType;
27+
28+
public class CompatibilityUtils {
29+
30+
private static ImmutableMap<OperationType, Operation> operationTypeMap =
31+
ImmutableMap.<OperationType, Operation>builder()
32+
// Metalake operation
33+
.put(OperationType.CREATE_METALAKE, Operation.CREATE_METALAKE)
34+
.put(OperationType.ALTER_METALAKE, Operation.ALTER_METALAKE)
35+
.put(OperationType.DROP_METALAKE, Operation.DROP_METALAKE)
36+
.put(OperationType.LOAD_METALAKE, Operation.LOAD_METALAKE)
37+
.put(OperationType.LIST_METALAKE, Operation.LIST_METALAKE)
38+
39+
// Catalog operation
40+
.put(OperationType.CREATE_CATALOG, Operation.CREATE_CATALOG)
41+
.put(OperationType.ALTER_CATALOG, Operation.ALTER_CATALOG)
42+
.put(OperationType.DROP_CATALOG, Operation.DROP_CATALOG)
43+
.put(OperationType.LOAD_CATALOG, Operation.LOAD_CATALOG)
44+
.put(OperationType.LIST_CATALOG, Operation.LIST_CATALOG)
45+
46+
// Schema operation
47+
.put(OperationType.CREATE_SCHEMA, Operation.CREATE_SCHEMA)
48+
.put(OperationType.ALTER_SCHEMA, Operation.ALTER_SCHEMA)
49+
.put(OperationType.DROP_SCHEMA, Operation.DROP_SCHEMA)
50+
.put(OperationType.LOAD_SCHEMA, Operation.LOAD_SCHEMA)
51+
.put(OperationType.LIST_SCHEMA, Operation.LIST_SCHEMA)
52+
53+
// Table operation
54+
.put(OperationType.CREATE_TABLE, Operation.CREATE_TABLE)
55+
.put(OperationType.ALTER_TABLE, Operation.ALTER_TABLE)
56+
.put(OperationType.DROP_TABLE, Operation.DROP_TABLE)
57+
.put(OperationType.PURGE_TABLE, Operation.PURGE_TABLE)
58+
.put(OperationType.LOAD_TABLE, Operation.LOAD_TABLE)
59+
.put(OperationType.TABLE_EXISTS, Operation.UNKNOWN_OPERATION)
60+
.put(OperationType.LIST_TABLE, Operation.LIST_TABLE)
61+
62+
// Partition operation
63+
.put(OperationType.ADD_PARTITION, Operation.UNKNOWN_OPERATION)
64+
.put(OperationType.DROP_PARTITION, Operation.UNKNOWN_OPERATION)
65+
.put(OperationType.PURGE_PARTITION, Operation.PURGE_PARTITION)
66+
.put(OperationType.LOAD_PARTITION, Operation.GET_PARTITION)
67+
.put(OperationType.PARTITION_EXISTS, Operation.PARTITION_EXIST)
68+
.put(OperationType.LIST_PARTITION, Operation.LIST_PARTITION)
69+
.put(OperationType.LIST_PARTITION_NAMES, Operation.LIST_PARTITION)
70+
71+
// Fileset operation
72+
.put(OperationType.CREATE_FILESET, Operation.CREATE_FILESET)
73+
.put(OperationType.ALTER_FILESET, Operation.ALTER_FILESET)
74+
.put(OperationType.DROP_FILESET, Operation.DROP_FILESET)
75+
.put(OperationType.LOAD_FILESET, Operation.LOAD_FILESET)
76+
.put(OperationType.LIST_FILESET, Operation.LIST_FILESET)
77+
.put(OperationType.GET_FILESET_LOCATION, Operation.GET_FILE_LOCATION)
78+
79+
// Topic operation
80+
.put(OperationType.CREATE_TOPIC, Operation.CREATE_TOPIC)
81+
.put(OperationType.ALTER_TOPIC, Operation.ALTER_TOPIC)
82+
.put(OperationType.DROP_TOPIC, Operation.DROP_TOPIC)
83+
.put(OperationType.LOAD_TOPIC, Operation.LOAD_TOPIC)
84+
.put(OperationType.LIST_TOPIC, Operation.LIST_TOPIC)
85+
.build();
86+
87+
static Operation toAuditLogOperation(OperationType operationType) {
88+
return operationTypeMap.getOrDefault(operationType, Operation.UNKNOWN_OPERATION);
89+
}
90+
91+
static Status toAuditLogStatus(OperationStatus operationStatus) {
92+
if (operationStatus.equals(OperationStatus.SUCCESS)) {
93+
return Status.SUCCESS;
94+
} else if (operationStatus.equals(OperationStatus.FAILURE)) {
95+
return Status.FAILURE;
96+
} else {
97+
return Status.UNKNOWN;
98+
}
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.gravitino.audit.v2;
21+
22+
import java.text.SimpleDateFormat;
23+
import java.util.Map;
24+
import java.util.Optional;
25+
import org.apache.gravitino.NameIdentifier;
26+
import org.apache.gravitino.audit.AuditLog;
27+
import org.apache.gravitino.listener.api.event.BaseEvent;
28+
import org.apache.gravitino.listener.api.event.EventSource;
29+
import org.apache.gravitino.listener.api.event.OperationStatus;
30+
import org.apache.gravitino.listener.api.event.OperationType;
31+
32+
/**
33+
* Compared to {@link org.apache.gravitino.audit.SimpleAuditLog}, adds audit log for Iceberg REST
34+
* server, add eventSource and remoteAddress to audit log.
35+
*/
36+
public class SimpleAuditLogV2 implements AuditLog {
37+
38+
private final BaseEvent event;
39+
40+
public SimpleAuditLogV2(BaseEvent event) {
41+
this.event = event;
42+
}
43+
44+
@Override
45+
public String user() {
46+
return event.user();
47+
}
48+
49+
@Override
50+
@SuppressWarnings("deprecation")
51+
public Operation operation() {
52+
return CompatibilityUtils.toAuditLogOperation(event.operationType());
53+
}
54+
55+
@Override
56+
public String identifier() {
57+
return Optional.ofNullable(event.identifier()).map(NameIdentifier::toString).orElse(null);
58+
}
59+
60+
@Override
61+
public long timestamp() {
62+
return event.eventTime();
63+
}
64+
65+
@Override
66+
@SuppressWarnings("deprecation")
67+
public Status status() {
68+
return CompatibilityUtils.toAuditLogStatus(event.operationStatus());
69+
}
70+
71+
@Override
72+
public String remoteAddress() {
73+
return event.remoteAddress();
74+
}
75+
76+
@Override
77+
public OperationStatus operationStatus() {
78+
return event.operationStatus();
79+
}
80+
81+
@Override
82+
public OperationType operationType() {
83+
return event.operationType();
84+
}
85+
86+
@Override
87+
public EventSource eventSource() {
88+
return event.eventSource();
89+
}
90+
91+
@Override
92+
public Map<String, String> customInfo() {
93+
return event.customInfo();
94+
}
95+
96+
@Override
97+
public String toString() {
98+
return String.format(
99+
"[%s]\t%s\t%s\t%s\t%s\t%s\t%s",
100+
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp()),
101+
user(),
102+
operationType(),
103+
identifier(),
104+
operationStatus(),
105+
eventSource(),
106+
remoteAddress());
107+
}
108+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.gravitino.audit.v2;
21+
22+
import org.apache.gravitino.audit.Formatter;
23+
import org.apache.gravitino.listener.api.event.Event;
24+
25+
/** The default formatter implementation of the audit log. */
26+
public class SimpleFormatterV2 implements Formatter {
27+
28+
@Override
29+
public SimpleAuditLogV2 format(Event event) {
30+
return new SimpleAuditLogV2(event);
31+
}
32+
}

0 commit comments

Comments
 (0)