All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.Configuration Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog2;

import com.github.joschi.jadconfig.Parameter;
import com.github.joschi.jadconfig.ValidationException;
import com.github.joschi.jadconfig.Validator;
import com.github.joschi.jadconfig.ValidatorMethod;
import com.github.joschi.jadconfig.converters.StringSetConverter;
import com.github.joschi.jadconfig.converters.TrimmedStringSetConverter;
import com.github.joschi.jadconfig.util.Duration;
import com.github.joschi.jadconfig.validators.PositiveDurationValidator;
import com.github.joschi.jadconfig.validators.PositiveIntegerValidator;
import com.github.joschi.jadconfig.validators.PositiveLongValidator;
import com.github.joschi.jadconfig.validators.StringNotBlankValidator;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.graylog.plugins.views.search.engine.suggestions.FieldValueSuggestionMode;
import org.graylog.plugins.views.search.engine.suggestions.FieldValueSuggestionModeConverter;
import org.graylog.security.certutil.CaConfiguration;
import org.graylog2.cluster.leader.AutomaticLeaderElectionService;
import org.graylog2.cluster.leader.LeaderElectionMode;
import org.graylog2.cluster.leader.LeaderElectionService;
import org.graylog2.cluster.lock.MongoLockService;
import org.graylog2.configuration.converters.JavaDurationConverter;
import org.graylog2.notifications.Notification;
import org.graylog2.security.realm.RootAccountRealm;
import org.graylog2.utilities.IPSubnetConverter;
import org.graylog2.utilities.IpSubnet;
import org.joda.time.DateTimeZone;
import org.joda.time.Period;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Set;

import static org.graylog2.shared.utilities.StringUtils.f;

/**
 * Helper class to hold configuration of Graylog
 */
@SuppressWarnings("FieldMayBeFinal")
public class Configuration extends CaConfiguration {
    public static final String SAFE_CLASSES = "safe_classes";

    /**
     * Deprecated! Use isLeader() instead.
     */
    @Parameter(value = "is_master")
    private boolean isMaster = true;

    @Parameter(value = "stream_aware_field_types")
    private boolean streamAwareFieldTypes = false;

    /**
     * Used for initializing static leader election. You shouldn't use this for other purposes, but if you must, don't
     * use @{@link javax.inject.Named} injection but the getter isLeader() instead.
     **/
    @Parameter(value = "is_leader")
    private Boolean isLeader;

    @Parameter(value = "password_secret", required = true, validators = StringNotBlankValidator.class)
    private String passwordSecret;

    @Parameter(value = "output_batch_size", required = true, validators = PositiveIntegerValidator.class)
    private int outputBatchSize = 500;

    @Parameter(value = "output_flush_interval", required = true, validators = PositiveIntegerValidator.class)
    private int outputFlushInterval = 1;

    @Parameter(value = "outputbuffer_processors", required = true, validators = PositiveIntegerValidator.class)
    private int outputBufferProcessors = 3;

    @Parameter(value = "outputbuffer_processor_threads_core_pool_size", required = true, validators = PositiveIntegerValidator.class)
    private int outputBufferProcessorThreadsCorePoolSize = 3;

    @Parameter(value = "node_id_file", validators = NodeIdFileValidator.class)
    private String nodeIdFile = "/etc/graylog/server/node-id";

    @Parameter(value = "root_username")
    private String rootUsername = "admin";

    // Required unless "root-user" is deactivated in the "deactivated_builtin_authentication_providers" setting
    @Parameter(value = "root_password_sha2")
    private String rootPasswordSha2;

    @Parameter(value = "root_timezone")
    private DateTimeZone rootTimeZone = DateTimeZone.UTC;

    @Parameter(value = "root_email")
    private String rootEmail = "";

    @Parameter(value = "allow_leading_wildcard_searches")
    private boolean allowLeadingWildcardSearches = false;

    @Parameter(value = "allow_highlighting")
    private boolean allowHighlighting = false;

    @Parameter(value = "lb_recognition_period_seconds", validators = PositiveIntegerValidator.class)
    private int loadBalancerRecognitionPeriodSeconds = 3;

    @Parameter(value = "lb_throttle_threshold_percentage", validators = PositiveIntegerValidator.class)
    private int loadBalancerThrottleThresholdPercentage = 100;

    @Parameter(value = "stream_processing_timeout", validators = PositiveLongValidator.class)
    private long streamProcessingTimeout = 2000;

    @Parameter(value = "stream_processing_max_faults", validators = PositiveIntegerValidator.class)
    private int streamProcessingMaxFaults = 3;

    @Parameter(value = "output_module_timeout", validators = PositiveLongValidator.class)
    private long outputModuleTimeout = 10000;

    @Parameter(value = "output_fault_count_threshold", validators = PositiveLongValidator.class)
    private long outputFaultCountThreshold = 5;

    @Parameter(value = "output_fault_penalty_seconds", validators = PositiveLongValidator.class)
    private long outputFaultPenaltySeconds = 30;

    /**
     * Deprecated! Use staleLeaderTimeout instead
     */
    @Parameter(value = "stale_master_timeout", validators = PositiveIntegerValidator.class)
    private int staleMasterTimeout = 2000;

    /**
     * Don't use @{@link javax.inject.Named} injection but the getter getStaleLeaderTimeout() instead.
     **/
    @Parameter(value = "stale_leader_timeout", validators = PositiveIntegerValidator.class)
    private Integer staleLeaderTimeout;

    @Parameter(value = "ldap_connection_timeout", validators = PositiveIntegerValidator.class)
    private int ldapConnectionTimeout = 2000;

    @Parameter(value = "alert_check_interval", validators = PositiveIntegerValidator.class)
    @Deprecated
    private int alertCheckInterval = 60;

    @Parameter(value = "default_message_output_class")
    private String defaultMessageOutputClass = "";

    @Parameter(value = "dashboard_widget_default_cache_time", validators = PositiveDurationValidator.class)
    private Duration dashboardWidgetDefaultCacheTime = Duration.seconds(10L);

    @Parameter(value = "user_password_default_algorithm")
    private String userPasswordDefaultAlgorithm = "bcrypt";

    @Parameter(value = "user_password_bcrypt_salt_size", validators = PositiveIntegerValidator.class)
    private int userPasswordBCryptSaltSize = 10;

    @Parameter(value = "content_packs_loader_enabled")
    private boolean contentPacksLoaderEnabled = false;

    @Parameter(value = "content_packs_dir")
    private Path contentPacksDir = DEFAULT_DATA_DIR.resolve("contentpacks");

    @Parameter(value = "content_packs_auto_install", converter = TrimmedStringSetConverter.class)
    private Set contentPacksAutoInstall = Collections.emptySet();

    @Parameter(value = "index_ranges_cleanup_interval", validators = PositiveDurationValidator.class)
    private Duration indexRangesCleanupInterval = Duration.hours(1L);

    @Parameter(value = "trusted_proxies", converter = IPSubnetConverter.class)
    private Set trustedProxies = Collections.emptySet();

    @Parameter(value = "deactivated_builtin_authentication_providers", converter = StringSetConverter.class)
    private Set deactivatedBuiltinAuthenticationProviders = Collections.emptySet();

    // This is needed for backwards compatibility. The setting in TLSProtocolsConfiguration should be used instead.
    @Parameter(value = "enabled_tls_protocols", converter = StringSetConverter.class)
    private Set enabledTlsProtocols = null;

    @Parameter(value = "failure_handling_queue_capacity", validators = {PositiveIntegerValidator.class})
    private int failureHandlingQueueCapacity = 1000;

    @Parameter(value = "failure_handling_shutdown_await", validators = {PositiveDurationValidator.class})
    private Duration failureHandlingShutdownAwait = Duration.milliseconds(3000);

    @Parameter(value = "is_cloud")
    private boolean isCloud = false;

    @Parameter(value = "auto_restart_inputs")
    private boolean autoRestartInputs = false;

    @Parameter(value = "run_migrations")
    private boolean runMigrations = true;

    @Parameter(value = "ignore_migration_failures")
    private boolean ignoreMigrationFailures = false;

    @Parameter(value = "skip_preflight_checks")
    private boolean skipPreflightChecks = false;

    @Parameter(value = "enable_preflight_web")
    private boolean enablePreflightWeb = false;

    @Parameter(value = "leader_election_mode", converter = LeaderElectionMode.Converter.class)
    private LeaderElectionMode leaderElectionMode = LeaderElectionMode.STATIC;

    @Parameter(value = "leader_election_lock_polling_interval", converter = JavaDurationConverter.class)
    private java.time.Duration leaderElectionLockPollingInterval = AutomaticLeaderElectionService.DEFAULT_POLLING_INTERVAL;

    @Parameter(value = "lock_service_lock_ttl", converter = JavaDurationConverter.class)
    private java.time.Duration lockServiceLockTTL = MongoLockService.MIN_LOCK_TTL;

    @Parameter(value = "system_event_excluded_types", converter = TrimmedStringSetConverter.class)
    private Set systemEventExcludedTypes = Sets.newHashSet(Notification.Type.SIDECAR_STATUS_UNKNOWN.name());

    @Parameter(value = "datanode_proxy_api_allowlist")
    private boolean datanodeProxyAPIAllowlist = true;

    @Parameter(value = "minimum_auto_refresh_interval", required = true)
    private Period minimumAutoRefreshInterval = Period.seconds(1);

    /**
     * Classes considered safe to load by name. A set of prefixes matched against the fully qualified class name.
     */
    @Parameter(value = SAFE_CLASSES, converter = StringSetConverter.class, validators = SafeClassesValidator.class)
    private Set safeClasses = Set.of("org.graylog.", "org.graylog2.");

    @Parameter(value = "field_value_suggestion_mode", required = true, converter = FieldValueSuggestionModeConverter.class)
    private FieldValueSuggestionMode fieldValueSuggestionMode = FieldValueSuggestionMode.ON;

    public boolean maintainsStreamAwareFieldTypes() {
        return streamAwareFieldTypes;
    }

    /**
     * @deprecated Use {@link #isLeader()} instead.
     */
    @Deprecated
    public boolean isMaster() {
        return isLeader();
    }

    /**
     * Returns the configured leader status. This is only valid for static leader election. You should probably
     * use {@link LeaderElectionService#isLeader()} instead.
     */
    public boolean isLeader() {
        return isLeader != null ? isLeader : isMaster;
    }

    /**
     * @deprecated Use {@link #setIsLeader(boolean)} instead
     */
    @Deprecated
    public void setIsMaster(boolean is) {
        setIsLeader(is);
    }

    /**
     * We should remove this method after refactoring {@link org.graylog2.cluster.leader.StaticLeaderElectionService}
     * and {@link org.graylog2.commands.Server} so that they don't need this to communicate demotion from leader to
     * follower anymore.
     */
    public void setIsLeader(boolean is) {
        isLeader = isMaster = is;
    }

    public LeaderElectionMode getLeaderElectionMode() {
        return leaderElectionMode;
    }

    public java.time.Duration getLockServiceLockTTL() {
        return lockServiceLockTTL;
    }

    public Set getSystemEventExcludedTypes() {
        return systemEventExcludedTypes;
    }

    public java.time.Duration getLeaderElectionLockPollingInterval() {
        return leaderElectionLockPollingInterval;
    }

    public String getPasswordSecret() {
        return passwordSecret.trim();
    }

    public int getOutputBatchSize() {
        return outputBatchSize;
    }

    public int getOutputFlushInterval() {
        return outputFlushInterval;
    }

    public int getOutputBufferProcessors() {
        return outputBufferProcessors;
    }

    public int getOutputBufferProcessorThreadsCorePoolSize() {
        return outputBufferProcessorThreadsCorePoolSize;
    }

    public boolean isCloud() {
        return isCloud;
    }

    public boolean getAutoRestartInputs() {
        return autoRestartInputs;
    }

    public boolean runMigrations() {
        return runMigrations;
    }

    public boolean ignoreMigrationFailures() {
        return ignoreMigrationFailures;
    }

    public boolean getSkipPreflightChecks() {
        return skipPreflightChecks;
    }

    public String getNodeIdFile() {
        return nodeIdFile;
    }

    public String getRootUsername() {
        return rootUsername;
    }

    public String getRootPasswordSha2() {
        return rootPasswordSha2;
    }

    public DateTimeZone getRootTimeZone() {
        return rootTimeZone;
    }

    public String getRootEmail() {
        return rootEmail;
    }

    public boolean isAllowLeadingWildcardSearches() {
        return allowLeadingWildcardSearches;
    }

    public boolean isAllowHighlighting() {
        return allowHighlighting;
    }

    public int getLoadBalancerRecognitionPeriodSeconds() {
        return loadBalancerRecognitionPeriodSeconds;
    }

    public long getStreamProcessingTimeout() {
        return streamProcessingTimeout;
    }

    public int getStreamProcessingMaxFaults() {
        return streamProcessingMaxFaults;
    }

    public long getOutputModuleTimeout() {
        return outputModuleTimeout;
    }

    public long getOutputFaultCountThreshold() {
        return outputFaultCountThreshold;
    }

    public long getOutputFaultPenaltySeconds() {
        return outputFaultPenaltySeconds;
    }

    /**
     * @deprecated Use getStaleLeaderTimeout instead
     */
    @Deprecated
    public int getStaleMasterTimeout() {
        return getStaleLeaderTimeout();
    }

    public int getStaleLeaderTimeout() {
        return staleLeaderTimeout != null ? staleLeaderTimeout : staleMasterTimeout;
    }

    public int getLdapConnectionTimeout() {
        return ldapConnectionTimeout;
    }

    @Deprecated
    public int getAlertCheckInterval() {
        return alertCheckInterval;
    }

    public String getDefaultMessageOutputClass() {
        return defaultMessageOutputClass;
    }

    public Duration getDashboardWidgetDefaultCacheTime() {
        return dashboardWidgetDefaultCacheTime;
    }

    public String getUserPasswordDefaultAlgorithm() {
        return userPasswordDefaultAlgorithm;
    }

    public int getUserPasswordBCryptSaltSize() {
        return userPasswordBCryptSaltSize;
    }

    public boolean isContentPacksLoaderEnabled() {
        return contentPacksLoaderEnabled;
    }

    public Path getContentPacksDir() {
        return contentPacksDir;
    }

    public Set getContentPacksAutoInstall() {
        return contentPacksAutoInstall;
    }

    public Duration getIndexRangesCleanupInterval() {
        return indexRangesCleanupInterval;
    }

    public Set getTrustedProxies() {
        return trustedProxies;
    }

    public int getLoadBalancerRequestThrottleJournalUsage() {
        return loadBalancerThrottleThresholdPercentage;
    }

    public Set getDeactivatedBuiltinAuthenticationProviders() {
        return deactivatedBuiltinAuthenticationProviders;
    }

    public int getFailureHandlingQueueCapacity() {
        return failureHandlingQueueCapacity;
    }


    public Duration getFailureHandlingShutdownAwait() {
        return failureHandlingShutdownAwait;
    }

    public Period getMinimumAutoRefreshInterval() {
        return minimumAutoRefreshInterval;
    }

    public Set getSafeClasses() {
        return safeClasses;
    }

    public FieldValueSuggestionMode getFieldValueSuggestionMode() {
        return fieldValueSuggestionMode;
    }

    /**
     * This is needed for backwards compatibility. The setting in TLSProtocolsConfiguration should be used instead.
     */
    @Deprecated
    public Set getEnabledTlsProtocols() {
        return enabledTlsProtocols;
    }

    @ValidatorMethod
    @SuppressWarnings("unused")
    public void validatePasswordSecret() throws ValidationException {
        final String passwordSecret = getPasswordSecret();
        if (passwordSecret == null || passwordSecret.length() < 16) {
            throw new ValidationException("The minimum length for \"password_secret\" is 16 characters.");
        }
    }

    @ValidatorMethod
    @SuppressWarnings("unused")
    public void validateRootUser() throws ValidationException {
        if (getRootPasswordSha2() == null && !isRootUserDisabled()) {
            throw new ValidationException("Required parameter \"root_password_sha2\" not found.");
        }
    }

    @ValidatorMethod
    public void validateLeaderElectionTimeouts() throws ValidationException {
        if (leaderElectionMode != LeaderElectionMode.AUTOMATIC) {
            return;
        }
        if (lockServiceLockTTL.compareTo(MongoLockService.MIN_LOCK_TTL) < 0) {
            throw new ValidationException("The minimum valid \"lock_service_lock_ttl\" is 60 seconds");
        }
        if (leaderElectionLockPollingInterval.compareTo(java.time.Duration.ofSeconds(1)) < 0) {
            throw new ValidationException("The minimum valid \"leader_election_lock_polling_interval\" is 1 second");
        }
        if (lockServiceLockTTL.compareTo(leaderElectionLockPollingInterval) < 1) {
            throw new ValidationException("The \"leader_election_lock_polling_interval\" needs to be greater than the \"lock_service_lock_ttl\"!");
        }
    }

    /**
     * The root user is disabled if the {@link RootAccountRealm} is deactivated.
     */
    public boolean isRootUserDisabled() {
        return getDeactivatedBuiltinAuthenticationProviders().contains(RootAccountRealm.NAME);
    }

    public boolean enablePreflightWebserver() {
        return enablePreflightWeb;
    }

    public static class NodeIdFileValidator implements Validator {
        @Override
        public void validate(String name, String path) throws ValidationException {
            if (path == null) {
                return;
            }
            final File file = Paths.get(path).toFile();
            final StringBuilder b = new StringBuilder();

            if (!file.exists()) {
                final File parent = file.getParentFile();
                if (!parent.isDirectory()) {
                    throw new ValidationException("Parent path " + parent + " for Node ID file at " + path + " is not a directory");
                } else {
                    if (!parent.canRead()) {
                        throw new ValidationException("Parent directory " + parent + " for Node ID file at " + path + " is not readable");
                    }
                    if (!parent.canWrite()) {
                        throw new ValidationException("Parent directory " + parent + " for Node ID file at " + path + " is not writable");
                    }

                    // parent directory exists and is readable and writable
                    return;
                }
            }

            if (!file.isFile()) {
                b.append("a file");
            }
            final boolean readable = file.canRead();
            final boolean writable = file.canWrite();
            if (!readable) {
                if (b.length() > 0) {
                    b.append(", ");
                }
                b.append("readable");
            }
            final boolean empty = file.length() == 0;
            if (!writable && readable && empty) {
                if (b.length() > 0) {
                    b.append(", ");
                }
                b.append("writable, but it is empty");
            }
            if (b.length() == 0) {
                // all good
                return;
            }
            throw new ValidationException("Node ID file at path " + path + " isn't " + b + ". Please specify the correct path or change the permissions");
        }
    }

    public static class SafeClassesValidator implements Validator> {
        @Override
        public void validate(String name, Set set) throws ValidationException {
            if (set.isEmpty()) {
                throw new ValidationException(f("\"%s\" must not be empty. Please specify a comma-separated list of " +
                        "fully-qualified class name prefixes.", name));
            }
            if (set.stream().anyMatch(StringUtils::isBlank)) {
                throw new ValidationException(f("\"%s\" must only contain non-empty class name prefixes.", name));
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy