Skip to content

Commit 7df3b0f

Browse files
committed
Add basic matrix to test PHPLIB on evergreen
1 parent 07b994b commit 7df3b0f

File tree

107 files changed

+6603
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+6603
-0
lines changed

.evergreen/auth_aws/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Configuration Scripts for End-to-end Testing
2+
3+
These scripts were taken from [mongo-enterprise-modules](https://github.com/10gen/mongo-enterprise-modules/tree/master/jstests/external_auth_aws)
4+
and intended to simplify creating users, attaching roles to existing EC2 instances, launching an Amazon ECS container instance, etc.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Verify the AWS IAM Auth works with temporary credentials from sts:AssumeRole
3+
*/
4+
5+
load("lib/aws_e2e_lib.js");
6+
7+
(function() {
8+
"use strict";
9+
10+
const ASSUMED_ROLE = "arn:aws:sts::557821124784:assumed-role/authtest_user_assume_role/*";
11+
12+
function getAssumeCredentials() {
13+
const config = readSetupJson();
14+
15+
const env = {
16+
AWS_ACCESS_KEY_ID: config["iam_auth_assume_aws_account"],
17+
AWS_SECRET_ACCESS_KEY: config["iam_auth_assume_aws_secret_access_key"],
18+
};
19+
20+
const role_name = config["iam_auth_assume_role_name"];
21+
22+
const python_command = getPython3Binary() +
23+
` -u lib/aws_assume_role.py --role_name=${role_name} > creds.json`;
24+
25+
const ret = runShellCmdWithEnv(python_command, env);
26+
assert.eq(ret, 0, "Failed to assume role on the current machine");
27+
28+
const result = cat("creds.json");
29+
try {
30+
return JSON.parse(result);
31+
} catch (e) {
32+
jsTestLog("Failed to parse: " + result);
33+
throw e;
34+
}
35+
}
36+
37+
const credentials = getAssumeCredentials();
38+
const admin = Mongo().getDB("admin");
39+
const external = admin.getMongo().getDB("$external");
40+
41+
assert(admin.auth("bob", "pwd123"));
42+
assert.commandWorked(external.runCommand({createUser: ASSUMED_ROLE, roles:[{role: 'read', db: "aws"}]}));
43+
assert(external.auth({
44+
user: credentials["AccessKeyId"],
45+
pwd: credentials["SecretAccessKey"],
46+
awsIamSessionToken: credentials["SessionToken"],
47+
mechanism: 'MONGODB-AWS'
48+
}));
49+
}());

.evergreen/auth_aws/aws_e2e_ec2.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Verify the AWS IAM EC2 hosted auth works
3+
*/
4+
load("lib/aws_e2e_lib.js");
5+
6+
(function() {
7+
"use strict";
8+
9+
// This varies based on hosting EC2 as the account id and role name can vary
10+
const AWS_ACCOUNT_ARN = "arn:aws:sts::557821124784:assumed-role/authtest_instance_profile_role/*";
11+
12+
function assignInstanceProfile() {
13+
const config = readSetupJson();
14+
15+
const env = {
16+
AWS_ACCESS_KEY_ID: config["iam_auth_ec2_instance_account"],
17+
AWS_SECRET_ACCESS_KEY: config["iam_auth_ec2_instance_secret_access_key"],
18+
};
19+
20+
const instanceProfileName = config["iam_auth_ec2_instance_profile"];
21+
const python_command = getPython3Binary() +
22+
` -u lib/aws_assign_instance_profile.py --instance_profile_arn=${instanceProfileName}`;
23+
24+
const ret = runShellCmdWithEnv(python_command, env);
25+
if (ret == 2) {
26+
print("WARNING: Request limit exceeded for AWS API");
27+
return false;
28+
}
29+
30+
assert.eq(ret, 0, "Failed to assign an instance profile to the current machine");
31+
return true;
32+
}
33+
34+
if (!assignInstanceProfile()) {
35+
return;
36+
}
37+
38+
const admin = Mongo().getDB("admin");
39+
const external = admin.getMongo().getDB("$external");
40+
41+
assert(admin.auth("bob", "pwd123"));
42+
assert.commandWorked(external.runCommand({createUser: AWS_ACCOUNT_ARN, roles:[{role: 'read', db: "aws"}]}));
43+
44+
// Try the command line
45+
const smoke = runMongoProgram("mongo",
46+
"--host",
47+
"localhost",
48+
'--authenticationMechanism',
49+
'MONGODB-AWS',
50+
'--authenticationDatabase',
51+
'$external',
52+
"--eval",
53+
"1");
54+
assert.eq(smoke, 0, "Could not auth with smoke user");
55+
56+
// Try the auth function
57+
assert(external.auth({mechanism: 'MONGODB-AWS'}));
58+
}());

.evergreen/auth_aws/aws_e2e_ecs.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Validate that MONGODB-AWS auth works from ECS temporary credentials.
3+
*/
4+
load("lib/aws_e2e_lib.js");
5+
6+
(function() {
7+
'use strict';
8+
9+
assert.eq(typeof mongo_binaries != 'undefined', true, "mongo_binaries must be set");
10+
assert.eq(typeof project_dir != 'undefined', true, "project_dir must be set");
11+
12+
const config = readSetupJson();
13+
14+
const base_command = getPython3Binary() + " -u lib/container_tester.py";
15+
const run_prune_command = base_command + ' -v remote_gc_services ' +
16+
' --cluster ' + config['iam_auth_ecs_cluster'];
17+
18+
const run_test_command = base_command + ' -d -v run_e2e_test' +
19+
' --cluster ' + config['iam_auth_ecs_cluster'] + ' --task_definition ' +
20+
config['iam_auth_ecs_task_definition'] + ' --subnets ' +
21+
config['iam_auth_ecs_subnet_a'] + ' --subnets ' +
22+
config['iam_auth_ecs_subnet_b'] + ' --security_group ' +
23+
config['iam_auth_ecs_security_group'] +
24+
` --files ${mongo_binaries}/mongod:/root/mongod ${mongo_binaries}/mongo:/root/mongo ` +
25+
" lib/ecs_hosted_test.js:/root/ecs_hosted_test.js " +
26+
`${project_dir}:/root` +
27+
" --script lib/ecs_hosted_test.sh";
28+
29+
// Pass in the AWS credentials as environment variables
30+
// AWS_SHARED_CREDENTIALS_FILE does not work in evergreen for an unknown
31+
// reason
32+
const env = {
33+
AWS_ACCESS_KEY_ID: config['iam_auth_ecs_account'],
34+
AWS_SECRET_ACCESS_KEY: config['iam_auth_ecs_secret_access_key'],
35+
};
36+
37+
// Prune other containers
38+
let ret = runWithEnv(['/bin/sh', '-c', run_prune_command], env);
39+
assert.eq(ret, 0, 'Prune Container failed');
40+
41+
// Run the test in a container
42+
ret = runWithEnv(['/bin/sh', '-c', run_test_command], env);
43+
assert.eq(ret, 0, 'Container Test failed');
44+
}());
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Validate that the server supports real credentials from AWS and can talk to a real AWS STS
3+
* service
4+
*/
5+
load("lib/aws_e2e_lib.js");
6+
7+
(function() {
8+
"use strict";
9+
10+
const admin = Mongo().getDB("admin");
11+
const external = admin.getMongo().getDB("$external");
12+
assert(admin.auth("bob", "pwd123"));
13+
14+
const config = readSetupJson();
15+
assert.commandWorked(
16+
external.runCommand({createUser: config["iam_auth_ecs_account_arn"], roles:[{role: 'read', db: "aws"}]}));
17+
18+
assert(external.auth({
19+
user: config["iam_auth_ecs_account"],
20+
pwd: config["iam_auth_ecs_secret_access_key"],
21+
mechanism: 'MONGODB-AWS'
22+
}));
23+
}());
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script for assign an instance policy to the current machine.
4+
"""
5+
6+
import argparse
7+
import urllib.request
8+
import logging
9+
import sys
10+
import time
11+
12+
import boto3
13+
import botocore
14+
15+
LOGGER = logging.getLogger(__name__)
16+
17+
def _get_local_instance_id():
18+
return urllib.request.urlopen('http://169.254.169.254/latest/meta-data/instance-id').read().decode()
19+
20+
def _has_instance_profile():
21+
base_url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
22+
try:
23+
print("Reading: " + base_url)
24+
iam_role = urllib.request.urlopen(base_url).read().decode()
25+
except urllib.error.HTTPError as e:
26+
print(e)
27+
if e.code == 404:
28+
return False
29+
raise e
30+
31+
try:
32+
url = base_url + iam_role
33+
print("Reading: " + url)
34+
req = urllib.request.urlopen(url)
35+
except urllib.error.HTTPError as e:
36+
print(e)
37+
if e.code == 404:
38+
return False
39+
raise e
40+
41+
return True
42+
43+
def _wait_instance_profile():
44+
retry = 60
45+
while not _has_instance_profile() and retry:
46+
time.sleep(5)
47+
retry -= 1
48+
49+
if retry == 0:
50+
raise ValueError("Timeout on waiting for instance profile")
51+
52+
def _assign_instance_policy(iam_instance_arn):
53+
54+
if _has_instance_profile():
55+
print("IMPORTANT: Found machine already has instance profile, skipping the assignment")
56+
return
57+
58+
instance_id = _get_local_instance_id()
59+
60+
ec2_client = boto3.client("ec2", 'us-east-1')
61+
62+
#https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.associate_iam_instance_profile
63+
try:
64+
response = ec2_client.associate_iam_instance_profile(
65+
IamInstanceProfile={
66+
'Arn' : iam_instance_arn,
67+
},
68+
InstanceId = instance_id)
69+
70+
print(response)
71+
72+
# Wait for the instance profile to be assigned by polling the local instance metadata service
73+
_wait_instance_profile()
74+
75+
except botocore.exceptions.ClientError as ce:
76+
if ce.response["Error"]["Code"] == "RequestLimitExceeded":
77+
print("WARNING: RequestLimitExceeded, exiting with error code 2")
78+
sys.exit(2)
79+
raise
80+
81+
def main() -> None:
82+
"""Execute Main entry point."""
83+
84+
parser = argparse.ArgumentParser(description='IAM Assign Instance frontend.')
85+
86+
parser.add_argument('-v', "--verbose", action='store_true', help="Enable verbose logging")
87+
parser.add_argument('-d', "--debug", action='store_true', help="Enable debug logging")
88+
89+
parser.add_argument('--instance_profile_arn', type=str, help="Name of instance profile")
90+
91+
args = parser.parse_args()
92+
93+
if args.debug:
94+
logging.basicConfig(level=logging.DEBUG)
95+
elif args.verbose:
96+
logging.basicConfig(level=logging.INFO)
97+
98+
_assign_instance_policy(args.instance_profile_arn)
99+
100+
101+
if __name__ == "__main__":
102+
main()
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script for assuming an aws role.
4+
"""
5+
6+
import argparse
7+
import uuid
8+
import logging
9+
10+
import boto3
11+
12+
LOGGER = logging.getLogger(__name__)
13+
14+
STS_DEFAULT_ROLE_NAME = "arn:aws:iam::579766882180:role/mark.benvenuto"
15+
16+
def _assume_role(role_name):
17+
sts_client = boto3.client("sts")
18+
19+
response = sts_client.assume_role(RoleArn=role_name, RoleSessionName=str(uuid.uuid4()), DurationSeconds=900)
20+
21+
creds = response["Credentials"]
22+
23+
24+
print(f"""{{
25+
"AccessKeyId" : "{creds["AccessKeyId"]}",
26+
"SecretAccessKey" : "{creds["SecretAccessKey"]}",
27+
"SessionToken" : "{creds["SessionToken"]}",
28+
"Expiration" : "{str(creds["Expiration"])}"
29+
}}""")
30+
31+
32+
def main() -> None:
33+
"""Execute Main entry point."""
34+
35+
parser = argparse.ArgumentParser(description='Assume Role frontend.')
36+
37+
parser.add_argument('-v', "--verbose", action='store_true', help="Enable verbose logging")
38+
parser.add_argument('-d', "--debug", action='store_true', help="Enable debug logging")
39+
40+
parser.add_argument('--role_name', type=str, default=STS_DEFAULT_ROLE_NAME, help="Role to assume")
41+
42+
args = parser.parse_args()
43+
44+
if args.debug:
45+
logging.basicConfig(level=logging.DEBUG)
46+
elif args.verbose:
47+
logging.basicConfig(level=logging.INFO)
48+
49+
_assume_role(args.role_name)
50+
51+
52+
if __name__ == "__main__":
53+
main()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
function readSetupJson() {
3+
let result;
4+
try {
5+
result = cat("aws_e2e_setup.json");
6+
} catch (e) {
7+
jsTestLog(
8+
"Failed to parse read aws_e2e_setup.json. See evergreen.yml for how to generate this file which contains evergreen secrets.");
9+
throw e;
10+
}
11+
12+
try {
13+
return JSON.parse(result);
14+
} catch (e) {
15+
jsTestLog("Failed to parse: aws_e2e_setup.json");
16+
throw e;
17+
}
18+
}
19+
20+
function runWithEnv(args, env) {
21+
const pid = _startMongoProgram({args: args, env: env});
22+
return waitProgram(pid);
23+
}
24+
25+
function runShellCmdWithEnv(argStr, env) {
26+
if (_isWindows()) {
27+
return runWithEnv(['cmd.exe', '/c', argStr], env);
28+
} else {
29+
return runWithEnv(['/bin/sh', '-c', argStr], env);
30+
}
31+
}
32+
33+
function getPython3Binary() {
34+
if (_isWindows()) {
35+
return "python.exe";
36+
}
37+
38+
return "python3";
39+
}

0 commit comments

Comments
 (0)