-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat: Adds Client-Side Credential Access Boundary Factory example. #9994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
minherz
merged 9 commits into
GoogleCloudPlatform:main
from
nbayati:client-side-cab-example
Feb 11, 2025
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
368b58c
feat: Adds Client-Side Credential Access Boundary Factory example.
nbayati d574740
Update readme and pom. Add integration test for the client side cab.
nbayati 3599a4a
chore: update the library name.
nbayati 6dd229a
Split the example into two files.
nbayati 9760f5a
Rename the classes.
nbayati b3ca58f
Add versions to the java auth library dependencies.
nbayati fd9fb02
Disabling the test temporarily while ldetmer is working on it.
nbayati f1d2252
Ignoring the failing test (issue #10023)
nbayati 3cde41a
Add a TODO comment with the issue number
nbayati File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
.../java/com/google/cloud/auth/samples/ClientSideCredentialAccessBoundaryFactoryExample.java
This file contains hidden or 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,159 @@ | ||
| /* | ||
| * Copyright 2025 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 | ||
| * | ||
| * http://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 com.google.cloud.auth.samples; | ||
|
|
||
| import com.google.auth.credentialaccessboundary; | ||
| import com.google.auth.oauth2.AccessToken; | ||
| import com.google.auth.oauth2.CredentialAccessBoundary; | ||
| import com.google.auth.oauth2.GoogleCredentials; | ||
| import com.google.auth.oauth2.OAuth2CredentialsWithRefresh; | ||
| import com.google.cloud.storage.Blob; | ||
| import com.google.cloud.storage.Storage; | ||
| import com.google.cloud.storage.StorageOptions; | ||
| import java.io.IOException; | ||
|
|
||
| /** Demonstrates how to use ClientSideCredentialAccessBoundaryFactory to generate downscoped tokens. */ | ||
| public class ClientSideCredentialAccessBoundaryFactoryExample { | ||
|
|
||
| /** | ||
| * Tests the ClientSideCredentialAccessBoundaryFactory functionality. | ||
| * | ||
| * <p>This will generate a downscoped token with readonly access to the specified GCS bucket, | ||
| * inject them into a storage instance and then test print the contents of the specified object. | ||
| */ | ||
| public static void main(String[] args) throws IOException { | ||
| // TODO(developer): Replace these variables before running the sample. | ||
| // The Cloud Storage bucket name. | ||
| String bucketName = "your-gcs-bucket-name"; | ||
| // The Cloud Storage object name that resides in the specified bucket. | ||
| String objectName = "your-gcs-object-name"; | ||
|
|
||
| tokenConsumer(bucketName, objectName); | ||
| } | ||
|
|
||
| /** Simulates token broker generating downscoped tokens for specified bucket. */ | ||
| // [START auth_client_cab_token_broker] | ||
nbayati marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| public static AccessToken getTokenFromBroker(String bucketName, String objectPrefix) | ||
| throws IOException { | ||
| // Retrieve the source credentials from ADC. | ||
| GoogleCredentials sourceCredentials = | ||
| GoogleCredentials.getApplicationDefault() | ||
| .createScoped("https://www.googleapis.com/auth/cloud-platform"); | ||
|
|
||
| // [START auth_client_cab_rules] | ||
| // Initialize the Credential Access Boundary rules. | ||
| String availableResource = "//storage.googleapis.com/projects/_/buckets/" + bucketName; | ||
|
|
||
| // Downscoped credentials will have readonly access to the resource. | ||
| String availablePermission = "inRole:roles/storage.objectViewer"; | ||
|
|
||
| // Only objects starting with the specified prefix string in the object name will be allowed | ||
| // read access. | ||
| String expression = | ||
| "resource.name.startsWith('projects/_/buckets/" | ||
| + bucketName | ||
| + "/objects/" | ||
| + objectPrefix | ||
| + "')"; | ||
|
|
||
| // Build the AvailabilityCondition. | ||
| CredentialAccessBoundary.AccessBoundaryRule.AvailabilityCondition availabilityCondition = | ||
| CredentialAccessBoundary.AccessBoundaryRule.AvailabilityCondition.newBuilder() | ||
| .setExpression(expression) | ||
| .build(); | ||
|
|
||
| // Define the single access boundary rule using the above properties. | ||
| CredentialAccessBoundary.AccessBoundaryRule rule = | ||
| CredentialAccessBoundary.AccessBoundaryRule.newBuilder() | ||
| .setAvailableResource(availableResource) | ||
| .addAvailablePermission(availablePermission) | ||
| .setAvailabilityCondition(availabilityCondition) | ||
| .build(); | ||
|
|
||
| // Define the Credential Access Boundary with all the relevant rules. | ||
| CredentialAccessBoundary credentialAccessBoundary = | ||
| CredentialAccessBoundary.newBuilder().addRule(rule).build(); | ||
| // [END auth_client_cab_rules] | ||
|
|
||
| // [START auth_client_cab_initialize_factory] | ||
| // Create an instance of ClientSideCredentialAccessBoundaryFactory. | ||
| ClientSideCredentialAccessBoundaryFactory factory = | ||
| ClientSideCredentialAccessBoundaryFactory.newBuilder() | ||
| .setSourceCredential(sourceCredentials) | ||
| .build(); | ||
| // [END auth_client_cab_initialize_factory] | ||
|
|
||
| // [START auth_client_cab_generate_downscoped_token] | ||
| // Generate the token. | ||
| // This will need to be passed to the Token Consumer. | ||
| AccessToken accessToken = factory.generateToken(credentialAccessBoundary); | ||
| // [END auth_client_cab_generate_downscoped_token] | ||
| return accessToken; | ||
| } | ||
| // [END auth_client_cab_token_broker] | ||
|
|
||
| /** Simulates token consumer readonly access to the specified object. */ | ||
| // [START auth_client_cab_token_consumer] | ||
| public static void tokenConsumer(final String bucketName, final String objectName) | ||
| throws IOException { | ||
| // You can pass an `OAuth2RefreshHandler` to `OAuth2CredentialsWithRefresh` which will allow the | ||
| // library to seamlessly handle downscoped token refreshes on expiration. | ||
| OAuth2CredentialsWithRefresh.OAuth2RefreshHandler handler = | ||
| new OAuth2CredentialsWithRefresh.OAuth2RefreshHandler() { | ||
| @Override | ||
| public AccessToken refreshAccessToken() throws IOException { | ||
| // The common pattern of usage is to have a token broker pass the downscoped short-lived | ||
| // access tokens to a token consumer via some secure authenticated channel. | ||
| // For illustration purposes, we are generating the downscoped token locally. | ||
| // We want to test the ability to limit access to objects with a certain prefix string | ||
| // in the resource bucket. objectName.substring(0, 3) is the prefix here. This field is | ||
| // not required if access to all bucket resources are allowed. If access to limited | ||
| // resources in the bucket is needed, this mechanism can be used. | ||
| return getTokenFromBroker(bucketName, objectName.substring(0, 3)); | ||
| } | ||
| }; | ||
|
|
||
| // Downscoped token retrieved from token broker. | ||
| AccessToken downscopedToken = handler.refreshAccessToken(); | ||
|
|
||
| // Create the OAuth2CredentialsWithRefresh from the downscoped token and pass a refresh handler | ||
| // which will handle token expiration. | ||
| // This will allow the consumer to seamlessly obtain new downscoped tokens on demand every time | ||
| // token expires. | ||
| OAuth2CredentialsWithRefresh credentials = | ||
| OAuth2CredentialsWithRefresh.newBuilder() | ||
| .setAccessToken(downscopedToken) | ||
| .setRefreshHandler(handler) | ||
| .build(); | ||
|
|
||
| // Use the credentials with the Cloud Storage SDK. | ||
| StorageOptions options = StorageOptions.newBuilder().setCredentials(credentials).build(); | ||
| Storage storage = options.getService(); | ||
|
|
||
| // Call Cloud Storage APIs. | ||
| Blob blob = storage.get(bucketName, objectName); | ||
| String content = new String(blob.getContent()); | ||
| System.out.println( | ||
| "Retrieved object, " | ||
| + objectName | ||
| + ", from bucket," | ||
| + bucketName | ||
| + ", with content: " | ||
| + content); | ||
| } | ||
| // [END auth_client_cab_token_consumer] | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.