This is an automated email from the ASF dual-hosted git repository. mck pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 1defa0851f7c1a557ebf76a566070308c222fa16 Merge: b9f900947a 2dea5c7588 Author: mck <[email protected]> AuthorDate: Wed Oct 9 13:52:22 2024 +0200 Merge branch 'cassandra-5.0' into trunk * cassandra-5.0: Use ParameterizedClass for all auth-related implementations CHANGES.txt | 1 + conf/cassandra.yaml | 32 +++++++++-- conf/cassandra_latest.yaml | 32 +++++++++-- src/java/org/apache/cassandra/auth/AuthConfig.java | 64 ++++++++++++---------- .../org/apache/cassandra/auth/ICIDRAuthorizer.java | 17 ------ src/java/org/apache/cassandra/config/Config.java | 6 +- .../org/apache/cassandra/utils/FBUtilities.java | 39 ------------- test/data/config/version=5.0-alpha1.yml | 14 +++-- ...rsion=5.0-alpha1.yml => version=5.1-alpha1.yml} | 17 ++++-- .../cassandra/audit/AuditLoggerAuthTest.java | 4 +- .../cassandra/config/ConfigCompatibilityTest.java | 16 +++++- .../cassandra/transport/CQLUserAuditTest.java | 2 +- .../apache/cassandra/transport/TlsTestUtils.java | 4 +- 13 files changed, 136 insertions(+), 112 deletions(-) diff --cc CHANGES.txt index 54dbbe1cf5,27d68e9c80..33aae06b4e --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,92 -1,16 +1,93 @@@ -5.0.2 +5.1 + * Add total space used for a keyspace to nodetool tablestats (CASSANDRA-19671) + * Ensure Relation#toRestriction() handles ReversedType properly (CASSANDRA-19950) + * Add JSON and YAML output option to nodetool gcstats (CASSANDRA-19771) + * Introduce metadata serialization version V4 (CASSANDRA-19970) + * Allow CMS reconfiguration to work around DOWN nodes (CASSANDRA-19943) + * Make TableParams.Serializer set allowAutoSnapshots and incrementalBackups (CASSANDRA-19954) + * Make sstabledump possible to show tombstones only (CASSANDRA-19939) + * Ensure that RFP queries potentially stale replicas even with only key columns in the row filter (CASSANDRA-19938) + * Allow nodes to change IP address while upgrading to TCM (CASSANDRA-19921) + * Retain existing keyspace params on system tables after upgrade (CASSANDRA-19916) + * Deprecate use of gossip state for paxos electorate verification (CASSANDRA-19904) + * Update dtest-api to 0.0.17 to fix jvm17 crash in jvm-dtests (CASSANDRA-19239) + * Add resource leak test and Update Netty to 4.1.113.Final to fix leak (CASSANDRA-19783) + * Fix incorrect nodetool suggestion when gossip mode is running (CASSANDRA-19905) + * SAI support for BETWEEN operator (CASSANDRA-19688) + * Fix BETWEEN filtering for reversed clustering columns (CASSANDRA-19878) + * Retry if node leaves CMS while committing a transformation (CASSANDRA-19872) + * Add support for NOT operators in WHERE clauses. Fixed Three Valued Logic (CASSANDRA-18584) + * Allow getendpoints for system tables and make sure getNaturalReplicas work for MetaStrategy (CASSANDRA-19846) + * On upgrade, handle pre-existing tables with unexpected table ids (CASSANDRA-19845) + * Reconfigure CMS before assassinate (CASSANDRA-19768) + * Warn about unqualified prepared statement only if it is select or modification statement (CASSANDRA-18322) + * Update legacy peers tables during node replacement (CASSANDRA-19782) + * Refactor ColumnCondition (CASSANDRA-19620) + * Allow configuring log format for Audit Logs (CASSANDRA-19792) + * Support for noboolean rpm (centos7 compatible) packages removed (CASSANDRA-19787) + * Allow threads waiting for the metadata log follower to be interrupted (CASSANDRA-19761) + * Support dictionary lookup for CassandraPasswordValidator (CASSANDRA-19762) + * Disallow denylisting keys in system_cluster_metadata (CASSANDRA-19713) + * Fix gossip status after replacement (CASSANDRA-19712) + * Ignore repair requests for system_cluster_metadata (CASSANDRA-19711) + * Avoid ClassCastException when verifying tables with reversed partitioner (CASSANDRA-19710) + * Always repair the full range when repairing system_cluster_metadata (CASSANDRA-19709) + * Use table-specific partitioners during Paxos repair (CASSANDRA-19714) + * Expose current compaction throughput in nodetool (CASSANDRA-13890) + * CEP-24 Password validation / generation (CASSANDRA-17457) + * Reconfigure CMS after replacement, bootstrap and move operations (CASSANDRA-19705) + * Support querying LocalStrategy tables with any partitioner (CASSANDRA-19692) + * Relax slow_query_log_timeout for MultiNodeSAITest (CASSANDRA-19693) + * Audit Log entries are missing identity for mTLS connections (CASSANDRA-19669) + * Add support for the BETWEEN operator in WHERE clauses (CASSANDRA-19604) + * Replace Stream iteration with for-loop for SimpleRestriction::bindAndGetClusteringElements (CASSANDRA-19679) + * Consolidate logging on trace level (CASSANDRA-19632) + * Expand DDL statements on coordinator before submission to the CMS (CASSANDRA-19592) + * Fix number of arguments of String.format() in various classes (CASSANDRA-19645) + * Remove unused fields from config (CASSANDRA-19599) + * Refactor Relation and Restriction hierarchies (CASSANDRA-19341) + * Raise priority of TCM internode messages during critical operations (CASSANDRA-19517) + * Add nodetool command to unregister LEFT nodes (CASSANDRA-19581) + * Add cluster metadata id to gossip syn messages (CASSANDRA-19613) + * Reduce heap usage occupied by the metrics (CASSANDRA-19567) + * Improve handling of transient replicas during range movements (CASSANDRA-19344) + * Enable debounced internode log requests to be cancelled at shutdown (CASSANDRA-19514) + * Correctly set last modified epoch when combining multistep operations into a single step (CASSANDRA-19538) + * Add new TriggersPolicy configuration to allow operators to disable triggers (CASSANDRA-19532) + * Use Transformation.Kind.id in local and distributed log tables (CASSANDRA-19516) + * Remove period field from ClusterMetadata and metadata log tables (CASSANDRA-19482) + * Enrich system_views.pending_hints vtable with hints sizes (CASSANDRA-19486) + * Expose all dropwizard metrics in virtual tables (CASSANDRA-14572) + * Ensured that PropertyFileSnitchTest do not overwrite cassandra-toploogy.properties (CASSANDRA-19502) + * Add option for MutualTlsAuthenticator to restrict the certificate validity period (CASSANDRA-18951) + * Fix StorageService::constructRangeToEndpointMap for non-distributed keyspaces (CASSANDRA-19255) + * Group nodetool cms commands into single command group (CASSANDRA-19393) + * Register the measurements of the bootstrap process as Dropwizard metrics (CASSANDRA-19447) + * Add LIST SUPERUSERS CQL statement (CASSANDRA-19417) + * Modernize CQLSH datetime conversions (CASSANDRA-18879) + * Harry model and in-JVM tests for partition-restricted 2i queries (CASSANDRA-18275) + * Refactor cqlshmain global constants (CASSANDRA-19201) + * Remove native_transport_port_ssl (CASSANDRA-19397) + * Make nodetool reconfigurecms sync by default and add --cancel to be able to cancel ongoing reconfigurations (CASSANDRA-19216) + * Expose auth mode in system_views.clients, nodetool clientstats, metrics (CASSANDRA-19366) + * Remove sealed_periods and last_sealed_period tables (CASSANDRA-19189) + * Improve setup and initialisation of LocalLog/LogSpec (CASSANDRA-19271) + * Refactor structure of caching metrics and expose auth cache metrics via JMX (CASSANDRA-17062) + * Allow CQL client certificate authentication to work without sending an AUTHENTICATE request (CASSANDRA-18857) + * Extend nodetool tpstats and system_views.thread_pools with detailed pool parameters (CASSANDRA-19289) + * Remove dependency on Sigar in favor of OSHI (CASSANDRA-16565) + * Simplify the bind marker and Term logic (CASSANDRA-18813) + * Limit cassandra startup to supported JDKs, allow higher JDKs by setting CASSANDRA_JDK_UNSUPPORTED (CASSANDRA-18688) + * Standardize nodetool tablestats formatting of data units (CASSANDRA-19104) + * Make nodetool tablestats use number of significant digits for time and average values consistently (CASSANDRA-19015) + * Upgrade jackson to 2.15.3 and snakeyaml to 2.1 (CASSANDRA-18875) + * Transactional Cluster Metadata [CEP-21] (CASSANDRA-18330) + * Add ELAPSED command to cqlsh (CASSANDRA-18861) + * Add the ability to disable bulk loading of SSTables (CASSANDRA-18781) + * Clean up obsolete functions and simplify cql_version handling in cqlsh (CASSANDRA-18787) +Merged from 5.0: + * Use ParameterizedClass for all auth-related implementations (CASSANDRA-19946) * Correct out-of-date metrics and configuration documentation for SAI (CASSANDRA-19898) -Merged from 4.1: - * Fix race condition in DecayingEstimatedHistogramReservoir during rescale (CASSANDRA-19365) -Merged from 4.0: - * Ensure thread-safety for CommitLogArchiver in CommitLog (CASSANDRA-19960) - * Fix text containing "/*" being interpreted as multiline comment in cqlsh (CASSANDRA-17667) - * Fix indexing of a frozen collection that is the clustering key and reversed (CASSANDRA-19889) - * Emit error when altering a table with non-frozen UDTs with nested non-frozen collections the same way as done upon table creation (CASSANDRA-19925) - - -5.0.1 * Make configuration entries in memtable section order-independent (CASSANDRA-19906) * Add guardrail for enabling usage of VectorType (CASSANDRA-19903) * Set executable flag for shell scripts in .build directory for source artifact (CASSANDRA-19896) diff --cc conf/cassandra.yaml index 546333dfcf,5562a2c156..1c53401057 --- a/conf/cassandra.yaml +++ b/conf/cassandra.yaml @@@ -165,8 -169,7 +169,8 @@@ batchlog_replay_throttle: 1024Ki # users. It keeps usernames and hashed passwords in system_auth.roles table. # Please increase system_auth keyspace replication factor if you use this authenticator. # If using PasswordAuthenticator, CassandraRoleManager must also be used (see below) -authenticator: AllowAllAuthenticator +authenticator: - class_name : org.apache.cassandra.auth.AllowAllAuthenticator ++ class_name : AllowAllAuthenticator # MutualTlsAuthenticator can be configured using the following configuration. One can add their own validator # which implements MutualTlsCertificateValidator class and provide logic for extracting identity out of certificates # and validating certificates. @@@ -181,7 -188,7 +189,8 @@@ # - AllowAllAuthorizer allows any action to any user - set it to disable authorization. # - CassandraAuthorizer stores permissions in system_auth.role_permissions table. Please # increase system_auth keyspace replication factor if you use this authorizer. --authorizer: AllowAllAuthorizer ++authorizer: ++ class_name: AllowAllAuthorizer # Part of the Authentication & Authorization backend, implementing IRoleManager; used # to maintain grants and memberships between roles. @@@ -192,7 -203,7 +205,8 @@@ # # - CassandraRoleManager stores role data in the system_auth keyspace. Please # increase system_auth keyspace replication factor if you use this role manager. --role_manager: CassandraRoleManager ++role_manager: ++ class_name: CassandraRoleManager # Network authorization backend, implementing INetworkAuthorizer; used to restrict user # access to certain DCs @@@ -202,7 -217,7 +220,8 @@@ # - AllowAllNetworkAuthorizer allows access to any DC to any user - set it to disable authorization. # - CassandraNetworkAuthorizer stores permissions in system_auth.network_permissions table. Please # increase system_auth keyspace replication factor if you use this authorizer. --network_authorizer: AllowAllNetworkAuthorizer ++network_authorizer: ++ class_name: AllowAllNetworkAuthorizer # CIDR authorization backend, implementing ICIDRAuthorizer; used to restrict user # access from certain CIDRs diff --cc test/data/config/version=5.1-alpha1.yml index ce1da70bd9,0000000000..e730adcdb9 mode 100644,000000..100644 --- a/test/data/config/version=5.1-alpha1.yml +++ b/test/data/config/version=5.1-alpha1.yml @@@ -1,490 -1,0 +1,495 @@@ +# 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. +# +# +--- +columns_per_table_warn_threshold: "java.lang.Integer" +repaired_data_tracking_for_range_reads_enabled: "java.lang.Boolean" +cdc_block_writes: "java.lang.Boolean" +block_for_peers_timeout_in_secs: "java.lang.Integer" +flush_compression: "org.apache.cassandra.config.Config.FlushCompression" +commitlog_total_space: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +audit_logging_options: + audit_logs_dir: "java.lang.String" + included_users: "java.lang.String" + logger: + class_name: "java.lang.String" + parameters: "java.util.Map" + excluded_categories: "java.lang.String" + roll_cycle: "java.lang.String" + enabled: "java.lang.Boolean" + included_categories: "java.lang.String" + max_archive_retries: "java.lang.Integer" + excluded_keyspaces: "java.lang.String" + archive_command: "java.lang.String" + included_keyspaces: "java.lang.String" + max_log_size: "java.lang.Long" + allow_nodetool_archive_command: "java.lang.Boolean" + block: "java.lang.Boolean" + excluded_users: "java.lang.String" + max_queue_weight: "java.lang.Integer" +row_cache_save_period: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +snapshot_links_per_second: "java.lang.Long" +disk_optimization_estimate_percentile: "java.lang.Double" +roles_update_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +hinted_handoff_disabled_datacenters: "java.util.Set" +cdc_enabled: "java.lang.Boolean" +internode_application_receive_queue_reserve_endpoint_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +roles_validity: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +coordinator_read_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +scripted_user_defined_functions_enabled: "java.lang.Boolean" +auth_cache_warming_enabled: "java.lang.Boolean" +alter_table_enabled: "java.lang.Boolean" +client_request_size_metrics_enabled: "java.lang.Boolean" +cdc_on_repair_enabled: "java.lang.Boolean" +entire_sstable_stream_throughput_outbound: "org.apache.cassandra.config.DataRateSpec.LongBytesPerSecondBound" +partition_tombstones_warn_threshold: "java.lang.Long" +roles_cache_active_update: "java.lang.Boolean" +commitlog_sync: "org.apache.cassandra.config.Config.CommitLogSync" +paxos_repair_parallelism: "java.lang.Integer" +dynamic_snitch_reset_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +dynamic_snitch_update_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +native_transport_idle_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +internode_application_send_queue_reserve_global_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +concurrent_materialized_view_writes: "java.lang.Integer" +read_before_write_list_operations_enabled: "java.lang.Boolean" +table_properties_ignored: "java.util.Set" +maximum_timestamp_warn_threshold: "org.apache.cassandra.config.DurationSpec.LongMicrosecondsBound" +hints_directory: "java.lang.String" +dump_heap_on_uncaught_exception: "java.lang.Boolean" +native_transport_max_concurrent_connections_per_ip: "java.lang.Long" +secondary_indexes_per_table_fail_threshold: "java.lang.Integer" +vector_dimensions_warn_threshold: "java.lang.Integer" +auto_snapshot_ttl: "java.lang.String" +rpc_interface_prefer_ipv6: "java.lang.Boolean" +check_for_duplicate_rows_during_compaction: "java.lang.Boolean" +gc_log_threshold: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +secondary_indexes_enabled: "java.lang.Boolean" +user_function_timeout_policy: "org.apache.cassandra.config.Config.UserFunctionTimeoutPolicy" +memtable_allocation_type: "org.apache.cassandra.config.Config.MemtableAllocationType" +hints_flush_period: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +default_keyspace_rf: "java.lang.Integer" +tombstone_warn_threshold: "java.lang.Integer" +write_consistency_levels_warned: "java.util.Set" +full_query_logging_options: + log_dir: "java.lang.String" + archive_command: "java.lang.String" + max_log_size: "java.lang.Long" + allow_nodetool_archive_command: "java.lang.Boolean" + block: "java.lang.Boolean" + roll_cycle: "java.lang.String" + max_queue_weight: "java.lang.Integer" + max_archive_retries: "java.lang.Integer" +streaming_keep_alive_period: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +auto_optimise_inc_repair_streams: "java.lang.Boolean" +user_defined_functions_fail_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +write_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +min_tracked_partition_tombstone_count: "java.lang.Long" +sasi_indexes_enabled: "java.lang.Boolean" +disk_failure_policy: "org.apache.cassandra.config.Config.DiskFailurePolicy" +heap_dump_path: "java.lang.String" +tombstone_failure_threshold: "java.lang.Integer" +native_transport_max_request_data_in_flight: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +initial_token: "java.lang.String" +keyspaces_warn_threshold: "java.lang.Integer" +dynamic_snitch_badness_threshold: "java.lang.Double" +transient_replication_enabled: "java.lang.Boolean" +allocate_tokens_for_local_replication_factor: "java.lang.Integer" +native_transport_max_requests_per_second: "java.lang.Integer" +counter_cache_keys_to_save: "java.lang.Integer" +disk_optimization_page_cross_chance: "java.lang.Double" +in_select_cartesian_product_fail_threshold: "java.lang.Integer" +listen_on_broadcast_address: "java.lang.Boolean" +row_cache_class_name: "java.lang.String" +permissions_update_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +denylist_initial_load_retry: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +trace_type_query_ttl: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +disk_optimization_strategy: "org.apache.cassandra.config.Config.DiskOptimizationStrategy" +drop_keyspace_enabled: "java.lang.Boolean" +otc_backlog_expiration_interval_ms: "java.lang.Integer" +native_transport_max_request_data_in_flight_per_ip: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +counter_cache_save_period: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +tables_fail_threshold: "java.lang.Integer" +trace_type_repair_ttl: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +minimum_replication_factor_warn_threshold: "java.lang.Integer" +page_size_warn_threshold: "java.lang.Integer" - role_manager: "java.lang.String" ++role_manager: ++ class_name: "java.lang.String" ++ parameters: "java.util.Map" +counter_write_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +denylist_writes_enabled: "java.lang.Boolean" +block_for_peers_in_remote_dcs: "java.lang.Boolean" +inter_dc_stream_throughput_outbound: "org.apache.cassandra.config.DataRateSpec.LongBytesPerSecondBound" +repair_command_pool_size: "java.lang.Integer" +denylist_consistency_level: "org.apache.cassandra.db.ConsistencyLevel" +table_properties_warned: "java.util.Set" +entire_sstable_inter_dc_stream_throughput_outbound: "org.apache.cassandra.config.DataRateSpec.LongBytesPerSecondBound" +data_file_directories: "java.util.List" +default_secondary_index: "java.lang.String" +networking_cache_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +fields_per_udt_fail_threshold: "java.lang.Integer" +key_cache_size: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +max_hint_window: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +sai_options: + segment_write_buffer_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +vector_dimensions_fail_threshold: "java.lang.Integer" +max_hints_size_per_host: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +partition_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +maximum_timestamp_fail_threshold: "org.apache.cassandra.config.DurationSpec.LongMicrosecondsBound" +minimum_timestamp_warn_threshold: "org.apache.cassandra.config.DurationSpec.LongMicrosecondsBound" +client_error_reporting_exclusions: + subnets: "java.util.Set" +seed_provider: + class_name: "java.lang.String" + parameters: "java.util.Map" +check_for_duplicate_rows_during_reads: "java.lang.Boolean" +internode_max_message_size: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +items_per_collection_warn_threshold: "java.lang.Integer" +key_cache_migrate_during_compaction: "java.lang.Boolean" +sstable_read_rate_persistence_enabled: "java.lang.Boolean" - network_authorizer: "java.lang.String" ++network_authorizer: ++ class_name: "java.lang.String" ++ parameters: "java.util.Map" +data_disk_usage_max_disk_size: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +memtable_offheap_space: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +prepared_statements_cache_size: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +paxos_contention_wait_randomizer: "java.lang.String" +commitlog_compression: + class_name: "java.lang.String" + parameters: "java.util.Map" +broadcast_address: "java.lang.String" +repair_session_space: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +partition_denylist_enabled: "java.lang.Boolean" +paxos_cache_size: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +snapshot_before_compaction: "java.lang.Boolean" +back_pressure_strategy: + class_name: "java.lang.String" + parameters: "java.util.Map" - native_transport_port_ssl: "java.lang.Integer" +allocate_tokens_for_keyspace: "java.lang.String" +uuid_sstable_identifiers_enabled: "java.lang.Boolean" +credentials_cache_active_update: "java.lang.Boolean" +diagnostic_events_enabled: "java.lang.Boolean" +failure_detector: "java.lang.String" +storage_port: "java.lang.Integer" +drop_compact_storage_enabled: "java.lang.Boolean" +uncompressed_tables_enabled: "java.lang.Boolean" +commitlog_sync_group_window: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +auth_read_consistency_level: "java.lang.String" +autocompaction_on_startup_enabled: "java.lang.Boolean" +items_per_collection_fail_threshold: "java.lang.Integer" +paxos_state_purging: "org.apache.cassandra.config.Config.PaxosStatePurging" +column_index_cache_size: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +commit_failure_policy: "org.apache.cassandra.config.Config.CommitFailurePolicy" +concurrent_writes: "java.lang.Integer" +max_value_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +read_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +hinted_handoff_enabled: "java.lang.Boolean" +automatic_sstable_upgrade: "java.lang.Boolean" +memtable_flush_writers: "java.lang.Integer" +otc_coalescing_strategy: "java.lang.String" +snapshot_on_repaired_data_mismatch: "java.lang.Boolean" +cidr_authorizer: + class_name: "java.lang.String" + parameters: "java.util.Map" +commitlog_max_compression_buffers_in_pool: "java.lang.Integer" +zero_ttl_on_twcs_enabled: "java.lang.Boolean" +cdc_free_space_check_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +roles_cache_max_entries: "java.lang.Integer" +allow_filtering_enabled: "java.lang.Boolean" +columns_per_table_fail_threshold: "java.lang.Integer" +start_native_transport: "java.lang.Boolean" +ssl_storage_port: "java.lang.Integer" +cluster_name: "java.lang.String" +credentials_update_interval: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +incremental_backups: "java.lang.Boolean" +internode_socket_send_buffer_size: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +default_compaction: + class_name: "java.lang.String" + parameters: "java.util.Map" +min_tracked_partition_size: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +cas_contention_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +key_cache_save_period: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +windows_timer_interval: "java.lang.Integer" +rpc_interface: "java.lang.String" +row_cache_keys_to_save: "java.lang.Integer" +compact_tables_enabled: "java.lang.Boolean" +partition_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +minimum_timestamp_fail_threshold: "org.apache.cassandra.config.DurationSpec.LongMicrosecondsBound" +repair_command_pool_full_strategy: "org.apache.cassandra.config.Config.RepairCommandPoolFullStrategy" +drop_truncate_table_enabled: "java.lang.Boolean" +max_top_size_partition_count: "java.lang.Integer" +client_encryption_options: + optional: "java.lang.Boolean" + store_type: "java.lang.String" + cipher_suites: "java.util.List" + enabled: "java.lang.Boolean" + require_endpoint_verification: "java.lang.Boolean" + accepted_protocols: "java.util.List" + keystore_password: "java.lang.String" + protocol: "java.lang.String" - require_client_auth: "java.lang.Boolean" ++ require_client_auth: "java.lang.String" + ssl_context_factory: + class_name: "java.lang.String" + parameters: "java.util.Map" + truststore_password: "java.lang.String" + keystore: "java.lang.String" + truststore: "java.lang.String" + algorithm: "java.lang.String" +concurrent_validations: "java.lang.Integer" +ideal_consistency_level: "org.apache.cassandra.db.ConsistencyLevel" +partition_keys_in_select_warn_threshold: "java.lang.Integer" +consecutive_message_errors_threshold: "java.lang.Integer" +read_thresholds_enabled: "java.lang.Boolean" +internode_application_send_queue_reserve_endpoint_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +partition_keys_in_select_fail_threshold: "java.lang.Integer" +trickle_fsync: "java.lang.Boolean" +group_by_enabled: "java.lang.Boolean" +reject_repair_compaction_threshold: "java.lang.Integer" +request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +cdc_total_space: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +default_secondary_index_enabled: "java.lang.Boolean" +paxos_variant: "org.apache.cassandra.config.Config.PaxosVariant" +index_summary_resize_interval: "org.apache.cassandra.config.DurationSpec.IntMinutesBound" +max_top_tombstone_partition_count: "java.lang.Integer" +data_disk_usage_percentage_fail_threshold: "java.lang.Integer" +max_streaming_retries: "java.lang.Integer" +internode_timeout: "java.lang.Boolean" +native_transport_flush_in_batches_legacy: "java.lang.Boolean" +rpc_address: "java.lang.String" +trickle_fsync_interval: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +file_cache_enabled: "java.lang.Boolean" +cdc_raw_directory: "java.lang.String" +num_tokens: "java.lang.Integer" +native_transport_max_frame_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +user_timestamps_enabled: "java.lang.Boolean" +paxos_topology_repair_no_dc_checks: "java.lang.Boolean" +repaired_data_tracking_for_partition_reads_enabled: "java.lang.Boolean" +internode_streaming_tcp_user_timeout: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +file_cache_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +denylist_max_keys_per_table: "java.lang.Integer" +commitlog_directory: "java.lang.String" +unlogged_batch_across_partitions_warn_threshold: "java.lang.Integer" +write_consistency_levels_disallowed: "java.util.Set" +auto_bootstrap: "java.lang.Boolean" - authorizer: "java.lang.String" ++authorizer: ++ class_name: "java.lang.String" ++ parameters: "java.util.Map" +auth_write_consistency_level: "java.lang.String" +counter_cache_size: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +denylist_range_reads_enabled: "java.lang.Boolean" +batchlog_replay_throttle: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +compaction_throughput: "org.apache.cassandra.config.DataRateSpec.LongBytesPerSecondBound" +stream_throughput_outbound: "org.apache.cassandra.config.DataRateSpec.LongBytesPerSecondBound" +streaming_state_expires: "org.apache.cassandra.config.DurationSpec.LongNanosecondsBound" +broadcast_rpc_address: "java.lang.String" +listen_interface_prefer_ipv6: "java.lang.Boolean" +repair_session_max_tree_depth: "java.lang.Integer" +auto_optimise_preview_repair_streams: "java.lang.Boolean" +column_value_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +internode_tcp_connect_timeout: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +paxos_purge_grace_period: "org.apache.cassandra.config.DurationSpec.LongSecondsBound" +commitlog_sync_period: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +concurrent_compactors: "java.lang.Integer" +hint_window_persistent_enabled: "java.lang.Boolean" +buffer_pool_use_heap_if_exhausted: "java.lang.Boolean" +paxos_contention_max_wait: "java.lang.String" +native_transport_receive_queue_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +concurrent_index_builders: "java.lang.Integer" +in_select_cartesian_product_warn_threshold: "java.lang.Integer" +local_system_data_file_directory: "java.lang.String" +stream_entire_sstables: "java.lang.Boolean" +stream_transfer_task_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +internode_tcp_user_timeout: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +corrupted_tombstone_strategy: "org.apache.cassandra.config.Config.CorruptedTombstoneStrategy" +paxos_topology_repair_strict_each_quorum: "java.lang.Boolean" +listen_address: "java.lang.String" +top_partitions_enabled: "java.lang.Boolean" +sstable_preemptive_open_interval: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +rpc_keepalive: "java.lang.Boolean" +min_free_space_per_drive: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +read_consistency_levels_warned: "java.util.Set" +allow_extra_insecure_udfs: "java.lang.Boolean" +batch_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +disk_access_mode: "org.apache.cassandra.config.Config.DiskAccessMode" +concurrent_counter_writes: "java.lang.Integer" +internode_error_reporting_exclusions: + subnets: "java.util.Set" +paxos_contention_min_delta: "java.lang.String" +simplestrategy_enabled: "java.lang.Boolean" +dynamic_snitch: "java.lang.Boolean" +use_deterministic_table_id: "java.lang.Boolean" +phi_convict_threshold: "java.lang.Double" +max_hints_file_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +native_transport_max_threads: "java.lang.Integer" +sstable: + selected_format: "java.lang.String" + format: "java.util.Map" +minimum_replication_factor_fail_threshold: "java.lang.Integer" +table_properties_disallowed: "java.util.Set" +collection_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +memtable: + configurations: "java.util.LinkedHashMap" +authenticator: + class_name: "java.lang.String" + parameters: "java.util.Map" +internode_socket_receive_buffer_size: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +allow_insecure_udfs: "java.lang.Boolean" +internode_application_receive_queue_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +user_defined_functions_enabled: "java.lang.Boolean" +user_defined_functions_threads_enabled: "java.lang.Boolean" +streaming_slow_events_log_timeout: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +truncate_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +severity_during_decommission: "java.lang.Double" +periodic_commitlog_sync_lag_block: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +repair_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +auto_optimise_full_repair_streams: "java.lang.Boolean" +commitlog_segment_size: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +batch_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +streaming_state_size: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +denylist_max_keys_total: "java.lang.Integer" +dynamic_data_masking_enabled: "java.lang.Boolean" +storage_compatibility_mode: "org.apache.cassandra.utils.StorageCompatibilityMode" +repair_state_expires: "org.apache.cassandra.config.DurationSpec.LongNanosecondsBound" +native_transport_allow_older_protocols: "java.lang.Boolean" +otc_coalescing_enough_coalesced_messages: "java.lang.Integer" +transfer_hints_on_decommission: "java.lang.Boolean" +report_unconfirmed_repaired_data_mismatches: "java.lang.Boolean" +fields_per_udt_warn_threshold: "java.lang.Integer" +paxos_on_linearizability_violations: "org.apache.cassandra.config.Config.PaxosOnLinearizabilityViolation" +read_consistency_levels_disallowed: "java.util.Set" +use_offheap_merkle_trees: "java.lang.Boolean" +concurrent_materialized_view_builders: "java.lang.Integer" +server_encryption_options: + outbound_keystore: "java.lang.String" + optional: "java.lang.Boolean" + store_type: "java.lang.String" + cipher_suites: "java.util.List" + enabled: "java.lang.Boolean" + outbound_keystore_password: "java.lang.String" + require_endpoint_verification: "java.lang.Boolean" + accepted_protocols: "java.util.List" + keystore_password: "java.lang.String" + protocol: "java.lang.String" - require_client_auth: "java.lang.Boolean" ++ require_client_auth: "java.lang.String" + internode_encryption: "org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.InternodeEncryption" + ssl_context_factory: + class_name: "java.lang.String" + parameters: "java.util.Map" + legacy_ssl_storage_port_enabled: "java.lang.Boolean" + truststore_password: "java.lang.String" + keystore: "java.lang.String" + truststore: "java.lang.String" + algorithm: "java.lang.String" + max_certificate_validity_period: "org.apache.cassandra.config.DurationSpec.IntMinutesBound" + certificate_validity_warn_threshold: "org.apache.cassandra.config.DurationSpec.IntMinutesBound" +partition_tombstones_fail_threshold: "java.lang.Long" +traverse_auth_from_root: "java.lang.Boolean" +denylist_refresh: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +max_hints_delivery_threads: "java.lang.Integer" +permissions_validity: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +materialized_views_enabled: "java.lang.Boolean" +saved_caches_directory: "java.lang.String" +internode_application_send_queue_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +memtable_heap_space: "org.apache.cassandra.config.DataStorageSpec.IntMebibytesBound" +max_concurrent_automatic_sstable_upgrades: "java.lang.Integer" +maximum_replication_factor_warn_threshold: "java.lang.Integer" +denylist_reads_enabled: "java.lang.Boolean" +permissions_cache_active_update: "java.lang.Boolean" +available_processors: "java.lang.Integer" +file_cache_round_up: "java.lang.Boolean" +secondary_indexes_per_table_warn_threshold: "java.lang.Integer" +tables_warn_threshold: "java.lang.Integer" +column_value_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +snapshot_on_duplicate_row_detection: "java.lang.Boolean" +internode_application_receive_queue_reserve_global_capacity: "org.apache.cassandra.config.DataStorageSpec.IntBytesBound" +internode_compression: "org.apache.cassandra.config.Config.InternodeCompression" +range_request_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +streaming_stats_enabled: "java.lang.Boolean" +local_read_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +otc_coalescing_window_us: "java.lang.Integer" +page_size_fail_threshold: "java.lang.Integer" +credentials_cache_max_entries: "java.lang.Integer" +coordinator_read_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +row_index_read_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +index_summary_capacity: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +collection_size_fail_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +column_index_size: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +validation_preview_purge_head_start: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +skip_paxos_repair_on_topology_change_keyspaces: "java.util.Set" +materialized_views_per_table_fail_threshold: "java.lang.Integer" +max_mutation_size: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +keyspaces_fail_threshold: "java.lang.Integer" +data_disk_usage_percentage_warn_threshold: "java.lang.Integer" +slow_query_log_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +paxos_contention_min_wait: "java.lang.String" +repair_state_size: "java.lang.Integer" +user_defined_functions_warn_timeout: "org.apache.cassandra.config.DurationSpec.LongMillisecondsBound" +zero_ttl_on_twcs_warned: "java.lang.Boolean" +native_transport_port: "java.lang.Integer" +permissions_cache_max_entries: "java.lang.Integer" +hinted_handoff_throttle: "org.apache.cassandra.config.DataStorageSpec.IntKibibytesBound" +row_index_read_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +hints_compression: + class_name: "java.lang.String" + parameters: "java.util.Map" +native_transport_max_auth_threads: "java.lang.Integer" +force_new_prepared_statement_behaviour: "java.lang.Boolean" +back_pressure_enabled: "java.lang.Boolean" +materialized_views_per_table_warn_threshold: "java.lang.Integer" +transparent_data_encryption_options: + cipher: "java.lang.String" + chunk_length_kb: "java.lang.Integer" + iv_length: "java.lang.Integer" + key_alias: "java.lang.String" + key_provider: + class_name: "java.lang.String" + parameters: "java.util.Map" + enabled: "java.lang.Boolean" +initial_range_tombstone_list_allocation_size: "java.lang.Integer" +partitioner: "java.lang.String" +gc_warn_threshold: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +listen_interface: "java.lang.String" +row_cache_size: "org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound" +skip_stream_disk_space_check: "java.lang.Boolean" +paxos_repair_enabled: "java.lang.Boolean" +inter_dc_tcp_nodelay: "java.lang.Boolean" +internode_authenticator: + class_name: "java.lang.String" + parameters: "java.util.Map" +key_cache_keys_to_save: "java.lang.Integer" +crypto_provider: + class_name: "java.lang.String" + parameters: "java.util.Map" +local_read_size_warn_threshold: "org.apache.cassandra.config.DataStorageSpec.LongBytesBound" +replica_filtering_protection: + cached_rows_fail_threshold: "java.lang.Integer" + cached_rows_warn_threshold: "java.lang.Integer" +range_tombstone_list_growth_factor: "java.lang.Double" +startup_checks: "java.util.Map" +max_space_usable_for_compactions_in_percentage: "java.lang.Double" +native_transport_max_concurrent_connections: "java.lang.Long" +maximum_replication_factor_fail_threshold: "java.lang.Integer" +memtable_cleanup_threshold: "java.lang.Float" +concurrent_reads: "java.lang.Integer" +credentials_validity: "org.apache.cassandra.config.DurationSpec.IntMillisecondsBound" +streaming_connections_per_host: "java.lang.Integer" +cache_load_timeout: "org.apache.cassandra.config.DurationSpec.IntSecondsBound" +native_transport_rate_limiting_enabled: "java.lang.Boolean" +use_statements_enabled: "java.lang.Boolean" +auto_hints_cleanup_enabled: "java.lang.Boolean" +auto_snapshot: "java.lang.Boolean" +skip_paxos_repair_on_topology_change: "java.lang.Boolean" +endpoint_snitch: "java.lang.String" diff --cc test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java index 19d7f17d76,d94cb57920..f5d10a6b52 --- a/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java +++ b/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java @@@ -110,9 -102,14 +110,15 @@@ public class ConfigCompatibilityTes // Switched to a parameterized class that can construct from a bare string .add("internode_authenticator types do not match; org.apache.cassandra.config.ParameterizedClass != java.lang.String") .add("authenticator types do not match; org.apache.cassandra.config.ParameterizedClass != java.lang.String") + .add("authorizer types do not match; org.apache.cassandra.config.ParameterizedClass != java.lang.String") + .add("network_authorizer types do not match; org.apache.cassandra.config.ParameterizedClass != java.lang.String") + .add("role_manager types do not match; org.apache.cassandra.config.ParameterizedClass != java.lang.String") .add("Property internode_authenticator used to be a value-type, but now is nested type class org.apache.cassandra.config.ParameterizedClass") .add("Property authenticator used to be a value-type, but now is nested type class org.apache.cassandra.config.ParameterizedClass") + .add("Property authorizer used to be a value-type, but now is nested type class org.apache.cassandra.config.ParameterizedClass") + .add("Property role_manager used to be a value-type, but now is nested type class org.apache.cassandra.config.ParameterizedClass") + .add("Property network_authorizer used to be a value-type, but now is nested type class org.apache.cassandra.config.ParameterizedClass") + .add("require_client_auth types do not match; java.lang.String != java.lang.Boolean") .build(); /** @@@ -154,10 -151,10 +160,18 @@@ @Test public void diff_5_0() throws IOException { - diff(TEST_DIR + "/version=5.0-alpha1.yml", ImmutableSet.<String>builder().addAll(REMOVED_IN_51) + diff(TEST_DIR + "/version=5.0-alpha1.yml", ImmutableSet.<String>builder() ++ .addAll(REMOVED_IN_51) + .build(), EXPECTED_FOR_50); + } + ++ @Test ++ public void diff_5_1() throws IOException ++ { ++ diff(TEST_DIR + "/version=5.1-alpha1.yml", ImmutableSet.<String>builder() + .build(), ImmutableSet.of()); + } + private void diff(String original, Set<String> ignore, Set<String> expectedErrors) throws IOException { Class<Config> type = Config.class; diff --cc test/unit/org/apache/cassandra/transport/TlsTestUtils.java index 6e6425c77b,0000000000..24f3124f86 mode 100644,000000..100644 --- a/test/unit/org/apache/cassandra/transport/TlsTestUtils.java +++ b/test/unit/org/apache/cassandra/transport/TlsTestUtils.java @@@ -1,222 -1,0 +1,222 @@@ +/* + * 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.transport; + +import java.io.File; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import javax.net.ssl.SSLException; + +import com.google.common.collect.ImmutableMap; + +import com.datastax.driver.core.PlainTextAuthProvider; +import com.datastax.driver.core.RemoteEndpointAwareJdkSSLOptions; +import com.datastax.driver.core.SSLOptions; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import org.apache.cassandra.config.Config; +import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.ParameterizedClass; +import org.apache.cassandra.distributed.api.ICluster; +import org.apache.cassandra.distributed.api.IInvokableInstance; +import org.apache.cassandra.distributed.shared.ClusterUtils; +import org.apache.cassandra.distributed.util.Auth; +import org.apache.cassandra.distributed.util.SingleHostLoadBalancingPolicy; +import org.apache.cassandra.security.ISslContextFactory; +import org.apache.cassandra.utils.tls.CertificateBuilder; +import org.apache.cassandra.utils.tls.CertificateBundle; + +import static org.apache.cassandra.auth.CassandraRoleManager.DEFAULT_SUPERUSER_NAME; +import static org.apache.cassandra.auth.CassandraRoleManager.DEFAULT_SUPERUSER_PASSWORD; + +public class TlsTestUtils +{ + public static String SERVER_KEYSTORE_PATH = "test/conf/cassandra_ssl_test.keystore"; + public static String SERVER_KEYSTORE_PATH_PEM = "test/conf/cassandra_ssl_test.keystore.pem"; + public static String SERVER_KEYSTORE_PATH_UNENCRYPTED_PEM = "test/conf/cassandra_ssl_test.unencrypted_keystore.pem"; + public static String SERVER_KEYSTORE_PASSWORD = "cassandra"; + + public static String SERVER_KEYSTORE_ENDPOINT_VERIFY_PATH = "test/conf/cassandra_ssl_test_endpoint_verify.keystore"; + public static String SERVER_KEYSTORE_ENDPOINT_VERIFY_PASSWORD = "cassandra"; + + public static String SERVER_OUTBOUND_KEYSTORE_PATH = "test/conf/cassandra_ssl_test_outbound.keystore"; + public static String SERVER_OUTBOUND_KEYSTORE_PASSWORD = "cassandra"; + + public static String SERVER_TRUSTSTORE_PATH = "test/conf/cassandra_ssl_test.truststore"; + public static String SERVER_TRUSTSTORE_PEM_PATH = "test/conf/cassandra_ssl_test.truststore.pem"; + public static String SERVER_TRUSTSTORE_PASSWORD = "cassandra"; + + // To regenerate: + // 1. generate keystore + // keytool -genkeypair -keystore test/conf/cassandra_ssl_test_spiffe.keystore -validity 100000 -keyalg RSA -dname "CN=Apache Cassandra, OU=ssl_test, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -keypass cassandra -storepass cassandra -alias spiffecert -ext SAN=URI:spiffe://test.cassandra.apache.org/unitTest/mtls -storetype jks + // 2. export cert + // keytool -export -alias spiffecert -file spiffecert.cer -keystore test/conf/cassandra_ssl_test_spiffe.keystore + // 3. import cert into truststore + // keytool -import -v -trustcacerts -alias spiffecert -file spiffecert.cer -keystore test/conf/cassandra_ssl_test.truststore + public static String CLIENT_SPIFFE_KEYSTORE_PATH = "test/conf/cassandra_ssl_test_spiffe.keystore"; + public static String CLIENT_SPIFFE_KEYSTORE_PASSWORD = "cassandra"; + public static String CLIENT_SPIFFE_IDENTITY = "spiffe://test.cassandra.apache.org/unitTest/mtls"; + + public static String CLIENT_TRUSTSTORE_PATH = "test/conf/cassandra_ssl_test.truststore"; + public static String CLIENT_TRUSTSTORE_PASSWORD = "cassandra"; + + public static EncryptionOptions getClientEncryptionOptions() + { + return new EncryptionOptions(new EncryptionOptions() + .withEnabled(true) + .withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL) + .withOptional(true) + .withKeyStore(SERVER_KEYSTORE_PATH) + .withKeyStorePassword(SERVER_KEYSTORE_PASSWORD) + .withTrustStore(SERVER_TRUSTSTORE_PATH) + .withTrustStorePassword(SERVER_TRUSTSTORE_PASSWORD) + .withRequireEndpointVerification(false)); + } + + public static void configureWithMutualTlsWithPasswordFallbackAuthenticator(Config config) + { + // Configure an authenticator that supports multiple authentication mechanisms. + Map<String, String> parameters = Collections.singletonMap("validator_class_name", "org.apache.cassandra.auth.SpiffeCertificateValidator"); + config.authenticator = new ParameterizedClass("MutualTlsWithPasswordFallbackAuthenticator", parameters); + // Configure client encryption such that we can optionally connect with SSL. + config.client_encryption_options = TlsTestUtils.getClientEncryptionOptions(); - config.role_manager = "CassandraRoleManager"; - config.authorizer = "CassandraAuthorizer"; ++ config.role_manager = new ParameterizedClass("CassandraRoleManager"); ++ config.authorizer = new ParameterizedClass("CassandraAuthorizer"); + } + + public static ISslContextFactory getClientSslContextFactory(boolean provideClientCert) + { + ImmutableMap.Builder<String, Object> params = ImmutableMap.<String, Object>builder() + .put("truststore", CLIENT_TRUSTSTORE_PATH) + .put("truststore_password", CLIENT_TRUSTSTORE_PASSWORD); + + if (provideClientCert) + { + params.put("keystore", CLIENT_SPIFFE_KEYSTORE_PATH) + .put("keystore_password", CLIENT_SPIFFE_KEYSTORE_PASSWORD); + } + + return new SimpleClientSslContextFactory(params.build()); + } + + public static SSLOptions getSSLOptions(boolean provideClientCert) throws SSLException + { + return RemoteEndpointAwareJdkSSLOptions.builder() + .withSSLContext(getClientSslContextFactory(provideClientCert) + .createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL)) + .build(); + } + + public static SSLOptions getSSLOptions(Path keystorePath, Path truststorePath) throws RuntimeException + { + try + { + return RemoteEndpointAwareJdkSSLOptions.builder() + .withSSLContext(getClientSslContextFactory(keystorePath, truststorePath) + .createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL)) + .build(); + } + catch (SSLException e) + { + throw new RuntimeException(e); + } + } + + private static ISslContextFactory getClientSslContextFactory(Path keystorePath, Path truststorePath) + { + ImmutableMap.Builder<String, Object> params = ImmutableMap.<String, Object>builder() + .put("truststore", truststorePath.toString()) + .put("truststore_password", CLIENT_TRUSTSTORE_PASSWORD); + + if (keystorePath != null) + { + params.put("keystore", keystorePath.toString()) + .put("keystore_password", "cassandra"); + } + + return new SimpleClientSslContextFactory(params.build()); + } + + public static void configureIdentity(ICluster<IInvokableInstance> cluster, SSLOptions sslOptions) + { + withAuthenticatedSession(cluster.get(1), DEFAULT_SUPERUSER_NAME, DEFAULT_SUPERUSER_PASSWORD, session -> { + session.execute("CREATE ROLE cassandra_ssl_test WITH LOGIN = true"); + session.execute(String.format("ADD IDENTITY '%s' TO ROLE 'cassandra_ssl_test'", CLIENT_SPIFFE_IDENTITY)); + // GRANT select to cassandra_ssl_test to be able to query the system_views.clients virtual table + session.execute("GRANT SELECT ON ALL KEYSPACES to cassandra_ssl_test"); + }, sslOptions); + } + + public static Path generateSelfSignedCertificate(Function<CertificateBuilder, CertificateBuilder> customizeCertificate, File targetDirectory) throws Exception + { + return generateClientCertificate(customizeCertificate, targetDirectory, null); + } + + public static Path generateClientCertificate(Function<CertificateBuilder, CertificateBuilder> customizeCertificate, File targetDirectory, CertificateBundle ca) throws Exception + { + CertificateBuilder builder = new CertificateBuilder().subject("CN=Apache Cassandra, OU=ssl_test, O=Unknown, L=Unknown, ST=Unknown, C=Unknown") + .notBefore(Instant.now().minus(1, ChronoUnit.DAYS)) + .notAfter(Instant.now().plus(1, ChronoUnit.DAYS)) + .alias("spiffecert") + .addSanUriName(CLIENT_SPIFFE_IDENTITY) + .rsa2048Algorithm(); + if (customizeCertificate != null) + { + builder = customizeCertificate.apply(builder); + } + CertificateBundle ssc = ca != null + ? builder.buildIssuedBy(ca) + : builder.buildSelfSigned(); + return ssc.toTempKeyStorePath(targetDirectory.toPath(), SERVER_KEYSTORE_PASSWORD.toCharArray(), SERVER_KEYSTORE_PASSWORD.toCharArray()); + } + + public static void withAuthenticatedSession(IInvokableInstance instance, + String username, + String password, + Consumer<Session> consumer, + SSLOptions sslOptions) + { + // wait for existing roles + Auth.waitForExistingRoles(instance); + + InetSocketAddress nativeInetSocketAddress = ClusterUtils.getNativeInetSocketAddress(instance); + InetAddress address = nativeInetSocketAddress.getAddress(); + LoadBalancingPolicy lbc = new SingleHostLoadBalancingPolicy(address); + + com.datastax.driver.core.Cluster.Builder builder = com.datastax.driver.core.Cluster.builder() + .withLoadBalancingPolicy(lbc) + .withSSL(sslOptions) + .withAuthProvider(new PlainTextAuthProvider(username, password)) + .addContactPoint(address.getHostAddress()) + .withPort(nativeInetSocketAddress.getPort()); + + try (com.datastax.driver.core.Cluster c = builder.build(); Session session = c.connect()) + { + consumer.accept(session); + } + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
