0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-21 20:49:10 +01:00

SERVER-77907 Add Azure OIDC machine flow tests

This commit is contained in:
Adam Rayner 2023-10-16 17:57:29 +00:00 committed by Evergreen Agent
parent a47b1e2e4a
commit 7efbefcb7e
11 changed files with 120 additions and 10 deletions

View File

@ -161,6 +161,7 @@ globals:
runProgram: true runProgram: true
runMongoProgram: true runMongoProgram: true
runNonMongoProgram: true runNonMongoProgram: true
runNonMongoProgramQuietly: true
_runMongoProgram: true _runMongoProgram: true
_startMongoProgram: true _startMongoProgram: true
startMongoProgram: true startMongoProgram: true

View File

@ -0,0 +1,10 @@
test_kind: js_test
selector:
roots:
- src/mongo/db/modules/enterprise/jstests/external_auth_oidc_azure/*.js
executor:
config:
shell_options:
nodb: ''

View File

@ -9,3 +9,6 @@ selector:
exclude_tests: exclude_tests:
# Requires external_auth_oidc.sh to run beforehand. # Requires external_auth_oidc.sh to run beforehand.
- src/mongo/db/modules/enterprise/jstests/external_auth_oidc/oidc_e2e_okta.js - src/mongo/db/modules/enterprise/jstests/external_auth_oidc/oidc_e2e_okta.js
#Requres external_auth_azure_setup.sh to run before, and external_auth_azure_teardown.sh to run after
- src/mongo/db/modules/enterprise/jstests/external_auth_oidc_azure/oidc_e2e_azure.js
- src/mongo/db/modules/enterprise/jstests/external_auth_oidc_azure/oidc_e2e_azure_machine.js

View File

@ -5716,6 +5716,25 @@ tasks:
vars: vars:
resmoke_jobs_max: ${external_auth_oidc_jobs_max|1} resmoke_jobs_max: ${external_auth_oidc_jobs_max|1}
- <<: *task_template
name: external_auth_oidc_azure
tags: []
commands:
- *f_expansions_write
- func: "do setup"
- func: "f_expansions_write"
- command: subprocess.exec
params:
binary: bash
args:
- "src/evergreen/external_auth_azure_setup.sh"
- func: "run tests"
- command: subprocess.exec
params:
binary: bash
args:
- "src/evergreen/external_auth_azure_teardown.sh"
- <<: *task_template - <<: *task_template
name: external_auth_windows name: external_auth_windows
tags: [] tags: []
@ -9199,6 +9218,17 @@ task_groups:
tasks: tasks:
- iwyu_self_test - iwyu_self_test
- <<: *compile_task_group_template
name: external_auth_oidc_azure_TG
tasks:
- external_auth_oidc_azure
teardown_task:
- command: subprocess.exec
params:
binary: bash
args:
- "src/evergreen/external_auth_azure_teardown.sh"
- <<: *compile_task_group_template - <<: *compile_task_group_template
name: compile_ninja_TG name: compile_ninja_TG
tasks: tasks:

View File

@ -2187,6 +2187,7 @@ buildvariants:
- name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore - name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore
- name: external_auth - name: external_auth
- name: external_auth_aws - name: external_auth_aws
- name: external_auth_oidc_azure
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded - name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
- name: jsCore_auth - name: jsCore_auth
- name: .jstestfuzz .common - name: .jstestfuzz .common

View File

@ -0,0 +1,44 @@
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)"
. "$DIR/prelude.sh"
cd src
set -o errexit
cat << EOF > $HOME/azure_e2e_config.json
{
"tD548GwE1@outlook.com" : "${oidc_azure_test_user_account_one_secret}",
"tD548GwE2@outlook.com" : "${oidc_azure_test_user_account_two_secret}",
"tD548GwE3@outlook.com" : "${oidc_azure_test_user_account_three_secret}",
"oidc_azure_client_secret_id" : "${oidc_azure_client_secret_id}",
"oidc_azure_client_secret_val" : "${oidc_azure_client_secret_val}",
"oidc_azure_client_id" : "${oidc_azure_client_id}",
"oidc_azure_tenant_id" : "${oidc_azure_tenant_id}",
"oidc_azure_subscription_id" : "${oidc_azure_subscription_id}",
"oidc_azure_group_name" : "${oidc_azure_group_name}",
"oidc_azure_container_app_name" : "${oidc_azure_container_app_name}",
"oidc_azure_container_port" : "${oidc_azure_container_port}",
"oidc_azure_api_version" : "${oidc_azure_api_version}",
"oidc_azure_resource_name" : "${oidc_azure_resource_name}",
"oidc_azure_object_id" : "${oidc_azure_object_id}",
"oidc_azure_managed_identity_api_version": "${oidc_azure_managed_identity_api_version}"
}
EOF
cat << EOF > $HOME/azure_remote_key
${oidc_azure_container_key}
EOF
# EVG project variables do not preserve line breaks - rather these are replaced with spaces, so we will need to convert our pem back into proper format
sed s/\ OPENSSH\ PRIVATE\ KEY/OPENSSHPRIVATEKEY/g $HOME/azure_remote_key | sed s/\ /\\n/g | sed s/OPENSSHPRIVATEKEY/\ OPENSSH\ PRIVATE\ KEY/g > $HOME/azure_remote_key
# SSH will complain and fail if the private key permissions are too lenient (by default it is created with 644), so modify to run the test
chmod 600 $HOME/azure_remote_key
# Log some basic information about our SSH version and the final permissions and user/group of the private key file for debugging
ssh -V
ls -al $HOME/azure_remote_key
# This script enables ingress on the Azure Container App instance that we will use to obtain our managed identity token,
# restrict ingress to the local, publicly-facing IP of the host we are running on, and then output the hostname of the container app into a local file
# so that it can be dynamically consumed by subsequent test steps (such as get_token.py)
python src/mongo/db/modules/enterprise/jstests/external_auth_oidc_azure/lib/toggle_ingress.py enable --config_file=$HOME/azure_e2e_config.json --debug | tee $HOME/azure_remote_host

View File

@ -0,0 +1,6 @@
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)"
. "$DIR/prelude.sh"
cd src
python src/mongo/db/modules/enterprise/jstests/external_auth_oidc_azure/lib/toggle_ingress.py disable --config_file=$HOME/azure_e2e_config.json

View File

@ -78,6 +78,7 @@ def authenticate_azure(activation_endpoint, userCode, username, test_credentials
landing_header = WebDriverWait(driver, 30).until( landing_header = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((By.XPATH, "//p[@id='message'][@class='text-block-body no-margin-top']")) EC.presence_of_element_located((By.XPATH, "//p[@id='message'][@class='text-block-body no-margin-top']"))
) )
assert landing_header is not None and "You have signed in" in landing_header.text assert landing_header is not None and "You have signed in" in landing_header.text
except Exception as e: except Exception as e:

View File

@ -458,7 +458,7 @@ ProgramRunner::ProgramRunner(BSONObj args, BSONObj env, bool isMongo, ProgramReg
_port < 0 || !_parentRegistry->isPortRegistered(_port)); _port < 0 || !_parentRegistry->isPortRegistered(_port));
} }
void ProgramRunner::start() { void ProgramRunner::start(bool shouldLogArgs) {
int pipeEnds[2]; int pipeEnds[2];
{ {
@ -520,11 +520,15 @@ void ProgramRunner::start() {
_pipe = pipeEnds[0]; _pipe = pipeEnds[0];
LOGV2_INFO(22810, logv2::DynamicAttributes attrs;
"shell: Started program", attrs.add("pid", _pid);
"pid"_attr = _pid, attrs.add("port", _port);
"port"_attr = _port,
"argv"_attr = _argv); if (shouldLogArgs) {
attrs.add("argv", _argv);
}
LOGV2_INFO(22810, "shell: Started program", attrs);
} }
void ProgramRunner::operator()(ProgramOutputMultiplexer* multiplexer, bool shouldLogOutput) { void ProgramRunner::operator()(ProgramOutputMultiplexer* multiplexer, bool shouldLogOutput) {

View File

@ -138,7 +138,7 @@ public:
class ProgramRunner { class ProgramRunner {
public: public:
/** Launch the program. */ /** Launch the program. */
void start(); void start(bool shouldLogArgs = true);
/** Reads the program's output into the provided instance of ProgramOutputMultiplexer. /** Reads the program's output into the provided instance of ProgramOutputMultiplexer.
* Note that the passed-in multiplexer will typically be the global programOutputLogger so that * Note that the passed-in multiplexer will typically be the global programOutputLogger so that

View File

@ -246,13 +246,15 @@ BSONObj StartMongoProgram(const BSONObj& a, void* data) {
return BSON(string("") << runner.pid().asLongLong()); return BSON(string("") << runner.pid().asLongLong());
} }
BSONObj RunProgram(const BSONObj& a, void* data, bool isMongo) { BSONObj RunProgram(const BSONObj& a, void* data, bool isMongo, bool isQuiet = false) {
BSONObj env{}; BSONObj env{};
auto registry = ProgramRegistry::get(getGlobalServiceContext()); auto registry = ProgramRegistry::get(getGlobalServiceContext());
auto runner = registry->createProgramRunner(a, env, isMongo); auto runner = registry->createProgramRunner(a, env, isMongo);
runner.start();
runner.start(!isQuiet);
invariant(registry->isPidRegistered(runner.pid())); invariant(registry->isPidRegistered(runner.pid()));
stdx::thread t(runner, registry->getProgramOutputMultiplexer(), true /* shouldLogOutput */); stdx::thread t(runner, registry->getProgramOutputMultiplexer(), !isQuiet /* shouldLogOutput */);
registry->registerReaderThread(runner.pid(), std::move(t)); registry->registerReaderThread(runner.pid(), std::move(t));
int exit_code = -123456; // sentinel value int exit_code = -123456; // sentinel value
registry->waitForPid(runner.pid(), true, &exit_code); registry->waitForPid(runner.pid(), true, &exit_code);
@ -267,6 +269,13 @@ BSONObj RunNonMongoProgram(const BSONObj& a, void* data) {
return RunProgram(a, data, false); return RunProgram(a, data, false);
} }
// This function is identical to RunNonMongoProgram except that it enables flags that
// disable logging of program outputs and vargs in order to prevent sensitive data from
// inadvertently being output to logs.
BSONObj RunNonMongoProgramQuietly(const BSONObj& a, void* data) {
return RunProgram(a, data, false, true);
}
BSONObj ResetDbpath(const BSONObj& a, void* data) { BSONObj ResetDbpath(const BSONObj& a, void* data) {
uassert(ErrorCodes::FailedToParse, "Expected 1 field", a.nFields() == 1); uassert(ErrorCodes::FailedToParse, "Expected 1 field", a.nFields() == 1);
string path = a.firstElement().str(); string path = a.firstElement().str();
@ -946,6 +955,7 @@ void installShellUtilsLauncher(Scope& scope) {
scope.injectNative("run", RunMongoProgram); scope.injectNative("run", RunMongoProgram);
scope.injectNative("_runMongoProgram", RunMongoProgram); scope.injectNative("_runMongoProgram", RunMongoProgram);
scope.injectNative("runNonMongoProgram", RunNonMongoProgram); scope.injectNative("runNonMongoProgram", RunNonMongoProgram);
scope.injectNative("runNonMongoProgramQuietly", RunNonMongoProgramQuietly);
scope.injectNative("_stopMongoProgram", StopMongoProgram); scope.injectNative("_stopMongoProgram", StopMongoProgram);
scope.injectNative("stopMongoProgramByPid", StopMongoProgramByPid); scope.injectNative("stopMongoProgramByPid", StopMongoProgramByPid);
scope.injectNative("rawMongoProgramOutput", RawMongoProgramOutput); scope.injectNative("rawMongoProgramOutput", RawMongoProgramOutput);