Files
NLnetLabs-krill/tests/ui/mod.rs
T
Ximon EighteenandGitHub 0f930f37ef Logout enhancements (closes #385, closes #397, fixes #408, closes #425) (#436)
- Formalize support for different logout strategies and add the fallback strategy.
- Generate the logout URL at logout time in preparation for supporting dynamic logout requests (as needed by token revocation).
- Secure the connection to the mock OpenID Connect provider with a self-signed TLS certificate.
- Allow self-signed certificates for HTTPS connections to localhost (same policy as elsewhere in Krill).
- Upgrade openidconnect-rs to latest v2.0.0 alpha to gain contributed support for OAuth 2.0 Token Revocation. (#385 and #397)
- Use reqwest 0.9.x directly instead of via the openidconnect-rs crate (we cannot use the v0.11.x reqwest that comes with the crate as (a) it doesn't permit self-signed certificates, (b) the blocking implementation was changed to be async which causes problems when inside an existing async runtime, and (c) switching the OpenID Connect client code over to be async is non-trivial - see #428).
- Pass the ID token as `id_token_hint` to the OpenID Connect RP-Initiated Logout 1.0 endpoint. (#408)
- Refined logic for the various logout mechanism permutations. (#425).
- Require OpenID Connection RP-Initiated Logout 1.0 and OAuth 2.0 Token Revocation endpoints to be HTTPS per the specs.
- Passes manual testing with Microsoft Azure Active Directory RP-Initiated Logout support and Google Compute Cloud OAuth 2.0 Token Revocation support.
- Added a Google Cloud Platform example to the comments in the default config file.
- Updated and added tests.
- Fixed logout and token revocation in the mock OpenID Connect provider to actually terminate login sessions.
- Handle a race condition in Lagosta where null user data was accessed that was just deleted due to logout.
- Handle errors from the Krill logout endpoint in Lagosta.
2021-03-08 23:39:45 +01:00

137 lines
4.7 KiB
Rust

#[cfg(feature = "multi-user")]
mod openid_connect_mock;
use tokio::task;
use std::{env, process::ExitStatus};
use std::process::Command;
use krill::daemon::config::Config;
use krill::test::*;
#[allow(dead_code)]
pub enum OpenIDConnectMockMode {
OIDCProviderWillNotBeStarted,
OIDCProviderWithRPInitiatedLogout,
OIDCProviderWithOAuth2Revocation,
OIDCProviderWithNoLogoutEndpoints,
}
#[cfg(not(feature = "multi-user"))]
pub async fn run_krill_ui_test(
test_name: &str,
_: OpenIDConnectMockMode,
testbed_enabled: bool,
) {
do_run_krill_ui_test(test_name, testbed_enabled).await;
}
#[cfg(feature = "multi-user")]
pub async fn run_krill_ui_test(
test_name: &str,
openid_connect_mock_mode: OpenIDConnectMockMode,
testbed_enabled: bool,
) {
use OpenIDConnectMockMode::*;
let op_handle = match openid_connect_mock_mode {
OIDCProviderWillNotBeStarted => None,
_ => Some(openid_connect_mock::start(openid_connect_mock_mode, 1).await),
};
do_run_krill_ui_test(test_name, testbed_enabled).await;
if let Some(handle) = op_handle {
openid_connect_mock::stop(handle).await;
}
}
struct CypressRunner {
status: ExitStatus
}
impl CypressRunner {
pub async fn run(test_name: &str) -> Self {
let test_name = test_name.to_string();
ctrlc::set_handler(move || {
// If `cargo test` is stopped with CTRL-C the background Cypress Docker container continues to run. This
// prevents the next run of `cargo test` from working as the container unexpectedly already exists. Tell
// Docker to kill it to avoid leaving it lying around.
Command::new("docker").arg("kill").arg("cypress").spawn().expect("Failed to kill Cypress Docker container");
}).expect("Error setting Ctrl-C handler");
let task = task::spawn_blocking(move || {
// NOTE: the directory mentioned here must be the same as the directory
// mentioned in the tests/ui/cypress/plugins/index.js file in the
// "integrationFolder" property otherwise Cypress mysteriously complains
// that it cannot find the spec file.
let cypress_spec_path = format!("tests/ui/cypress/specs/{}.js", test_name);
let mut cmd = Command::new("docker");
cmd
.arg("run")
.arg("--name").arg("cypress")
.arg("--rm")
.arg("--net=host")
.arg("--ipc=host")
.arg("-v").arg(format!("{}:/e2e", env::current_dir().unwrap().display()))
.arg("-w").arg("/e2e");
if let Ok(debug_level) = std::env::var("CYPRESS_DEBUG") {
// Example values:
// - To get LOTS of Cypress logging: CYPRESS_DEBUG=cypress:*
// - To get logging relating to HTTP requests: CYPRESS_DEBUG=cypress:proxy:http:*
cmd
.arg("-e").arg(format!("DEBUG={}", debug_level));
}
if std::env::var("CYPRESS_INTERACTIVE").is_ok() {
// After running `cargo test` a Chrome browser should open from the Cypress Docker container on your local
// X server. For this to work you might need to run this command in your shell prior to `cargo test`:
// xhost +
cmd
.arg("-v").arg(format!("/tmp/.X11-unix:/tmp/.X11-unix"))
.arg("-e").arg("DISPLAY")
.arg("--entrypoint").arg("cypress");
}
cmd.arg("cypress/included:6.2.0");
if std::env::var("CYPRESS_INTERACTIVE").is_ok() {
cmd
.arg("open")
.arg("--project").arg(".");
} else {
cmd
.arg("--spec").arg(cypress_spec_path);
}
cmd
.arg("--browser").arg("chrome")
.status()
.expect("Failed to run Cypress Docker UI test suite")
}).await;
Self {
status: task.unwrap()
}
}
pub fn success(self) -> bool {
self.status.success()
}
}
async fn do_run_krill_ui_test(test_name: &str, testbed_enabled: bool) {
krill::constants::enable_test_mode();
let config_path = &format!("test-resources/ui/{}.conf", test_name);
let config = Config::read_config(&config_path).unwrap();
// Start Krill as a Tokio task in the background and wait just until we can tell that it has started.
start_krill(Some(config), testbed_enabled).await;
// Run the specified Cypress UI test suite and wait for it to finish
assert!(CypressRunner::run(test_name).await.success());
}