| /* |
| * 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.util.Arrays; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.function.BiConsumer; |
| import java.util.function.Function; |
| import java.util.stream.Collectors; |
| import javax.management.openmbean.CompositeData; |
| import javax.management.openmbean.CompositeDataSupport; |
| import javax.management.openmbean.CompositeType; |
| import javax.management.openmbean.OpenDataException; |
| import javax.management.openmbean.OpenType; |
| import javax.management.openmbean.SimpleType; |
| |
| import org.apache.cassandra.config.ParameterizedClass; |
| import org.apache.cassandra.utils.Pair; |
| |
| import static org.apache.cassandra.audit.AuditLogOptionsCompositeData.AuditLogOption.option; |
| |
| public class AuditLogOptionsCompositeData |
| { |
| public static class AuditLogOption |
| { |
| // TODO these constants will be used in upcoming audit log vtable too, see CASSANDRA-16725 |
| public static final String AUDIT_LOGS_DIR = "audit_logs_dir"; |
| public static final String ARCHIVE_COMMAND = "archive_command"; |
| public static final String ROLL_CYCLE = "roll_cycle"; |
| public static final String BLOCK = "block"; |
| public static final String MAX_QUEUE_WEIGHT = "max_queue_weight"; |
| public static final String MAX_LOG_SIZE = "max_log_size"; |
| public static final String MAX_ARCHIVE_RETRIES = "max_archive_retries"; |
| public static final String ENABLED = "enabled"; |
| public static final String INCLUDED_KEYSPACES = "included_keyspaces"; |
| public static final String EXCLUDED_KEYSPACES = "excluded_keyspaces"; |
| public static final String INCLUDED_CATEGORIES = "included_categories"; |
| public static final String EXCLUDED_CATEGORIES = "excluded_categories"; |
| public static final String INCLUDED_USERS = "included_users"; |
| public static final String EXCLUDED_USERS = "excluded_users"; |
| public static final String LOGGER = "logger"; |
| |
| private final String name; |
| private final String description; |
| private final OpenType<?> type; |
| private final Function<AuditLogOptions, Object> toCompositeMapping; |
| private final BiConsumer<AuditLogOptions, Object> fromCompositeMapping; |
| |
| public AuditLogOption(final String name, |
| final String description, |
| final OpenType<?> type, |
| final Function<AuditLogOptions, Object> toCompositeMapping, |
| final BiConsumer<AuditLogOptions, Object> fromCompositeMapping) |
| { |
| this.name = name; |
| this.description = description; |
| this.type = type; |
| this.toCompositeMapping = toCompositeMapping; |
| this.fromCompositeMapping = fromCompositeMapping; |
| } |
| |
| public static AuditLogOption option(final String name, |
| final String description, |
| final OpenType<?> type, |
| final Function<AuditLogOptions, Object> toCompositeMapping, |
| final BiConsumer<AuditLogOptions, Object> fromCompositeMapping) |
| { |
| return new AuditLogOption(name, description, type, toCompositeMapping, fromCompositeMapping); |
| } |
| } |
| |
| private static final AuditLogOption[] options = new AuditLogOption[]{ |
| option(AuditLogOption.AUDIT_LOGS_DIR, |
| "directory where audit data are stored", |
| SimpleType.STRING, |
| o -> o.audit_logs_dir, |
| (opts, obj) -> opts.audit_logs_dir = (String) obj), |
| |
| option(AuditLogOption.ARCHIVE_COMMAND, |
| "archive command for audit data", |
| SimpleType.STRING, |
| o -> o.archive_command, |
| (opts, obj) -> opts.archive_command = (String) obj), |
| |
| option(AuditLogOption.ROLL_CYCLE, |
| "how often to roll BinLog segments so they can potentially be reclaimed", |
| SimpleType.STRING, |
| o -> o.roll_cycle, |
| (opts, obj) -> opts.roll_cycle = (String) obj), |
| |
| option(AuditLogOption.BLOCK, |
| "indicates if the BinLog should block if it falls behind or should drop bin log records", |
| SimpleType.BOOLEAN, |
| o -> o.block, |
| (opts, obj) -> opts.block = (Boolean) obj), |
| |
| option(AuditLogOption.MAX_QUEUE_WEIGHT, |
| "maximum weight of in-memory queue for records waiting to be written to the binlog file before blocking or dropping the log records", |
| SimpleType.INTEGER, |
| o -> o.max_queue_weight, |
| (opts, obj) -> opts.max_queue_weight = (Integer) obj), |
| |
| option(AuditLogOption.MAX_LOG_SIZE, |
| "maximum size of the rolled files to retain on disk before deleting the oldest file", |
| SimpleType.LONG, |
| o -> o.max_log_size, |
| (opts, obj) -> opts.max_log_size = (Long) obj), |
| |
| option(AuditLogOption.MAX_ARCHIVE_RETRIES, |
| "number of times to retry an archive command", |
| SimpleType.INTEGER, |
| o -> o.max_archive_retries, |
| (opts, obj) -> opts.max_archive_retries = (Integer) obj), |
| |
| option(AuditLogOption.ENABLED, |
| "boolean telling if we are enabled or not", |
| SimpleType.BOOLEAN, |
| o -> o.enabled, |
| (opts, obj) -> opts.enabled = (Boolean) obj), |
| |
| option(AuditLogOption.INCLUDED_KEYSPACES, |
| "included keyspaces", |
| SimpleType.STRING, |
| o -> o.included_keyspaces, |
| (opts, obj) -> opts.included_keyspaces = (String) obj), |
| |
| option(AuditLogOption.EXCLUDED_KEYSPACES, |
| "excluded keyspaces", |
| SimpleType.STRING, |
| o -> o.excluded_keyspaces, |
| (opts, obj) -> opts.excluded_keyspaces = (String) obj), |
| |
| option(AuditLogOption.INCLUDED_CATEGORIES, |
| "included categories", |
| SimpleType.STRING, |
| o -> o.included_categories, |
| (opts, obj) -> opts.included_categories = (String) obj), |
| |
| option(AuditLogOption.EXCLUDED_CATEGORIES, |
| "excluded categories", |
| SimpleType.STRING, |
| o -> o.excluded_categories, |
| (opts, obj) -> opts.excluded_categories = (String) obj), |
| |
| option(AuditLogOption.INCLUDED_USERS, |
| "included users", |
| SimpleType.STRING, |
| o -> o.included_users, |
| (opts, obj) -> opts.included_users = (String) obj), |
| |
| option(AuditLogOption.EXCLUDED_USERS, |
| "excluded users", |
| SimpleType.STRING, |
| o -> o.excluded_users, |
| (opts, obj) -> opts.excluded_users = (String) obj), |
| |
| option(AuditLogOption.LOGGER, |
| "audit logger implementation class name", |
| SimpleType.STRING, |
| o -> o.logger.class_name, |
| (opts, obj) -> opts.logger = new ParameterizedClass((String) obj, new HashMap<>())) |
| }; |
| |
| public static final CompositeType COMPOSITE_TYPE; |
| |
| static |
| { |
| try |
| { |
| COMPOSITE_TYPE = new CompositeType(AuditLogOptions.class.getName(), |
| "AuditLogOptions", |
| Arrays.stream(options).map(o -> o.name).toArray(String[]::new), |
| Arrays.stream(options).map(o -> o.description).toArray(String[]::new), |
| Arrays.stream(options).map(o -> o.type).toArray(OpenType[]::new)); |
| } |
| catch (final OpenDataException e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| public static CompositeData toCompositeData(final AuditLogOptions opts) |
| { |
| try |
| { |
| final Map<String, Object> valueMap = new HashMap<>(); |
| |
| for (final Pair<String, Function<AuditLogOptions, Object>> pair : Arrays.stream(options).map(o -> Pair.create(o.name, o.toCompositeMapping)).collect(Collectors.toList())) |
| { |
| valueMap.put(pair.left, pair.right.apply(opts)); |
| } |
| |
| return new CompositeDataSupport(COMPOSITE_TYPE, valueMap); |
| } |
| catch (final OpenDataException e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| public static AuditLogOptions fromCompositeData(final CompositeData data) |
| { |
| assert data.getCompositeType().equals(COMPOSITE_TYPE); |
| |
| final Object[] values = data.getAll(Arrays.stream(options).map(o -> o.name).toArray(String[]::new)); |
| final AuditLogOptions opts = new AuditLogOptions(); |
| |
| for (int i = 0; i < values.length; i++) |
| { |
| options[i].fromCompositeMapping.accept(opts, values[i]); |
| } |
| |
| return opts; |
| } |
| } |