forked from GoogleCloudPlatform/golang-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(auth): add auth samples (GoogleCloudPlatform#2706)
- Loading branch information
1 parent
8f94c6d
commit 18ab11c
Showing
8 changed files
with
485 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package snippets | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"os" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/GoogleCloudPlatform/golang-samples/internal/testutil" | ||
"golang.org/x/oauth2/google" | ||
"google.golang.org/api/idtoken" | ||
"google.golang.org/api/option" | ||
) | ||
|
||
func TestAuthSnippets(t *testing.T) { | ||
ctx := context.Background() | ||
tc := testutil.SystemTest(t) | ||
audience := "https://example.com" | ||
|
||
want := "Listed all storage buckets." | ||
|
||
buf := &bytes.Buffer{} | ||
|
||
if err := authenticateExplicitWithAdc(buf); err != nil { | ||
t.Fatalf("authenticateExplicitWithAdc got err: %v", err) | ||
} | ||
if got := buf.String(); !strings.Contains(got, want) { | ||
t.Errorf("authenticateExplicitWithAdc got %q, want %q", got, want) | ||
} | ||
|
||
buf.Reset() | ||
|
||
if err := authenticateImplicitWithAdc(buf, tc.ProjectID); err != nil { | ||
t.Fatalf("authenticateImplicitWithAdc got err: %v", err) | ||
} | ||
if got := buf.String(); !strings.Contains(got, want) { | ||
t.Errorf("authenticateImplicitWithAdc got %q, want %q", got, want) | ||
} | ||
|
||
want = "Generated ID token." | ||
buf.Reset() | ||
|
||
if err := getIdTokenFromMetadataServer(buf, audience); err != nil { | ||
t.Fatalf("getIdTokenFromMetadataServer got err: %v", err) | ||
} | ||
if got := buf.String(); !strings.Contains(got, want) { | ||
t.Errorf("getIdTokenFromMetadataServer got %q, want %q", got, want) | ||
} | ||
|
||
buf.Reset() | ||
|
||
if err := getIdTokenFromServiceAccount(buf, os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"), audience); err != nil { | ||
t.Fatalf("getIdTokenFromServiceAccount got err: %v", err) | ||
} | ||
if got := buf.String(); !strings.Contains(got, want) { | ||
t.Errorf("getIdTokenFromServiceAccount got %q, want %q", got, want) | ||
} | ||
|
||
buf.Reset() | ||
want = "ID token verified." | ||
|
||
credentials, err := google.FindDefaultCredentials(ctx) | ||
if err != nil { | ||
t.Fatalf("failed to generate default credentials: %v", err) | ||
} | ||
|
||
ts, err := idtoken.NewTokenSource(ctx, audience, option.WithCredentials(credentials)) | ||
if err != nil { | ||
t.Fatalf("failed to create NewTokenSource: %v", err) | ||
} | ||
|
||
token, err := ts.Token() | ||
if err != nil { | ||
t.Fatalf("failed to get ID token: %v", err) | ||
} | ||
|
||
if err := verifyGoogleIdToken(buf, token.AccessToken, audience); err != nil { | ||
t.Fatalf("verifyGoogleIdToken got err: %v", err) | ||
} | ||
if got := buf.String(); !strings.Contains(got, want) { | ||
t.Errorf("verifyGoogleIdToken got %q, want %q", got, want) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package snippets | ||
|
||
// [START auth_cloud_explicit_adc] | ||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
|
||
"cloud.google.com/go/storage" | ||
"golang.org/x/oauth2/google" | ||
"google.golang.org/api/iterator" | ||
"google.golang.org/api/option" | ||
) | ||
|
||
// authenticateExplicitWithAdc uses Application Default Credentials | ||
// to print storage buckets. | ||
func authenticateExplicitWithAdc(w io.Writer) error { | ||
ctx := context.Background() | ||
|
||
// Construct the Google credentials object which obtains the default configuration from your | ||
// working environment. | ||
// google.FindDefaultCredentials() will give you ComputeEngineCredentials | ||
// if you are on a GCE (or other metadata server supported environments). | ||
credentials, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform") | ||
if err != nil { | ||
return fmt.Errorf("failed to generate default credentials: %v", err) | ||
} | ||
// If you are authenticating to a Cloud API, you can let the library include the default scope, | ||
// https://www.googleapis.com/auth/cloud-platform, because IAM is used to provide fine-grained | ||
// permissions for Cloud. | ||
// For more information on scopes to use, | ||
// see: https://developers.google.com/identity/protocols/oauth2/scopes | ||
|
||
// Construct the Storage client. | ||
client, err := storage.NewClient(ctx, option.WithCredentials(credentials)) | ||
if err != nil { | ||
return fmt.Errorf("NewClient: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
it := client.Buckets(ctx, credentials.ProjectID) | ||
for { | ||
bucketAttrs, err := it.Next() | ||
if err == iterator.Done { | ||
break | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(w, "Bucket: %v\n", bucketAttrs.Name) | ||
} | ||
|
||
fmt.Fprintf(w, "Listed all storage buckets.\n") | ||
|
||
return nil | ||
} | ||
|
||
// [END auth_cloud_explicit_adc] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package snippets | ||
|
||
// [START auth_cloud_implicit_adc] | ||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
|
||
"cloud.google.com/go/storage" | ||
"google.golang.org/api/iterator" | ||
) | ||
|
||
// authenticateImplicitWithAdc uses Application Default Credentials | ||
// to automatically find credentials and authenticate. | ||
func authenticateImplicitWithAdc(w io.Writer, projectId string) error { | ||
// projectId := "your_project_id" | ||
|
||
ctx := context.Background() | ||
|
||
// NOTE: Replace the client created below with the client required for your application. | ||
// Note that the credentials are not specified when constructing the client. | ||
// The client library finds your credentials using ADC. | ||
client, err := storage.NewClient(ctx) | ||
if err != nil { | ||
return fmt.Errorf("NewClient: %v", err) | ||
} | ||
defer client.Close() | ||
|
||
it := client.Buckets(ctx, projectId) | ||
for { | ||
bucketAttrs, err := it.Next() | ||
if err == iterator.Done { | ||
break | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(w, "Bucket: %v\n", bucketAttrs.Name) | ||
} | ||
|
||
fmt.Fprintf(w, "Listed all storage buckets.\n") | ||
|
||
return nil | ||
} | ||
|
||
// [END auth_cloud_implicit_adc] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package snippets | ||
|
||
// [START auth_cloud_idtoken_impersonated_credentials] | ||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
|
||
"golang.org/x/oauth2/google" | ||
"google.golang.org/api/impersonate" | ||
"google.golang.org/api/option" | ||
) | ||
|
||
// getIdTokenFromImpersonatedCredentials uses a service account (SA1) to impersonate as | ||
// another service account (SA2) and obtain id token for the impersonated account. | ||
// To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission on SA2. | ||
func getIdTokenFromImpersonatedCredentials(w io.Writer, scope, targetAudience, impersonatedServiceAccount string) error { | ||
// scope := "https://www.googleapis.com/auth/cloud-platform" | ||
// targetAudience := "http://www.example.com" | ||
// impersonatedServiceAccount := "[email protected]" | ||
|
||
ctx := context.Background() | ||
|
||
// Construct the GoogleCredentials object which obtains the default configuration from your | ||
// working environment. | ||
credentials, err := google.FindDefaultCredentials(ctx, scope) | ||
if err != nil { | ||
return fmt.Errorf("failed to generate default credentials: %v", err) | ||
} | ||
|
||
ts, err := impersonate.IDTokenSource(ctx, impersonate.IDTokenConfig{ | ||
Audience: targetAudience, | ||
TargetPrincipal: impersonatedServiceAccount, | ||
IncludeEmail: true, | ||
// delegates: The chained list of delegates required to grant the final accessToken. | ||
// For more information, see: | ||
// https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions | ||
// Delegates is NOT USED here. | ||
Delegates: []string{}, | ||
}, option.WithCredentials(credentials)) | ||
if err != nil { | ||
return fmt.Errorf("IDTokenSource error: %v", err) | ||
} | ||
|
||
// Get the ID token. | ||
// Once you've obtained the ID token, you can use it to make an authenticated call | ||
// to the target audience. | ||
_, err = ts.Token() | ||
if err != nil { | ||
return fmt.Errorf("failed to receive token: %v", err) | ||
} | ||
fmt.Fprintf(w, "Generated ID token.\n") | ||
|
||
return nil | ||
} | ||
|
||
// [END auth_cloud_idtoken_impersonated_credentials] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package snippets | ||
|
||
// [START auth_cloud_idtoken_metadata_server] | ||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
|
||
"golang.org/x/oauth2/google" | ||
"google.golang.org/api/idtoken" | ||
"google.golang.org/api/option" | ||
) | ||
|
||
// getIdTokenFromMetadataServer uses the Google Cloud metadata server environment | ||
// to create an identity token and add it to the HTTP request as part of an Authorization header. | ||
func getIdTokenFromMetadataServer(w io.Writer, url string) error { | ||
// url := "http://www.example.com" | ||
|
||
ctx := context.Background() | ||
|
||
// Construct the GoogleCredentials object which obtains the default configuration from your | ||
// working environment. | ||
credentials, err := google.FindDefaultCredentials(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to generate default credentials: %v", err) | ||
} | ||
|
||
ts, err := idtoken.NewTokenSource(ctx, url, option.WithCredentials(credentials)) | ||
if err != nil { | ||
return fmt.Errorf("failed to create NewTokenSource: %v", err) | ||
} | ||
|
||
// Get the ID token. | ||
// Once you've obtained the ID token, you can use it to make an authenticated call | ||
// to the target audience. | ||
_, err = ts.Token() | ||
if err != nil { | ||
return fmt.Errorf("failed to receive token: %v", err) | ||
} | ||
fmt.Fprintf(w, "Generated ID token.\n") | ||
|
||
return nil | ||
} | ||
|
||
// [END auth_cloud_idtoken_metadata_server] |
Oops, something went wrong.