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

aws, blob: Add support for anonymous query param for gcsblob and all AWSv2 providers #3513

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func NewDefaultV2Config(ctx context.Context) (awsv2.Config, error) {
//
// The following query options are supported:
// - region: The AWS region for requests; sets WithRegion.
// - anonymous: A value of "true" forces use of anonymous credentials.
// - profile: The shared config profile to use; sets SharedConfigProfile.
// - endpoint: The AWS service endpoint to send HTTP request.
// - hostname_immutable: Make the hostname immutable, only works if endpoint is also set.
Expand Down Expand Up @@ -245,6 +246,14 @@ func V2ConfigFromURLParams(ctx context.Context, q url.Values) (awsv2.Config, err
if err != nil {
return awsv2.Config{}, fmt.Errorf("invalid value for capacity: %w", err)
}
case "anonymous":
anon, err := strconv.ParseBool(value)
if err != nil {
return awsv2.Config{}, fmt.Errorf("invalid value for anonymous: %w", err)
}
if anon {
opts = append(opts, awsv2cfg.WithCredentialsProvider(awsv2.AnonymousCredentials{}))
}
case "awssdk":
// ignore, should be handled before this
default:
Expand Down
4 changes: 4 additions & 0 deletions aws/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ func TestV2ConfigFromURLParams(t *testing.T) {
name: "FIPS and dual stack",
query: url.Values{"fips": {"true"}, "dualstack": {"true"}},
},
{
name: "anonymous",
query: url.Values{"anonymous": {"true"}},
},
{
name: "Rate limit capacity",
query: url.Values{"rate_limiter_capacity": {"500"}},
Expand Down
24 changes: 17 additions & 7 deletions blob/gcsblob/gcsblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import (
"net/url"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -206,14 +207,13 @@ const Scheme = "gs"
//
// The following query parameters are supported:
//
// - access_id: sets Options.GoogleAccessID
// - private_key_path: path to read for Options.PrivateKey
//
// Currently their use is limited to SignedURL, except that setting access_id
// to "-" forces the use of an unauthenticated client.
// - anonymous: A value of "true" forces the use of an unauthenticated client.
// - access_id: Sets Options.GoogleAccessID; only used in SignedURL, except that
// a value of "-" forces the use of an unauthenticated client.
// - private_key_path: Path to read for Options.PrivateKey; only used in SignedURL.
type URLOpener struct {
// Client must be set to a non-nil HTTP client authenticated with
// Cloud Storage scope or equivalent.
// Cloud Storage scope or equivalent (unless anonymous=true).
Client *gcp.HTTPClient

// Options specifies the default options to pass to OpenBucket.
Expand All @@ -231,13 +231,23 @@ func (o *URLOpener) OpenBucketURL(ctx context.Context, u *url.URL) (*blob.Bucket

func (o *URLOpener) forParams(ctx context.Context, q url.Values) (*Options, *gcp.HTTPClient, error) {
for k := range q {
if k != "access_id" && k != "private_key_path" {
if k != "access_id" && k != "private_key_path" && k != "anonymous" {
return nil, nil, fmt.Errorf("invalid query parameter %q", k)
}
}
opts := new(Options)
*opts = o.Options
client := o.Client
if anon := q.Get("anonymous"); anon != "" {
isAnon, err := strconv.ParseBool(anon)
if err != nil {
return nil, nil, fmt.Errorf("invalid value %q for query parameter \"anonymous\": %w", anon, err)
}
if isAnon {
opts.clear()
client = gcp.NewAnonymousHTTPClient(gcp.DefaultTransport())
}
}
if accessID := q.Get("access_id"); accessID != "" && accessID != opts.GoogleAccessID {
opts.clear()
if accessID == "-" {
Expand Down
16 changes: 16 additions & 0 deletions blob/gcsblob/gcsblob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,22 @@ func TestURLOpenerForParams(t *testing.T) {
currOpts: Options{GoogleAccessID: "bar"},
wantOpts: Options{GoogleAccessID: "bar"},
},
{
name: "Invalid value for anonymous",
query: url.Values{
"anonymous": {"bad"},
},
wantErr: true,
},
{
name: "Anonymous",
currOpts: Options{GoogleAccessID: "foo"},
query: url.Values{
"anonymous": {"true"},
},
wantOpts: Options{}, // cleared
wantClient: true,
},
{
name: "BadPrivateKeyPath",
query: url.Values{
Expand Down
2 changes: 2 additions & 0 deletions blob/s3blob/s3blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,8 @@ func TestOpenBucketFromURL(t *testing.T) {
{"s3://mybucket?disable_https=true", false},
// OK, use FIPS endpoints (v1)
{"s3://mybucket?awssdk=v1&fips=true", false},
// OK, use anonymous.
{"s3://mybucket?awssdk=v2&anonymous=true", false},
// Invalid accelerate (v1)
{"s3://mybucket?awssdk=v1&accelerate=bogus", true},
// Invalid accelerate (v2)
Expand Down