Skip to content
Open
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
50 changes: 48 additions & 2 deletions .evergreen/config_generator/components/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ def task_groups():
script='./drivers-evergreen-tools/.evergreen/auth_oidc/teardown.sh',
)
],
),
EvgTaskGroup(
name='test-oidc-azure-task-group',
tasks=['oidc-azure-auth-test-task'],
setup_group_can_fail_task=True,
setup_group_timeout_secs=60 * 60, # 1 hour
teardown_group_can_fail_task=True,
teardown_group_timeout_secs=180, # 3 minutes
setup_group=[
FetchDET.call(),
ec2_assume_role(role_arn='${aws_test_secrets_role}'),
bash_exec(
command_type=EvgCommandType.SETUP,
include_expansions_in_env=['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN'],
env={"AZUREOIDC_VMNAME_PREFIX": "CDRIVER"},
script='./drivers-evergreen-tools/.evergreen/auth_oidc/azure/create-and-setup-vm.sh',
),
],
teardown_group=[
bash_exec(
command_type=EvgCommandType.SETUP,
script='./drivers-evergreen-tools/.evergreen/auth_oidc/azure/delete-vm.sh',
)
],
)
]

Expand All @@ -59,6 +83,29 @@ def tasks():
),
RunTests.call(),
],
),
EvgTask(
name='oidc-azure-auth-test-task',
run_on=['debian11-small'], # TODO: switch to 'debian11-latest' after DEVPROD-23011 fixed.
commands=[
FetchSource.call(),
bash_exec(
working_dir="mongoc",
add_expansions_to_env=True,
command_type=EvgCommandType.TEST,
script='.evergreen/scripts/oidc-azure-compile.sh',
),
expansions_update(file="mongoc/oidc-remote-test-expansion.yml"),
bash_exec(
add_expansions_to_env=True,
command_type=EvgCommandType.TEST,
env={
"AZUREOIDC_DRIVERS_TAR_FILE": "${OIDC_TEST_TARBALL}",
"AZUREOIDC_TEST_CMD": "source ./env.sh && ./.evergreen/scripts/oidc-azure-test.sh"
},
script='./drivers-evergreen-tools/.evergreen/auth_oidc/azure/run-driver-test.sh',
),
],
)
]

Expand All @@ -68,7 +115,6 @@ def variants():
BuildVariant(
name='oidc',
display_name='OIDC',
run_on=[find_small_distro('ubuntu2404').name],
tasks=[EvgTaskRef(name='test-oidc-task-group')],
tasks=[EvgTaskRef(name='test-oidc-task-group'), EvgTaskRef(name='test-oidc-azure-task-group')],
),
]
32 changes: 32 additions & 0 deletions .evergreen/generated_configs/task_groups.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
task_groups:
- name: test-oidc-azure-task-group
setup_group:
- func: fetch-det
- command: ec2.assume_role
params:
role_arn: ${aws_test_secrets_role}
- command: subprocess.exec
type: setup
params:
binary: bash
env:
AZUREOIDC_VMNAME_PREFIX: CDRIVER
include_expansions_in_env:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
args:
- -c
- ./drivers-evergreen-tools/.evergreen/auth_oidc/azure/create-and-setup-vm.sh
setup_group_can_fail_task: true
setup_group_timeout_secs: 3600
tasks:
- oidc-azure-auth-test-task
teardown_group:
- command: subprocess.exec
type: setup
params:
binary: bash
args:
- -c
- ./drivers-evergreen-tools/.evergreen/auth_oidc/azure/delete-vm.sh
teardown_group_timeout_secs: 180
- name: test-oidc-task-group
setup_group:
- func: fetch-det
Expand Down
28 changes: 28 additions & 0 deletions .evergreen/generated_configs/tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4221,6 +4221,34 @@ tasks:
- { key: MONGODB_VERSION, value: latest }
- { key: TOPOLOGY, value: replica_set }
- func: run-tests
- name: oidc-azure-auth-test-task
run_on:
- debian11-small
commands:
- func: fetch-source
- command: subprocess.exec
type: test
params:
binary: bash
working_dir: mongoc
add_expansions_to_env: true
args:
- -c
- .evergreen/scripts/oidc-azure-compile.sh
- command: expansions.update
params:
file: mongoc/oidc-remote-test-expansion.yml
- command: subprocess.exec
type: test
params:
binary: bash
add_expansions_to_env: true
env:
AZUREOIDC_DRIVERS_TAR_FILE: ${OIDC_TEST_TARBALL}
AZUREOIDC_TEST_CMD: source ./env.sh && ./.evergreen/scripts/oidc-azure-test.sh
args:
- -c
- ./drivers-evergreen-tools/.evergreen/auth_oidc/azure/run-driver-test.sh
- name: openssl-compat-1.0.2-shared-ubuntu2404-gcc
run_on: ubuntu2404-large
tags: [openssl-compat, openssl-1.0.2, openssl-shared, ubuntu2404, gcc]
Expand Down
3 changes: 1 addition & 2 deletions .evergreen/generated_configs/variants.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,9 @@ buildvariants:
- name: mock-server-test
- name: oidc
display_name: OIDC
run_on:
- ubuntu2404-small
tasks:
- name: test-oidc-task-group
- name: test-oidc-azure-task-group
- name: openssl-compat-matrix
display_name: OpenSSL Compatibility Matrix
tasks:
Expand Down
57 changes: 57 additions & 0 deletions .evergreen/scripts/oidc-azure-compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset

# shellcheck source=.evergreen/scripts/use-tools.sh
. "$(dirname "${BASH_SOURCE[0]}")/use-tools.sh" paths # Sets MONGOC_DIR

cd "$MONGOC_DIR"

if [[ "${distro_id:?}" == "debian11-small" ]]; then
# Temporary workaround for lack of uv on `debian11`. TODO: remove after DEVPROD-23011 is resolved.
uv_dir="$(mktemp -d)"
python3 -m virtualenv "${uv_dir:?}"
# shellcheck source=/dev/null
(. "${uv_dir:?}/bin/activate" && python -m pip install uv)
PATH="${uv_dir:?}/bin:${PATH:-}"
command -V uv >/dev/null
fi

. .evergreen/scripts/install-build-tools.sh
install_build_tools
export CMAKE_GENERATOR="Ninja"

# Use ccache if able.
. .evergreen/scripts/find-ccache.sh
find_ccache_and_export_vars "$(pwd)" || true

echo "Compile test-libmongoc ... begin"
# Disable unnecessary dependencies. test-libmongoc is copied to a remote host for testing, which may not have all dependent libraries.
cmake \
-DENABLE_SASL=OFF \
-DENABLE_SNAPPY=OFF \
-DENABLE_ZSTD=OFF \
-DENABLE_ZLIB=OFF \
-DENABLE_SRV=OFF \
-DENABLE_CLIENT_SIDE_ENCRYPTION=OFF \
-DENABLE_EXAMPLES=OFF \
-DENABLE_SRV=OFF \
-S. -Bcmake-build
cmake --build cmake-build --target test-libmongoc --parallel
echo "Compile test-libmongoc ... end"

# Create tarball for remote testing.
echo "Creating test-libmongoc tarball ... begin"

# Copy test binary and JSON test files. All JSON test files are needed to start test-libmongoc.
tar -czf test-libmongoc.tar.gz \
.evergreen/scripts/oidc-azure-test.sh \
./cmake-build/src/libmongoc/test-libmongoc \
src/libmongoc/tests/json \
src/libbson/tests/json
echo "Creating test-libmongoc tarball ... end"

cat <<EOT > oidc-remote-test-expansion.yml
OIDC_TEST_TARBALL: ${MONGOC_DIR}/test-libmongoc.tar.gz
EOT
14 changes: 14 additions & 0 deletions .evergreen/scripts/oidc-azure-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset

export MONGOC_TEST_OIDC="ON"
export MONGOC_TEST_USER="$OIDC_ADMIN_USER"
export MONGOC_TEST_PASSWORD="$OIDC_ADMIN_PWD"
export MONGOC_AZURE_RESOURCE="$AZUREOIDC_RESOURCE"

# Install required OpenSSL runtime library.
sudo apt install -y libssl-dev

./cmake-build/src/libmongoc/test-libmongoc -d --match '/auth/unified/*' --match '/oidc/*'
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ To run test cases with large allocations, set:
* `MONGOC_TEST_LARGE_ALLOCATIONS=on` This may result in sudden test suite termination due to allocation failure. Use with caution.

* `MONGOC_TEST_OIDC=on` to test OIDC using a test environment described [here](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/d7a7337b384392a09fbe7fc80a7244e6f1226c18/.evergreen/auth_oidc).
* `MONGOC_AZURE_RESOURCE=<resource>` to test OIDC using an Azure test environment described [here](https://github.com/mongodb-labs/drivers-evergreen-tools/blob/d7a7337b384392a09fbe7fc80a7244e6f1226c18/.evergreen/auth_oidc/azure/README.md).

All tests should pass before submitting a patch.

Expand Down
62 changes: 52 additions & 10 deletions src/libmongoc/src/mongoc/mcd-azure.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,23 @@

#define AZURE_API_VERSION "2018-02-01"

static const char *const DEFAULT_METADATA_PATH =
"/metadata/identity/oauth2/"
"token?api-version=" AZURE_API_VERSION "&resource=https%3A%2F%2Fvault.azure.net";
static const char *const DEFAULT_METADATA_PATH = "/metadata/identity/oauth2/token?api-version=" AZURE_API_VERSION;

void
bool
mcd_azure_imds_request_init(mcd_azure_imds_request *req,
const char *token_resource,
const char *const opt_imds_host,
int opt_port,
const char *const opt_extra_headers)
const char *const opt_extra_headers,
const char *const opt_client_id)
{
BSON_ASSERT_PARAM(req);
BSON_ASSERT_PARAM(token_resource);

bool ok = false;
char *encoded_token_resource = NULL;
mcommon_string_append_t path = {0};

_mongoc_http_request_init(&req->req);
// The HTTP host of the IMDS server
req->req.host = req->_owned_host = bson_strdup(opt_imds_host ? opt_imds_host : "169.254.169.254");
Expand All @@ -50,9 +56,33 @@ mcd_azure_imds_request_init(mcd_azure_imds_request *req,
req->req.extra_headers = req->_owned_headers = bson_strdup_printf("Metadata: true\r\n"
"Accept: application/json\r\n%s",
opt_extra_headers ? opt_extra_headers : "");
// The default path is suitable. In the future, we may want to add query
// parameters to disambiguate a managed identity.
req->req.path = req->_owned_path = bson_strdup(DEFAULT_METADATA_PATH);
// Build the path with query parameters.
encoded_token_resource = mongoc_percent_encode(token_resource);
if (!encoded_token_resource) {
goto fail;
}

mcommon_string_new_as_append(&path);

if (!mcommon_string_append(&path, DEFAULT_METADATA_PATH) ||
!mcommon_string_append_printf(&path, "&resource=%s", encoded_token_resource)) {
goto fail;
}

if (opt_client_id) {
if (!mcommon_string_append_printf(&path, "&client_id=%s", opt_client_id)) {
goto fail;
}
}

req->req.path = req->_owned_path = mcommon_string_from_append_destroy_with_steal(&path);
path = (mcommon_string_append_t){0};

ok = true;
fail:
bson_free(encoded_token_resource);
mcommon_string_from_append_destroy(&path);
return ok;
}

void
Expand Down Expand Up @@ -156,11 +186,15 @@ mcd_azure_access_token_destroy(mcd_azure_access_token *c)

bool
mcd_azure_access_token_from_imds(mcd_azure_access_token *const out,
const char *token_resource,
const char *const opt_imds_host,
int opt_port,
const char *opt_extra_headers,
int opt_timeout_ms,
const char *opt_client_id,
bson_error_t *error)
{
BSON_ASSERT_PARAM(token_resource);
BSON_ASSERT_PARAM(out);

bool okay = false;
Expand All @@ -172,9 +206,17 @@ mcd_azure_access_token_from_imds(mcd_azure_access_token *const out,
_mongoc_http_response_init(&resp);

mcd_azure_imds_request req = MCD_AZURE_IMDS_REQUEST_INIT;
mcd_azure_imds_request_init(&req, opt_imds_host, opt_port, opt_extra_headers);
if (!mcd_azure_imds_request_init(&req, token_resource, opt_imds_host, opt_port, opt_extra_headers, opt_client_id)) {
_mongoc_set_error(error, MONGOC_ERROR_AZURE, MONGOC_ERROR_KMS_SERVER_HTTP, "Failed to initialize request");
goto fail;
}

int timeout_ms = 3 * 1000; // Default 3 second timeout
if (opt_timeout_ms > 0) {
timeout_ms = opt_timeout_ms;
}

if (!_mongoc_http_send(&req.req, 3 * 1000, false, NULL, &resp, error)) {
if (!_mongoc_http_send(&req.req, timeout_ms, false, NULL, &resp, error)) {
goto fail;
}

Expand Down
Loading