blob: 4d3b86745e71e42476af3b04fa9cfd936fec5ef8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.audit;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.apache.cassandra.auth.AuthenticatedUser;
import org.apache.cassandra.cql3.CQLStatement;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.utils.FBUtilities;
public class AuditLogEntry
{
private final InetAddressAndPort host = FBUtilities.getBroadcastAddressAndPort();
private final InetAddressAndPort source;
private final String user;
private final long timestamp;
private final AuditLogEntryType type;
private final UUID batch;
private final String keyspace;
private final String scope;
private final String operation;
private final QueryOptions options;
private final QueryState state;
private AuditLogEntry(AuditLogEntryType type,
InetAddressAndPort source,
String user,
long timestamp,
UUID batch,
String keyspace,
String scope,
String operation,
QueryOptions options,
QueryState state)
{
this.type = type;
this.source = source;
this.user = user;
this.timestamp = timestamp;
this.batch = batch;
this.keyspace = keyspace;
this.scope = scope;
this.operation = operation;
this.options = options;
this.state = state;
}
String getLogString()
{
StringBuilder builder = new StringBuilder(100);
builder.append("user:").append(user)
.append("|host:").append(host)
.append("|source:").append(source.address);
if (source.port > 0)
{
builder.append("|port:").append(source.port);
}
builder.append("|timestamp:").append(timestamp)
.append("|type:").append(type)
.append("|category:").append(type.getCategory());
if (batch != null)
{
builder.append("|batch:").append(batch);
}
if (StringUtils.isNotBlank(keyspace))
{
builder.append("|ks:").append(keyspace);
}
if (StringUtils.isNotBlank(scope))
{
builder.append("|scope:").append(scope);
}
if (StringUtils.isNotBlank(operation))
{
builder.append("|operation:").append(operation);
}
return builder.toString();
}
public InetAddressAndPort getHost()
{
return host;
}
public InetAddressAndPort getSource()
{
return source;
}
public String getUser()
{
return user;
}
public long getTimestamp()
{
return timestamp;
}
public AuditLogEntryType getType()
{
return type;
}
public UUID getBatch()
{
return batch;
}
public String getKeyspace()
{
return keyspace;
}
public String getScope()
{
return scope;
}
public String getOperation()
{
return operation;
}
public QueryOptions getOptions()
{
return options;
}
public QueryState getState()
{
return state;
}
public static class Builder
{
private static final InetAddressAndPort DEFAULT_SOURCE;
static
{
try
{
DEFAULT_SOURCE = InetAddressAndPort.getByNameOverrideDefaults("0.0.0.0", 0);
}
catch (UnknownHostException e)
{
throw new RuntimeException("failed to create default source address", e);
}
}
private static final String DEFAULT_OPERATION = StringUtils.EMPTY;
private AuditLogEntryType type;
private InetAddressAndPort source;
private String user;
private long timestamp;
private UUID batch;
private String keyspace;
private String scope;
private String operation;
private QueryOptions options;
private QueryState state;
public Builder(QueryState queryState)
{
state = queryState;
ClientState clientState = queryState.getClientState();
if (clientState != null)
{
if (clientState.getRemoteAddress() != null)
{
InetSocketAddress addr = clientState.getRemoteAddress();
source = InetAddressAndPort.getByAddressOverrideDefaults(addr.getAddress(), addr.getPort());
}
if (clientState.getUser() != null)
{
user = clientState.getUser().getName();
}
keyspace = clientState.getRawKeyspace();
}
else
{
source = DEFAULT_SOURCE;
user = AuthenticatedUser.SYSTEM_USER.getName();
}
timestamp = System.currentTimeMillis();
}
public Builder(AuditLogEntry entry)
{
type = entry.type;
source = entry.source;
user = entry.user;
timestamp = entry.timestamp;
batch = entry.batch;
keyspace = entry.keyspace;
scope = entry.scope;
operation = entry.operation;
options = entry.options;
state = entry.state;
}
public Builder setType(AuditLogEntryType type)
{
this.type = type;
return this;
}
public Builder(AuditLogEntryType type)
{
this.type = type;
operation = DEFAULT_OPERATION;
}
public Builder setUser(String user)
{
this.user = user;
return this;
}
public Builder setBatch(UUID batch)
{
this.batch = batch;
return this;
}
public Builder setTimestamp(long timestampMillis)
{
this.timestamp = timestampMillis;
return this;
}
public Builder setKeyspace(QueryState queryState, @Nullable CQLStatement statement)
{
keyspace = statement != null && statement.getAuditLogContext().keyspace != null
? statement.getAuditLogContext().keyspace
: queryState.getClientState().getRawKeyspace();
return this;
}
public Builder setKeyspace(String keyspace)
{
this.keyspace = keyspace;
return this;
}
public Builder setKeyspace(CQLStatement statement)
{
this.keyspace = statement.getAuditLogContext().keyspace;
return this;
}
public Builder setScope(CQLStatement statement)
{
this.scope = statement.getAuditLogContext().scope;
return this;
}
public Builder setOperation(String operation)
{
this.operation = operation;
return this;
}
public void appendToOperation(String str)
{
if (StringUtils.isNotBlank(str))
{
if (operation.isEmpty())
operation = str;
else
operation = operation.concat("; ").concat(str);
}
}
public Builder setOptions(QueryOptions options)
{
this.options = options;
return this;
}
public AuditLogEntry build()
{
timestamp = timestamp > 0 ? timestamp : System.currentTimeMillis();
return new AuditLogEntry(type, source, user, timestamp, batch, keyspace, scope, operation, options, state);
}
}
}