Skip to content
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
39cfd11
Clean up AWS and add output file
blink1073 Feb 15, 2025
c94b0bd
fix typo
blink1073 Feb 15, 2025
07078cc
fix path
blink1073 Feb 15, 2025
b6437d3
use export
blink1073 Feb 15, 2025
4851288
fix newline on windows
blink1073 Feb 16, 2025
a81621b
add mongodb uri
blink1073 Feb 17, 2025
3c18960
try with new secret
blink1073 Feb 17, 2025
024b746
Use standard admin
blink1073 Feb 18, 2025
5e44b66
popd
blink1073 Feb 18, 2025
02b5ecf
debug
blink1073 Feb 18, 2025
439940c
fix handling of mongodb_uri
blink1073 Feb 18, 2025
652fc2c
remove debug
blink1073 Feb 18, 2025
b2a1d84
handle quoting
blink1073 Feb 18, 2025
348ddab
fix missing char
blink1073 Feb 18, 2025
0a47818
use new user
blink1073 Feb 18, 2025
45b2b77
add debug
blink1073 Feb 18, 2025
daac114
Merge branch 'master' of github.com:mongodb-labs/drivers-evergreen-to…
blink1073 Feb 18, 2025
b142f39
revert change
blink1073 Feb 18, 2025
9ace3bd
add both users
blink1073 Feb 18, 2025
7e6a996
do not add bob user
blink1073 Feb 18, 2025
2b4df1a
cleanup
blink1073 Feb 19, 2025
a26fb94
fix usage
blink1073 Feb 19, 2025
3fc0801
revert change
blink1073 Feb 19, 2025
f19589a
do not load second user
blink1073 Feb 19, 2025
01f24d4
debug
blink1073 Feb 19, 2025
635489c
debug
blink1073 Feb 19, 2025
396e976
debug
blink1073 Feb 19, 2025
8f4a7e3
debug
blink1073 Feb 19, 2025
f2eaf2d
debug
blink1073 Feb 19, 2025
cbb86b1
debug
blink1073 Feb 19, 2025
d4a0618
debug
blink1073 Feb 19, 2025
5c74dc9
debug
blink1073 Feb 19, 2025
0c41af1
debug
blink1073 Feb 20, 2025
77a245b
undo debug
blink1073 Feb 20, 2025
f3d7ee3
undo unrelated changes
blink1073 Feb 20, 2025
72316b7
Merge branch 'master' of github.com:mongodb-labs/drivers-evergreen-to…
blink1073 Feb 26, 2025
b33d28c
remove test.env
blink1073 Feb 26, 2025
c9049e3
clean up env vars
blink1073 Feb 26, 2025
d9bda56
Merge branch 'master' of github.com:mongodb-labs/drivers-evergreen-to…
blink1073 Feb 26, 2025
4291bd5
undo env removal
blink1073 Feb 27, 2025
47233a0
avoid double quoting
blink1073 Feb 27, 2025
4bb2f40
remove creds
blink1073 Feb 27, 2025
75c9e07
fix aws teardown
blink1073 Feb 27, 2025
927b95b
debug
blink1073 Feb 27, 2025
ca42379
debug
blink1073 Feb 27, 2025
0209b78
debug
blink1073 Feb 27, 2025
b82546c
debug
blink1073 Feb 27, 2025
f47012d
debug
blink1073 Feb 27, 2025
f2378c0
add auth_aws option
blink1073 Mar 2, 2025
ce94638
clean up help
blink1073 Mar 2, 2025
97cfbbb
Merge branch 'master' of github.com:mongodb-labs/drivers-evergreen-to…
blink1073 Mar 4, 2025
852bfcf
address review
blink1073 Mar 4, 2025
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
101 changes: 13 additions & 88 deletions .evergreen/auth_aws/aws_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,108 +6,33 @@
# . ./aws_setup.sh <test-name>
#
# Handles AWS credential setup and exports relevant environment variables.
# Assumes you have already set up secrets.
# Sets up secrets if they have not already been set up.
set -eu

SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]})
. $SCRIPT_DIR/../handle-paths.sh
pushd $SCRIPT_DIR

# Ensure that secrets have already been set up.
if [ ! -f "secrets-export.sh" ]; then
echo "ERROR: please run './setup-secrets.sh' in this folder"
fi

# Activate the venv and source the secrets file.
. ./activate-authawsvenv.sh
source secrets-export.sh

if [ "$1" == "web-identity" ]; then
export AWS_WEB_IDENTITY_TOKEN_FILE="./token_file.txt"
fi

# Handle the test setup if not using env variables.
case $1 in
session-creds)
echo "Running aws_tester.py with assume-role"
# Set up credentials with assume-role to create user in MongoDB and write AWS credentials.
python aws_tester.py "assume-role"
;;
env-creds)
echo "Running aws_tester.py with regular"
# Set up credentials with regular to create user in MongoDB and write AWS credentials.
python aws_tester.py "regular"
;;
*)
python aws_tester.py "$1"
;;
esac

# If this is ecs, exit now.
if [ "$1" == "ecs" ]; then
exit 0
# Ensure that secrets have already been set up.
if [ ! -f "./secrets-export.sh" ]; then
bash ./setup-secrets.sh
fi

# Convenience functions.
urlencode () {
python -c "import sys, urllib.parse as ulp; sys.stdout.write(ulp.quote_plus(sys.argv[1]))" "$1"
}
# Remove any AWS creds that might be set in the parent env.
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN

jsonkey () {
python -c "import json,sys;sys.stdout.write(json.load(sys.stdin)[sys.argv[1]])" "$1" < ./creds.json
}
source ./secrets-export.sh

# Handle extra vars based on auth type.
USER=""
case $1 in
assume-role)
USER=$(jsonkey AccessKeyId)
USER=$(urlencode "$USER")
PASS=$(jsonkey SecretAccessKey)
PASS=$(urlencode "$PASS")
SESSION_TOKEN=$(jsonkey SessionToken)
SESSION_TOKEN=$(urlencode "$SESSION_TOKEN")
;;

session-creds)
AWS_ACCESS_KEY_ID=$(jsonkey AccessKeyId)
AWS_SECRET_ACCESS_KEY=$(jsonkey SecretAccessKey)
AWS_SESSION_TOKEN=$(jsonkey SessionToken)

export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
export AWS_SESSION_TOKEN
;;

web-identity)
export AWS_ROLE_ARN=$IAM_AUTH_ASSUME_WEB_ROLE_NAME
export AWS_WEB_IDENTITY_TOKEN_FILE="$SCRIPT_DIR/$AWS_WEB_IDENTITY_TOKEN_FILE"
;;

regular)
USER=$(urlencode "${IAM_AUTH_ECS_ACCOUNT}")
PASS=$(urlencode "${IAM_AUTH_ECS_SECRET_ACCESS_KEY}")
;;

env-creds)
export AWS_ACCESS_KEY_ID=$IAM_AUTH_ECS_ACCOUNT
export AWS_SECRET_ACCESS_KEY=$IAM_AUTH_ECS_SECRET_ACCESS_KEY
;;
esac

# Handle the URI.
if [ -n "$USER" ]; then
MONGODB_URI="mongodb://$USER:$PASS@localhost"
export USER
export PASS
else
MONGODB_URI="mongodb://localhost"
fi
MONGODB_URI="${MONGODB_URI}/aws?authMechanism=MONGODB-AWS"
if [[ -n ${SESSION_TOKEN:-} ]]; then
MONGODB_URI="${MONGODB_URI}&authMechanismProperties=AWS_SESSION_TOKEN:${SESSION_TOKEN}"
if [ -f $SCRIPT_DIR/test-env.sh ]; then
rm $SCRIPT_DIR/test-env.sh
fi

export MONGODB_URI="$MONGODB_URI"
python aws_tester.py "$1"
source $SCRIPT_DIR/test-env.sh

popd
68 changes: 57 additions & 11 deletions .evergreen/auth_aws/aws_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,27 @@

import argparse
import json
import logging
import os
import subprocess
import sys
from functools import partial
from pathlib import Path
from urllib.parse import quote_plus

from pymongo import MongoClient
from pymongo.errors import OperationFailure

HERE = os.path.abspath(os.path.dirname(__file__))
HERE = Path(__file__).absolute().parent
LOGGER = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(message)s")


def join(*parts):
return os.path.join(*parts).replace(os.sep, "/")


sys.path.insert(0, join(HERE, "lib"))
sys.path.insert(0, str(HERE / "lib"))
from aws_assign_instance_profile import _assign_instance_policy
from aws_assume_role import _assume_role
from aws_assume_web_role import _assume_role_with_web_identity
Expand All @@ -35,7 +39,7 @@ def join(*parts):
_USE_AWS_SECRETS = False

try:
with open(join(HERE, "aws_e2e_setup.json")) as fid:
with (HERE / "aws_e2e_setup.json").open() as fid:
CONFIG = json.load(fid)
get_key = partial(_get_key, uppercase=False)
except FileNotFoundError:
Expand All @@ -51,7 +55,7 @@ def run(args, env):

def create_user(user, kwargs):
"""Create a user and verify access."""
print("Creating user", user)
LOGGER.info("Creating user %s", user)
client = MongoClient(username="bob", password="pwd123")
db = client["$external"]
try:
Expand All @@ -76,7 +80,7 @@ def setup_assume_role():

role_name = CONFIG[get_key("iam_auth_assume_role_name")]
creds = _assume_role(role_name, quiet=True)
with open(join(HERE, "creds.json"), "w") as fid:
with (HERE / "creds.json").open("w") as fid:
json.dump(creds, fid)

# Create the user.
Expand All @@ -87,6 +91,11 @@ def setup_assume_role():
authmechanismproperties=f"AWS_SESSION_TOKEN:{token}",
)
create_user(ASSUMED_ROLE, kwargs)
return dict(
USER=kwargs["username"],
PASS=kwargs["password"],
SESSION_TOKEN=creds["SessionToken"],
)


def setup_ec2():
Expand All @@ -95,6 +104,7 @@ def setup_ec2():
os.environ.pop("AWS_ACCESS_KEY_ID", None)
os.environ.pop("AWS_SECRET_ACCESS_KEY", None)
create_user(AWS_ACCOUNT_ARN, dict())
return dict()


def setup_ecs():
Expand Down Expand Up @@ -138,6 +148,8 @@ def setup_ecs():
# Run the test in a container
subprocess.check_call(["/bin/sh", "-c", run_test_command], env=env)

return dict()


def setup_regular():
# Create the user.
Expand All @@ -147,6 +159,8 @@ def setup_regular():
)
create_user(CONFIG[get_key("iam_auth_ecs_account_arn")], kwargs)

return dict(USER=kwargs["username"], PASS=kwargs["password"])


def setup_web_identity():
# Unassign the instance profile.
Expand All @@ -161,7 +175,7 @@ def setup_web_identity():
raise RuntimeError("Request limit exceeded for AWS API")

if ret != 0:
print("ret was", ret)
LOGGER.debug("return code was %s", ret)
raise RuntimeError(
"Failed to unassign an instance profile from the current machine"
)
Expand All @@ -186,10 +200,11 @@ def setup_web_identity():

# Assume the web role to get temp credentials.
os.environ["AWS_WEB_IDENTITY_TOKEN_FILE"] = token_file
os.environ["AWS_ROLE_ARN"] = CONFIG[get_key("iam_auth_assume_web_role_name")]
role_arn = CONFIG[get_key("iam_auth_assume_web_role_name")]
os.environ["AWS_ROLE_ARN"] = role_arn

creds = _assume_role_with_web_identity(True)
with open(join(HERE, "creds.json"), "w") as fid:
with (HERE / "creds.json").open("w") as fid:
json.dump(creds, fid)

# Create the user.
Expand All @@ -201,12 +216,37 @@ def setup_web_identity():
)
create_user(ASSUMED_WEB_ROLE, kwargs)

return dict(AWS_WEB_IDENTITY_TOKEN_FILE=token_file, AWS_ROLE_ARN=role_arn)


def handle_creds(creds: dict):
if "USER" in creds:
USER = quote_plus(creds.pop("USER"))
PASS = quote_plus(creds.pop("PASS"))
MONGODB_URI = f"mongodb://{USER}:{PASS}@localhost"
else:
MONGODB_URI = "mongodb://localhost"
MONGODB_URI = f"{MONGODB_URI}/aws?authMechanism=MONGODB-AWS"
if "SESSION_TOKEN" in creds:
SESSION_TOKEN = quote_plus(creds.pop("SESSION_TOKEN"))
MONGODB_URI = (
f"{MONGODB_URI}&authMechanismProperties=AWS_SESSION_TOKEN:{SESSION_TOKEN}"
)
with (HERE / "test-env.sh").open("w", newline="\n") as fid:
fid.write("#!/usr/bin/env bash\n\n")
fid.write("set +x\n")
for key, value in creds.items():
fid.write(f"export {key}={value}\n")
fid.write(f"export MONGODB_URI={MONGODB_URI}\n")


def main():
parser = argparse.ArgumentParser(description="MONGODB-AWS tester.")
sub = parser.add_subparsers(title="Tester subcommands", help="sub-command help")

run_assume_role_cmd = sub.add_parser("assume-role", help="Assume role test")
run_assume_role_cmd = sub.add_parser(
"assume-role", aliases=["session-creds"], help="Assume role test"
)
run_assume_role_cmd.set_defaults(func=setup_assume_role)

run_ec2_cmd = sub.add_parser("ec2", help="EC2 test")
Expand All @@ -215,14 +255,20 @@ def main():
run_ecs_cmd = sub.add_parser("ecs", help="ECS test")
run_ecs_cmd.set_defaults(func=setup_ecs)

run_regular_cmd = sub.add_parser("regular", help="Regular credentials test")
run_regular_cmd = sub.add_parser(
"regular", aliases=["env-creds"], help="Regular credentials test"
)
run_regular_cmd.set_defaults(func=setup_regular)

run_web_identity_cmd = sub.add_parser("web-identity", help="Web identity test")
run_web_identity_cmd.set_defaults(func=setup_web_identity)

args = parser.parse_args()
args.func()
func_name = args.func.__name__.replace("setup_", "")
LOGGER.info("Running aws_tester.py with %s...", func_name)
creds = args.func()
handle_creds(creds)
LOGGER.info("Running aws_tester.py with %s... done.", func_name)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/auth_aws/lib/aws_assign_instance_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def _has_instance_profile():
print("Reading: " + base_url)
iam_role = urllib.request.urlopen(base_url).read().decode()
except urllib.error.HTTPError as e:
print(e)
if e.code == 404:
return False
print(e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a logger instead of a print?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

raise e

try:
Expand Down
15 changes: 12 additions & 3 deletions .evergreen/orchestration/drivers_orchestration.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ def get_options():
parser.add_argument(
"--version",
default="latest",
help='The version to download (Required). Use "latest" to download '
help='The version to download. Use "latest" to download '
"the newest available version (including release candidates).",
)
parser.add_argument(
"--topology",
choices=["standalone", "replica_set", "sharded_cluster"],
default="standalone",
help="The topology of the server deployment",
help="The topology of the server deployment (defaults to standalone unless another flag like load_balancer is set)",
)
parser.add_argument(
"--auth", action="store_true", help="Whether to add authentication"
Expand All @@ -78,6 +77,9 @@ def get_options():
other_group.add_argument(
"--load-balancer", action="store_true", help="Whether to use a load balancer"
)
other_group.add_argument(
"--auth-aws", action="store_true", help="Whether to use MONGODB-AWS auth"
)
other_group.add_argument(
"--skip-crypt-shared",
action="store_true",
Expand Down Expand Up @@ -148,6 +150,11 @@ def get_options():
opts.mongo_orchestration_home = DRIVERS_TOOLS / ".evergreen/orchestration"
if opts.mongodb_binaries is None:
opts.mongodb_binaries = DRIVERS_TOOLS / "mongodb/bin"
if not opts.topology and opts.load_balancer:
opts.topology = "sharded_cluster"
if opts.auth_aws:
opts.auth = True
opts.orchestration_file = "auth-aws.json"
if opts.topology == "standalone" or not opts.topology:
opts.topology = "server"
if not opts.version:
Expand Down Expand Up @@ -395,6 +402,8 @@ def run(opts):
MO_EXPANSION_YML.write_text(
MO_EXPANSION_YML.read_text() + f'\nMONGODB_URI: "{uri}"'
)
MO_EXPANSION_SH.touch()
MO_EXPANSION_SH.write_text(MO_EXPANSION_SH.read_text() + f'\nMONGODB_URI="{uri}"')
URI_TXT.write_text(uri)
LOGGER.info(f"Cluster URI: {uri}")

Expand Down
1 change: 1 addition & 0 deletions .evergreen/run-orchestration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set -eu
# SKIP_CRYPT_SHARED Set to a non-empty string to skip downloading crypt_shared
# MONGODB_BINARIES Set the path to the MONGODB_BINARIES for mongo orchestration.
# LOAD_BALANCER Set to a non-empty string to enable load balancer. Only supported for sharded clusters.
# AUTH_AWS Set to a non-empty string to enable MONGODB-AWS authentication.
# PYTHON Set the Python binary to use.
# INSTALL_LEGACY_SHELL Set to a non-empty string to install the legacy mongo shell.
# TLS_CERT_KEY_FILE Set a .pem file to be used as the tlsCertificateKeyFile option in mongo-orchestration
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ evergreen_config_generator/dist
*-expansion.yml
secrets-export.sh
token_file.txt
test-env.sh

# Virtual envs
.venv
Expand Down
Loading