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

storage: sign URL with gcloud application default credentials #5979

Closed
wkalt opened this issue May 3, 2022 · 8 comments
Closed

storage: sign URL with gcloud application default credentials #5979

wkalt opened this issue May 3, 2022 · 8 comments
Assignees
Labels
api: storage Issues related to the Cloud Storage API. priority: p2 Moderately-important priority. Fix may not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@wkalt
Copy link

wkalt commented May 3, 2022

I would like to be able to create signed links using my application default credentials in a local development context, similar to how the library allows me to read and write to buckets without configuring separate authentication.

I believe some related work in #4604 may have addressed this for VMs running in GCE, but it does not seem to work when running locally under my gcloud login.

I would expect this code to work:

func main() {
	ctx := context.Background()
	bucket := "mybucket"
	filename := "myobject"
	method := "PUT"
	expires := time.Now().Add(time.Second * 60).Unix()
	client, err := storage.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	url, err := client.Bucket(bucket).SignedURL(filename, &storage.SignedURLOptions{
		Method:  method,
		Expires: time.Unix(expires, 0),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("URL:", url)
}

however it returns this error:

storage: unable to detect default GoogleAccessID: storage: empty client email in credentials

Is there any limitation that prevents this from working (or bug in my code)? I have owner on the project and write access to the bucket through the lib, so it seems like it should be possible for me to sign links.

My goal is to avoid developers working on this code needing to manage GOOGLE_APPLICATION_CREDENTIALS or a service account key, separate from their gcloud login.

@wkalt wkalt added the triage me I really want to be triaged. label May 3, 2022
@product-auto-label product-auto-label bot added the api: storage Issues related to the Cloud Storage API. label May 3, 2022
@ddelgrosso1 ddelgrosso1 added priority: p2 Moderately-important priority. Fix may not be included in next release. type: question Request for information or clarification. Not an issue. and removed triage me I really want to be triaged. labels May 3, 2022
@codyoss
Copy link
Member

codyoss commented May 3, 2022

IIRC in this case you need to set the GoogleAccessID field. This can only be detected if you are using an SA or compute for auth. Then you will be using an impersonation flow which requires some IAM permissions and proper iamcredentails API enabled. If those items are done I believe this should work, but I am going off of memory 😄

@tritone
Copy link
Contributor

tritone commented May 4, 2022

@wkalt just to confirm, are you able to make requests using the client itself using the auth you provided? (e.g. successfully call client.Bucket().Attrs())

@codyoss if this is accurate, then I think we should update the docs for the method accordingly at least.

@codyoss
Copy link
Member

codyoss commented May 4, 2022

@tritone Took a quick look at the code and I believe what I said stands. This is all alluded to in the third paragraph of https://pkg.go.dev/cloud.google.com/go/storage#BucketHandle.SignedURL, but maybe we could be even more explicit here.

@willie
Copy link

willie commented Jun 22, 2022

Same problem here. I've long been developing with a PrivateKey, but I'm trying super hard to move my local and deployments (Cloud Run) to default credentials for simplicity and security.

As I understand it, I'll have to pass in my email address for the GoogleAccessID field for local testing since default a. I don't understand the third paragraph's instructions, as when I click the link, that panel only appears to work with service accounts. I'm sorry for being dense here.

@BrennaEpp BrennaEpp self-assigned this Aug 12, 2022
@tritone
Copy link
Contributor

tritone commented Aug 29, 2022

Update: we're working on supporting this without requiring passing in GoogleAccessID separately; @BrennaEpp should have a PR up soon.

@tritone tritone added type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. and removed type: question Request for information or clarification. Not an issue. labels Aug 29, 2022
tritone added a commit that referenced this issue Sep 14, 2022
`bucket.SignedURL` and `bucket.GenerateSignedPostPolicyV4` now automatically detect the GoogleAccessID when using impersonated credentials, i.e. when authenticated via `gcloud auth application-default login --impersonate-service-account ${SERVICE_ACCOUNT}`

This prevents users from having to manage a private key or pass in the service account to these methods in their code; see #5979 

Co-authored-by: Chris Cotter <cjcotter@google.com>
@BrennaEpp
Copy link
Contributor

Hi all, the PR is now merged and the changes should be available in the next release.

@willie a service account is needed to sign a URL. When you log in with gcloud, GCS can use those user credentials to perform bucket and object operations; however, signing a URL requires more than just user credentials. By default gcloud does not have a service account attached (unlike GCE, for example, which has a service account attached to the environment), making it necessary, as you mention, to pass in a service account email for the GoogleAccessID field (or, with the new changes, to login with impersonation -- see below).

@wkalt The new changes add support for detecting the service account/GoogleAccessID when logged in to gcloud application-default with the --impersonate-service-account flag set (since we need a service account to sign the url). This allows you to not have to manage a private key locally nor change your code to pass in GoogleAccessID. Just make sure, as always, that you follow the best practices for working with service accounts.

Closing this issue now; feel free to re-open if you have more questions.

@willie
Copy link

willie commented Mar 7, 2023

I'm not sure how to make this work for local development and continue to be able to use my default credentials for Berglas secrets. If I use the --impersonate-service-account flag, it ends up causing an error for Berglas. This might not be something you all can resolve. For now, I'm just going to use the service account key instead.

@BrennaEpp
Copy link
Contributor

@willie Thank you for checking the functionality. That sounds like an issue with Berglas (possibly a simple case of lack of support for impersonation), I would suggest opening an issue there. Feel free to leave more details here as well, but as you say, it may not be something we can resolve on the Cloud Storage side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the Cloud Storage API. priority: p2 Moderately-important priority. 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

6 participants