diff options
| -rw-r--r-- | Makefile | 29 | ||||
| -rw-r--r-- | docs/rabbitmq.conf.example | 60 | ||||
| -rw-r--r-- | docs/rabbitmq.config.example | 36 | ||||
| -rw-r--r-- | priv/schema/rabbitmq.schema | 8 | ||||
| -rw-r--r-- | rabbitmq-components.mk | 7 | ||||
| -rw-r--r-- | rabbitmq.conf.d/ldap.conf | 138 | ||||
| -rw-r--r-- | rabbitmq.conf.d/rabbitmq.conf | 731 | ||||
| -rw-r--r-- | scripts/rabbitmq-server.bat | 8 | ||||
| -rw-r--r-- | scripts/rabbitmq-service.bat | 8 | ||||
| -rw-r--r-- | src/rabbit.erl | 4 | ||||
| -rw-r--r-- | src/rabbit_mirror_queue_sync.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_priority_queue.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_ssl.erl | 228 | ||||
| -rw-r--r-- | src/rabbit_table.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_upgrade_functions.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_variable_queue.erl | 133 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/snippets.config | 141 | ||||
| -rw-r--r-- | test/dynamic_ha_SUITE.erl | 28 | ||||
| -rw-r--r-- | test/priority_queue_SUITE.erl | 26 | ||||
| -rw-r--r-- | test/proxy_protocol_SUITE.erl | 100 | ||||
| -rw-r--r-- | test/topic_permission_SUITE.erl | 46 | ||||
| -rw-r--r-- | test/unit_inbroker_SUITE.erl | 24 |
22 files changed, 505 insertions, 1258 deletions
@@ -89,11 +89,11 @@ define PROJECT_ENV %% setting has no effect because credit_flow is not used when %% writing to the queue index. See the setting %% queue_index_embed_msgs_below above. - {msg_store_credit_disc_bound, {2000, 500}}, + {msg_store_credit_disc_bound, {3000, 800}}, {msg_store_io_batch_size, 2048}, - %% see rabbitmq-server#143 - %% and rabbitmq-server#949 - {credit_flow_default_credit, {200, 100}}, + %% see rabbitmq-server#143, + %% rabbitmq-server#949, rabbitmq-server#1098 + {credit_flow_default_credit, {400, 200}}, %% see rabbitmq-server#248 %% and rabbitmq-server#667 {channel_operation_timeout, 15000}, @@ -112,8 +112,10 @@ define PROJECT_ENV %% rabbitmq-server-973 {queue_explicit_gc_run_operation_threshold, 1000}, {lazy_queue_explicit_gc_run_operation_threshold, 1000}, - {background_gc_enabled, true}, - {background_gc_target_interval, 60000} + {background_gc_enabled, false}, + {background_gc_target_interval, 60000}, + %% rabbitmq-server-589 + {proxy_protocol, false} ] endef @@ -139,10 +141,6 @@ EXTRA_SOURCES += $(USAGES_ERL) .DEFAULT_GOAL = all $(PROJECT).d:: $(EXTRA_SOURCES) -copy-escripts: - cp -r ${DEPS_DIR}/rabbitmq_cli/escript ./ - - DEP_PLUGINS = rabbit_common/mk/rabbitmq-build.mk \ rabbit_common/mk/rabbitmq-dist.mk \ rabbit_common/mk/rabbitmq-run.mk \ @@ -180,13 +178,22 @@ USE_PROPER_QC := $(shell $(ERL) -eval 'io:format({module, proper} =:= code:ensur RMQ_ERLC_OPTS += $(if $(filter true,$(USE_PROPER_QC)),-Duse_proper_qc) endif +.PHONY: copy-escripts clean-extra-sources clean-escripts + +CLI_ESCRIPTS_DIR = escript + +copy-escripts: + $(gen_verbose) $(MAKE) -C $(DEPS_DIR)/rabbitmq_cli install \ + PREFIX="$(abspath $(CLI_ESCRIPTS_DIR))" \ + DESTDIR= + clean:: clean-extra-sources clean-escripts clean-extra-sources: $(gen_verbose) rm -f $(EXTRA_SOURCES) clean-escripts: - $(gen_verbose) rm -rf escript + $(gen_verbose) rm -rf "$(CLI_ESCRIPTS_DIR)" # -------------------------------------------------------------------- # Documentation. diff --git a/docs/rabbitmq.conf.example b/docs/rabbitmq.conf.example index 96d0967db7..0e8d1e0596 100644 --- a/docs/rabbitmq.conf.example +++ b/docs/rabbitmq.conf.example @@ -395,6 +395,16 @@ ## # background_gc_target_interval = 60000 +## Whether or not to enable proxy protocol support. +## Once enabled, clients cannot directly connect to the broker +## anymore. They must connect through a load balancer that sends the +## proxy protocol header to the broker at connection time. +## This setting applies only to AMQP clients, other protocols +## like MQTT or STOMP have their own setting to enable proxy protocol. +## See the plugins documentation for more information. +## +# proxy_protocol = false + ## ---------------------------------------------------------------------------- ## Advanced Erlang Networking/Clustering Options. ## @@ -515,6 +525,16 @@ ## # stomp.implicit_connect = true +## Whether or not to enable proxy protocol support. +## Once enabled, clients cannot directly connect to the broker +## anymore. They must connect through a load balancer that sends the +## proxy protocol header to the broker at connection time. +## This setting applies only to STOMP clients, other protocols +## like MQTT or AMQP have their own setting to enable proxy protocol. +## See the plugins or broker documentation for more information. +## +# stomp.proxy_protocol = false + ## ---------------------------------------------------------------------------- ## RabbitMQ MQTT Adapter ## @@ -578,6 +598,16 @@ # mqtt.tcp_listen_options.backlog = 128 # mqtt.tcp_listen_options.nodelay = true +## Whether or not to enable proxy protocol support. +## Once enabled, clients cannot directly connect to the broker +## anymore. They must connect through a load balancer that sends the +## proxy protocol header to the broker at connection time. +## This setting applies only to STOMP clients, other protocols +## like STOMP or AMQP have their own setting to enable proxy protocol. +## See the plugins or broker documentation for more information. +## +# mqtt.proxy_protocol = false + ## ---------------------------------------------------------------------------- ## RabbitMQ AMQP 1.0 Support ## @@ -660,25 +690,25 @@ ## Specify servers to bind to. You *must* set this in order for the plugin ## to work properly. ## -# ldap.servers.1 = your-server-name-goes-here +# auth_ldap.servers.1 = your-server-name-goes-here ## You can define multiple servers -# ldap.servers.2 = your-other-server +# auth_ldap.servers.2 = your-other-server ## Connect to the LDAP server using SSL ## -# ldap.use_ssl = false +# auth_ldap.use_ssl = false ## Specify the LDAP port to connect to ## -# ldap.port = 389 +# auth_ldap.port = 389 ## LDAP connection timeout, in milliseconds or 'infinity' ## -# ldap.timeout = infinity +# auth_ldap.timeout = infinity ## Or number -# ldap.timeout = 500 +# auth_ldap.timeout = 500 ## Enable logging of LDAP queries. ## One of @@ -688,11 +718,11 @@ ## ## Defaults to false. ## -# ldap.log = false +# auth_ldap.log = false ## Also can be true or network -# ldap.log = true -# ldap.log = network +# auth_ldap.log = true +# auth_ldap.log = network ## ## Authentication @@ -702,7 +732,7 @@ ## Pattern to convert the username given through AMQP to a DN before ## binding ## -# ldap.user_dn_pattern = cn=${username},ou=People,dc=example,dc=com +# auth_ldap.user_dn_pattern = cn=${username},ou=People,dc=example,dc=com ## Alternatively, you can convert a username to a Distinguished ## Name via an LDAP lookup after binding. See the documentation for @@ -712,8 +742,8 @@ ## the name of the attribute that represents the user name, and the ## base DN for the lookup query. ## -# ldap.dn_lookup_attribute = userPrincipalName -# ldap.dn_lookup_base = DC=gopivotal,DC=com +# auth_ldap.dn_lookup_attribute = userPrincipalName +# auth_ldap.dn_lookup_base = DC=gopivotal,DC=com ## Controls how to bind for authorisation queries and also to ## retrieve the details of users logging in without presenting a @@ -725,11 +755,11 @@ ## ## Defaults to 'as_user'. ## -# ldap.other_bind = as_user +# auth_ldap.other_bind = as_user ## Or can be more complex: -# ldap.other_bind.user_dn = User -# ldap.other_bind.password = Password +# auth_ldap.other_bind.user_dn = User +# auth_ldap.other_bind.password = Password ## If user_dn and password defined - other options is ignored. diff --git a/docs/rabbitmq.config.example b/docs/rabbitmq.config.example index aaffcab2d8..50e97cd3bb 100644 --- a/docs/rabbitmq.config.example +++ b/docs/rabbitmq.config.example @@ -346,7 +346,17 @@ %% the operation (can be higher than this interval). Values less than %% 30000 milliseconds are not recommended. %% - %% {background_gc_target_interval, 60000} + %% {background_gc_target_interval, 60000}, + + %% Whether or not to enable proxy protocol support. + %% Once enabled, clients cannot directly connect to the broker + %% anymore. They must connect through a load balancer that sends the + %% proxy protocol header to the broker at connection time. + %% This setting applies only to AMQP clients, other protocols + %% like MQTT or STOMP have their own setting to enable proxy protocol. + %% See the plugins documentation for more information. + %% + %% {proxy_protocol, false} ]}, @@ -517,7 +527,17 @@ %% SSL certificate whenever the first frame sent on a session is not a %% CONNECT frame. %% - %% {implicit_connect, true} + %% {implicit_connect, true}, + + %% Whether or not to enable proxy protocol support. + %% Once enabled, clients cannot directly connect to the broker + %% anymore. They must connect through a load balancer that sends the + %% proxy protocol header to the broker at connection time. + %% This setting applies only to STOMP clients, other protocols + %% like MQTT or AMQP have their own setting to enable proxy protocol. + %% See the plugins or broker documentation for more information. + %% + %% {proxy_protocol, false} ]}, %% ---------------------------------------------------------------------------- @@ -575,7 +595,17 @@ %% TCP/Socket options (as per the broker configuration). %% %% {tcp_listen_options, [{backlog, 128}, - %% {nodelay, true}]} + %% {nodelay, true}]}, + + %% Whether or not to enable proxy protocol support. + %% Once enabled, clients cannot directly connect to the broker + %% anymore. They must connect through a load balancer that sends the + %% proxy protocol header to the broker at connection time. + %% This setting applies only to MQTT clients, other protocols + %% like STOMP or AMQP have their own setting to enable proxy protocol. + %% See the plugins or broker documentation for more information. + %% + %% {proxy_protocol, false} ]}, %% ---------------------------------------------------------------------------- diff --git a/priv/schema/rabbitmq.schema b/priv/schema/rabbitmq.schema index 71032c4ffb..6f3f42e4ed 100644 --- a/priv/schema/rabbitmq.schema +++ b/priv/schema/rabbitmq.schema @@ -284,6 +284,7 @@ fun(Conf) -> (internal) -> rabbit_auth_backend_internal; (ldap) -> rabbit_auth_backend_ldap; (http) -> rabbit_auth_backend_http; + (cache) -> rabbit_auth_backend_cache; (amqp) -> rabbit_auth_backend_amqp; (dummy) -> rabbit_auth_backend_dummy; (Other) when is_atom(Other) -> Other; @@ -941,6 +942,13 @@ end}. {mapping, "background_gc_target_interval", "rabbit.background_gc_target_interval", [{datatype, integer}]}. +%% Whether or not to enable proxy protocol support. +%% +%% {proxy_protocol, false} + +{mapping, "proxy_protocol", "rabbit.proxy_protocol", + [{datatype, {enum, [true, false]}}]}. + % ========================== % Lager section % ========================== diff --git a/rabbitmq-components.mk b/rabbitmq-components.mk index fdabf1ac11..590c204d65 100644 --- a/rabbitmq-components.mk +++ b/rabbitmq-components.mk @@ -42,6 +42,7 @@ dep_rabbit = git_rmq rabbitmq-server $(current_rmq_re dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master @@ -59,6 +60,7 @@ dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rm dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master +dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_lvc = git_rmq rabbitmq-lvc-plugin $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master @@ -102,14 +104,16 @@ dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(curre dep_cowboy_commit = 1.1.0 dep_mochiweb = git git://github.com/basho/mochiweb.git v2.9.0p2 -dep_ranch_commit = 1.3.1 +dep_ranch_commit = 1.3.2 dep_webmachine_commit = 1.10.8p2 +dep_ranch_proxy_protocol = git git://github.com/heroku/ranch_proxy_protocol.git 1.4.2 RABBITMQ_COMPONENTS = amqp_client \ rabbit \ rabbit_common \ rabbitmq_amqp1_0 \ rabbitmq_auth_backend_amqp \ + rabbitmq_auth_backend_cache \ rabbitmq_auth_backend_http \ rabbitmq_auth_backend_ldap \ rabbitmq_auth_mechanism_ssl \ @@ -127,6 +131,7 @@ RABBITMQ_COMPONENTS = amqp_client \ rabbitmq_federation_management \ rabbitmq_java_client \ rabbitmq_jms_client \ + rabbitmq_jms_cts \ rabbitmq_jms_topic_exchange \ rabbitmq_lvc \ rabbitmq_management \ diff --git a/rabbitmq.conf.d/ldap.conf b/rabbitmq.conf.d/ldap.conf deleted file mode 100644 index 2f51cbb409..0000000000 --- a/rabbitmq.conf.d/ldap.conf +++ /dev/null @@ -1,138 +0,0 @@ -# ## ---------------------------------------------------------------------------- -# ## RabbitMQ LDAP Plugin -# ## -# ## See http://www.rabbitmq.com/ldap.html for details. -# ## -# ## ---------------------------------------------------------------------------- - - -# ======================================= -# LDAP section -# ======================================= - -# Should be defined in additional.conf maybe? - -# {rabbitmq_auth_backend_ldap, -# [## -# ## Connecting to the LDAP server(s) -# ## ================================ -# ## - -# ## Specify servers to bind to. You *must* set this in order for the plugin -# ## to work properly. -# ## -# ## {servers, ["your-server-name-goes-here"]}, - -ldap.servers.myserver = your-server-name-goes-here - -# ## Connect to the LDAP server using SSL -# ## -# ## {use_ssl, false}, - -ldap.use_ssl = false - -# ## Specify the LDAP port to connect to -# ## -# ## {port, 389}, - -ldap.port = 389 - -# ## LDAP connection timeout, in milliseconds or 'infinity' -# ## -# ## {timeout, infinity}, - -ldap.timeout = infinity - -# Or number -# ldap.timeout = 500 - -# ## Enable logging of LDAP queries. -# ## One of -# ## - false (no logging is performed) -# ## - true (verbose logging of the logic used by the plugin) -# ## - network (as true, but additionally logs LDAP network traffic) -# ## -# ## Defaults to false. -# ## -# ## {log, false}, - -ldap.log = false - -# Also can be true or network -# ldap.log = true -# ldap.log = network - -# ## -# ## Authentication -# ## ============== -# ## - -# ## Pattern to convert the username given through AMQP to a DN before -# ## binding -# ## -# ## {user_dn_pattern, "cn=${username},ou=People,dc=example,dc=com"}, - -ldap.user_dn_pattern = cn=${username},ou=People,dc=example,dc=com - -# ## Alternatively, you can convert a username to a Distinguished -# ## Name via an LDAP lookup after binding. See the documentation for -# ## full details. - -# ## When converting a username to a dn via a lookup, set these to -# ## the name of the attribute that represents the user name, and the -# ## base DN for the lookup query. -# ## -# ## {dn_lookup_attribute, "userPrincipalName"}, -# ## {dn_lookup_base, "DC=gopivotal,DC=com"}, - -ldap.dn_lookup_attribute = userPrincipalName -ldap.dn_lookup_base = DC=gopivotal,DC=com - -# ## Controls how to bind for authorisation queries and also to -# ## retrieve the details of users logging in without presenting a -# ## password (e.g., SASL EXTERNAL). -# ## One of -# ## - as_user (to bind as the authenticated user - requires a password) -# ## - anon (to bind anonymously) -# ## - {UserDN, Password} (to bind with a specified user name and password) -# ## -# ## Defaults to 'as_user'. -# ## -# ## {other_bind, as_user}, - -ldap.other_bind = as_user - -# Or can be more complex: -# ldap.other_bind.user_dn = User -# ldap.other_bind.password = Password -# If user_dn and password defined - other options is ignored. - -# ----------------------------- -# Too complex section of LDAP -# ----------------------------- - -# ## -# ## Authorisation -# ## ============= -# ## - -# ## The LDAP plugin can perform a variety of queries against your -# ## LDAP server to determine questions of authorisation. See -# ## http://www.rabbitmq.com/ldap.html#authorisation for more -# ## information. - -# ## Set the query to use when determining vhost access -# ## -# ## {vhost_access_query, {in_group, -# ## "ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}}, - -# ## Set the query to use when determining resource (e.g., queue) access -# ## -# ## {resource_access_query, {constant, true}}, - -# ## Set queries to determine which tags a user has -# ## -# ## {tag_queries, []} -# ]}, -# ----------------------------- - diff --git a/rabbitmq.conf.d/rabbitmq.conf b/rabbitmq.conf.d/rabbitmq.conf deleted file mode 100644 index 6d43dc9f7f..0000000000 --- a/rabbitmq.conf.d/rabbitmq.conf +++ /dev/null @@ -1,731 +0,0 @@ -# ====================================== -# RabbbitMQ broker section -# ====================================== - -## Network Connectivity -## ==================== -## -## By default, RabbitMQ will listen on all interfaces, using -## the standard (reserved) AMQP port. -## -listener.tcp.default = 5672 - - -## To listen on a specific interface, provide an IP address with port. -## For example, to listen only on localhost for both IPv4 and IPv6: -## -# IPv4 -# listener.tcp.local = 127.0.0.1:5672 -# IPv6 -# listener.tcp.local_v6 = ::1:5672 - -## You can define multiple listeners using listener names -# listener.tcp.other_port = 5673 -# listener.tcp.other_ip = 10.10.10.10:5672 - - -## SSL listeners are configured in the same fashion as TCP listeners, -## including the option to control the choice of interface. -## -# listener.ssl.default = 5671 - -## Number of Erlang processes that will accept connections for the TCP -## and SSL listeners. -## -num_acceptors.tcp = 10 -num_acceptors.ssl = 1 - - -## Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection -## and SSL handshake), in milliseconds. -## -handshake_timeout = 10000 - -## Set to 'true' to perform reverse DNS lookups when accepting a -## connection. Hostnames will then be shown instead of IP addresses -## in rabbitmqctl and the management plugin. -## -reverse_dns_lookups = true - -## -## Security / AAA -## ============== -## - -## The default "guest" user is only permitted to access the server -## via a loopback interface (e.g. localhost). -## {loopback_users, [<<"guest">>]}, -## -loopback_user.guest = true - -## Uncomment the following line if you want to allow access to the -## guest user from anywhere on the network. -# loopback_user.guest = false - -## Configuring SSL. -## See http://www.rabbitmq.com/ssl.html for full documentation. -## -ssl_option.verify = verify_peer -ssl_option.fail_if_no_peer_cert = false -# ssl_option.cacertfile = /path/to/rabbitmq.crt -# ssl_option.certfile = /path/to/rabbitmq.crt -# ssl_option.keyfile = /path/to/rabbitmq.key - -## Choose the available SASL mechanism(s) to expose. -## The two default (built in) mechanisms are 'PLAIN' and -## 'AMQPLAIN'. Additional mechanisms can be added via -## plugins. -## -## See http://www.rabbitmq.com/authentication.html for more details. -## -auth_mechanism.plain = PLAIN -auth_mechanism.amqplain = AMQPLAIN - -## Select an authentication database to use. RabbitMQ comes bundled -## with a built-in auth-database, based on mnesia. -## -auth_backends.1 = internal - -auth_backends.2.authn = ldap -auth_backends.2.authz = internal - -auth_backends.3.authz = rabbit_auth_backend_uaa - -## Configurations supporting the rabbitmq_auth_mechanism_ssl and -## rabbitmq_auth_backend_ldap plugins. -## -## NB: These options require that the relevant plugin is enabled. -## See http://www.rabbitmq.com/plugins.html for further details. - - -## The RabbitMQ-auth-mechanism-ssl plugin makes it possible to -## authenticate a user based on the client's SSL certificate. -## -## To use auth-mechanism-ssl, add to or replace the auth_mechanisms -## with EXTERNAL value. -## -#auth_mechanism.external = EXTERNAL - -## The rabbitmq_auth_backend_ldap plugin allows the broker to -## perform authentication and authorisation by deferring to an -## external LDAP server. -## -## For more information about configuring the LDAP backend, see -## http://www.rabbitmq.com/ldap.html. -## -## Enable the LDAP auth backend by adding to or replacing the -## auth_backends entry: -## -# auth_backends.2 = rabbit_auth_backend_ldap - -## Add another backend -# auth_backend.3 = rabbit_auth_backend_http - - -## This pertains to both the rabbitmq_auth_mechanism_ssl plugin and -## STOMP ssl_cert_login configurations. See the rabbitmq_stomp -## configuration section later in this file and the README in -## https://github.com/rabbitmq/rabbitmq-auth-mechanism-ssl for further -## details. -## -## To use the SSL cert's CN instead of its DN as the username -## -# ssl_cert_login_from = common_name - -## SSL handshake timeout, in milliseconds. -## -# ssl_handshake_timeout = 5000 - - -## Password hashing implementation. Will only affect newly -## created users. To recalculate hash for an existing user -## it's necessary to update her password. -## -## To use SHA-512, set to rabbit_password_hashing_sha512. -## -password_hashing_module = rabbit_password_hashing_sha256 - -## When importing definitions exported from versions earlier -## than 3.6.0, it is possible to go back to MD5 (only do this -## as a temporary measure!) by setting this to rabbit_password_hashing_md5. -## -# password_hashing_module = rabbit_password_hashing_md5 - -## -## Default User / VHost -## ==================== -## - -## On first start RabbitMQ will create a vhost and a user. These -## config items control what gets created. See -## http://www.rabbitmq.com/access-control.html for further -## information about vhosts and access control. -## -default_vhost = / -default_user = guest -default_pass = guest - -default_permissions.configure = .* -default_permissions.read = .* -default_permissions.write = .* - -## Tags for default user -## -## For more details about tags, see the documentation for the -## Management Plugin at http://www.rabbitmq.com/management.html. -## -default_user_tags.administrator = true - -## Define other tags like this: -# default_user_tags.management = true -# default_user_tags.custom_tag = true - -## -## Additional network and protocol related configuration -## ===================================================== -## - -## Set the default AMQP heartbeat delay (in seconds). -## -heartbeat = 600 - -## Set the max permissible size of an AMQP frame (in bytes). -## -frame_max = 131072 - -## Set the max frame size the server will accept before connection -## tuning occurs -## -initial_frame_max = 4096 - -## Set the max permissible number of channels per connection. -## 0 means "no limit". -## -channel_max = 128 - -## Customising Socket Options. -## -## See (http://www.erlang.org/doc/man/inet.html#setopts-2) for -## further documentation. -## - -tcp_listen_option.backlog = 128 -tcp_listen_option.nodelay = true -tcp_listen_option.exit_on_close = false - -## -## Resource Limits & Flow Control -## ============================== -## -## See http://www.rabbitmq.com/memory.html for full details. - -## Memory-based Flow Control threshold. -## -vm_memory_high_watermark.relative = 0.4 - -## Alternatively, we can set a limit (in bytes) of RAM used by the node. -## -# vm_memory_high_watermark.absolute = 1073741824 - -## Or you can set absolute value using memory units (with RabbitMQ 3.6.0+). -## Absolute watermark will be ignored if relative is defined! -## -# vm_memory_high_watermark.absolute = 2GB -## -## Supported units suffixes: -## -## kb, KB: kibibytes (2^10 bytes) -## mb, MB: mebibytes (2^20) -## gb, GB: gibibytes (2^30) - - - -## Fraction of the high watermark limit at which queues start to -## page message out to disc in order to free up memory. -## -## Values greater than 0.9 can be dangerous and should be used carefully. -## -vm_memory_high_watermark_paging_ratio = 0.5 - -## Interval (in milliseconds) at which we perform the check of the memory -## levels against the watermarks. -## -memory_monitor_interval = 2500 - -## Set disk free limit (in bytes). Once free disk space reaches this -## lower bound, a disk alarm will be set - see the documentation -## listed above for more details. -## -## Absolute watermark will be ignored if relative is defined! -disk_free_limit.absolute = 50000 - -## Or you can set it using memory units (same as in vm_memory_high_watermark) -## with RabbitMQ 3.6.0+. -# disk_free_limit.absolute = 500KB -# disk_free_limit.absolute = 50mb -# disk_free_limit.absolute = 5GB - -## Alternatively, we can set a limit relative to total available RAM. -## -## Values lower than 1.0 can be dangerous and should be used carefully. -disk_free_limit.relative = 2.0 - -## -## Clustering -## ===================== -## -cluster_partition_handling = ignore - -## pause_if_all_down strategy require additional configuration -# cluster_partition_handling = pause_if_all_down - -## Recover strategy. Can be either 'autoheal' or 'ignore' -# cluster_partition_handling.pause_if_all_down.recover = ignore - -## Node names to check -# cluster_partition_handling.pause_if_all_down.node.rabbit = rabbit@localhost -# cluster_partition_handling.pause_if_all_down.node.hare = hare@localhost - -## Mirror sync batch size, in messages. Increasing this will speed -## up syncing but total batch size in bytes must not exceed 2 GiB. -## Available in RabbitMQ 3.6.0 or later. -## -mirroring_sync_batch_size = 4096 - -## Make clustering happen *automatically* at startup - only applied -## to nodes that have just been reset or started for the first time. -## See http://www.rabbitmq.com/clustering.html#auto-config for -## further details. -## -# cluster_nodes.disc.1 = rabbit@my.host.com - -## You can define multiple nodes -# cluster_nodes.disc.2 = hare@my.host.com - -## There can be also ram nodes. -## Ram nodes should not be defined together with disk nodes -# cluster_nodes.ram.1 = rabbit@my.host.com - -## Interval (in milliseconds) at which we send keepalive messages -## to other cluster members. Note that this is not the same thing -## as net_ticktime; missed keepalive messages will not cause nodes -## to be considered down. -## -# cluster_keepalive_interval = 10000 - -## -## Statistics Collection -## ===================== -## - -## Set (internal) statistics collection granularity. -## -## Can be none, coarse or fine -collect_statistics = none - -# collect_statistics = coarse - -## Statistics collection interval (in milliseconds). Increasing -## this will reduce the load on management database. -## -collect_statistics_interval = 5000 - -## -## Misc/Advanced Options -## ===================== -## -## NB: Change these only if you understand what you are doing! -## - -## Explicitly enable/disable hipe compilation. -## -hipe_compile = false - -## Timeout used when waiting for Mnesia tables in a cluster to -## become available. -## -mnesia_table_loading_retry_timeout = 30000 - -## Retries when waiting for Mnesia tables in the cluster startup. Note that -## this setting is not applied to Mnesia upgrades or node deletions. -## -## mnesia_table_loading_retry_limit = 10 - -## Size in bytes below which to embed messages in the queue index. See -## http://www.rabbitmq.com/persistence-conf.html -## -queue_index_embed_msgs_below = 4096 - -## You can also set this size in memory units -## -queue_index_embed_msgs_below = 4kb - -## ---------------------------------------------------------------------------- -## Advanced Erlang Networking/Clustering Options. -## -## See http://www.rabbitmq.com/clustering.html for details -## ---------------------------------------------------------------------------- - -# ====================================== -# Kernel section -# ====================================== - -# kernel.net_ticktime = 60 - -## ---------------------------------------------------------------------------- -## RabbitMQ Management Plugin -## -## See http://www.rabbitmq.com/management.html for details -## ---------------------------------------------------------------------------- - -# ======================================= -# Management section -# ======================================= - -## Pre-Load schema definitions from the following JSON file. See -## http://www.rabbitmq.com/management.html#load-definitions -## -# management.load_definitions = /path/to/schema.json - -## Log all requests to the management HTTP API to a file. -## -# management.http_log_dir = /path/to/access.log - -## Change the port on which the HTTP listener listens, -## specifying an interface for the web server to bind to. -## Also set the listener to use SSL and provide SSL options. -## - -# QA: Maybe use IP type like in tcp_listener? -management.listener.port = 12345 -management.listener.ip = 127.0.0.1 -# management.listener.ssl = true - -# management.listener.ssl_opts.cacertfile = /path/to/cacert.pem -# management.listener.ssl_opts.certfile = /path/to/cert.pem -# management.listener.ssl_opts.keyfile = /path/to/key.pem - -## One of 'basic', 'detailed' or 'none'. See -## http://www.rabbitmq.com/management.html#fine-stats for more details. -management.rates_mode = basic - -## Configure how long aggregated data (such as message rates and queue -## lengths) is retained. Please read the plugin's documentation in -## http://www.rabbitmq.com/management.html#configuration for more -## details. -## Your can use 'minute', 'hour' and '24hours' keys or integer key (in seconds) -management.sample_retention_policies.global.minute = 5 -management.sample_retention_policies.global.hour = 60 -management.sample_retention_policies.global.day = 1200 - -management.sample_retention_policies.basic.minute = 5 -management.sample_retention_policies.basic.hour = 60 - -management.sample_retention_policies.detailed.10 = 5 - -## ---------------------------------------------------------------------------- -## RabbitMQ Shovel Plugin -## -## See http://www.rabbitmq.com/shovel.html for details -## ---------------------------------------------------------------------------- - -## Shovel plugin config example is defined in additional.config file - - -## ---------------------------------------------------------------------------- -## RabbitMQ Stomp Adapter -## -## See http://www.rabbitmq.com/stomp.html for details -## ---------------------------------------------------------------------------- - -# ======================================= -# STOMP section -# ======================================= - -## Network Configuration - the format is generally the same as for the broker -## -stomp.listener.tcp.default = 61613 - -## Same for ssl listeners -## -# stomp.listener.ssl.default = 61614 - -## Number of Erlang processes that will accept connections for the TCP -## and SSL listeners. -## -stomp.num_acceptors.tcp = 10 -stomp.num_acceptors.ssl = 1 - -## Additional SSL options - -## Extract a name from the client's certificate when using SSL. -## -stomp.ssl_cert_login = true - -## Set a default user name and password. This is used as the default login -## whenever a CONNECT frame omits the login and passcode headers. -## -## Please note that setting this will allow clients to connect without -## authenticating! -## -# stomp.default_user = guest -# stomp.default_pass = guest - -## If a default user is configured, or you have configured use SSL client -## certificate based authentication, you can choose to allow clients to -## omit the CONNECT frame entirely. If set to true, the client is -## automatically connected as the default user or user supplied in the -## SSL certificate whenever the first frame sent on a session is not a -## CONNECT frame. -## -# stomp.implicit_connect = true - -## ---------------------------------------------------------------------------- -## RabbitMQ MQTT Adapter -## -## See https://github.com/rabbitmq/rabbitmq-mqtt/blob/stable/README.md -## for details -## ---------------------------------------------------------------------------- - -# ======================================= -# MQTT section -# ======================================= - -## Set the default user name and password. Will be used as the default login -## if a connecting client provides no other login details. -## -## Please note that setting this will allow clients to connect without -## authenticating! -## -# mqtt.default_user = guest -# mqtt.default_pass = guest - -## Enable anonymous access. If this is set to false, clients MUST provide -## login information in order to connect. See the default_user/default_pass -## configuration elements for managing logins without authentication. -## -# mqtt.allow_anonymous = true - -## If you have multiple chosts, specify the one to which the -## adapter connects. -## -mqtt.vhost = / - -## Specify the exchange to which messages from MQTT clients are published. -## -mqtt.exchange = amq.topic - -## Specify TTL (time to live) to control the lifetime of non-clean sessions. -## -# mqtt.subscription_ttl = 1800000 - -## Set the prefetch count (governing the maximum number of unacknowledged -## messages that will be delivered). -## -mqtt.prefetch = 10 - -## TCP/SSL Configuration (as per the broker configuration). -## -mqtt.listener.tcp.default = 1883 - -## Same for ssl listener -## -# mqtt.listener.ssl.default = 1884 - -## Number of Erlang processes that will accept connections for the TCP -## and SSL listeners. -## -mqtt.num_acceptors.tcp = 10 -mqtt.num_acceptors.ssl = 1 - -## TCP/Socket options (as per the broker configuration). -## -# mqtt.tcp_listen_option.backlog = 128 -# mqtt.tcp_listen_option.nodelay = true - -## ---------------------------------------------------------------------------- -## RabbitMQ AMQP 1.0 Support -## -## See https://github.com/rabbitmq/rabbitmq-amqp1.0/blob/stable/README.md -## for details -## ---------------------------------------------------------------------------- - -# ======================================= -# AMQP_1 section -# ======================================= - - -## Connections that are not authenticated with SASL will connect as this -## account. See the README for more information. -## -## Please note that setting this will allow clients to connect without -## authenticating! -## -amqp1_0.default_user = guest - -## Enable protocol strict mode. See the README for more information. -## -amqp1_0.protocol_strict_mode = false - -## Lager controls logging. -## See https://github.com/basho/lager for more documentation -## -## Log direcrory, taken from the RABBITMQ_LOG_BASE env variable by default. -## -# log.dir = /var/log/rabbitmq - -## Logging to console (can be true or false) -## -# log.console = false - -## Loglevel to log to console -## -# log.console.level = info - -## Logging to file. Can be false or filename. -## Default: -# log.file = rabbit.log - -## To turn off: -# log.file = false - -## Loglevel to log to file -## -# log.file.level = info - -## File rotation config. No rotation by defualt. -## DO NOT SET rotation date to ''. Leave unset if require "" value -# log.file.rotation.date = $D0 -# log.file.rotation.size = 0 - - -## QA: Config for syslog logging -# log.syslog = false -# log.syslog.identity = rabbitmq -# log.syslog.level = info -# log.syslog.facility = daemon - - -## ---------------------------------------------------------------------------- -## RabbitMQ LDAP Plugin -## -## See http://www.rabbitmq.com/ldap.html for details. -## -## ---------------------------------------------------------------------------- - -# ======================================= -# LDAP section -# ======================================= - -## -## Connecting to the LDAP server(s) -## ================================ -## - -## Specify servers to bind to. You *must* set this in order for the plugin -## to work properly. -## -# ldap.servers.1 = your-server-name-goes-here - -## You can define multiple servers -# ldap.servers.2 = your-other-server - -## Connect to the LDAP server using SSL -## -# ldap.use_ssl = false - -## Specify the LDAP port to connect to -## -# ldap.port = 389 - -## LDAP connection timeout, in milliseconds or 'infinity' -## -# ldap.timeout = infinity - -## Or number -# ldap.timeout = 500 - -## Enable logging of LDAP queries. -## One of -## - false (no logging is performed) -## - true (verbose logging of the logic used by the plugin) -## - network (as true, but additionally logs LDAP network traffic) -## -## Defaults to false. -## -# ldap.log = false - -## Also can be true or network -# ldap.log = true -# ldap.log = network - -## -## Authentication -## ============== -## - -## Pattern to convert the username given through AMQP to a DN before -## binding -## -# ldap.user_dn_pattern = cn=${username},ou=People,dc=example,dc=com - -## Alternatively, you can convert a username to a Distinguished -## Name via an LDAP lookup after binding. See the documentation for -## full details. - -## When converting a username to a dn via a lookup, set these to -## the name of the attribute that represents the user name, and the -## base DN for the lookup query. -## -# ldap.dn_lookup_attribute = userPrincipalName -# ldap.dn_lookup_base = DC=gopivotal,DC=com - -## Controls how to bind for authorisation queries and also to -## retrieve the details of users logging in without presenting a -## password (e.g., SASL EXTERNAL). -## One of -## - as_user (to bind as the authenticated user - requires a password) -## - anon (to bind anonymously) -## - {UserDN, Password} (to bind with a specified user name and password) -## -## Defaults to 'as_user'. -## -# ldap.other_bind = as_user - -## Or can be more complex: -# ldap.other_bind.user_dn = User -# ldap.other_bind.password = Password - -## If user_dn and password defined - other options is ignored. - -# ----------------------------- -# Too complex section of LDAP -# ----------------------------- - -## -## Authorisation -## ============= -## - -## The LDAP plugin can perform a variety of queries against your -## LDAP server to determine questions of authorisation. See -## http://www.rabbitmq.com/ldap.html#authorisation for more -## information. - -## Following configuration should be defined in additional.config file -## DO NOT UNCOMMENT THIS LINES! - -## Set the query to use when determining vhost access -## -## {vhost_access_query, {in_group, -## "ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}}, - -## Set the query to use when determining resource (e.g., queue) access -## -## {resource_access_query, {constant, true}}, - -## Set queries to determine which tags a user has -## -## {tag_queries, []} -# ]}, -# ----------------------------- diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat index 5da2ac5632..de25f95bdf 100644 --- a/scripts/rabbitmq-server.bat +++ b/scripts/rabbitmq-server.bat @@ -93,9 +93,9 @@ if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.config" ( )
) else if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.conf" (
set RABBITMQ_CONFIG_ARG=-conf "!RABBITMQ_CONFIG_FILE_NOEX!" ^
- -conf_dir !RABBITMQ_GENERATED_CONFIG_DIR! ^
+ -conf_dir "!RABBITMQ_GENERATED_CONFIG_DIR!" ^
-conf_script_dir !CONF_SCRIPT_DIR:\=/! ^
- -conf_schema_dir !RABBITMQ_SCHEMA_DIR!
+ -conf_schema_dir "!RABBITMQ_SCHEMA_DIR!"
if exist "!RABBITMQ_ADVANCED_CONFIG_FILE!.config" (
set RABBITMQ_CONFIG_ARG=!RABBITMQ_CONFIG_ARG! ^
-conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^
@@ -106,9 +106,9 @@ if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.config" ( set RABBITMQ_CONFIG_ARG=-config "!RABBITMQ_CONFIG_FILE!"
) else if exist "!RABBITMQ_CONFIG_FILE!.conf" (
set RABBITMQ_CONFIG_ARG=-conf "!RABBITMQ_CONFIG_FILE!" ^
- -conf_dir !RABBITMQ_GENERATED_CONFIG_DIR! ^
+ -conf_dir "!RABBITMQ_GENERATED_CONFIG_DIR!" ^
-conf_script_dir !CONF_SCRIPT_DIR:\=/! ^
- -conf_schema_dir !RABBITMQ_SCHEMA_DIR!
+ -conf_schema_dir "!RABBITMQ_SCHEMA_DIR!"
if exist "!RABBITMQ_ADVANCED_CONFIG_FILE!.config" (
set RABBITMQ_CONFIG_ARG=!RABBITMQ_CONFIG_ARG! ^
-conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^
diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat index 6390324f0c..624d18d913 100644 --- a/scripts/rabbitmq-service.bat +++ b/scripts/rabbitmq-service.bat @@ -182,9 +182,9 @@ if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.config" ( )
) else if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.conf" (
set RABBITMQ_CONFIG_ARG=-conf "!RABBITMQ_CONFIG_FILE_NOEX!" ^
- -conf_dir !RABBITMQ_GENERATED_CONFIG_DIR! ^
+ -conf_dir "!RABBITMQ_GENERATED_CONFIG_DIR!" ^
-conf_script_dir !CONF_SCRIPT_DIR:\=/! ^
- -conf_schema_dir !RABBITMQ_SCHEMA_DIR!
+ -conf_schema_dir "!RABBITMQ_SCHEMA_DIR!"
if exist "!RABBITMQ_ADVANCED_CONFIG_FILE!.config" (
set RABBITMQ_CONFIG_ARG=!RABBITMQ_CONFIG_ARG! ^
-conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^
@@ -197,9 +197,9 @@ if "!RABBITMQ_CONFIG_FILE!" == "!RABBITMQ_CONFIG_FILE_NOEX!.config" ( rem Always specify generated config arguments, we cannot
rem assume .conf file is available
set RABBITMQ_CONFIG_ARG=-conf "!RABBITMQ_CONFIG_FILE!" ^
- -conf_dir !RABBITMQ_GENERATED_CONFIG_DIR! ^
+ -conf_dir "!RABBITMQ_GENERATED_CONFIG_DIR!" ^
-conf_script_dir !CONF_SCRIPT_DIR:\=/! ^
- -conf_schema_dir !RABBITMQ_SCHEMA_DIR!
+ -conf_schema_dir "!RABBITMQ_SCHEMA_DIR!"
if exist "!RABBITMQ_ADVANCED_CONFIG_FILE!.config" (
set RABBITMQ_CONFIG_ARG=!RABBITMQ_CONFIG_ARG! ^
-conf_advanced "!RABBITMQ_ADVANCED_CONFIG_FILE!" ^
diff --git a/src/rabbit.erl b/src/rabbit.erl index 588774a7a9..8498e54c09 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -95,8 +95,8 @@ [{description, "core metrics storage"}, {mfa, {rabbit_sup, start_child, [rabbit_metrics]}}, - {requires, external_infrastructure}, - {enables, kernel_ready}]}). + {requires, pre_boot}, + {enables, external_infrastructure}]}). -rabbit_boot_step({rabbit_event, [{description, "statistics event manager"}, diff --git a/src/rabbit_mirror_queue_sync.erl b/src/rabbit_mirror_queue_sync.erl index d6357e0dc0..2994e8cbcf 100644 --- a/src/rabbit_mirror_queue_sync.erl +++ b/src/rabbit_mirror_queue_sync.erl @@ -37,7 +37,7 @@ %% %% Master Syncer Slave(s) %% sync_mirrors -> || || -%% (from channel) || -- (spawns) --> || || +%% || -- (spawns) --> || || %% || --------- sync_start (over GM) -------> || %% || || <--- sync_ready ---- || %% || || (or) || diff --git a/src/rabbit_priority_queue.erl b/src/rabbit_priority_queue.erl index b7a3afd129..34e23260ba 100644 --- a/src/rabbit_priority_queue.erl +++ b/src/rabbit_priority_queue.erl @@ -657,7 +657,7 @@ cse(_, lazy) -> lazy; cse(lazy, _) -> lazy; %% numerical stats cse(A, B) when is_number(A) -> A + B; -cse({delta, _, _, _}, _) -> {delta, todo, todo, todo}; +cse({delta, _, _, _, _}, _) -> {delta, todo, todo, todo, todo}; cse(A, B) -> exit({A, B}). %% When asked about 'head_message_timestamp' fro this priority queue, we diff --git a/src/rabbit_ssl.erl b/src/rabbit_ssl.erl index ac9fb204d0..6a87d93a29 100644 --- a/src/rabbit_ssl.erl +++ b/src/rabbit_ssl.erl @@ -11,13 +11,11 @@ %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. -%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% Copyright (c) 2007-2017 Pivotal Software, Inc. All rights reserved. %% -module(rabbit_ssl). --include("rabbit.hrl"). - -include_lib("public_key/include/public_key.hrl"). -export([peer_cert_issuer/1, peer_cert_subject/1, peer_cert_validity/1]). @@ -27,15 +25,7 @@ -export_type([certificate/0]). --type certificate() :: binary(). - --spec peer_cert_issuer(certificate()) -> string(). --spec peer_cert_subject(certificate()) -> string(). --spec peer_cert_validity(certificate()) -> string(). --spec peer_cert_subject_items - (certificate(), tuple()) -> [string()] | 'not_found'. --spec peer_cert_auth_name - (certificate()) -> binary() | 'not_found' | 'unsafe'. +-type certificate() :: rabbit_cert_info:certificate(). %%-------------------------------------------------------------------------- %% High-level functions used by reader @@ -43,38 +33,24 @@ %% Return a string describing the certificate's issuer. peer_cert_issuer(Cert) -> - cert_info(fun(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - issuer = Issuer }}) -> - format_rdn_sequence(Issuer) - end, Cert). + rabbit_cert_info:issuer(Cert). %% Return a string describing the certificate's subject, as per RFC4514. peer_cert_subject(Cert) -> - cert_info(fun(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - subject = Subject }}) -> - format_rdn_sequence(Subject) - end, Cert). + rabbit_cert_info:subject(Cert). %% Return the parts of the certificate's subject. peer_cert_subject_items(Cert, Type) -> - cert_info(fun(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - subject = Subject }}) -> - find_by_type(Type, Subject) - end, Cert). + rabbit_cert_info:subject_items(Cert, Type). %% Return a string describing the certificate's validity. peer_cert_validity(Cert) -> - cert_info(fun(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - validity = {'Validity', Start, End} }}) -> - rabbit_misc:format("~s - ~s", [format_asn1_value(Start), - format_asn1_value(End)]) - end, Cert). + rabbit_cert_info:validity(Cert). %% Extract a username from the certificate +-spec peer_cert_auth_name + (certificate()) -> binary() | 'not_found' | 'unsafe'. + peer_cert_auth_name(Cert) -> {ok, Mode} = application:get_env(rabbit, ssl_cert_login_from), peer_cert_auth_name(Mode, Cert). @@ -106,189 +82,3 @@ auth_config_sane() -> "disabled, verify=~p~n", [V]), false end. - -%%-------------------------------------------------------------------------- - -cert_info(F, Cert) -> - F(case public_key:pkix_decode_cert(Cert, otp) of - {ok, DecCert} -> DecCert; %%pre R14B - DecCert -> DecCert %%R14B onwards - end). - -find_by_type(Type, {rdnSequence, RDNs}) -> - case [V || #'AttributeTypeAndValue'{type = T, value = V} - <- lists:flatten(RDNs), - T == Type] of - [] -> not_found; - L -> [format_asn1_value(V) || V <- L] - end. - -%%-------------------------------------------------------------------------- -%% Formatting functions -%%-------------------------------------------------------------------------- - -%% Format and rdnSequence as a RFC4514 subject string. -format_rdn_sequence({rdnSequence, Seq}) -> - string:join(lists:reverse([format_complex_rdn(RDN) || RDN <- Seq]), ","). - -%% Format an RDN set. -format_complex_rdn(RDNs) -> - string:join([format_rdn(RDN) || RDN <- RDNs], "+"). - -%% Format an RDN. If the type name is unknown, use the dotted decimal -%% representation. See RFC4514, section 2.3. -format_rdn(#'AttributeTypeAndValue'{type = T, value = V}) -> - FV = escape_rdn_value(format_asn1_value(V)), - Fmts = [{?'id-at-surname' , "SN"}, - {?'id-at-givenName' , "GIVENNAME"}, - {?'id-at-initials' , "INITIALS"}, - {?'id-at-generationQualifier' , "GENERATIONQUALIFIER"}, - {?'id-at-commonName' , "CN"}, - {?'id-at-localityName' , "L"}, - {?'id-at-stateOrProvinceName' , "ST"}, - {?'id-at-organizationName' , "O"}, - {?'id-at-organizationalUnitName' , "OU"}, - {?'id-at-title' , "TITLE"}, - {?'id-at-countryName' , "C"}, - {?'id-at-serialNumber' , "SERIALNUMBER"}, - {?'id-at-pseudonym' , "PSEUDONYM"}, - {?'id-domainComponent' , "DC"}, - {?'id-emailAddress' , "EMAILADDRESS"}, - {?'street-address' , "STREET"}, - {{0,9,2342,19200300,100,1,1} , "UID"}], %% Not in public_key.hrl - case proplists:lookup(T, Fmts) of - {_, Fmt} -> - rabbit_misc:format(Fmt ++ "=~s", [FV]); - none when is_tuple(T) -> - TypeL = [rabbit_misc:format("~w", [X]) || X <- tuple_to_list(T)], - rabbit_misc:format("~s=~s", [string:join(TypeL, "."), FV]); - none -> - rabbit_misc:format("~p=~s", [T, FV]) - end. - -%% Escape a string as per RFC4514. -escape_rdn_value(V) -> - escape_rdn_value(V, start). - -escape_rdn_value([], _) -> - []; -escape_rdn_value([C | S], start) when C =:= $ ; C =:= $# -> - [$\\, C | escape_rdn_value(S, middle)]; -escape_rdn_value(S, start) -> - escape_rdn_value(S, middle); -escape_rdn_value([$ ], middle) -> - [$\\, $ ]; -escape_rdn_value([C | S], middle) when C =:= $"; C =:= $+; C =:= $,; C =:= $;; - C =:= $<; C =:= $>; C =:= $\\ -> - [$\\, C | escape_rdn_value(S, middle)]; -escape_rdn_value([C | S], middle) when C < 32 ; C >= 126 -> - %% Of ASCII characters only U+0000 needs escaping, but for display - %% purposes it's handy to escape all non-printable chars. All non-ASCII - %% characters get converted to UTF-8 sequences and then escaped. We've - %% already got a UTF-8 sequence here, so just escape it. - rabbit_misc:format("\\~2.16.0B", [C]) ++ escape_rdn_value(S, middle); -escape_rdn_value([C | S], middle) -> - [C | escape_rdn_value(S, middle)]. - -%% Get the string representation of an OTPCertificate field. -format_asn1_value({ST, S}) when ST =:= teletexString; ST =:= printableString; - ST =:= universalString; ST =:= utf8String; - ST =:= bmpString -> - format_directory_string(ST, S); -format_asn1_value({utcTime, [Y1, Y2, M1, M2, D1, D2, H1, H2, - Min1, Min2, S1, S2, $Z]}) -> - rabbit_misc:format("20~c~c-~c~c-~c~cT~c~c:~c~c:~c~cZ", - [Y1, Y2, M1, M2, D1, D2, H1, H2, Min1, Min2, S1, S2]); -%% We appear to get an untagged value back for an ia5string -%% (e.g. domainComponent). -format_asn1_value(V) when is_list(V) -> - V; -format_asn1_value(V) when is_binary(V) -> - %% OTP does not decode some values when combined with an unknown - %% type. That's probably wrong, so as a last ditch effort let's - %% try manually decoding. 'DirectoryString' is semi-arbitrary - - %% but it is the type which covers the various string types we - %% handle below. - try - {ST, S} = public_key:der_decode('DirectoryString', V), - format_directory_string(ST, S) - catch _:_ -> - rabbit_misc:format("~p", [V]) - end; -format_asn1_value(V) -> - rabbit_misc:format("~p", [V]). - -%% DirectoryString { INTEGER : maxSize } ::= CHOICE { -%% teletexString TeletexString (SIZE (1..maxSize)), -%% printableString PrintableString (SIZE (1..maxSize)), -%% bmpString BMPString (SIZE (1..maxSize)), -%% universalString UniversalString (SIZE (1..maxSize)), -%% uTF8String UTF8String (SIZE (1..maxSize)) } -%% -%% Precise definitions of printable / teletexString are hard to come -%% by. This is what I reconstructed: -%% -%% printableString: -%% "intended to represent the limited character sets available to -%% mainframe input terminals" -%% A-Z a-z 0-9 ' ( ) + , - . / : = ? [space] -%% http://msdn.microsoft.com/en-us/library/bb540814(v=vs.85).aspx -%% -%% teletexString: -%% "a sizable volume of software in the world treats TeletexString -%% (T61String) as a simple 8-bit string with mostly Windows Latin 1 -%% (superset of iso-8859-1) encoding" -%% http://www.mail-archive.com/asn1@asn1.org/msg00460.html -%% -%% (However according to that link X.680 actually defines -%% TeletexString in some much more involved and crazy way. I suggest -%% we treat it as ISO-8859-1 since Erlang does not support Windows -%% Latin 1). -%% -%% bmpString: -%% UCS-2 according to RFC 3641. Hence cannot represent Unicode -%% characters above 65535 (outside the "Basic Multilingual Plane"). -%% -%% universalString: -%% UCS-4 according to RFC 3641. -%% -%% utf8String: -%% UTF-8 according to RFC 3641. -%% -%% Within Rabbit we assume UTF-8 encoding. Since printableString is a -%% subset of ASCII it is also a subset of UTF-8. The others need -%% converting. Fortunately since the Erlang SSL library does the -%% decoding for us (albeit into a weird format, see below), we just -%% need to handle encoding into UTF-8. Note also that utf8Strings come -%% back as binary. -%% -%% Note for testing: the default Ubuntu configuration for openssl will -%% only create printableString or teletexString types no matter what -%% you do. Edit string_mask in the [req] section of -%% /etc/ssl/openssl.cnf to change this (see comments there). You -%% probably also need to set utf8 = yes to get it to accept UTF-8 on -%% the command line. Also note I could not get openssl to generate a -%% universalString. - -format_directory_string(printableString, S) -> S; -format_directory_string(teletexString, S) -> utf8_list_from(S); -format_directory_string(bmpString, S) -> utf8_list_from(S); -format_directory_string(universalString, S) -> utf8_list_from(S); -format_directory_string(utf8String, S) -> binary_to_list(S). - -utf8_list_from(S) -> - binary_to_list( - unicode:characters_to_binary(flatten_ssl_list(S), utf32, utf8)). - -%% The Erlang SSL implementation invents its own representation for -%% non-ascii strings - looking like [97,{0,0,3,187}] (that's LATIN -%% SMALL LETTER A followed by GREEK SMALL LETTER LAMDA). We convert -%% this into a list of unicode characters, which we can tell -%% unicode:characters_to_binary is utf32. - -flatten_ssl_list(L) -> [flatten_ssl_list_item(I) || I <- L]. - -flatten_ssl_list_item({A, B, C, D}) -> - A * (1 bsl 24) + B * (1 bsl 16) + C * (1 bsl 8) + D; -flatten_ssl_list_item(N) when is_number (N) -> - N. diff --git a/src/rabbit_table.erl b/src/rabbit_table.erl index 040075ea87..56a9c2b578 100644 --- a/src/rabbit_table.erl +++ b/src/rabbit_table.erl @@ -280,7 +280,7 @@ definitions() -> {attributes, record_info(fields, topic_permission)}, {disc_copies, [node()]}, {match, #topic_permission{topic_permission_key = #topic_permission_key{_='_'}, - pattern = '_', + permission = #permission{_='_'}, _='_'}}]}, {rabbit_vhost, [{record_name, vhost}, diff --git a/src/rabbit_upgrade_functions.erl b/src/rabbit_upgrade_functions.erl index 0dcf84af6e..2116e2dfa1 100644 --- a/src/rabbit_upgrade_functions.erl +++ b/src/rabbit_upgrade_functions.erl @@ -591,7 +591,7 @@ user_password_hashing() -> topic_permission() -> create(rabbit_topic_permission, [{record_name, topic_permission}, - {attributes, [topic_permission_key, pattern]}, + {attributes, [topic_permission_key, permission]}, {disc_copies, [node()]}]). exchange_options() -> diff --git a/src/rabbit_variable_queue.erl b/src/rabbit_variable_queue.erl index 5581143e69..c42b4856f2 100644 --- a/src/rabbit_variable_queue.erl +++ b/src/rabbit_variable_queue.erl @@ -292,6 +292,7 @@ unacked_bytes, persistent_count, %% w unacked persistent_bytes, %% w unacked + delta_transient_bytes, %% target_ram_count, ram_msg_count, %% w/o unacked @@ -339,6 +340,7 @@ -record(delta, { start_seq_id, %% start_seq_id is inclusive count, + transient, end_seq_id %% end_seq_id is exclusive }). @@ -430,9 +432,11 @@ -define(BLANK_DELTA, #delta { start_seq_id = undefined, count = 0, + transient = 0, end_seq_id = undefined }). -define(BLANK_DELTA_PATTERN(Z), #delta { start_seq_id = Z, count = 0, + transient = 0, end_seq_id = Z }). -define(MICROS_PER_SECOND, 1000000.0). @@ -933,6 +937,8 @@ info(messages_ram, State) -> info(messages_ready_ram, State) + info(messages_unacknowledged_ram, State); info(messages_persistent, #vqstate{persistent_count = PersistentCount}) -> PersistentCount; +info(messages_paged_out, #vqstate{delta = #delta{transient = Count}}) -> + Count; info(message_bytes, #vqstate{bytes = Bytes, unacked_bytes = UBytes}) -> Bytes + UBytes; @@ -944,6 +950,8 @@ info(message_bytes_ram, #vqstate{ram_bytes = RamBytes}) -> RamBytes; info(message_bytes_persistent, #vqstate{persistent_bytes = PersistentBytes}) -> PersistentBytes; +info(message_bytes_paged_out, #vqstate{delta_transient_bytes = PagedOutBytes}) -> + PagedOutBytes; info(head_message_timestamp, #vqstate{ q3 = Q3, q4 = Q4, @@ -1303,14 +1311,14 @@ maybe_write_delivered(true, SeqId, IndexState) -> rabbit_queue_index:deliver([SeqId], IndexState). betas_from_index_entries(List, TransientThreshold, DelsAndAcksFun, State) -> - {Filtered, Delivers, Acks, RamReadyCount, RamBytes} = + {Filtered, Delivers, Acks, RamReadyCount, RamBytes, TransientCount, TransientBytes} = lists:foldr( fun ({_MsgOrId, SeqId, _MsgProps, IsPersistent, IsDelivered} = M, - {Filtered1, Delivers1, Acks1, RRC, RB} = Acc) -> + {Filtered1, Delivers1, Acks1, RRC, RB, TC, TB} = Acc) -> case SeqId < TransientThreshold andalso not IsPersistent of true -> {Filtered1, cons_if(not IsDelivered, SeqId, Delivers1), - [SeqId | Acks1], RRC, RB}; + [SeqId | Acks1], RRC, RB, TC, TB}; false -> MsgStatus = m(beta_msg_status(M)), HaveMsg = msg_in_ram(MsgStatus), Size = msg_size(MsgStatus), @@ -1318,12 +1326,15 @@ betas_from_index_entries(List, TransientThreshold, DelsAndAcksFun, State) -> false -> {?QUEUE:in_r(MsgStatus, Filtered1), Delivers1, Acks1, RRC + one_if(HaveMsg), - RB + one_if(HaveMsg) * Size}; + RB + one_if(HaveMsg) * Size, + TC + one_if(not IsPersistent), + TB + one_if(not IsPersistent) * Size}; true -> Acc %% [0] end end - end, {?QUEUE:new(), [], [], 0, 0}, List), - {Filtered, RamReadyCount, RamBytes, DelsAndAcksFun(Delivers, Acks, State)}. + end, {?QUEUE:new(), [], [], 0, 0, 0, 0}, List), + {Filtered, RamReadyCount, RamBytes, DelsAndAcksFun(Delivers, Acks, State), + TransientCount, TransientBytes}. %% [0] We don't increase RamBytes here, even though it pertains to %% unacked messages too, since if HaveMsg then the message must have %% been stored in the QI, thus the message must have been in @@ -1336,18 +1347,28 @@ is_msg_in_pending_acks(SeqId, #vqstate { ram_pending_ack = RPA, gb_trees:is_defined(SeqId, DPA) orelse gb_trees:is_defined(SeqId, QPA)). -expand_delta(SeqId, ?BLANK_DELTA_PATTERN(X)) -> - d(#delta { start_seq_id = SeqId, count = 1, end_seq_id = SeqId + 1 }); +expand_delta(SeqId, ?BLANK_DELTA_PATTERN(X), IsPersistent) -> + d(#delta { start_seq_id = SeqId, count = 1, end_seq_id = SeqId + 1, + transient = one_if(not IsPersistent)}); expand_delta(SeqId, #delta { start_seq_id = StartSeqId, - count = Count } = Delta) + count = Count, + transient = Transient } = Delta, + IsPersistent ) when SeqId < StartSeqId -> - d(Delta #delta { start_seq_id = SeqId, count = Count + 1 }); + d(Delta #delta { start_seq_id = SeqId, count = Count + 1, + transient = Transient + one_if(not IsPersistent)}); expand_delta(SeqId, #delta { count = Count, - end_seq_id = EndSeqId } = Delta) + end_seq_id = EndSeqId, + transient = Transient } = Delta, + IsPersistent) when SeqId >= EndSeqId -> - d(Delta #delta { count = Count + 1, end_seq_id = SeqId + 1 }); -expand_delta(_SeqId, #delta { count = Count } = Delta) -> - d(Delta #delta { count = Count + 1 }). + d(Delta #delta { count = Count + 1, end_seq_id = SeqId + 1, + transient = Transient + one_if(not IsPersistent)}); +expand_delta(_SeqId, #delta { count = Count, + transient = Transient } = Delta, + IsPersistent ) -> + d(Delta #delta { count = Count + 1, + transient = Transient + one_if(not IsPersistent) }). %%---------------------------------------------------------------------------- %% Internal major helpers for Public API @@ -1369,6 +1390,7 @@ init(IsDurable, IndexState, DeltaCount, DeltaBytes, Terms, true -> ?BLANK_DELTA; false -> d(#delta { start_seq_id = LowSeqId, count = DeltaCount1, + transient = 0, end_seq_id = NextSeqId }) end, Now = erlang:monotonic_time(), @@ -1397,6 +1419,7 @@ init(IsDurable, IndexState, DeltaCount, DeltaBytes, Terms, persistent_count = DeltaCount1, bytes = DeltaBytes1, persistent_bytes = DeltaBytes1, + delta_transient_bytes = 0, target_ram_count = infinity, ram_msg_count = 0, @@ -1436,22 +1459,22 @@ in_r(MsgStatus = #msg_status { msg = undefined }, false -> {Msg, State1 = #vqstate { q4 = Q4a }} = read_msg(MsgStatus, State), MsgStatus1 = MsgStatus#msg_status{msg = Msg}, - stats(ready0, {MsgStatus, MsgStatus1}, + stats(ready0, {MsgStatus, MsgStatus1}, 0, State1 #vqstate { q4 = ?QUEUE:in_r(MsgStatus1, Q4a) }) end; in_r(MsgStatus, State = #vqstate { mode = default, q4 = Q4 }) -> State #vqstate { q4 = ?QUEUE:in_r(MsgStatus, Q4) }; %% lazy queues -in_r(MsgStatus = #msg_status { seq_id = SeqId }, +in_r(MsgStatus = #msg_status { seq_id = SeqId, is_persistent = IsPersistent }, State = #vqstate { mode = lazy, q3 = Q3, delta = Delta}) -> case ?QUEUE:is_empty(Q3) of true -> {_MsgStatus1, State1} = maybe_write_to_disk(true, true, MsgStatus, State), - State2 = stats(ready0, {MsgStatus, none}, State1), - Delta1 = expand_delta(SeqId, Delta), - State2 #vqstate{ delta = Delta1 }; + State2 = stats(ready0, {MsgStatus, none}, 1, State1), + Delta1 = expand_delta(SeqId, Delta, IsPersistent), + State2 #vqstate{ delta = Delta1}; false -> State #vqstate { q3 = ?QUEUE:in_r(MsgStatus, Q3) } end. @@ -1487,8 +1510,8 @@ read_msg(MsgId, IsPersistent, State = #vqstate{msg_store_clients = MSCState, {Msg, State #vqstate {msg_store_clients = MSCState1, disk_read_count = Count + 1}}. -stats(Signs, Statuses, State) -> - stats0(expand_signs(Signs), expand_statuses(Statuses), State). +stats(Signs, Statuses, DeltaPaged, State) -> + stats0(expand_signs(Signs), expand_statuses(Statuses), DeltaPaged, State). expand_signs(ready0) -> {0, 0, true}; expand_signs(lazy_pub) -> {1, 0, true}; @@ -1503,13 +1526,14 @@ expand_statuses({B, A}) -> {msg_in_ram(B), msg_in_ram(A), B}. %% contains "Ready" or "Unacked" iff that is what it counts. If %% neither is present it counts both. stats0({DeltaReady, DeltaUnacked, ReadyMsgPaged}, - {InRamBefore, InRamAfter, MsgStatus}, + {InRamBefore, InRamAfter, MsgStatus}, DeltaPaged, State = #vqstate{len = ReadyCount, bytes = ReadyBytes, ram_msg_count = RamReadyCount, persistent_count = PersistentCount, unacked_bytes = UnackedBytes, ram_bytes = RamBytes, + delta_transient_bytes = DeltaBytes, persistent_bytes = PersistentBytes}) -> S = msg_size(MsgStatus), DeltaTotal = DeltaReady + DeltaUnacked, @@ -1532,7 +1556,8 @@ stats0({DeltaReady, DeltaUnacked, ReadyMsgPaged}, bytes = ReadyBytes + DeltaReady * S, unacked_bytes = UnackedBytes + DeltaUnacked * S, ram_bytes = RamBytes + DeltaRam * S, - persistent_bytes = PersistentBytes + DeltaPersistent * S}. + persistent_bytes = PersistentBytes + DeltaPersistent * S, + delta_transient_bytes = DeltaBytes + DeltaPaged * one_if(not MsgStatus#msg_status.is_persistent) * S}. msg_size(#msg_status{msg_props = #message_properties{size = Size}}) -> Size. @@ -1554,7 +1579,7 @@ remove(true, MsgStatus = #msg_status { MsgStatus #msg_status { is_delivered = true }, State), - State2 = stats({-1, 1}, {MsgStatus, MsgStatus}, State1), + State2 = stats({-1, 1}, {MsgStatus, MsgStatus}, 0, State1), {SeqId, maybe_update_rates( State2 #vqstate {out_counter = OutCount + 1, @@ -1590,7 +1615,7 @@ remove(false, MsgStatus = #msg_status { false -> IndexState1 end, - State1 = stats({-1, 0}, {MsgStatus, none}, State), + State1 = stats({-1, 0}, {MsgStatus, none}, 0, State), {undefined, maybe_update_rates( State1 #vqstate {out_counter = OutCount + 1, @@ -1674,7 +1699,7 @@ process_queue_entries1( is_delivered = true }, State1), {cons_if(IndexOnDisk andalso not IsDelivered, SeqId, Delivers), Fun(Msg, SeqId, FetchAcc), - stats({-1, 1}, {MsgStatus, MsgStatus}, State2)}. + stats({-1, 1}, {MsgStatus, MsgStatus}, 0, State2)}. collect_by_predicate(Pred, QAcc, State) -> case queue_out(State) of @@ -1776,7 +1801,7 @@ remove_queue_entries1( end, cons_if(IndexOnDisk andalso not IsDelivered, SeqId, Delivers), cons_if(IndexOnDisk, SeqId, Acks), - stats({-1, 0}, {MsgStatus, none}, State)}. + stats({-1, 0}, {MsgStatus, none}, 0, State)}. process_delivers_and_acks_fun(deliver_and_ack) -> fun (Delivers, Acks, State = #vqstate { index_state = IndexState }) -> @@ -1813,7 +1838,7 @@ publish1(Msg = #basic_message { is_persistent = IsPersistent, id = MsgId }, end, InCount1 = InCount + 1, UC1 = gb_sets_maybe_insert(NeedsConfirming, MsgId, UC), - stats({1, 0}, {none, MsgStatus1}, + stats({1, 0}, {none, MsgStatus1}, 0, State2#vqstate{ next_seq_id = SeqId + 1, in_counter = InCount1, unconfirmed = UC1 }); @@ -1826,17 +1851,17 @@ publish1(Msg = #basic_message { is_persistent = IsPersistent, id = MsgId }, in_counter = InCount, durable = IsDurable, unconfirmed = UC, - delta = Delta }) -> + delta = Delta}) -> IsPersistent1 = IsDurable andalso IsPersistent, MsgStatus = msg_status(IsPersistent1, IsDelivered, SeqId, Msg, MsgProps, IndexMaxSize), {MsgStatus1, State1} = PersistFun(true, true, MsgStatus, State), - Delta1 = expand_delta(SeqId, Delta), + Delta1 = expand_delta(SeqId, Delta, IsPersistent), UC1 = gb_sets_maybe_insert(NeedsConfirming, MsgId, UC), - stats(lazy_pub, {lazy, m(MsgStatus1)}, + stats(lazy_pub, {lazy, m(MsgStatus1)}, 1, State1#vqstate{ delta = Delta1, next_seq_id = SeqId + 1, in_counter = InCount + 1, - unconfirmed = UC1 }). + unconfirmed = UC1}). batch_publish1({Msg, MsgProps, IsDelivered}, {ChPid, Flow, State}) -> {ChPid, Flow, publish1(Msg, MsgProps, IsDelivered, ChPid, Flow, @@ -1859,7 +1884,7 @@ publish_delivered1(Msg = #basic_message { is_persistent = IsPersistent, {MsgStatus1, State1} = PersistFun(false, false, MsgStatus, State), State2 = record_pending_ack(m(MsgStatus1), State1), UC1 = gb_sets_maybe_insert(NeedsConfirming, MsgId, UC), - State3 = stats({0, 1}, {none, MsgStatus1}, + State3 = stats({0, 1}, {none, MsgStatus1}, 0, State2 #vqstate { next_seq_id = SeqId + 1, out_counter = OutCount + 1, in_counter = InCount + 1, @@ -1882,7 +1907,7 @@ publish_delivered1(Msg = #basic_message { is_persistent = IsPersistent, {MsgStatus1, State1} = PersistFun(true, true, MsgStatus, State), State2 = record_pending_ack(m(MsgStatus1), State1), UC1 = gb_sets_maybe_insert(NeedsConfirming, MsgId, UC), - State3 = stats({0, 1}, {none, MsgStatus1}, + State3 = stats({0, 1}, {none, MsgStatus1}, 0, State2 #vqstate { next_seq_id = SeqId + 1, out_counter = OutCount + 1, in_counter = InCount + 1, @@ -2070,7 +2095,7 @@ remove_pending_ack(true, SeqId, State) -> {none, _} -> {none, State}; {MsgStatus, State1} -> - {MsgStatus, stats({0, -1}, {MsgStatus, none}, State1)} + {MsgStatus, stats({0, -1}, {MsgStatus, none}, 0, State1)} end; remove_pending_ack(false, SeqId, State = #vqstate{ram_pending_ack = RPA, disk_pending_ack = DPA, @@ -2215,14 +2240,14 @@ msgs_and_indices_written_to_disk(Callback, MsgIdSet) -> publish_alpha(#msg_status { msg = undefined } = MsgStatus, State) -> {Msg, State1} = read_msg(MsgStatus, State), MsgStatus1 = MsgStatus#msg_status { msg = Msg }, - {MsgStatus1, stats({1, -1}, {MsgStatus, MsgStatus1}, State1)}; + {MsgStatus1, stats({1, -1}, {MsgStatus, MsgStatus1}, 0, State1)}; publish_alpha(MsgStatus, State) -> - {MsgStatus, stats({1, -1}, {MsgStatus, MsgStatus}, State)}. + {MsgStatus, stats({1, -1}, {MsgStatus, MsgStatus}, 0, State)}. publish_beta(MsgStatus, State) -> {MsgStatus1, State1} = maybe_prepare_write_to_disk(true, false, MsgStatus, State), MsgStatus2 = m(trim_msg_status(MsgStatus1)), - {MsgStatus2, stats({1, -1}, {MsgStatus, MsgStatus2}, State1)}. + {MsgStatus2, stats({1, -1}, {MsgStatus, MsgStatus2}, 0, State1)}. %% Rebuild queue, inserting sequence ids to maintain ordering queue_merge(SeqIds, Q, MsgIds, Limit, PubFun, State) -> @@ -2261,11 +2286,12 @@ delta_merge(SeqIds, Delta, MsgIds, State) -> case msg_from_pending_ack(SeqId, State0) of {none, _} -> Acc; - {#msg_status { msg_id = MsgId } = MsgStatus, State1} -> + {#msg_status { msg_id = MsgId, + is_persistent = IsPersistent } = MsgStatus, State1} -> {_MsgStatus, State2} = maybe_prepare_write_to_disk(true, true, MsgStatus, State1), - {expand_delta(SeqId, Delta0), [MsgId | MsgIds0], - stats({1, -1}, {MsgStatus, none}, State2)} + {expand_delta(SeqId, Delta0, IsPersistent), [MsgId | MsgIds0], + stats({1, -1}, {MsgStatus, none}, 1, State2)} end end, {Delta, MsgIds, State}, SeqIds). @@ -2467,7 +2493,7 @@ limit_ram_acks(Quota, State = #vqstate { ram_pending_ack = RPA, MsgStatus2 = m(trim_msg_status(MsgStatus1)), DPA1 = gb_trees:insert(SeqId, MsgStatus2, DPA), limit_ram_acks(Quota - 1, - stats({0, 0}, {MsgStatus, MsgStatus2}, + stats({0, 0}, {MsgStatus, MsgStatus2}, 0, State1 #vqstate { ram_pending_ack = RPA1, disk_pending_ack = DPA1 })) end. @@ -2556,16 +2582,18 @@ maybe_deltas_to_betas(DelsAndAcksFun, ram_msg_count = RamMsgCount, ram_bytes = RamBytes, disk_read_count = DiskReadCount, + delta_transient_bytes = DeltaTransientBytes, transient_threshold = TransientThreshold }) -> #delta { start_seq_id = DeltaSeqId, count = DeltaCount, + transient = Transient, end_seq_id = DeltaSeqIdEnd } = Delta, DeltaSeqId1 = lists:min([rabbit_queue_index:next_segment_boundary(DeltaSeqId), DeltaSeqIdEnd]), {List, IndexState1} = rabbit_queue_index:read(DeltaSeqId, DeltaSeqId1, IndexState), - {Q3a, RamCountsInc, RamBytesInc, State1} = + {Q3a, RamCountsInc, RamBytesInc, State1, TransientCount, TransientBytes} = betas_from_index_entries(List, TransientThreshold, DelsAndAcksFun, State #vqstate { index_state = IndexState1 }), @@ -2588,13 +2616,16 @@ maybe_deltas_to_betas(DelsAndAcksFun, %% can now join q2 onto q3 State2 #vqstate { q2 = ?QUEUE:new(), delta = ?BLANK_DELTA, - q3 = ?QUEUE:join(Q3b, Q2) }; + q3 = ?QUEUE:join(Q3b, Q2), + delta_transient_bytes = 0}; N when N > 0 -> Delta1 = d(#delta { start_seq_id = DeltaSeqId1, count = N, + transient = Transient - TransientCount, end_seq_id = DeltaSeqIdEnd }), State2 #vqstate { delta = Delta1, - q3 = Q3b } + q3 = Q3b, + delta_transient_bytes = DeltaTransientBytes - TransientBytes } end end. @@ -2603,7 +2634,8 @@ push_alphas_to_betas(Quota, State) -> push_alphas_to_betas( fun ?QUEUE:out/1, fun (MsgStatus, Q1a, - State0 = #vqstate { q3 = Q3, delta = #delta { count = 0 } }) -> + State0 = #vqstate { q3 = Q3, delta = #delta { count = 0, + transient = 0 } }) -> State0 #vqstate { q1 = Q1a, q3 = ?QUEUE:in(MsgStatus, Q3) }; (MsgStatus, Q1a, State0 = #vqstate { q2 = Q2 }) -> State0 #vqstate { q1 = Q1a, q2 = ?QUEUE:in(MsgStatus, Q2) } @@ -2639,7 +2671,7 @@ push_alphas_to_betas(Generator, Consumer, Quota, Q, State) -> State), MsgStatus2 = m(trim_msg_status(MsgStatus1)), State2 = stats( - ready0, {MsgStatus, MsgStatus2}, State1), + ready0, {MsgStatus, MsgStatus2}, 0, State1), State3 = Consumer(MsgStatus2, Qa, State2), push_alphas_to_betas(Generator, Consumer, Quota - 1, Qa, State3) @@ -2702,10 +2734,11 @@ push_betas_to_deltas1(Generator, Limit, Q, {Quota, Delta, State}) -> when SeqId < Limit -> {Q, {Quota, Delta, ui(State)}}; {{value, MsgStatus = #msg_status { seq_id = SeqId }}, Qa} -> - {#msg_status { index_on_disk = true }, State1} = + {#msg_status { index_on_disk = true, + is_persistent = IsPersistent }, State1} = maybe_batch_write_index_to_disk(true, MsgStatus, State), - State2 = stats(ready0, {MsgStatus, none}, State1), - Delta1 = expand_delta(SeqId, Delta), + State2 = stats(ready0, {MsgStatus, none}, 1, State1), + Delta1 = expand_delta(SeqId, Delta, IsPersistent), push_betas_to_deltas1(Generator, Limit, Qa, {Quota - 1, Delta1, State2}) end. diff --git a/test/config_schema_SUITE_data/snippets.config b/test/config_schema_SUITE_data/snippets.config index 7a854a10e1..9fb0b7519b 100644 --- a/test/config_schema_SUITE_data/snippets.config +++ b/test/config_schema_SUITE_data/snippets.config @@ -50,7 +50,12 @@ auth_backends.2 = internal", ] }],[]} , - +{7.1, +"auth_backends.1.authn = ldap", +[{rabbit, [ + {auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_ldap}]} + ] + }],[]}, {8, "ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem @@ -134,41 +139,47 @@ auth_backends.2 = internal", [{rabbit,[{auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal}, rabbit_auth_backend_internal]}]}],[]} , -{16, -"rabbitmq_auth_backend_ldap.servers.1 = some_server - rabbitmq_auth_backend_ldap.servers.2 = some_other_server", -[{rabbitmq_auth_backend_ldap, [{servers, ["some_server", "some_other_server"]}]}], +{16.1, +"auth_ldap.servers.1 = DC1.domain.com + auth_ldap.servers.2 = DC1.eng.domain.com", +[{rabbitmq_auth_backend_ldap, [{servers, ["DC1.domain.com", "DC1.eng.domain.com"]}]}], +[rabbitmq_auth_backend_ldap]} +, +{16.2, +"auth_ldap.servers.1 = hostname1 + auth_ldap.servers.2 = hostname2", +[{rabbitmq_auth_backend_ldap, [{servers, ["hostname1", "hostname2"]}]}], [rabbitmq_auth_backend_ldap]} , {17, -"rabbitmq_auth_backend_ldap.dn_lookup_attribute = userPrincipalName -rabbitmq_auth_backend_ldap.dn_lookup_base = DC=gopivotal,DC=com -rabbitmq_auth_backend_ldap.dn_lookup_bind = as_user", +"auth_ldap.dn_lookup_attribute = userPrincipalName +auth_ldap.dn_lookup_base = DC=gopivotal,DC=com +auth_ldap.dn_lookup_bind = as_user", [{rabbitmq_auth_backend_ldap, [{dn_lookup_attribute, "userPrincipalName"}, {dn_lookup_base, "DC=gopivotal,DC=com"}, {dn_lookup_bind, as_user}]}], [rabbitmq_auth_backend_ldap]} , {18, -"rabbitmq_auth_backend_ldap.dn_lookup_bind.user_dn = username -rabbitmq_auth_backend_ldap.dn_lookup_bind.password = password", +"auth_ldap.dn_lookup_bind.user_dn = username +auth_ldap.dn_lookup_bind.password = password", [{rabbitmq_auth_backend_ldap, [ {dn_lookup_bind, {"username", "password"}}]}], [rabbitmq_auth_backend_ldap]} , {19, -"rabbitmq_auth_backend_ldap.other_bind = anon", +"auth_ldap.other_bind = anon", [{rabbitmq_auth_backend_ldap, [{other_bind, anon}]}], [rabbitmq_auth_backend_ldap]} , {20, -"rabbitmq_auth_backend_ldap.other_bind = as_user", +"auth_ldap.other_bind = as_user", [{rabbitmq_auth_backend_ldap, [{other_bind, as_user}]}], [rabbitmq_auth_backend_ldap]} , {21, -"rabbitmq_auth_backend_ldap.other_bind.user_dn = username -rabbitmq_auth_backend_ldap.other_bind.password = password", +"auth_ldap.other_bind.user_dn = username +auth_ldap.other_bind.password = password", [{rabbitmq_auth_backend_ldap, [{other_bind, {"username", "password"}}]}], [rabbitmq_auth_backend_ldap]} , @@ -252,7 +263,8 @@ mqtt.listeners.ssl = none # mqtt.listeners.ssl.default = 8883 mqtt.listeners.tcp.default = 1883 mqtt.tcp_listen_options.backlog = 128 -mqtt.tcp_listen_options.nodelay = true", +mqtt.tcp_listen_options.nodelay = true +mqtt.proxy_protocol = false", [{rabbit, [{tcp_listeners, [5672]}]}, {rabbitmq_mqtt, [{default_user, <<"guest">>}, {default_pass, <<"guest">>}, @@ -266,7 +278,8 @@ mqtt.tcp_listen_options.nodelay = true", %% {ssl_listeners, [8883]} {tcp_listeners, [1883]}, {tcp_listen_options, [{backlog, 128}, - {nodelay, true}]}]} + {nodelay, true}]}, + {proxy_protocol, false}]} ], [rabbitmq_mqtt]} , @@ -312,7 +325,8 @@ mqtt.allow_anonymous = true mqtt.vhost = / mqtt.exchange = amq.topic mqtt.subscription_ttl = undefined -mqtt.prefetch = 10", +mqtt.prefetch = 10 +mqtt.proxy_protocol = true", [{rabbit, [{tcp_listeners, [5672]}]}, {rabbitmq_mqtt, [{default_user, <<"guest">>}, {default_pass, <<"guest">>}, @@ -320,7 +334,8 @@ mqtt.prefetch = 10", {vhost, <<"/">>}, {exchange, <<"amq.topic">>}, {subscription_ttl, undefined}, - {prefetch, 10}]} + {prefetch, 10}, + {proxy_protocol, true}]} ], [rabbitmq_mqtt]} , @@ -634,8 +649,10 @@ stomp.listeners.ssl.1 = 61614", {57, "stomp.default_user = guest -stomp.default_pass = guest", -[{rabbitmq_stomp, [{default_user, [{login, "guest"},{passcode, "guest"}]}]}], +stomp.default_pass = guest +stomp.proxy_protocol = false", +[{rabbitmq_stomp, [{default_user, [{login, "guest"},{passcode, "guest"}]}, + {proxy_protocol, false}]}], [rabbitmq_stomp]} , {58, @@ -650,8 +667,10 @@ stomp.default_pass = guest", {60, "stomp.default_user = guest stomp.default_pass = guest -stomp.implicit_connect = true", -[{rabbitmq_stomp, [{default_user,[{login, "guest"}, {passcode, "guest"}]},{implicit_connect, true}]}], +stomp.implicit_connect = true +stomp.proxy_protocol = true", +[{rabbitmq_stomp, [{default_user,[{login, "guest"}, {passcode, "guest"}]}, + {implicit_connect, true}, {proxy_protocol, true}]}], [rabbitmq_stomp]} , {61, @@ -721,9 +740,9 @@ web_stomp.ssl.password = changeme", [rabbitmq_web_stomp]}, {69, "auth_backends.1 = http -rabbitmq_auth_backend_http.user_path = http://some-server/auth/user -rabbitmq_auth_backend_http.vhost_path = http://some-server/auth/vhost -rabbitmq_auth_backend_http.resource_path = http://some-server/auth/resource", +auth_http.user_path = http://some-server/auth/user +auth_http.vhost_path = http://some-server/auth/vhost +auth_http.resource_path = http://some-server/auth/resource", [{rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}, {rabbitmq_auth_backend_http, [{user_path, "http://some-server/auth/user"}, @@ -806,6 +825,78 @@ credential_validator.regexp = ^abc\\d+", {validation_backend, rabbit_credential_validator_password_regexp}, {regexp, "^abc\\d+"} ]} +]}],[]}, + +{79, +"auth_backends.1 = amqp +auth_amqp.username = user +auth_amqp.vhost = my_vhost +auth_amqp.exchange = exchange_name +auth_amqp.timeout = 100", +[{rabbit, [{auth_backends, [rabbit_auth_backend_amqp]}]}, + {rabbitmq_auth_backend_amqp, + [{username, <<"user">>}, + {vhost, <<"my_vhost">>}, + {exchange, <<"exchange_name">>}, + {timeout, 100}]}], +[rabbitmq_auth_backend_amqp]}, + +{80, +"auth_backends.1 = cache +auth_cache.cached_backend = ldap", +[ + {rabbit, + [{auth_backends,[rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, + [{cached_backend,rabbit_auth_backend_ldap}]} +], [rabbitmq_auth_backend_cache]}, + +{auth_backend_cache, + "auth_backends.1 = cache", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}], + [rabbitmq_auth_backend_cache]}, + +{auth_backend_cache_cached_backend, + "auth_backends.1 = cache + auth_cache.cached_backend = ldap", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, [{cached_backend, rabbit_auth_backend_ldap}]}], + [rabbitmq_auth_backend_cache]}, +{auth_backend_cache_cached_authn_authz, + "auth_backends.1 = cache + auth_cache.cached_backend.authn = ldap + auth_cache.cached_backend.authz = http", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, [{cached_backend, {rabbit_auth_backend_ldap, rabbit_auth_backend_http}}]}], + [rabbitmq_auth_backend_cache]}, +{auth_backend_cache_cached_authn, + "auth_backends.1 = cache + auth_cache.cached_backend.authn = ldap", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, [{cached_backend, {rabbit_auth_backend_ldap, rabbit_auth_backend_ldap}}]}], + [rabbitmq_auth_backend_cache]}, +{auth_backend_cache_cache_ttl, + "auth_backends.1 = cache + auth_cache.cache_ttl = 200", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, [{cache_ttl, 200}]}], + [rabbitmq_auth_backend_cache]}, +{auth_backend_cache_cache_module, + "auth_backends.1 = cache + auth_cache.cache_module = rabbit_auth_backend_ets_segmented", + [{rabbit, [{auth_backends, [rabbit_auth_backend_cache]}]}, + {rabbitmq_auth_backend_cache, [{cache_module, rabbit_auth_backend_ets_segmented}]}], + [rabbitmq_auth_backend_cache]}, + +{81.1, +"proxy_protocol = true", +[{rabbit, [ + {proxy_protocol, true} +]}],[]}, +{81.2, +"proxy_protocol = false", +[{rabbit, [ + {proxy_protocol, false} ]}],[]} ]. diff --git a/test/dynamic_ha_SUITE.erl b/test/dynamic_ha_SUITE.erl index 1e32fae254..acb46ad872 100644 --- a/test/dynamic_ha_SUITE.erl +++ b/test/dynamic_ha_SUITE.erl @@ -65,8 +65,8 @@ groups() -> nodes_policy_should_pick_master_from_its_params % FIXME: Re-enable those tests when the know issues are % fixed. - %failing_random_policies, - %random_policy + % failing_random_policies, + % random_policy ]} ]} ]. @@ -124,17 +124,18 @@ change_policy(Config) -> %% When we first declare a queue with no policy, it's not HA. amqp_channel:call(ACh, #'queue.declare'{queue = ?QNAME}), + timer:sleep(100), assert_slaves(A, ?QNAME, {A, ''}), %% Give it policy "all", it becomes HA and gets all mirrors rabbit_ct_broker_helpers:set_ha_policy(Config, A, ?POLICY, <<"all">>), - assert_slaves(A, ?QNAME, {A, [B, C]}), + assert_slaves(A, ?QNAME, {A, [B, C]}, [{A, []}, {A, [B]}, {A, [C]}]), %% Give it policy "nodes", it gets specific mirrors rabbit_ct_broker_helpers:set_ha_policy(Config, A, ?POLICY, {<<"nodes">>, [rabbit_misc:atom_to_binary(A), rabbit_misc:atom_to_binary(B)]}), - assert_slaves(A, ?QNAME, {A, [B]}), + assert_slaves(A, ?QNAME, {A, [B]}, [{A, [B, C]}]), %% Now explicitly change the mirrors rabbit_ct_broker_helpers:set_ha_policy(Config, A, ?POLICY, @@ -150,7 +151,7 @@ change_policy(Config) -> rabbit_ct_broker_helpers:set_ha_policy(Config, A, ?POLICY, {<<"nodes">>, [rabbit_misc:atom_to_binary(B), rabbit_misc:atom_to_binary(C)]}), - assert_slaves(A, ?QNAME, {A, [B, C]}, [{A, [B]}, {A, [C]}]), + assert_slaves(A, ?QNAME, {B, [C]}, [{A, []}, {A, [B]}, {A, [C]}, {A, [B, C]}]), ok. @@ -166,15 +167,15 @@ change_cluster(Config) -> %% Give it policy exactly 4, it should mirror to all 3 nodes rabbit_ct_broker_helpers:set_ha_policy(Config, A, ?POLICY, {<<"exactly">>, 4}), - assert_slaves(A, ?QNAME, {A, [B, C]}), + assert_slaves(A, ?QNAME, {A, [B, C]}, [{A, []}, {A, [B]}, {A, [C]}]), %% Add D and E, D joins in rabbit_ct_broker_helpers:cluster_nodes(Config, [A, D, E]), - assert_slaves(A, ?QNAME, {A, [B, C, D]}), + assert_slaves(A, ?QNAME, {A, [B, C, D]}, [{A, [B, C]}]), %% Remove D, E joins in rabbit_ct_broker_helpers:stop_node(Config, D), - assert_slaves(A, ?QNAME, {A, [B, C, E]}), + assert_slaves(A, ?QNAME, {A, [B, C, E]}, [{A, [B, C]}]), ok. @@ -343,15 +344,18 @@ assert_slaves0(RPCNode, QName, {ExpMNode, ExpSNodes}, PermittedIntermediate) -> %% just wait - of course this means if something does not %% change when expected then we time out the test which is %% a bit tedious - case [found || {PermMNode, PermSNodes} <- PermittedIntermediate, + case [{PermMNode, PermSNodes} || {PermMNode, PermSNodes} <- PermittedIntermediate, PermMNode =:= ActMNode, equal_list(PermSNodes, ActSNodes)] of [] -> ct:fail("Expected ~p / ~p, got ~p / ~p~nat ~p~n", [ExpMNode, ExpSNodes, ActMNode, ActSNodes, get_stacktrace()]); - _ -> timer:sleep(100), - assert_slaves0(RPCNode, QName, {ExpMNode, ExpSNodes}, - PermittedIntermediate) + State -> + ct:pal("Waiting to leave state ~p~n Waiting for ~p~n", + [State, {ExpMNode, ExpSNodes}]), + timer:sleep(100), + assert_slaves0(RPCNode, QName, {ExpMNode, ExpSNodes}, + PermittedIntermediate) end; true -> put(previous_exp_m_node, ExpMNode), diff --git a/test/priority_queue_SUITE.erl b/test/priority_queue_SUITE.erl index 8e1b48dd3b..eecd59b879 100644 --- a/test/priority_queue_SUITE.erl +++ b/test/priority_queue_SUITE.erl @@ -44,7 +44,8 @@ groups() -> resume, simple_order, straight_through, - invoke + invoke, + gen_server2_stats ]}, {cluster_size_3, [], [ mirror_queue_auto_ack, @@ -214,6 +215,29 @@ invoke(Config) -> rabbit_ct_client_helpers:close_connection(Conn), passed. + +gen_server2_stats(Config) -> + %% Synthetic test to check the invoke callback, as the bug tested here + %% is only triggered with a race condition. + %% When mirroring is stopped, the backing queue of rabbit_amqqueue_process + %% changes from rabbit_mirror_queue_master to rabbit_priority_queue, + %% which shouldn't receive any invoke call. However, there might + %% be pending messages so the priority queue receives the + %% `run_backing_queue` cast message sent to the old master. + A = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename), + {Conn, Ch} = rabbit_ct_client_helpers:open_connection_and_channel(Config, A), + Q = <<"gen_server2_stats_queue">>, + declare(Ch, Q, 3), + Pid = queue_pid(Config, A, rabbit_misc:r(<<"/">>, queue, Q)), + Metrics = rabbit_ct_broker_helpers:rpc( + Config, A, rabbit_core_metrics, get_gen_server2_stats, + [Pid]), + true = is_number(Metrics), + delete(Ch, Q), + rabbit_ct_client_helpers:close_channel(Ch), + rabbit_ct_client_helpers:close_connection(Conn), + passed. + dropwhile_fetchwhile(Config) -> {Conn, Ch} = rabbit_ct_client_helpers:open_connection_and_channel(Config, 0), Q = <<"dropwhile_fetchwhile-queue">>, diff --git a/test/proxy_protocol_SUITE.erl b/test/proxy_protocol_SUITE.erl new file mode 100644 index 0000000000..136d2bb980 --- /dev/null +++ b/test/proxy_protocol_SUITE.erl @@ -0,0 +1,100 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (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.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. +%% + +-module(proxy_protocol_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("rabbit_common/include/rabbit.hrl"). + +-compile(export_all). + +-define(TIMEOUT, 5000). + +all() -> + [ + {group, sequential_tests} + ]. + +groups() -> [ + {sequential_tests, [], [ + proxy_protocol, + proxy_protocol_tls + ]} + ]. + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, ?MODULE} + ]), + Config2 = rabbit_ct_helpers:merge_app_env(Config1, [ + {rabbit, [ + {proxy_protocol, true} + ]} + ]), + Config3 = rabbit_ct_helpers:set_config(Config2, {rabbitmq_ct_tls_verify, verify_none}), + rabbit_ct_helpers:run_setup_steps(Config3, + rabbit_ct_broker_helpers:setup_steps() ++ + rabbit_ct_client_helpers:setup_steps()). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config, + rabbit_ct_client_helpers:teardown_steps() ++ + rabbit_ct_broker_helpers:teardown_steps()). + +init_per_group(_, Config) -> Config. +end_per_group(_, Config) -> Config. + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase). + +end_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_finished(Config, Testcase). + +proxy_protocol(Config) -> + Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_amqp), + {ok, Socket} = gen_tcp:connect({127,0,0,1}, Port, + [binary, {active, false}, {packet, raw}]), + ok = inet:send(Socket, "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"), + ok = inet:send(Socket, <<"AMQP", 0, 0, 9, 1>>), + {ok, _Packet} = gen_tcp:recv(Socket, 0, ?TIMEOUT), + ConnectionName = rabbit_ct_broker_helpers:rpc(Config, 0, + ?MODULE, connection_name, []), + match = re:run(ConnectionName, <<"^192.168.1.1:80 ">>, [{capture, none}]), + gen_tcp:close(Socket), + ok. + +proxy_protocol_tls(Config) -> + app_utils:start_applications([asn1, crypto, public_key, ssl]), + Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_amqp_tls), + {ok, Socket} = gen_tcp:connect({127,0,0,1}, Port, + [binary, {active, false}, {packet, raw}]), + ok = inet:send(Socket, "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"), + {ok, SslSocket} = ssl:connect(Socket, [], ?TIMEOUT), + ok = ssl:send(SslSocket, <<"AMQP", 0, 0, 9, 1>>), + {ok, _Packet} = ssl:recv(SslSocket, 0, ?TIMEOUT), + ConnectionName = rabbit_ct_broker_helpers:rpc(Config, 0, + ?MODULE, connection_name, []), + match = re:run(ConnectionName, <<"^192.168.1.1:80 ">>, [{capture, none}]), + gen_tcp:close(Socket), + ok. + +connection_name() -> + Pids = pg_local:get_members(rabbit_connections), + Pid = lists:nth(1, Pids), + {dictionary, Dict} = process_info(Pid, dictionary), + {process_name, {rabbit_reader, ConnectionName}} = lists:keyfind(process_name, 1, Dict), + ConnectionName.
\ No newline at end of file diff --git a/test/topic_permission_SUITE.erl b/test/topic_permission_SUITE.erl index 57d48af4ab..7b9d9f7701 100644 --- a/test/topic_permission_SUITE.erl +++ b/test/topic_permission_SUITE.erl @@ -76,7 +76,7 @@ topic_permission_database_access1(_Config) -> rabbit_auth_backend_internal:add_user(<<"dummy">>, <<"dummy">>, <<"acting-user">>), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"/">>, <<"amq.topic">>, "^a", <<"acting-user">> + <<"guest">>, <<"/">>, <<"amq.topic">>, "^a", "^a", <<"acting-user">> ), 1 = length(ets:tab2list(rabbit_topic_permission)), 1 = length(rabbit_auth_backend_internal:list_user_topic_permissions(<<"guest">>)), @@ -88,7 +88,7 @@ topic_permission_database_access1(_Config) -> 1 = length(rabbit_auth_backend_internal:list_topic_permissions()), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"other-vhost">>, <<"amq.topic">>, ".*", <<"acting-user">> + <<"guest">>, <<"other-vhost">>, <<"amq.topic">>, ".*", ".*", <<"acting-user">> ), 2 = length(ets:tab2list(rabbit_topic_permission)), 2 = length(rabbit_auth_backend_internal:list_user_topic_permissions(<<"guest">>)), @@ -100,10 +100,10 @@ topic_permission_database_access1(_Config) -> 2 = length(rabbit_auth_backend_internal:list_topic_permissions()), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"/">>, <<"topic1">>, "^a", <<"acting-user">> + <<"guest">>, <<"/">>, <<"topic1">>, "^a", "^a", <<"acting-user">> ), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"/">>, <<"topic2">>, "^a", <<"acting-user">> + <<"guest">>, <<"/">>, <<"topic2">>, "^a", "^a", <<"acting-user">> ), 4 = length(rabbit_auth_backend_internal:list_user_topic_permissions(<<"guest">>)), @@ -124,16 +124,15 @@ topic_permission_database_access1(_Config) -> {error, {no_such_user, _}} = (catch rabbit_auth_backend_internal:set_topic_permissions( - <<"non-existing-user">>, <<"other-vhost">>, <<"amq.topic">>, ".*", <<"acting-user">> + <<"non-existing-user">>, <<"other-vhost">>, <<"amq.topic">>, ".*", ".*", <<"acting-user">> )), {error, {no_such_vhost, _}} = (catch rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"non-existing-vhost">>, <<"amq.topic">>, ".*", <<"acting-user">> + <<"guest">>, <<"non-existing-vhost">>, <<"amq.topic">>, ".*", ".*", <<"acting-user">> )), {error, {no_such_user, _}} = (catch rabbit_auth_backend_internal:set_topic_permissions( - <<"non-existing-user">>, <<"non-existing-vhost">>, <<"amq.topic">>, ".*", - <<"acting-user">> + <<"non-existing-user">>, <<"non-existing-vhost">>, <<"amq.topic">>, ".*", ".*", <<"acting-user">> )), {error, {no_such_user, _}} = (catch rabbit_auth_backend_internal:list_user_topic_permissions( @@ -145,7 +144,7 @@ topic_permission_database_access1(_Config) -> )), {error, {invalid_regexp, _, _}} = (catch rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"/">>, <<"amq.topic">>, "[", <<"acting-user">> + <<"guest">>, <<"/">>, <<"amq.topic">>, "[", "^a", <<"acting-user">> )), ok. @@ -167,7 +166,7 @@ topic_permission_checks1(_Config) -> rabbit_auth_backend_internal:add_user(<<"dummy">>, <<"dummy">>, <<"acting-user">>), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"/">>, <<"amq.topic">>, "^a", <<"acting-user">> + <<"guest">>, <<"/">>, <<"amq.topic">>, "^a", "^a", <<"acting-user">> ), 1 = length(ets:tab2list(rabbit_topic_permission)), 1 = length(rabbit_auth_backend_internal:list_user_topic_permissions(<<"guest">>)), @@ -176,7 +175,7 @@ topic_permission_checks1(_Config) -> 0 = length(rabbit_auth_backend_internal:list_vhost_topic_permissions(<<"other-vhost">>)), rabbit_auth_backend_internal:set_topic_permissions( - <<"guest">>, <<"other-vhost">>, <<"amq.topic">>, ".*", <<"acting-user">> + <<"guest">>, <<"other-vhost">>, <<"amq.topic">>, ".*", ".*", <<"acting-user">> ), 2 = length(ets:tab2list(rabbit_topic_permission)), 2 = length(rabbit_auth_backend_internal:list_user_topic_permissions(<<"guest">>)), @@ -188,34 +187,35 @@ topic_permission_checks1(_Config) -> Topic = #resource{name = <<"amq.topic">>, virtual_host = <<"/">>, kind = topic}, Context = #{routing_key => <<"a.b.c">>}, + Permissions = [write, read], %% user has access to exchange, routing key matches - true = rabbit_auth_backend_internal:check_topic_access( + [true = rabbit_auth_backend_internal:check_topic_access( User, Topic, - write, + Perm, Context - ), + ) || Perm <- Permissions], %% user has access to exchange, routing key does not match - false = rabbit_auth_backend_internal:check_topic_access( + [false = rabbit_auth_backend_internal:check_topic_access( User, Topic, - write, + Perm, #{routing_key => <<"x.y.z">>} - ), + ) || Perm <- Permissions], %% user has access to exchange but not on this vhost %% let pass when there's no match - true = rabbit_auth_backend_internal:check_topic_access( + [true = rabbit_auth_backend_internal:check_topic_access( User, Topic#resource{virtual_host = <<"fancyvhost">>}, - write, + Perm, Context - ), + ) || Perm <- Permissions], %% user does not have access to exchange %% let pass when there's no match - true = rabbit_auth_backend_internal:check_topic_access( + [true = rabbit_auth_backend_internal:check_topic_access( #auth_user{username = <<"dummy">>}, Topic, - write, + Perm, Context - ), + ) || Perm <- Permissions], ok. diff --git a/test/unit_inbroker_SUITE.erl b/test/unit_inbroker_SUITE.erl index b1ebd054cf..f2451ce5c4 100644 --- a/test/unit_inbroker_SUITE.erl +++ b/test/unit_inbroker_SUITE.erl @@ -1694,24 +1694,18 @@ check_variable_queue_status(VQ0, Props) -> %% --------------------------------------------------------------------------- credit_flow_settings(Config) -> - passed = rabbit_ct_broker_helpers:rpc(Config, 0, + rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, credit_flow_settings1, [Config]). credit_flow_settings1(_Config) -> - %% default values - passed = test_proc(200, 100), - - application:set_env(rabbit, credit_flow_default_credit, {100, 300}), - passed = test_proc(100, 300), - - application:unset_env(rabbit, credit_flow_default_credit), - - % back to defaults - passed = test_proc(200, 100), + passed = test_proc(400, 200, {400, 200}), + passed = test_proc(600, 300), passed. test_proc(InitialCredit, MoreCreditAfter) -> - Pid = spawn(fun dummy/0), + test_proc(InitialCredit, MoreCreditAfter, {InitialCredit, MoreCreditAfter}). +test_proc(InitialCredit, MoreCreditAfter, Settings) -> + Pid = spawn(?MODULE, dummy, [Settings]), Pid ! {credit, self()}, {InitialCredit, MoreCreditAfter} = receive @@ -1719,13 +1713,13 @@ test_proc(InitialCredit, MoreCreditAfter) -> end, passed. -dummy() -> +dummy(Settings) -> credit_flow:send(self()), receive {credit, From} -> - From ! {credit, get(credit_flow_default_credit)}; + From ! {credit, Settings}; _ -> - dummy() + dummy(Settings) end. %% ------------------------------------------------------------------- |
