Skip to content
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

Generate signed URLs when using workload identity in Java #10464

Open
pedrosdf opened this issue Mar 4, 2024 · 3 comments
Open

Generate signed URLs when using workload identity in Java #10464

pedrosdf opened this issue Mar 4, 2024 · 3 comments
Labels
priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@pedrosdf
Copy link

pedrosdf commented Mar 4, 2024

Thanks for stopping by to let us know something could be better!

PLEASE READ: If you have a support contract with Google, please create an issue in the support console instead of filing on GitHub. This will ensure a timely response.

Is your feature request related to a problem? Please describe.
[Storage] We are opening this Feature Request as we want to be able to easily generate signed URLs when using workload identity. We understand that this is a known missing feature and it is being worked on through other GitHub feature requests for .net [1] and ruby [2], but we want this functionality to also be available for java.

Describe the solution you'd like
We found a recent Google Cloud Collective response in a Stack Overflow issue [3] explaining the following: “External account credentials (Workload ID) are not supported as URL signers and you need to use the IAM service to sign the blob yourself. External account credentials are not currently supported for URL signing because it's not always possible to know client side which service account the credential maps back to, and that's a requirement (we would be calling the IAM service internally for this).”
We know this is already being worked on and there are some workarounds for .net [1] and ruby [2], therefore, we want to have a resolution/workaround on the Java side as well.

Describe alternatives you've considered
Tried using this example [4] by adapting it to Java, but started receiving the following exception:

Exception in thread "main" java.lang.IllegalStateException: Signing key was not provided and could not be derived
    at com.google.common.base.Preconditions.checkState(Preconditions.java:512)
    at com.google.cloud.storage.StorageImpl.signUrl(StorageImpl.java:709)
    at com.ayla.cloud.gcs.controller.GCSController.getDownloadURL(GCSController.java:70)
    at com.ayla.cloud.gcs.controller.GCSController.greeting(GCSController.java:42)
    at com.ayla.cloud.gcs.controller.GCSController.main(GCSController.java:49)

This is the code being used:

package com.ayla.cloud.gcs.controller;
import com.google.auth.oauth2.ComputeEngineCredentials;
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class GCSController {
    public String greeting() {
        String bucketName = "";
        String path = "example2/example-1001";
        long ttl = 60;
        String gcsSignatureVersion = "V4";
        ComputeEngineCredentials caCreds = ComputeEngineCredentials.create();
        String targetAudience = "https://example.com";
        IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder() .setIdTokenProvider(caCreds)
            .setTargetAudience(targetAudience)
            .setOptions(Arrays.asList(ComputeEngineCredentials.Option.FORMAT_FULL)) .build();
        URL url = getDownloadURL(bucketName, path, ttl, gcsSignatureVersion, tokenCredential);
        return url.toString();
    }
    
    public static void main(String[] args) throws IOException {
        System.out.println(new GCSController().greeting());
    }
    
    public URL getDownloadURL(String bucketName, String path, long ttl, final String gcsSignatureVersion, IdTokenCredentials tokenCredential) {
        BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, path)).build();
        Storage.SignUrlOption signUrlOption = null;

        switch (gcsSignatureVersion) {
            case "V2":
                signUrlOption = Storage.SignUrlOption.withV2Signature();
                break;
            case "V4":
            default:
                signUrlOption = Storage.SignUrlOption.withV4Signature();
        }
        if (null == signUrlOption) {
            return null;
        }
        Storage storage = StorageOptions.newBuilder().setCredentials(tokenCredential).build().getService();
        return storage.signUrl(blobInfo, ttl, TimeUnit.MINUTES, signUrlOption);
    }
}

Additional context
[1] googleapis/google-api-dotnet-client#2410
[2] googleapis/google-cloud-ruby#13307
[3] https://stackoverflow.com/a/76266912
[4] https://gist.github.com/jezhumble/91051485db4462add82045ef9ac2a0ec

@zhumin8 zhumin8 added priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. labels Mar 12, 2024
@zhumin8
Copy link
Contributor

zhumin8 commented Mar 15, 2024

Feature request to java-storage.
@BenWhitehead Do you mind taking a look?

@BenWhitehead
Copy link
Contributor

The code in google-cloud-storage to sign urls depends upon the value provided in com.google.cloud.storage.Storage.SignUrlOption#signWith, if that is not provided then it will attempt to fallback and use the instance of credentials provided at client creation time. The library specifically invokes com.google.auth.ServiceAccountSigner#sign(byte[]) here.

In this case it sounds like the type of credentials provided doesn't know how to sign.

I think this is actually an issue that would need to be addressed in google-auth-library, rather than the storage library code itself.

@TimurSadykov Do you know if there is anything already on the roadmap to implement the sign method for credentials that work with workload identity?

@TimurSadykov
Copy link
Member

ack, I'll chat with the team that owns WIF

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

No branches or pull requests

4 participants