Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/rabbitmq_management/src/rabbit_mgmt_login.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ login(<<"POST">>, Req0, State) ->
AccessToken -> handleAccessToken(Req0, AccessToken, State)
end;

login(<<"GET">>, Req, State) ->
login(<<"GET">>, Req, State) ->
Auth = case rabbit_mgmt_util:qs_val(?MANAGEMENT_LOGIN_STRICT_AUTH_MECHANISM, Req) of
undefined ->
case rabbit_mgmt_util:qs_val(?MANAGEMENT_LOGIN_PREFERRED_AUTH_MECHANISM, Req) of
Expand Down
18 changes: 10 additions & 8 deletions deps/rabbitmq_management/src/rabbit_mgmt_oauth_bootstrap.erl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ get_auth_mechanism(Req) ->

get_auth_mechanism_from_cookies(Req) ->
Cookies = cowboy_req:parse_cookies(Req),
?LOG_DEBUG("get_auth_mechanism_from_cookies: ~p", [Cookies]),
case proplists:get_value(?MANAGEMENT_LOGIN_STRICT_AUTH_MECHANISM, Cookies) of
undefined ->
case proplists:get_value(?MANAGEMENT_LOGIN_PREFERRED_AUTH_MECHANISM, Cookies) of
Expand Down Expand Up @@ -114,9 +115,14 @@ set_token_auth(AuthSettings, Req0) ->
["set_token_auth('", Token, "');"]
};
_ ->
Cookies = cowboy_req:parse_cookies(Req0),
case lists:keyfind(?OAUTH2_ACCESS_TOKEN, 1, Cookies) of
{_, Token} ->
Cookies = cowboy_req:parse_cookies(Req0),
?LOG_DEBUG("set_token_auth: ~p", [Cookies]),
case proplists:get_value(?OAUTH2_ACCESS_TOKEN, Cookies) of
undefined -> {
Req0,
[]
};
Token ->
{
cowboy_req:set_resp_cookie(
?OAUTH2_ACCESS_TOKEN, <<"">>, Req0, #{
Expand All @@ -126,11 +132,7 @@ set_token_auth(AuthSettings, Req0) ->
same_site => strict
}),
["set_token_auth('", Token, "');"]
};
false -> {
Req0,
[]
}
}
end
end;
false -> {
Expand Down
3 changes: 2 additions & 1 deletion selenium/short-suite-management-ui
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ mgt/queuesAndStreams.sh
mgt/limits.sh
mgt/amqp10-connections.sh
mgt/mqtt-connections.sh
mgt/feature-flags.sh
mgt/feature-flags.sh
authnz-mgt/multi-oauth-with-basic-auth.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const { By, Key, until, Builder } = require('selenium-webdriver')
require('chromedriver')
const assert = require('assert')
const { buildDriver, goToHome, goToLogin, captureScreensFor, teardown, findOption } = require('../../utils')

const SSOHomePage = require('../../pageobjects/SSOHomePage')

describe('Given two oauth resources and basic auth enabled, an unauthenticated user', function () {
let driver;
let captureScreen;
let login;

before(async function () {
this.driver = buildDriver();
this.captureScreen = captureScreensFor(this.driver, __filename);

login = async (key, value) => {
await goToLogin(this.driver, key, value);
const homePage = new SSOHomePage(this.driver);
await homePage.isLoaded();
return homePage;
}
})

it('can preselect rabbit_dev oauth2 resource', async function () {
const homePage = await login("preferred_auth_mechanism", "oauth2:rabbit_dev");

const oauth2Section = await homePage.isOAuth2SectionVisible();
assert.ok((await oauth2Section.getAttribute("class")).includes("section-visible"))
const basicSection = await homePage.isBasicAuthSectionVisible();
assert.ok((await basicSection.getAttribute("class")).includes("section-invisible"))

resources = await homePage.getOAuthResourceOptions();
const option = findOption("rabbit_dev", resources);
assert.ok(option);
assert.ok(option.selected);

})
it('can preselect rabbit_prod oauth2 resource', async function () {
const homePage = await login("preferred_auth_mechanism", "oauth2:rabbit_prod");

const oauth2Section = await homePage.isOAuth2SectionVisible();
assert.ok((await oauth2Section.getAttribute("class")).includes("section-visible"))
const basicSection = await homePage.isBasicAuthSectionVisible();
assert.ok((await basicSection.getAttribute("class")).includes("section-invisible"))

resources = await homePage.getOAuthResourceOptions();
const option = findOption("rabbit_prod", resources);
assert.ok(option);
assert.ok(option.selected);

})

it('can preselect basic auth', async function () {
const homePage = await login("preferred_auth_mechanism", "basic");

const oauth2Section = await homePage.isOAuth2SectionVisible();
assert.ok((await oauth2Section.getAttribute("class")).includes("section-invisible"))
const basicSection = await homePage.isBasicAuthSectionVisible();
assert.ok((await basicSection.getAttribute("class")).includes("section-visible"))
})

it('can force only to authenticate only with rabbit_dev oauth2 resource', async function () {
const homePage = await login("strict_auth_mechanism", "oauth2:rabbit_dev");
const value = await homePage.getLoginButtonOnClick();
assert.ok(value.includes("rabbit_dev"));
})
it('can force only to authenticate only with rabbit_prod oauth2 resource', async function () {
const homePage = await login("strict_auth_mechanism", "oauth2:rabbit_prod");
const value = await homePage.getLoginButtonOnClick();
assert.ok(value.includes("rabbit_prod"));
})
it('can force only to authenticate only with basic auth', async function () {
const homePage = await login("strict_auth_mechanism", "basic");
await homePage.isOAuth2SectionNotVisible();
const basicSection = await homePage.isBasicAuthSectionVisible();
assert.ok((await basicSection.getAttribute("class")).includes("section-visible"))

})

after(async function () {
await teardown(this.driver, this, this.captureScreen);
})
})
8 changes: 5 additions & 3 deletions selenium/test/pageobjects/BasePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ module.exports = class BasePage {
for (const index in optionList) {
const t = await optionList[index].getText()
const v = await optionList[index].getAttribute('value')
table_model.push({"text":t, "value": v})
const s = await optionList[index].getAttribute('selected')
table_model.push({"text": t, "value": v, "selected" : s !== undefined})
}

return table_model
Expand Down Expand Up @@ -300,13 +301,14 @@ module.exports = class BasePage {

async isDisplayed(locator) {
try {
let element = await driver.findElement(locator)
let element = await this.driver.findElement(locator)

return this.driver.wait(until.elementIsVisible(element), this.timeout,
'Timed out after [timeout=' + this.timeout + ';polling=' + this.polling + '] awaiting till visible ' + element,
this.polling / 2)
}catch(error) {
return Promise.resolve(false)
console.log("isDisplayed failed due to " + error);
return Promise.resolve(false);
}
}

Expand Down
8 changes: 8 additions & 0 deletions selenium/test/pageobjects/SSOHomePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ module.exports = class SSOHomePage extends BasePage {
async getLoginButton () {
return this.getText(OAUTH2_LOGIN_BUTTON)
}
async getLoginButtonOnClick () {
const element = await this.waitForDisplayed(OAUTH2_LOGIN_BUTTON);
return element.getAttribute('onClick');
}
async getLogoutButton () {
return this.getText(LOGOUT_BUTTON)
}
Expand Down Expand Up @@ -74,6 +78,10 @@ module.exports = class SSOHomePage extends BasePage {
async isOAuth2SectionVisible() {
return this.isDisplayed(SECTION_LOGIN_WITH_OAUTH)
}
async isOAuth2SectionNotVisible() {
return this.isElementNotVisible(SECTION_LOGIN_WITH_OAUTH)
}

async getOAuth2Section() {
return this.waitForDisplayed(SECTION_LOGIN_WITH_OAUTH)
}
Expand Down
44 changes: 39 additions & 5 deletions selenium/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ class CaptureScreenshot {
const screenshotsSubDir = path.join(screenshotsDir, this.test)
if (!fs.existsSync(screenshotsSubDir)) {
await fsp.mkdir(screenshotsSubDir)
}
}
const dest = path.join(screenshotsSubDir, name + '.png')
console.log("screenshot saved to " + dest)
await fsp.writeFile(dest, image, 'base64')
}
}
Expand Down Expand Up @@ -122,8 +123,31 @@ module.exports = {
return d.driver.get(d.baseUrl)
},

goToLogin: (d, token) => {
return d.driver.get(d.baseUrl + '#/login?access_token=' + token)
/**
* For instance,
* goToLogin(d, access_token, myAccessToken)
* or
* goToLogin(d, preferred_auth_mechanism, "oauth2:my-resource")
*/
goToLogin: (d, ...keyValuePairs) => {
const params = [];
for (let i = 0; i < keyValuePairs.length; i += 2) {
const key = keyValuePairs[i];
const value = keyValuePairs[i + 1];

if (key !== undefined) {
// URL-encode both key and value
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(value || '');
params.push(`${encodedKey}=${encodedValue}`);
}
}
// Build query string: "key1=value1&key2=value2"
const queryString = params.join('&');

const url = d.baseUrl + '/login?' + queryString;
console.log("Navigating to " + url);
return d.driver.get(url);
},

goToConnections: (d) => {
Expand Down Expand Up @@ -263,8 +287,15 @@ module.exports = {
&& actualOption.text == expectedOptions[i].text))
}
},
findOption: (value, options) => {
for (let i = 0; i < options.length; i++) {
if (options[i].value === value) return options[i];
}
return undefined;
},

teardown: async (d, test, captureScreen = null) => {

driver = d.driver
driver.manage().logs().get(logging.Type.BROWSER).then(function(entries) {
entries.forEach(function(entry) {
Expand All @@ -274,8 +305,11 @@ module.exports = {
if (test.currentTest) {
if (test.currentTest.isPassed()) {
driver.executeScript('lambda-status=passed')
} else {
if (captureScreen != null) await captureScreen.shot('after-failed')
} else {
if (captureScreen != null) {
console.log("Teardown failed . capture...");
await captureScreen.shot('after-failed');
}
driver.executeScript('lambda-status=failed')
}
}
Expand Down
Loading