Skip to content

Commit

Permalink
Merge pull request #12779 from rabbitmq/mergify/bp/v4.0.x/pr-12749
Browse files Browse the repository at this point in the history
4.0.5: Management UI: serve all static assets with a control-cache header (backport #12749)
  • Loading branch information
michaelklishin authored Nov 25, 2024
2 parents 78aebbc + 3ae9d95 commit 3ccd630
Show file tree
Hide file tree
Showing 31 changed files with 158 additions and 281 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/test-management-ui-for-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,24 @@ jobs:
cd ${SELENIUM_DIR}
docker build -t mocha-test --target test .
- name: Run full ui suites on a standalone rabbitmq server
- name: Run short ui suites on a standalone rabbitmq server
run: |
RABBITMQ_DOCKER_IMAGE=bazel/packaging/docker-image:rabbitmq-amd64 \
${SELENIUM_DIR}/run-suites.sh
mkdir -p /tmp/full-suite
mv /tmp/selenium/* /tmp/full-suite
mkdir -p /tmp/full-suite/logs
mv ${SELENIUM_DIR}/logs/* /tmp/full-suite/logs
mkdir -p /tmp/full-suite/screens
mv ${SELENIUM_DIR}/screens/* /tmp/full-suite/screens
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh short-suite-management-ui
mkdir -p /tmp/short-suite
mv /tmp/selenium/* /tmp/short-suite
mkdir -p /tmp/short-suite/logs
mv ${SELENIUM_DIR}/logs/* /tmp/short-suite/logs
mkdir -p /tmp/short-suite/screens
mv ${SELENIUM_DIR}/screens/* /tmp/short-suite/screens
- name: Upload Test Artifacts
if: always()
uses: actions/[email protected]
with:
name: test-artifacts-${{ matrix.browser }}-${{ matrix.erlang_version }}
path: |
/tmp/full-suite
/tmp/short-suite
summary-selenium:
needs:
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/test-management-ui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ jobs:
- name: Run short ui suite on a 3-node rabbitmq cluster
run: |
RABBITMQ_DOCKER_IMAGE=bazel/packaging/docker-image:rabbitmq-amd64 \
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh short-suite-management-ui
mkdir -p /tmp/short-suite
mv /tmp/selenium/* /tmp/short-suite
mkdir -p /tmp/short-suite/logs
mv ${SELENIUM_DIR}/logs/* /tmp/short-suite/logs
mkdir -p /tmp/short-suite/screens
mv ${SELENIUM_DIR}/screens/* /tmp/short-suite/screens
ADDON_PROFILES=cluster ${SELENIUM_DIR}/run-suites.sh full-suite-management-ui
mkdir -p /tmp/full-suite
mv /tmp/selenium/* /tmp/full-suite
mkdir -p /tmp/full-suite/logs
mv ${SELENIUM_DIR}/logs/* /tmp/full-suite/logs
mkdir -p /tmp/full-suite/screens
mv ${SELENIUM_DIR}/screens/* /tmp/full-suite/screens
- name: Upload Test Artifacts
if: always()
Expand Down
3 changes: 3 additions & 0 deletions deps/rabbitmq_management/app.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def all_beam_files(name = "all_beam_files"):
"src/rabbit_mgmt_wm_vhost.erl",
"src/rabbit_mgmt_wm_vhost_restart.erl",
"src/rabbit_mgmt_wm_vhosts.erl",
"src/rabbit_mgmt_wm_version.erl",
"src/rabbit_mgmt_wm_whoami.erl",
],
hdrs = [":public_and_private_hdrs"],
Expand Down Expand Up @@ -248,6 +249,7 @@ def all_test_beam_files(name = "all_test_beam_files"):
"src/rabbit_mgmt_wm_vhost.erl",
"src/rabbit_mgmt_wm_vhost_restart.erl",
"src/rabbit_mgmt_wm_vhosts.erl",
"src/rabbit_mgmt_wm_version.erl",
"src/rabbit_mgmt_wm_whoami.erl",
],
hdrs = [":public_and_private_hdrs"],
Expand Down Expand Up @@ -472,6 +474,7 @@ def all_srcs(name = "all_srcs"):
"src/rabbit_mgmt_wm_vhost.erl",
"src/rabbit_mgmt_wm_vhost_restart.erl",
"src/rabbit_mgmt_wm_vhosts.erl",
"src/rabbit_mgmt_wm_version.erl",
"src/rabbit_mgmt_wm_whoami.erl",
],
)
Expand Down
6 changes: 3 additions & 3 deletions deps/rabbitmq_management/priv/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
<link href="css/main.css" rel="stylesheet" type="text/css"/>
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon"/>

<script type="module">
window.oauth = oauth_initialize_if_required();

<script type="module">
check_version()
window.oauth = oauth_initialize_if_required()
</script>


Expand Down
13 changes: 10 additions & 3 deletions deps/rabbitmq_management/priv/www/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,13 @@ function check_login () {
if (user == false || user.error) {
clear_auth();
if (oauth.enabled) {
//hide_popup_warn();
renderWarningMessageInLoginStatus(oauth, 'Not authorized');
} else {
//hide_popup_warn();
replace_content('login-status', '<p>Login failed</p>');
}
return false;
}

check_version()
hide_popup_warn()
replace_content('outer', format('layout', {}))
var user_login_session_timeout = parseInt(user.login_session_timeout)
Expand Down Expand Up @@ -1845,3 +1843,12 @@ function get_chart_range_type(arg) {
console.log('[WARNING]: range type not found for arg: ' + arg);
return 'basic';
}

function check_version() {
let curVersion = sync_get('/version')
let storedVersion = get_pref('version')
if (!storedVersion || storedVersion != curVersion) {
store_pref('version', curVersion)
location.reload()
}
}
28 changes: 17 additions & 11 deletions deps/rabbitmq_management/priv/www/js/oidc-oauth/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,18 +301,26 @@ export function oauth_completeLogin() {

export function oauth_initiateLogout() {
if (oauth.sp_initiated) {
mgr.metadataService.getEndSessionEndpoint().then(endpoint => {
if (endpoint == undefined) {
// Logout only from management UI
mgr.removeUser().then(res => {
clear_auth()
oauth_redirectToLogin()
return mgr.getUser().then(user => {
if (user != null) {
mgr.metadataService.getEndSessionEndpoint().then(endpoint => {
if (endpoint == undefined) {
// Logout only from management UI
mgr.removeUser().then(res => {
clear_auth()
oauth_redirectToLogin()
})
}else {
// OpenId Connect RP-Initiated Logout
mgr.signoutRedirect()
}
})
}else {
// OpenId Connect RP-Initiated Logout
mgr.signoutRedirect()
clear_auth()
go_to_home()
}
})

} else {
go_to_authority()
}
Expand Down Expand Up @@ -381,8 +389,7 @@ export function hasAnyResourceServerReady(oauth, onReadyCallback) {
return group;
}, {})
let warnings = []
for(var url in groupByProviderURL){
console.log(url + ': ' + groupByProviderURL[url]);
for(var url in groupByProviderURL){
const notReadyResources = groupByProviderURL[url].filter((oauthserver) => notReadyServers.includes(oauthserver.oauth_provider_url))
const notCompliantResources = groupByProviderURL[url].filter((oauthserver) => notCompliantServers.includes(oauthserver.oauth_provider_url))
if (notReadyResources.length == 1) {
Expand All @@ -396,7 +403,6 @@ export function hasAnyResourceServerReady(oauth, onReadyCallback) {
warnings.push(warningMessageOAuthResources(url, notCompliantResources, " not compliant"))
}
}
console.log("warnings:" + warnings)
oauth.declared_resource_servers_count = oauth.resource_servers.length
oauth.resource_servers = oauth.resource_servers.filter((resource) =>
!notReadyServers.includes(resource.oauth_provider_url) && !notCompliantServers.includes(resource.oauth_provider_url))
Expand Down
3 changes: 2 additions & 1 deletion deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,6 @@ dispatcher() ->
{"/auth/attempts/:node/source", rabbit_mgmt_wm_auth_attempts, [by_source]},
{"/login", rabbit_mgmt_wm_login, []},
{"/config/effective", rabbit_mgmt_wm_environment, []},
{"/auth/hash_password/:password", rabbit_mgmt_wm_hash_password, []}
{"/auth/hash_password/:password", rabbit_mgmt_wm_hash_password, []},
{"/version", rabbit_mgmt_wm_version, []}
].
8 changes: 6 additions & 2 deletions deps/rabbitmq_management/src/rabbit_mgmt_headers.erl
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,18 @@ set_common_permission_headers(ReqData0, EndpointModule) ->
lists:foldl(fun(Fun, ReqData) ->
Fun(ReqData, EndpointModule)
end, ReqData0,
[fun set_csp_headers/2,
[fun set_etag_based_cache_headers/2,
fun set_csp_headers/2,
fun set_hsts_headers/2,
fun set_cors_headers/2,
fun set_content_type_options_header/2,
fun set_xss_protection_header/2,
fun set_frame_options_header/2]).

set_etag_based_cache_headers(ReqData0, _Module) ->
cowboy_req:set_resp_header(<<"cache-control">>, <<"public, max-age=0, must-revalidate">>, ReqData0).

set_no_cache_headers(ReqData0, _Module) ->
ReqData1 = cowboy_req:set_resp_header(<<"cache-control">>, <<"no-cache, no-store, must-revalidate">>, ReqData0),
ReqData1 = cowboy_req:set_resp_header(<<"cache-control">>, <<"no-cache, no-store, max-age=0, must-revalidate">>, ReqData0),
ReqData2 = cowboy_req:set_resp_header(<<"pragma">>, <<"no-cache">>, ReqData1),
cowboy_req:set_resp_header(<<"expires">>, rabbit_data_coercion:to_binary(0), ReqData2).
38 changes: 38 additions & 0 deletions deps/rabbitmq_management/src/rabbit_mgmt_wm_version.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
%%

-module(rabbit_mgmt_wm_version).

-export([init/2]).
-export([to_json/2, content_types_provided/2]).
-export([variances/2]).

-include_lib("rabbit_common/include/rabbit.hrl").
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").

%%--------------------------------------------------------------------

init(Req, _State) ->
{cowboy_rest, rabbit_mgmt_headers:set_no_cache_headers(
rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), ?MODULE),
#context{}}.

variances(Req, Context) ->
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.

content_types_provided(ReqData, Context) ->
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.

to_json(ReqData, Context) ->
Version = case rabbit:product_info() of
#{product_version := Value} -> Value;
#{product_base_version := Base} -> Base
end,
rabbit_mgmt_util:reply(list_to_binary(Version), ReqData, Context).

%%--------------------------------------------------------------------

15 changes: 11 additions & 4 deletions deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ all() ->
].

groups() ->
[
[
{all_tests_with_prefix, [], some_tests() ++ all_tests()},
{all_tests_without_prefix, [], some_tests()},
%% We have several groups because their interference is
Expand Down Expand Up @@ -104,7 +104,6 @@ definitions_group4_tests() ->
definitions_vhost_test
].


all_tests() -> [
cli_redirect_test,
api_redirect_test,
Expand Down Expand Up @@ -201,8 +200,9 @@ all_tests() -> [
disabled_qq_replica_opers_test,
qq_status_test,
list_deprecated_features_test,
list_used_deprecated_features_test,
cluster_and_node_tags_test
list_used_deprecated_features_test,
cluster_and_node_tags_test,
version_test
].

%% -------------------------------------------------------------------
Expand Down Expand Up @@ -3749,6 +3749,13 @@ oauth_test(Config) ->
%% cleanup
rpc(Config, application, unset_env, [rabbitmq_management, oauth_enabled]).

version_test(Config) ->
ActualVersion = http_get(Config, "/version"),
ct:log("ActualVersion : ~p", [ActualVersion]),
ExpectedVersion = rpc(Config, rabbit, base_product_version, []),
ct:log("ExpectedVersion : ~p", [ExpectedVersion]),
?assertEqual(ExpectedVersion, binary_to_list(ActualVersion)).

login_test(Config) ->
http_put(Config, "/users/myuser", [{password, <<"myuser">>},
{tags, <<"management">>}], {group, '2xx'}),
Expand Down
3 changes: 3 additions & 0 deletions selenium/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ not see any browser interaction, everything happens in the background, i.e. rabb

**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.

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


## Run tests in headless-mode

Expand Down
2 changes: 1 addition & 1 deletion selenium/bin/components/keycloak
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ start_keycloak() {
--publish 8443:8443 \
--env KEYCLOAK_ADMIN=admin \
--env KEYCLOAK_ADMIN_PASSWORD=admin \
--mount type=bind,source=${MOUNT_KEYCLOAK_CONF_DIR},target=/opt/keycloak/data/import/ \
-v ${MOUNT_KEYCLOAK_CONF_DIR}:/opt/keycloak/data/import/ \
${KEYCLOAK_DOCKER_IMAGE} start-dev --import-realm \
--https-certificate-file=/opt/keycloak/data/import/server_keycloak_certificate.pem \
--https-certificate-key-file=/opt/keycloak/data/import/server_keycloak_key.pem
Expand Down
17 changes: 11 additions & 6 deletions selenium/bin/suite_template
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ teardown_local_others() {
if [[ $REQUIRED_COMPONENTS == "" ]]; then
print "There are no other components"
else
teardown_components
teardown_components true
fi
}
test_local() {
Expand Down Expand Up @@ -528,13 +528,18 @@ start_components() {
}

teardown_components() {
begin "Tear down ..."
skip_rabbitmq=${1:-false}

begin "Tear down ... "
for i in "${REQUIRED_COMPONENTS[@]}"
do
local component="$i"
stop="stop_$i"
type "$stop" &>/dev/null && $stop || kill_container_if_exist "$component"
print "Tear down $component"
if [[ $i != "rabbitmq" || ($i == "rabbitmq" && $skip_rabbitmq == false) ]]
then
local component="$i"
stop="stop_$i"
type "$stop" &>/dev/null && $stop || kill_container_if_exist "$component"
print "Tear down $component"
fi
done
end "Finished teardown"
}
Expand Down
3 changes: 3 additions & 0 deletions selenium/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

rm -r $TMPDIR/rabbitmq-test-instances
2 changes: 1 addition & 1 deletion selenium/suites/authnz-mgt/oauth-and-basic-auth.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

TEST_CASES_PATH=/oauth/with-basic-auth
TEST_CONFIG_PATH=/oauth
PROFILES="keycloak jwks keycloak-oauth-provider enable-basic-auth tls"
PROFILES="keycloak keycloak-oauth-provider keycloak-mgt-oauth-provider tls enable-basic-auth"

source $SCRIPT/../../bin/suite_template $@
runWith keycloak
7 changes: 3 additions & 4 deletions selenium/test/basic-auth/unauthorized.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ describe('An user without management tag', function () {
overview = new OverviewPage(driver)
captureScreen = captureScreensFor(driver, __filename)

assert.ok(!await login.isPopupWarningDisplayed())
await login.login('rabbit_no_management', 'rabbit_no_management')
await !overview.isLoaded()
//assert.ok(!await login.isPopupWarningDisplayed())
await login.login('rabbit_no_management', 'guest')
})

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

it('should get popup warning dialog', async function(){
assert.ok(login.isPopupWarningDisplayed())
assert.equal('Not_Authorized', await login.getPopupWarning())
assert.equal('Not management user', await login.getPopupWarning())
})

describe("After clicking on popup warning dialog button", function() {
Expand Down
10 changes: 10 additions & 0 deletions selenium/test/mgt-only/imports/users.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"vhosts": [
{
"name": "/"
},
{
"name": "other"
}
],
"permissions": [
Expand All @@ -59,6 +62,13 @@
"write": ".*",
"read": ".*"
},
{
"user": "guest",
"vhost": "other",
"configure": ".*",
"write": ".*",
"read": ".*"
},
{
"user": "management",
"vhost": "/",
Expand Down
Loading

0 comments on commit 3ccd630

Please sign in to comment.