Skip to content

Commit e3670f7

Browse files
authored
Merge pull request #1976 from matthewdale/godriver3175-oidc-k8s
GODRIVER-3175 Add Kubernetes support for OIDC.
2 parents 21a1d94 + 635eb59 commit e3670f7

File tree

10 files changed

+923
-561
lines changed

10 files changed

+923
-561
lines changed

.evergreen/config.yml

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,18 @@ functions:
162162
args:
163163
- ${DRIVERS_TOOLS}/.evergreen/teardown.sh
164164

165-
assume-ec2-role:
165+
assume-test-secrets-ec2-role:
166166
- command: ec2.assume_role
167167
params:
168168
role_arn: ${aws_test_secrets_role}
169+
duration_seconds: 1800
169170

170171
run-oidc-auth-test-with-test-credentials:
171172
- command: subprocess.exec
172173
type: test
173174
params:
174175
binary: bash
175-
env:
176+
env:
176177
OIDC: oidc
177178
include_expansions_in_env: [DRIVERS_TOOLS, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN]
178179
args: [*task-runner, test-oidc]
@@ -396,6 +397,16 @@ functions:
396397
include_expansions_in_env: ["MONGODB_URI"]
397398
args: [*task-runner, test-goleak]
398399

400+
"run oidc k8s test":
401+
- command: subprocess.exec
402+
type: test
403+
params:
404+
binary: bash
405+
include_expansions_in_env: [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, VARIANT, DRIVERS_TOOLS]
406+
env:
407+
OIDC_ENV: k8s
408+
args: [*task-runner, test-oidc-remote]
409+
399410
run-ocsp-server:
400411
- command: subprocess.exec
401412
params:
@@ -1658,6 +1669,19 @@ tasks:
16581669
OIDC_ENV: gcp
16591670
args: [*task-runner, test-oidc-remote]
16601671

1672+
- name: "oidc-auth-test-k8s"
1673+
commands:
1674+
- func: assume-test-secrets-ec2-role
1675+
- func: "run oidc k8s test"
1676+
vars:
1677+
VARIANT: eks
1678+
- func: "run oidc k8s test"
1679+
vars:
1680+
VARIANT: gke
1681+
- func: "run oidc k8s test"
1682+
vars:
1683+
VARIANT: aks
1684+
16611685
- name: "test-search-index"
16621686
commands:
16631687
- func: "bootstrap-mongo-orchestration"
@@ -1902,14 +1926,17 @@ task_groups:
19021926
- ${DRIVERS_TOOLS}/.evergreen/csfle/azurekms/teardown.sh
19031927
- func: teardown
19041928
- func: handle-test-artifacts
1905-
19061929
tasks:
19071930
- testazurekms-task
19081931

19091932
- name: testoidc_task_group
1933+
setup_group_can_fail_task: true
1934+
setup_group_timeout_secs: 1800
1935+
teardown_task_can_fail_task: true
1936+
teardown_group_timeout_secs: 180 # 3 minutes (max allowed time)
19101937
setup_group:
19111938
- func: setup-system
1912-
- func: assume-ec2-role
1939+
- func: assume-test-secrets-ec2-role
19131940
- command: subprocess.exec
19141941
params:
19151942
binary: bash
@@ -1926,12 +1953,14 @@ task_groups:
19261953
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/teardown.sh
19271954
- func: teardown
19281955
- func: handle-test-artifacts
1929-
setup_group_can_fail_task: true
1930-
setup_group_timeout_secs: 1800
19311956
tasks:
19321957
- oidc-auth-test
19331958

19341959
- name: testazureoidc_task_group
1960+
setup_group_can_fail_task: true
1961+
setup_group_timeout_secs: 1800
1962+
teardown_task_can_fail_task: true
1963+
teardown_group_timeout_secs: 180 # 3 minutes (max allowed time)
19351964
setup_group:
19361965
- func: setup-system
19371966
- command: subprocess.exec
@@ -1949,12 +1978,14 @@ task_groups:
19491978
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/azure/teardown.sh
19501979
- func: teardown
19511980
- func: handle-test-artifacts
1952-
setup_group_can_fail_task: true
1953-
setup_group_timeout_secs: 1800
19541981
tasks:
19551982
- oidc-auth-test-azure
19561983

19571984
- name: testgcpoidc_task_group
1985+
setup_group_can_fail_task: true
1986+
setup_group_timeout_secs: 1800
1987+
teardown_task_can_fail_task: true
1988+
teardown_group_timeout_secs: 180 # 3 minutes (max allowed time)
19581989
setup_group:
19591990
- func: setup-system
19601991
- command: subprocess.exec
@@ -1972,10 +2003,32 @@ task_groups:
19722003
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/gcp/teardown.sh
19732004
- func: teardown
19742005
- func: handle-test-artifacts
2006+
tasks:
2007+
- oidc-auth-test-gcp
2008+
2009+
- name: testk8soidc_task_group
19752010
setup_group_can_fail_task: true
19762011
setup_group_timeout_secs: 1800
2012+
teardown_task_can_fail_task: true
2013+
teardown_group_timeout_secs: 180 # 3 minutes (max allowed time)
2014+
setup_group:
2015+
- func: setup-system
2016+
- command: subprocess.exec
2017+
params:
2018+
binary: bash
2019+
include_expansions_in_env: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]
2020+
args:
2021+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/setup.sh
2022+
teardown_group:
2023+
- command: subprocess.exec
2024+
params:
2025+
binary: bash
2026+
args:
2027+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/teardown.sh
2028+
- func: teardown
2029+
- func: handle-test-artifacts
19772030
tasks:
1978-
- oidc-auth-test-gcp
2031+
- oidc-auth-test-k8s
19792032

19802033
- name: test-aws-lambda-task-group
19812034
setup_group:
@@ -2322,8 +2375,6 @@ buildvariants:
23222375
GO_DIST: "/opt/golang/go1.22"
23232376
tasks:
23242377
- name: testoidc_task_group
2325-
batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README
23262378
- name: testazureoidc_task_group
2327-
batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README
23282379
- name: testgcpoidc_task_group
2329-
batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README
2380+
- name: testk8soidc_task_group

etc/run-oidc-remote-test.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ elif [ $OIDC_ENV == "gcp" ]; then
3131
export GCPOIDC_TEST_CMD="PROJECT_DIRECTORY='.' OIDC_ENV=gcp OIDC=oidc ./etc/run-oidc-test.sh ./test"
3232
bash ${DRIVERS_TOOLS}/.evergreen/auth_oidc/gcp/run-driver-test.sh
3333

34+
elif [ $OIDC_ENV == "k8s" ]; then
35+
export K8S_VARIANT=${VARIANT}
36+
export K8S_DRIVERS_TAR_FILE=$DRIVERS_TAR_FILE
37+
export K8S_TEST_CMD="PROJECT_DIRECTORY='.' OIDC_ENV=k8s OIDC=oidc ./etc/run-oidc-test.sh ./test"
38+
bash ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/setup-pod.sh
39+
bash ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/run-driver-test.sh
40+
bash ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/teardown-pod.sh
41+
3442
else
3543
echo "Unrecognized OIDC_ENV $OIDC_ENV"
3644
exit 1

etc/run-oidc-test.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ elif [ $OIDC_ENV == "azure" ]; then
2121
elif [ $OIDC_ENV == "gcp" ]; then
2222
source ./secrets-export.sh
2323

24+
elif [ $OIDC_ENV == "k8s" ]; then
25+
# "run-driver-test.sh" in drivers-evergreen-tools takes care of sourcing
26+
# "secrets-export.sh". Nothing to do in this block, but we still need a
27+
# command to be syntactically valid, so use no-op command ":".
28+
:
29+
2430
else
2531
echo "Unrecognized OIDC_ENV $OIDC_ENV"
2632
exit 1

internal/cmd/testoidcauth/main.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"os"
1414
"path"
1515
"reflect"
16+
"strings"
1617
"sync"
1718
"time"
1819
"unsafe"
@@ -101,7 +102,7 @@ func main() {
101102

102103
hasError := false
103104
aux := func(test_name string, f func() error) {
104-
fmt.Printf("%s...", test_name)
105+
fmt.Printf("%s...\n", test_name)
105106
err := f()
106107
if err != nil {
107108
fmt.Println("Test Error: ", err)
@@ -148,6 +149,8 @@ func main() {
148149
aux("machine_5_2_azureWithNoUsername", machine52azureWithBadUsername)
149150
case "gcp":
150151
aux("machine_6_1_gcpWithNoUsername", machine61gcpWithNoUsername)
152+
case "k8s":
153+
aux("machine_k8s", machinek8s)
151154
default:
152155
log.Fatal("Unknown OIDC_ENV: ", env)
153156
}
@@ -282,7 +285,7 @@ func machine21validCallbackInputs() error {
282285
tokenFile := tokenFile("test_user1")
283286
accessToken, err := os.ReadFile(tokenFile)
284287
if err != nil {
285-
fmt.Printf("machine_2_1: failed reading token file: %v", err)
288+
return nil, fmt.Errorf("machine_2_1: failed reading token file: %w", err)
286289
}
287290
return &options.OIDCCredential{
288291
AccessToken: string(accessToken),
@@ -1817,3 +1820,27 @@ func machine61gcpWithNoUsername() error {
18171820
}
18181821
return nil
18191822
}
1823+
1824+
// machinek8s tests the "k8s" Kubernetes OIDC environment. There is no specified
1825+
// prose test for "k8s", so this test simply checks that you can run a "find"
1826+
// with the provided conn string.
1827+
func machinek8s() error {
1828+
if !strings.Contains(uriSingle, "ENVIRONMENT:k8s") {
1829+
return fmt.Errorf("expected MONGODB_URI_SINGLE to specify ENVIRONMENT:k8s for Kubernetes test")
1830+
}
1831+
1832+
opts := options.Client().ApplyURI(uriSingle)
1833+
client, err := mongo.Connect(opts)
1834+
if err != nil {
1835+
return fmt.Errorf("machine_k8s: failed connecting client: %v", err)
1836+
}
1837+
defer func() { _ = client.Disconnect(context.Background()) }()
1838+
1839+
coll := client.Database("test").Collection("test")
1840+
1841+
_, err = coll.Find(context.Background(), bson.D{})
1842+
if err != nil {
1843+
return fmt.Errorf("machine_k8s: failed executing Find: %v", err)
1844+
}
1845+
return nil
1846+
}

mongo/options/clientoptions.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -596,24 +596,45 @@ func (c *ClientOptions) Validate() error {
596596
return fmt.Errorf("cannot set both OIDCMachineCallback and OIDCHumanCallback, only one may be specified")
597597
}
598598
if c.Auth.OIDCHumanCallback == nil && c.Auth.AuthMechanismProperties[auth.AllowedHostsProp] != "" {
599-
return fmt.Errorf("Cannot specify ALLOWED_HOSTS without an OIDCHumanCallback")
599+
return fmt.Errorf("cannot specify ALLOWED_HOSTS without an OIDCHumanCallback")
600600
}
601+
if c.Auth.OIDCMachineCallback == nil && c.Auth.OIDCHumanCallback == nil && c.Auth.AuthMechanismProperties[auth.EnvironmentProp] == "" {
602+
return errors.New("must specify at least one of OIDCMachineCallback, OIDCHumanCallback, or ENVIRONMENT authMechanismProperty")
603+
}
604+
605+
// Return an error if an unsupported authMechanismProperty is specified
606+
// for MONGODB-OIDC.
607+
for prop := range c.Auth.AuthMechanismProperties {
608+
switch prop {
609+
case auth.AllowedHostsProp, auth.EnvironmentProp, auth.ResourceProp:
610+
default:
611+
return fmt.Errorf("auth mechanism property %q is not valid for MONGODB-OIDC", prop)
612+
}
613+
}
614+
601615
if env, ok := c.Auth.AuthMechanismProperties[auth.EnvironmentProp]; ok {
602616
switch env {
603617
case auth.GCPEnvironmentValue, auth.AzureEnvironmentValue:
618+
if c.Auth.AuthMechanismProperties[auth.ResourceProp] == "" {
619+
return fmt.Errorf("%q must be set for the %s %q", auth.ResourceProp, env, auth.EnvironmentProp)
620+
}
621+
fallthrough
622+
case auth.K8SEnvironmentValue:
604623
if c.Auth.OIDCMachineCallback != nil {
605624
return fmt.Errorf("OIDCMachineCallback cannot be specified with the %s %q", env, auth.EnvironmentProp)
606625
}
607626
if c.Auth.OIDCHumanCallback != nil {
608627
return fmt.Errorf("OIDCHumanCallback cannot be specified with the %s %q", env, auth.EnvironmentProp)
609628
}
610-
if c.Auth.AuthMechanismProperties[auth.ResourceProp] == "" {
611-
return fmt.Errorf("%q must be set for the %s %q", auth.ResourceProp, env, auth.EnvironmentProp)
612-
}
613-
default:
629+
case auth.TestEnvironmentValue:
614630
if c.Auth.AuthMechanismProperties[auth.ResourceProp] != "" {
615631
return fmt.Errorf("%q must not be set for the %s %q", auth.ResourceProp, env, auth.EnvironmentProp)
616632
}
633+
if c.Auth.Username != "" {
634+
return fmt.Errorf("must not specify username for %s %q", env, auth.EnvironmentProp)
635+
}
636+
default:
637+
return fmt.Errorf("the %s %q is not supported for MONGODB-OIDC", env, auth.EnvironmentProp)
617638
}
618639
}
619640
}

0 commit comments

Comments
 (0)