Skip to content

Commit 3ccd630

Browse files
Merge pull request #12779 from rabbitmq/mergify/bp/v4.0.x/pr-12749
4.0.5: Management UI: serve all static assets with a control-cache header (backport #12749)
2 parents 78aebbc + 3ae9d95 commit 3ccd630

31 files changed

+158
-281
lines changed

.github/workflows/test-management-ui-for-pr.yaml

+10-10
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,24 @@ jobs:
6969
cd ${SELENIUM_DIR}
7070
docker build -t mocha-test --target test .
7171
72-
- name: Run full ui suites on a standalone rabbitmq server
72+
- name: Run short ui suites on a standalone rabbitmq server
7373
run: |
7474
RABBITMQ_DOCKER_IMAGE=bazel/packaging/docker-image:rabbitmq-amd64 \
75-
${SELENIUM_DIR}/run-suites.sh
76-
mkdir -p /tmp/full-suite
77-
mv /tmp/selenium/* /tmp/full-suite
78-
mkdir -p /tmp/full-suite/logs
79-
mv ${SELENIUM_DIR}/logs/* /tmp/full-suite/logs
80-
mkdir -p /tmp/full-suite/screens
81-
mv ${SELENIUM_DIR}/screens/* /tmp/full-suite/screens
82-
75+
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh short-suite-management-ui
76+
mkdir -p /tmp/short-suite
77+
mv /tmp/selenium/* /tmp/short-suite
78+
mkdir -p /tmp/short-suite/logs
79+
mv ${SELENIUM_DIR}/logs/* /tmp/short-suite/logs
80+
mkdir -p /tmp/short-suite/screens
81+
mv ${SELENIUM_DIR}/screens/* /tmp/short-suite/screens
82+
8383
- name: Upload Test Artifacts
8484
if: always()
8585
uses: actions/[email protected]
8686
with:
8787
name: test-artifacts-${{ matrix.browser }}-${{ matrix.erlang_version }}
8888
path: |
89-
/tmp/full-suite
89+
/tmp/short-suite
9090
9191
summary-selenium:
9292
needs:

.github/workflows/test-management-ui.yaml

+7-7
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ jobs:
8787
- name: Run short ui suite on a 3-node rabbitmq cluster
8888
run: |
8989
RABBITMQ_DOCKER_IMAGE=bazel/packaging/docker-image:rabbitmq-amd64 \
90-
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh short-suite-management-ui
91-
mkdir -p /tmp/short-suite
92-
mv /tmp/selenium/* /tmp/short-suite
93-
mkdir -p /tmp/short-suite/logs
94-
mv ${SELENIUM_DIR}/logs/* /tmp/short-suite/logs
95-
mkdir -p /tmp/short-suite/screens
96-
mv ${SELENIUM_DIR}/screens/* /tmp/short-suite/screens
90+
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh full-suite-management-ui
91+
mkdir -p /tmp/full-suite
92+
mv /tmp/selenium/* /tmp/full-suite
93+
mkdir -p /tmp/full-suite/logs
94+
mv ${SELENIUM_DIR}/logs/* /tmp/full-suite/logs
95+
mkdir -p /tmp/full-suite/screens
96+
mv ${SELENIUM_DIR}/screens/* /tmp/full-suite/screens
9797
9898
- name: Upload Test Artifacts
9999
if: always()

deps/rabbitmq_management/app.bzl

+3
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def all_beam_files(name = "all_beam_files"):
115115
"src/rabbit_mgmt_wm_vhost.erl",
116116
"src/rabbit_mgmt_wm_vhost_restart.erl",
117117
"src/rabbit_mgmt_wm_vhosts.erl",
118+
"src/rabbit_mgmt_wm_version.erl",
118119
"src/rabbit_mgmt_wm_whoami.erl",
119120
],
120121
hdrs = [":public_and_private_hdrs"],
@@ -248,6 +249,7 @@ def all_test_beam_files(name = "all_test_beam_files"):
248249
"src/rabbit_mgmt_wm_vhost.erl",
249250
"src/rabbit_mgmt_wm_vhost_restart.erl",
250251
"src/rabbit_mgmt_wm_vhosts.erl",
252+
"src/rabbit_mgmt_wm_version.erl",
251253
"src/rabbit_mgmt_wm_whoami.erl",
252254
],
253255
hdrs = [":public_and_private_hdrs"],
@@ -472,6 +474,7 @@ def all_srcs(name = "all_srcs"):
472474
"src/rabbit_mgmt_wm_vhost.erl",
473475
"src/rabbit_mgmt_wm_vhost_restart.erl",
474476
"src/rabbit_mgmt_wm_vhosts.erl",
477+
"src/rabbit_mgmt_wm_version.erl",
475478
"src/rabbit_mgmt_wm_whoami.erl",
476479
],
477480
)

deps/rabbitmq_management/priv/www/index.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
<link href="css/main.css" rel="stylesheet" type="text/css"/>
2222
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon"/>
2323

24-
<script type="module">
25-
window.oauth = oauth_initialize_if_required();
26-
24+
<script type="module">
25+
check_version()
26+
window.oauth = oauth_initialize_if_required()
2727
</script>
2828

2929

deps/rabbitmq_management/priv/www/js/main.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,13 @@ function check_login () {
119119
if (user == false || user.error) {
120120
clear_auth();
121121
if (oauth.enabled) {
122-
//hide_popup_warn();
123122
renderWarningMessageInLoginStatus(oauth, 'Not authorized');
124123
} else {
125-
//hide_popup_warn();
126124
replace_content('login-status', '<p>Login failed</p>');
127125
}
128126
return false;
129127
}
130-
128+
check_version()
131129
hide_popup_warn()
132130
replace_content('outer', format('layout', {}))
133131
var user_login_session_timeout = parseInt(user.login_session_timeout)
@@ -1845,3 +1843,12 @@ function get_chart_range_type(arg) {
18451843
console.log('[WARNING]: range type not found for arg: ' + arg);
18461844
return 'basic';
18471845
}
1846+
1847+
function check_version() {
1848+
let curVersion = sync_get('/version')
1849+
let storedVersion = get_pref('version')
1850+
if (!storedVersion || storedVersion != curVersion) {
1851+
store_pref('version', curVersion)
1852+
location.reload()
1853+
}
1854+
}

deps/rabbitmq_management/priv/www/js/oidc-oauth/helper.js

+17-11
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,26 @@ export function oauth_completeLogin() {
301301

302302
export function oauth_initiateLogout() {
303303
if (oauth.sp_initiated) {
304-
mgr.metadataService.getEndSessionEndpoint().then(endpoint => {
305-
if (endpoint == undefined) {
306-
// Logout only from management UI
307-
mgr.removeUser().then(res => {
308-
clear_auth()
309-
oauth_redirectToLogin()
304+
return mgr.getUser().then(user => {
305+
if (user != null) {
306+
mgr.metadataService.getEndSessionEndpoint().then(endpoint => {
307+
if (endpoint == undefined) {
308+
// Logout only from management UI
309+
mgr.removeUser().then(res => {
310+
clear_auth()
311+
oauth_redirectToLogin()
312+
})
313+
}else {
314+
// OpenId Connect RP-Initiated Logout
315+
mgr.signoutRedirect()
316+
}
310317
})
311318
}else {
312-
// OpenId Connect RP-Initiated Logout
313-
mgr.signoutRedirect()
319+
clear_auth()
320+
go_to_home()
314321
}
315322
})
323+
316324
} else {
317325
go_to_authority()
318326
}
@@ -381,8 +389,7 @@ export function hasAnyResourceServerReady(oauth, onReadyCallback) {
381389
return group;
382390
}, {})
383391
let warnings = []
384-
for(var url in groupByProviderURL){
385-
console.log(url + ': ' + groupByProviderURL[url]);
392+
for(var url in groupByProviderURL){
386393
const notReadyResources = groupByProviderURL[url].filter((oauthserver) => notReadyServers.includes(oauthserver.oauth_provider_url))
387394
const notCompliantResources = groupByProviderURL[url].filter((oauthserver) => notCompliantServers.includes(oauthserver.oauth_provider_url))
388395
if (notReadyResources.length == 1) {
@@ -396,7 +403,6 @@ export function hasAnyResourceServerReady(oauth, onReadyCallback) {
396403
warnings.push(warningMessageOAuthResources(url, notCompliantResources, " not compliant"))
397404
}
398405
}
399-
console.log("warnings:" + warnings)
400406
oauth.declared_resource_servers_count = oauth.resource_servers.length
401407
oauth.resource_servers = oauth.resource_servers.filter((resource) =>
402408
!notReadyServers.includes(resource.oauth_provider_url) && !notCompliantServers.includes(resource.oauth_provider_url))

deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl

+2-1
Original file line numberDiff line numberDiff line change
@@ -207,5 +207,6 @@ dispatcher() ->
207207
{"/auth/attempts/:node/source", rabbit_mgmt_wm_auth_attempts, [by_source]},
208208
{"/login", rabbit_mgmt_wm_login, []},
209209
{"/config/effective", rabbit_mgmt_wm_environment, []},
210-
{"/auth/hash_password/:password", rabbit_mgmt_wm_hash_password, []}
210+
{"/auth/hash_password/:password", rabbit_mgmt_wm_hash_password, []},
211+
{"/version", rabbit_mgmt_wm_version, []}
211212
].

deps/rabbitmq_management/src/rabbit_mgmt_headers.erl

+6-2
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,18 @@ set_common_permission_headers(ReqData0, EndpointModule) ->
5555
lists:foldl(fun(Fun, ReqData) ->
5656
Fun(ReqData, EndpointModule)
5757
end, ReqData0,
58-
[fun set_csp_headers/2,
58+
[fun set_etag_based_cache_headers/2,
59+
fun set_csp_headers/2,
5960
fun set_hsts_headers/2,
6061
fun set_cors_headers/2,
6162
fun set_content_type_options_header/2,
6263
fun set_xss_protection_header/2,
6364
fun set_frame_options_header/2]).
6465

66+
set_etag_based_cache_headers(ReqData0, _Module) ->
67+
cowboy_req:set_resp_header(<<"cache-control">>, <<"public, max-age=0, must-revalidate">>, ReqData0).
68+
6569
set_no_cache_headers(ReqData0, _Module) ->
66-
ReqData1 = cowboy_req:set_resp_header(<<"cache-control">>, <<"no-cache, no-store, must-revalidate">>, ReqData0),
70+
ReqData1 = cowboy_req:set_resp_header(<<"cache-control">>, <<"no-cache, no-store, max-age=0, must-revalidate">>, ReqData0),
6771
ReqData2 = cowboy_req:set_resp_header(<<"pragma">>, <<"no-cache">>, ReqData1),
6872
cowboy_req:set_resp_header(<<"expires">>, rabbit_data_coercion:to_binary(0), ReqData2).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(rabbit_mgmt_wm_version).
9+
10+
-export([init/2]).
11+
-export([to_json/2, content_types_provided/2]).
12+
-export([variances/2]).
13+
14+
-include_lib("rabbit_common/include/rabbit.hrl").
15+
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
16+
17+
%%--------------------------------------------------------------------
18+
19+
init(Req, _State) ->
20+
{cowboy_rest, rabbit_mgmt_headers:set_no_cache_headers(
21+
rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), ?MODULE),
22+
#context{}}.
23+
24+
variances(Req, Context) ->
25+
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
26+
27+
content_types_provided(ReqData, Context) ->
28+
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
29+
30+
to_json(ReqData, Context) ->
31+
Version = case rabbit:product_info() of
32+
#{product_version := Value} -> Value;
33+
#{product_base_version := Base} -> Base
34+
end,
35+
rabbit_mgmt_util:reply(list_to_binary(Version), ReqData, Context).
36+
37+
%%--------------------------------------------------------------------
38+

deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl

+11-4
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ all() ->
5656
].
5757

5858
groups() ->
59-
[
59+
[
6060
{all_tests_with_prefix, [], some_tests() ++ all_tests()},
6161
{all_tests_without_prefix, [], some_tests()},
6262
%% We have several groups because their interference is
@@ -104,7 +104,6 @@ definitions_group4_tests() ->
104104
definitions_vhost_test
105105
].
106106

107-
108107
all_tests() -> [
109108
cli_redirect_test,
110109
api_redirect_test,
@@ -201,8 +200,9 @@ all_tests() -> [
201200
disabled_qq_replica_opers_test,
202201
qq_status_test,
203202
list_deprecated_features_test,
204-
list_used_deprecated_features_test,
205-
cluster_and_node_tags_test
203+
list_used_deprecated_features_test,
204+
cluster_and_node_tags_test,
205+
version_test
206206
].
207207

208208
%% -------------------------------------------------------------------
@@ -3749,6 +3749,13 @@ oauth_test(Config) ->
37493749
%% cleanup
37503750
rpc(Config, application, unset_env, [rabbitmq_management, oauth_enabled]).
37513751

3752+
version_test(Config) ->
3753+
ActualVersion = http_get(Config, "/version"),
3754+
ct:log("ActualVersion : ~p", [ActualVersion]),
3755+
ExpectedVersion = rpc(Config, rabbit, base_product_version, []),
3756+
ct:log("ExpectedVersion : ~p", [ExpectedVersion]),
3757+
?assertEqual(ExpectedVersion, binary_to_list(ActualVersion)).
3758+
37523759
login_test(Config) ->
37533760
http_put(Config, "/users/myuser", [{password, <<"myuser">>},
37543761
{tags, <<"management">>}], {group, '2xx'}),

selenium/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ not see any browser interaction, everything happens in the background, i.e. rabb
6262

6363
**The interactive mode** - This mode is convenient when we are still working on RabbitMQ source code and/or in the selenium tests. In this mode, you run RabbitMQ and tests directly from source to speed things up. The components, such as, UAA or keycloak, run in docker.
6464

65+
**IMPORTANT** - If you intend to switch between version of RabbitMQ, make sure
66+
you run `./clean.sh` to clear any state left from the last test run.
67+
6568

6669
## Run tests in headless-mode
6770

selenium/bin/components/keycloak

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ start_keycloak() {
3939
--publish 8443:8443 \
4040
--env KEYCLOAK_ADMIN=admin \
4141
--env KEYCLOAK_ADMIN_PASSWORD=admin \
42-
--mount type=bind,source=${MOUNT_KEYCLOAK_CONF_DIR},target=/opt/keycloak/data/import/ \
42+
-v ${MOUNT_KEYCLOAK_CONF_DIR}:/opt/keycloak/data/import/ \
4343
${KEYCLOAK_DOCKER_IMAGE} start-dev --import-realm \
4444
--https-certificate-file=/opt/keycloak/data/import/server_keycloak_certificate.pem \
4545
--https-certificate-key-file=/opt/keycloak/data/import/server_keycloak_key.pem

selenium/bin/suite_template

+11-6
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ teardown_local_others() {
475475
if [[ $REQUIRED_COMPONENTS == "" ]]; then
476476
print "There are no other components"
477477
else
478-
teardown_components
478+
teardown_components true
479479
fi
480480
}
481481
test_local() {
@@ -528,13 +528,18 @@ start_components() {
528528
}
529529

530530
teardown_components() {
531-
begin "Tear down ..."
531+
skip_rabbitmq=${1:-false}
532+
533+
begin "Tear down ... "
532534
for i in "${REQUIRED_COMPONENTS[@]}"
533535
do
534-
local component="$i"
535-
stop="stop_$i"
536-
type "$stop" &>/dev/null && $stop || kill_container_if_exist "$component"
537-
print "Tear down $component"
536+
if [[ $i != "rabbitmq" || ($i == "rabbitmq" && $skip_rabbitmq == false) ]]
537+
then
538+
local component="$i"
539+
stop="stop_$i"
540+
type "$stop" &>/dev/null && $stop || kill_container_if_exist "$component"
541+
print "Tear down $component"
542+
fi
538543
done
539544
end "Finished teardown"
540545
}

selenium/clean.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
3+
rm -r $TMPDIR/rabbitmq-test-instances

selenium/suites/authnz-mgt/oauth-and-basic-auth.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
44

55
TEST_CASES_PATH=/oauth/with-basic-auth
66
TEST_CONFIG_PATH=/oauth
7-
PROFILES="keycloak jwks keycloak-oauth-provider enable-basic-auth tls"
7+
PROFILES="keycloak keycloak-oauth-provider keycloak-mgt-oauth-provider tls enable-basic-auth"
88

99
source $SCRIPT/../../bin/suite_template $@
1010
runWith keycloak

selenium/test/basic-auth/unauthorized.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ describe('An user without management tag', function () {
1919
overview = new OverviewPage(driver)
2020
captureScreen = captureScreensFor(driver, __filename)
2121

22-
assert.ok(!await login.isPopupWarningDisplayed())
23-
await login.login('rabbit_no_management', 'rabbit_no_management')
24-
await !overview.isLoaded()
22+
//assert.ok(!await login.isPopupWarningDisplayed())
23+
await login.login('rabbit_no_management', 'guest')
2524
})
2625

2726
it('cannot log in into the management ui', async function () {
@@ -35,7 +34,7 @@ describe('An user without management tag', function () {
3534

3635
it('should get popup warning dialog', async function(){
3736
assert.ok(login.isPopupWarningDisplayed())
38-
assert.equal('Not_Authorized', await login.getPopupWarning())
37+
assert.equal('Not management user', await login.getPopupWarning())
3938
})
4039

4140
describe("After clicking on popup warning dialog button", function() {

selenium/test/mgt-only/imports/users.json

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
"vhosts": [
5050
{
5151
"name": "/"
52+
},
53+
{
54+
"name": "other"
5255
}
5356
],
5457
"permissions": [
@@ -59,6 +62,13 @@
5962
"write": ".*",
6063
"read": ".*"
6164
},
65+
{
66+
"user": "guest",
67+
"vhost": "other",
68+
"configure": ".*",
69+
"write": ".*",
70+
"read": ".*"
71+
},
6272
{
6373
"user": "management",
6474
"vhost": "/",

0 commit comments

Comments
 (0)