From 3a21e1898c67e6d37a6c79593f494e66e21e1d67 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Thu, 15 Aug 2024 19:20:26 -0400 Subject: [PATCH 01/11] GODRIVER-2758: Add documentation examples --- mongo/client_examples_test.go | 199 ++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 4123e8e0e4..8be968710a 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -10,6 +10,7 @@ import ( "context" "fmt" "log" + "os" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" @@ -468,3 +469,201 @@ func ExampleConnect_bSONOptions() { panic(err) } } + +func ExampleConnect_oIDC() { + // The `MONGODB-OIDC authentication mechanism`_ is available in MongoDB 7.0+ on Linux platforms. + // + // The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. + // The driver supports OIDC for workload identity, defined as an identity you assign to a software workload + // (such as an application, service, script, or container) to authenticate and access other services and resources. + // + // The driver also supports OIDC for workforce identity for a more secure flow with a human in + // the loop. + + // Credentials can be configured through the MongoDB URI or as arguments in the + // options.ClientOptions struct that is passed into the mongo.Connect function. + + // Built-in Support + // The driver has built-in support for Azure IMDS and GCP IMDS environments. Other environments + // are supported with `Custom Callbacks`_. + + // Azure IMDS + // For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`_, + // you can use the built-in support for Azure, where "" below is the client id of the Azure + // managed identity, and ```` is the url-encoded ``audience`` `configured on your MongoDB deployment`_. + { + uri := os.Getenv("MONGODB_URI") + props := map[string]string{"ENVIRONMENT": "azure", "TOKEN_RESOURCE": ""} + opts := options.Client().ApplyURI(uri) + opts.SetAuth( + options.Credential{ + Username: "", + AuthMechanism: "MONGODB-OIDC", + AuthMechanismProperties: props, + }, + ) + c, err := mongo.Connect(context.TODO(), opts) + if err != nil { + panic(err) + } + defer c.Disconnect(context.TODO()) + c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + } + + // If the application is running on an Azure VM and only one managed identity is associated with the + // VM, "username" can be omitted. + + // GCP IMDS + + // For an application running on an GCP VM or otherwise using the `GCP Internal Metadata Service`_, + // you can use the built-in support for GCP, where "" below is the url-encoded "audience" + // `configured on your MongoDB deployment`_. + { + uri := os.Getenv("MONGODB_URI") + props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + opts := options.Client().ApplyURI(uri) + opts.SetAuth( + options.Credential{ + AuthMechanism: "MONGODB-OIDC", + AuthMechanismProperties: props, + }, + ) + c, err := mongo.Connect(context.TODO(), opts) + if err != nil { + panic(err) + } + defer c.Disconnect(context.TODO()) + c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + } + + // Custom Callbacks + + // For environments that are not directly supported by the driver, you can use + // options.OIDCCallback. + // Some examples are given below. + + // AWS EKS + + // For an EKS Cluster with a configured `IAM OIDC provider`_, the token can be read from a path given by + // the "AWS_WEB_IDENTITY_TOKEN_FILE" environment variable. + { + eksCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { + accessToken, err := os.ReadFile(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) + if err != nil { + return nil, err + } + return &options.OIDCCredential{ + AccessToken: string(accessToken), + }, nil + } + uri := os.Getenv("MONGODB_URI") + props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + opts := options.Client().ApplyURI(uri) + opts.SetAuth( + options.Credential{ + AuthMechanism: "MONGODB-OIDC", + AuthMechanismProperties: props, + OIDCMachineCallback: eksCallback, + }, + ) + c, err := mongo.Connect(context.TODO(), opts) + if err != nil { + panic(err) + } + defer c.Disconnect(context.TODO()) + c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + } + + // Other Azure Environments + + // For applications running on Azure Functions, App Service Environment (ASE), or + // Azure Kubernetes Service (AKS), you can use the `azidentity package` + // (https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) + // to fetch the credentials. In each case, the OIDCCallback function should return + // the AccessToken from the azidentity package. + + // GCP GKE + + // For a Google Kubernetes Engine cluster with a `configured service account`_, the token can be read from the standard + // service account token file location. + { + gkeCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { + accessToken, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") + if err != nil { + return nil, err + } + return &options.OIDCCredential{ + AccessToken: string(accessToken), + }, nil + } + uri := os.Getenv("MONGODB_URI") + props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + opts := options.Client().ApplyURI(uri) + opts.SetAuth( + options.Credential{ + AuthMechanism: "MONGODB-OIDC", + AuthMechanismProperties: props, + OIDCMachineCallback: gkeCallback, + }, + ) + c, err := mongo.Connect(context.TODO(), opts) + if err != nil { + panic(err) + } + defer c.Disconnect(context.TODO()) + c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + } + + // For workforce identity, the Client must be configured with the OIDCHumanCallback rather than + // the OIDCMachineCallback. The OIDCHumanCallback is used by the driver in a process that is + // two step. In the first step, the driver retrieves the Identity Prodiver (IDP) Information (IDPInfo) for the + // passed username. The OIDCHumanCallback then needs negotiate with the IDP in order to obtain + // an AccessToken, possible RefreshToken, any timeouts, and return them, similar to the OIDCMachineCallbacks seen above. + // See https://docs.hidglobal.com/dev/auth-service/integration/openid-authentication-flows.html + // for more information on various OIDC authentication flows. + { + humanCallback := func(ctx context.Context, opts *options.OIDCArgs) (*options.OIDCCredential, error) { + // idpInfo passed from the driver by asking the MongoDB server for the info configured + // for the username + idpInfo := opts.IDPInfo + // negotiateWithIDP must work with the IdP to obtain an access token. In many cases this + // will involve opening a webbrowser or providing a URL on the command line to a + // human-in-the-loop who can give persmissions to the IdP. + accessToken, err := negotiateWithIDP(ctx, idpInfo.Issuer) + if err != nil { + return nil, err + } + return &options.OIDCCredential{ + AccessToken: string(accessToken), + }, nil + } + uri := os.Getenv("MONGODB_URI") + props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + opts := options.Client().ApplyURI(uri) + opts.SetAuth( + options.Credential{ + AuthMechanism: "MONGODB-OIDC", + AuthMechanismProperties: props, + OIDCHumanCallback: humanCallback, + }, + ) + c, err := mongo.Connect(context.TODO(), opts) + if err != nil { + panic(err) + } + defer c.Disconnect(context.TODO()) + c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + } + + // * MONGODB-OIDC authentication mechanism: https://www.mongodb.com/docs/manual/core/security-oidc/ + // * OIDC Identity Provider Configuration: https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.oidcIdentityProviders + // * Azure Internal Metadata Service: https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service + // * GCP Internal Metadata Service: https://cloud.google.com/compute/docs/metadata/querying-metadata + // * IAM OIDC provider: https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html + // * azure-identity package: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity + // * configured service account: https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts +} + +func negotiateWithIDP(_ context.Context, _ string) (string, error) { + return "", nil +} From 08fdf01a9131810856b18cb6b835d3d071cfb6bc Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Thu, 15 Aug 2024 19:26:30 -0400 Subject: [PATCH 02/11] GODRIVER-2758: Remove non-functional markdown --- mongo/client_examples_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 8be968710a..53d3ec8ec6 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -471,7 +471,7 @@ func ExampleConnect_bSONOptions() { } func ExampleConnect_oIDC() { - // The `MONGODB-OIDC authentication mechanism`_ is available in MongoDB 7.0+ on Linux platforms. + // The `MONGODB-OIDC authentication mechanism` is available in MongoDB 7.0+ on Linux platforms. // // The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. // The driver supports OIDC for workload identity, defined as an identity you assign to a software workload @@ -485,12 +485,12 @@ func ExampleConnect_oIDC() { // Built-in Support // The driver has built-in support for Azure IMDS and GCP IMDS environments. Other environments - // are supported with `Custom Callbacks`_. + // are supported with `Custom Callbacks`. // Azure IMDS - // For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`_, + // For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`, // you can use the built-in support for Azure, where "" below is the client id of the Azure - // managed identity, and ```` is the url-encoded ``audience`` `configured on your MongoDB deployment`_. + // managed identity, and ```` is the url-encoded ``audience`` `configured on your MongoDB deployment`. { uri := os.Getenv("MONGODB_URI") props := map[string]string{"ENVIRONMENT": "azure", "TOKEN_RESOURCE": ""} @@ -517,7 +517,7 @@ func ExampleConnect_oIDC() { // For an application running on an GCP VM or otherwise using the `GCP Internal Metadata Service`_, // you can use the built-in support for GCP, where "" below is the url-encoded "audience" - // `configured on your MongoDB deployment`_. + // `configured on your MongoDB deployment`. { uri := os.Getenv("MONGODB_URI") props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} @@ -544,7 +544,7 @@ func ExampleConnect_oIDC() { // AWS EKS - // For an EKS Cluster with a configured `IAM OIDC provider`_, the token can be read from a path given by + // For an EKS Cluster with a configured `IAM OIDC provider`, the token can be read from a path given by // the "AWS_WEB_IDENTITY_TOKEN_FILE" environment variable. { eksCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { @@ -584,7 +584,7 @@ func ExampleConnect_oIDC() { // GCP GKE - // For a Google Kubernetes Engine cluster with a `configured service account`_, the token can be read from the standard + // For a Google Kubernetes Engine cluster with a `configured service account`, the token can be read from the standard // service account token file location. { gkeCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { From 3f7bb3e19d7151599b1ce9eb89c5d868014fae74 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Thu, 15 Aug 2024 19:30:07 -0400 Subject: [PATCH 03/11] GODRIVER-2758: Update comment --- mongo/client_examples_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 53d3ec8ec6..2cd5efaf4f 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -617,7 +617,7 @@ func ExampleConnect_oIDC() { // For workforce identity, the Client must be configured with the OIDCHumanCallback rather than // the OIDCMachineCallback. The OIDCHumanCallback is used by the driver in a process that is // two step. In the first step, the driver retrieves the Identity Prodiver (IDP) Information (IDPInfo) for the - // passed username. The OIDCHumanCallback then needs negotiate with the IDP in order to obtain + // passed username. The OIDCHumanCallback then needs to negotiate with the IDP in order to obtain // an AccessToken, possible RefreshToken, any timeouts, and return them, similar to the OIDCMachineCallbacks seen above. // See https://docs.hidglobal.com/dev/auth-service/integration/openid-authentication-flows.html // for more information on various OIDC authentication flows. From 1d5cd911bc436b0b70a776534ec6911f1f528cf0 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Thu, 15 Aug 2024 19:54:15 -0400 Subject: [PATCH 04/11] GODRIVER-2758: Update comment --- mongo/client_examples_test.go | 182 ++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 66 deletions(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 2cd5efaf4f..ea23dce308 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -471,29 +471,39 @@ func ExampleConnect_bSONOptions() { } func ExampleConnect_oIDC() { - // The `MONGODB-OIDC authentication mechanism` is available in MongoDB 7.0+ on Linux platforms. + // The `MONGODB-OIDC authentication mechanism` is available in MongoDB 7.0+ + // on Linux platforms. // - // The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. - // The driver supports OIDC for workload identity, defined as an identity you assign to a software workload - // (such as an application, service, script, or container) to authenticate and access other services and resources. + // The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) + // access token. The driver supports OIDC for workload identity, defined as + // an identity you assign to a software workload (such as an application, + // service, script, or container) to authenticate and access other services + // and resources. // - // The driver also supports OIDC for workforce identity for a more secure flow with a human in - // the loop. + // The driver also supports OIDC for workforce identity for a more secure + // flow with a human in the loop. - // Credentials can be configured through the MongoDB URI or as arguments in the - // options.ClientOptions struct that is passed into the mongo.Connect function. + // Credentials can be configured through the MongoDB URI or as arguments in + // the options.ClientOptions struct that is passed into the mongo.Connect + // function. // Built-in Support - // The driver has built-in support for Azure IMDS and GCP IMDS environments. Other environments - // are supported with `Custom Callbacks`. + // The driver has built-in support for Azure IMDS and GCP + // IMDS environments. Other environments are supported with `Custom + // Callbacks`. // Azure IMDS - // For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`, - // you can use the built-in support for Azure, where "" below is the client id of the Azure - // managed identity, and ```` is the url-encoded ``audience`` `configured on your MongoDB deployment`. + // For an application running on an Azure VM or otherwise using the `Azure + // Internal Metadata Service`, you can use the built-in support for Azure, + // where "" below is the client id of the Azure managed identity, + // and ```` is the url-encoded ``audience`` `configured on your + // MongoDB deployment`. { uri := os.Getenv("MONGODB_URI") - props := map[string]string{"ENVIRONMENT": "azure", "TOKEN_RESOURCE": ""} + props := map[string]string{ + "ENVIRONMENT": "azure", + "TOKEN_RESOURCE": "", + } opts := options.Client().ApplyURI(uri) opts.SetAuth( options.Credential{ @@ -507,20 +517,26 @@ func ExampleConnect_oIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + c.Database("test"). + Collection("test"). + InsertOne(context.TODO(), bson.D{}) } - // If the application is running on an Azure VM and only one managed identity is associated with the - // VM, "username" can be omitted. + // If the application is running on an Azure VM and only one managed + // identity is associated with the VM, "username" can be omitted. // GCP IMDS - // For an application running on an GCP VM or otherwise using the `GCP Internal Metadata Service`_, - // you can use the built-in support for GCP, where "" below is the url-encoded "audience" - // `configured on your MongoDB deployment`. + // For an application running on an GCP VM or otherwise using the `GCP + // Internal Metadata Service`_, you can use the built-in support for GCP, + // where "" below is the url-encoded "audience" `configured on + // your MongoDB deployment`. { uri := os.Getenv("MONGODB_URI") - props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + props := map[string]string{ + "ENVIRONMENT": "gcp", + "TOKEN_RESOURCE": "", + } opts := options.Client().ApplyURI(uri) opts.SetAuth( options.Credential{ @@ -533,21 +549,24 @@ func ExampleConnect_oIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + c.Database("test"). + Collection("test"). + InsertOne(context.TODO(), bson.D{}) } // Custom Callbacks - // For environments that are not directly supported by the driver, you can use - // options.OIDCCallback. - // Some examples are given below. + // For environments that are not directly supported by the driver, you can + // use options.OIDCCallback. Some examples are given below. // AWS EKS - // For an EKS Cluster with a configured `IAM OIDC provider`, the token can be read from a path given by - // the "AWS_WEB_IDENTITY_TOKEN_FILE" environment variable. + // For an EKS Cluster with a configured `IAM OIDC provider`, the token can + // be read from a path given by the "AWS_WEB_IDENTITY_TOKEN_FILE" + // environment variable. { - eksCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { + eksCallback := func(_ context.Context, + _ *options.OIDCArgs) (*options.OIDCCredential, error) { accessToken, err := os.ReadFile(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) if err != nil { return nil, err @@ -557,7 +576,10 @@ func ExampleConnect_oIDC() { }, nil } uri := os.Getenv("MONGODB_URI") - props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + props := map[string]string{ + "ENVIRONMENT": "gcp", + "TOKEN_RESOURCE": "", + } opts := options.Client().ApplyURI(uri) opts.SetAuth( options.Credential{ @@ -571,24 +593,30 @@ func ExampleConnect_oIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) + c.Database("test"). + Collection("test"). + InsertOne(context.TODO(), bson.D{}) } // Other Azure Environments - // For applications running on Azure Functions, App Service Environment (ASE), or - // Azure Kubernetes Service (AKS), you can use the `azidentity package` - // (https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) - // to fetch the credentials. In each case, the OIDCCallback function should return - // the AccessToken from the azidentity package. + // For applications running on Azure Functions, App Service Environment + // (ASE), or Azure Kubernetes Service (AKS), you can use the `azidentity + // package` + // (https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) to + // fetch the credentials. In each case, the OIDCCallback function should + // return the AccessToken from the azidentity package. // GCP GKE - // For a Google Kubernetes Engine cluster with a `configured service account`, the token can be read from the standard - // service account token file location. + // For a Google Kubernetes Engine cluster with a `configured service + // account`, the token can be read from the standard service account token + // file location. { - gkeCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { - accessToken, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") + gkeCallback := func(_ context.Context, + _ *options.OIDCArgs) (*options.OIDCCredential, error) { + accessToken, err := os.ReadFile( + "/var/run/secrets/kubernetes.io/serviceaccount/token") if err != nil { return nil, err } @@ -597,7 +625,10 @@ func ExampleConnect_oIDC() { }, nil } uri := os.Getenv("MONGODB_URI") - props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + props := map[string]string{ + "ENVIRONMENT": "gcp", + "TOKEN_RESOURCE": "", + } opts := options.Client().ApplyURI(uri) opts.SetAuth( options.Credential{ @@ -611,24 +642,31 @@ func ExampleConnect_oIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) - } - - // For workforce identity, the Client must be configured with the OIDCHumanCallback rather than - // the OIDCMachineCallback. The OIDCHumanCallback is used by the driver in a process that is - // two step. In the first step, the driver retrieves the Identity Prodiver (IDP) Information (IDPInfo) for the - // passed username. The OIDCHumanCallback then needs to negotiate with the IDP in order to obtain - // an AccessToken, possible RefreshToken, any timeouts, and return them, similar to the OIDCMachineCallbacks seen above. - // See https://docs.hidglobal.com/dev/auth-service/integration/openid-authentication-flows.html + c.Database("test"). + Collection("test"). + InsertOne(context.TODO(), bson.D{}) + } + + // For workforce identity, the Client must be configured with the + // OIDCHumanCallback rather than the OIDCMachineCallback. The + // OIDCHumanCallback is used by the driver in a process that is two step. In + // the first step, the driver retrieves the Identity Prodiver (IDP) + // Information (IDPInfo) for the passed username. The OIDCHumanCallback then + // needs to negotiate with the IDP in order to obtain an AccessToken, + // possible RefreshToken, any timeouts, and return them, similar to the + // OIDCMachineCallbacks seen above. See + // https://docs.hidglobal.com/dev/auth-service/integration/openid-authentication-flows.html // for more information on various OIDC authentication flows. { - humanCallback := func(ctx context.Context, opts *options.OIDCArgs) (*options.OIDCCredential, error) { - // idpInfo passed from the driver by asking the MongoDB server for the info configured - // for the username + humanCallback := func(ctx context.Context, + opts *options.OIDCArgs) (*options.OIDCCredential, error) { + // idpInfo passed from the driver by asking the MongoDB server for + // the info configured for the username idpInfo := opts.IDPInfo - // negotiateWithIDP must work with the IdP to obtain an access token. In many cases this - // will involve opening a webbrowser or providing a URL on the command line to a - // human-in-the-loop who can give persmissions to the IdP. + // negotiateWithIDP must work with the IdP to obtain an access + // token. In many cases this will involve opening a webbrowser or + // providing a URL on the command line to a human-in-the-loop who + // can give persmissions to the IdP. accessToken, err := negotiateWithIDP(ctx, idpInfo.Issuer) if err != nil { return nil, err @@ -638,7 +676,10 @@ func ExampleConnect_oIDC() { }, nil } uri := os.Getenv("MONGODB_URI") - props := map[string]string{"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + props := map[string]string{ + "ENVIRONMENT": "gcp", + "TOKEN_RESOURCE": "", + } opts := options.Client().ApplyURI(uri) opts.SetAuth( options.Credential{ @@ -652,16 +693,25 @@ func ExampleConnect_oIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test").Collection("test").InsertOne(context.TODO(), bson.D{}) - } - - // * MONGODB-OIDC authentication mechanism: https://www.mongodb.com/docs/manual/core/security-oidc/ - // * OIDC Identity Provider Configuration: https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.oidcIdentityProviders - // * Azure Internal Metadata Service: https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service - // * GCP Internal Metadata Service: https://cloud.google.com/compute/docs/metadata/querying-metadata - // * IAM OIDC provider: https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html - // * azure-identity package: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity - // * configured service account: https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts + c.Database("test"). + Collection("test"). + InsertOne(context.TODO(), bson.D{}) + } + + // * MONGODB-OIDC authentication mechanism: + // https://www.mongodb.com/docs/manual/core/security-oidc/ + // * OIDC Identity Provider Configuration: + // https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.oidcIdentityProviders + // * Azure Internal Metadata Service: + // https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service + // * GCP Internal Metadata Service: + // https://cloud.google.com/compute/docs/metadata/querying-metadata + // * IAM OIDC provider: + // https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html + // * azure-identity package: + // https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity + // * configured service account: + // https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts } func negotiateWithIDP(_ context.Context, _ string) (string, error) { From 45a9ce74300073cde78016c7061508bfbfebc292 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Thu, 15 Aug 2024 19:58:50 -0400 Subject: [PATCH 05/11] GODRIVER-2758: fmt --- mongo/client_examples_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index ea23dce308..8fea676437 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -567,7 +567,8 @@ func ExampleConnect_oIDC() { { eksCallback := func(_ context.Context, _ *options.OIDCArgs) (*options.OIDCCredential, error) { - accessToken, err := os.ReadFile(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) + accessToken, err := os.ReadFile( + os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) if err != nil { return nil, err } From a0f80a10da56b064c3c31464f47f4faee089de7d Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Fri, 16 Aug 2024 12:23:01 -0400 Subject: [PATCH 06/11] Update mongo/client_examples_test.go Co-authored-by: Steven Silvester --- mongo/client_examples_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 8fea676437..3b9bfbf8ad 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -470,7 +470,7 @@ func ExampleConnect_bSONOptions() { } } -func ExampleConnect_oIDC() { +func ExampleConnect_OIDC() { // The `MONGODB-OIDC authentication mechanism` is available in MongoDB 7.0+ // on Linux platforms. // From f7cb8f11d8afe5251f2afa02ee2c2479f66cfe02 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Mon, 19 Aug 2024 21:11:12 -0400 Subject: [PATCH 07/11] GODRIVER-2758: Spelling errors + update codespell args --- .pre-commit-config.yaml | 2 +- mongo/client_examples_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d28a2056d9..15010ce288 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: rev: "v2.2.6" hooks: - id: codespell - args: ["-L", "te,fo,fle,alo,nin,compres,wil,collone,asess,sav,ot,wll,dne,nulll,hellow"] + args: ["-L", "te,fo,fle,alo,nin,compres,wil,collone,asess,sav,ot,wll,dne,nulll,hellow,aks"] exclude: ^(vendor/|benchmark/operation_test.go) exclude_types: [json,yaml,pem] diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 3b9bfbf8ad..aa8d4576d9 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -651,7 +651,7 @@ func ExampleConnect_OIDC() { // For workforce identity, the Client must be configured with the // OIDCHumanCallback rather than the OIDCMachineCallback. The // OIDCHumanCallback is used by the driver in a process that is two step. In - // the first step, the driver retrieves the Identity Prodiver (IDP) + // the first step, the driver retrieves the Identity Provider (IDP) // Information (IDPInfo) for the passed username. The OIDCHumanCallback then // needs to negotiate with the IDP in order to obtain an AccessToken, // possible RefreshToken, any timeouts, and return them, similar to the @@ -667,7 +667,7 @@ func ExampleConnect_OIDC() { // negotiateWithIDP must work with the IdP to obtain an access // token. In many cases this will involve opening a webbrowser or // providing a URL on the command line to a human-in-the-loop who - // can give persmissions to the IdP. + // can give permissions to the IdP. accessToken, err := negotiateWithIDP(ctx, idpInfo.Issuer) if err != nil { return nil, err From a57ed9073b93294344328d873294a2da30a5d14d Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Tue, 20 Aug 2024 11:49:24 -0400 Subject: [PATCH 08/11] GODRIVER-2758: Static analysis --- mongo/client_examples_test.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index aa8d4576d9..c04357dc47 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -517,9 +517,12 @@ func ExampleConnect_OIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test"). + _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) + if err != nil { + panic(err) + } } // If the application is running on an Azure VM and only one managed @@ -549,9 +552,12 @@ func ExampleConnect_OIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test"). + _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) + if err != nil { + panic(err) + } } // Custom Callbacks @@ -594,9 +600,12 @@ func ExampleConnect_OIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test"). + _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) + if err != nil { + panic(err) + } } // Other Azure Environments @@ -694,9 +703,12 @@ func ExampleConnect_OIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test"). + _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) + if err != nil { + panic(err) + } } // * MONGODB-OIDC authentication mechanism: From d744d8f0aeb7e3eae202697dafaa65922d147839 Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Tue, 20 Aug 2024 12:17:02 -0400 Subject: [PATCH 09/11] GODRIVER-2758: Static analysis --- mongo/client_examples_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index c04357dc47..86c068f6af 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -652,9 +652,12 @@ func ExampleConnect_OIDC() { panic(err) } defer c.Disconnect(context.TODO()) - c.Database("test"). + _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) + if err != nil { + panic(err) + } } // For workforce identity, the Client must be configured with the @@ -682,7 +685,7 @@ func ExampleConnect_OIDC() { return nil, err } return &options.OIDCCredential{ - AccessToken: string(accessToken), + AccessToken: accessToken, }, nil } uri := os.Getenv("MONGODB_URI") From 16a7d33e5a5c09f71b525c53ad80fa0368cc3c3e Mon Sep 17 00:00:00 2001 From: Patrick Meredith Date: Tue, 20 Aug 2024 12:38:23 -0400 Subject: [PATCH 10/11] GODRIVER-2758: I don't know why this needs to be lowercase, but it does --- mongo/client_examples_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 86c068f6af..72faf91b90 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -470,7 +470,7 @@ func ExampleConnect_bSONOptions() { } } -func ExampleConnect_OIDC() { +func ExampleConnect_oIDC() { // The `MONGODB-OIDC authentication mechanism` is available in MongoDB 7.0+ // on Linux platforms. // From 066c0b06022a231859c183692af1e9fe2ccaeff7 Mon Sep 17 00:00:00 2001 From: Matt Dale <9760375+matthewdale@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:16:39 -0700 Subject: [PATCH 11/11] Fix linter errors. --- mongo/client_examples_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mongo/client_examples_test.go b/mongo/client_examples_test.go index 40e47604d3..df6f2f25f2 100644 --- a/mongo/client_examples_test.go +++ b/mongo/client_examples_test.go @@ -516,7 +516,7 @@ func ExampleConnect_oIDC() { if err != nil { panic(err) } - defer c.Disconnect(context.TODO()) + defer func() { _ = c.Disconnect(context.TODO()) }() _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) @@ -551,7 +551,7 @@ func ExampleConnect_oIDC() { if err != nil { panic(err) } - defer c.Disconnect(context.TODO()) + defer func() { _ = c.Disconnect(context.TODO()) }() _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) @@ -599,7 +599,7 @@ func ExampleConnect_oIDC() { if err != nil { panic(err) } - defer c.Disconnect(context.TODO()) + defer func() { _ = c.Disconnect(context.TODO()) }() _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) @@ -651,7 +651,7 @@ func ExampleConnect_oIDC() { if err != nil { panic(err) } - defer c.Disconnect(context.TODO()) + defer func() { _ = c.Disconnect(context.TODO()) }() _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{}) @@ -705,7 +705,7 @@ func ExampleConnect_oIDC() { if err != nil { panic(err) } - defer c.Disconnect(context.TODO()) + defer func() { _ = c.Disconnect(context.TODO()) }() _, err = c.Database("test"). Collection("test"). InsertOne(context.TODO(), bson.D{})