This commit is contained in:
Houssein Mnaouar 2026-05-20 15:53:56 -04:00 committed by GitHub
commit 3a059091db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 76 additions and 14 deletions

3
changelog/31550.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:feature
gcs: add support for the `universe_domain` parameter, allowing the backend to work with GCP sovereign cloud environments that require a custom API domain.
```

View file

@ -48,6 +48,10 @@ const (
// objectDelimiter is the string to use to delimit objects.
objectDelimiter = "/"
// envUniverseDomain is an optional env var used to override the universe
// domain (helpful for custom GCS-compatible endpoints).
envUniverseDomain = "GOOGLE_UNIVERSE_DOMAIN"
)
var (
@ -124,6 +128,20 @@ func NewBackend(c map[string]string, logger log.Logger) (physical.Backend, error
// Values are specified as kb, but the API expects them as bytes.
chunkSize = chunkSize * 1024
// universe_domain: optional custom domain used by the GCS client
universeDomain := os.Getenv(envUniverseDomain)
if universeDomain == "" {
universeDomain = c["universe_domain"]
}
// Build client options (we always set a user-agent).
clientOptions := []option.ClientOption{option.WithUserAgent(useragent.String())}
if universeDomain != "" {
// WithUniverseDomain is optional and only appended when provided.
clientOptions = append(clientOptions, option.WithUniverseDomain(universeDomain))
logger.Debug("using custom universe_domain", "universe_domain", universeDomain)
}
// HA configuration
haClient := (*storage.Client)(nil)
haEnabled := false
@ -142,7 +160,7 @@ func NewBackend(c map[string]string, logger log.Logger) (physical.Backend, error
logger.Debug("creating client")
var err error
ctx := context.Background()
haClient, err = storage.NewClient(ctx, option.WithUserAgent(useragent.String()))
haClient, err = storage.NewClient(ctx, clientOptions...)
if err != nil {
return nil, fmt.Errorf("failed to create HA storage client: %w", err)
}
@ -163,7 +181,7 @@ func NewBackend(c map[string]string, logger log.Logger) (physical.Backend, error
logger.Debug("creating client")
ctx := context.Background()
client, err := storage.NewClient(ctx, option.WithUserAgent(useragent.String()))
client, err := storage.NewClient(ctx, clientOptions...)
if err != nil {
return nil, fmt.Errorf("failed to create storage client: %w", err)
}

View file

@ -15,6 +15,7 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/physical"
"google.golang.org/api/option"
)
func TestHABackend(t *testing.T) {
@ -23,27 +24,45 @@ func TestHABackend(t *testing.T) {
t.Skip("GOOGLE_PROJECT_ID not set")
}
universeDomain := os.Getenv("GOOGLE_UNIVERSE_DOMAIN")
r := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
bucket := fmt.Sprintf("vault-gcs-testacc-%d", r)
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
t.Fatal(err)
// Build client options: if a custom universe domain is provided in env, use it.
clientOpts := []option.ClientOption{}
if universeDomain != "" {
clientOpts = append(clientOpts, option.WithUniverseDomain(universeDomain))
}
client, err := storage.NewClient(ctx, clientOpts...)
testCleanup(t, client, bucket)
defer testCleanup(t, client, bucket)
bh := client.Bucket(bucket)
if err := bh.Create(context.Background(), projectID, nil); err != nil {
t.Fatal(err)
// Support minimal for providers that require an explicit Location.
bucketLocation := os.Getenv("GOOGLE_BUCKET_LOCATION")
if bucketLocation != "" {
// Create the bucket with the explicit location required by some universe domains.
if err := bh.Create(ctx, projectID, &storage.BucketAttrs{
Location: bucketLocation,
}); err != nil {
t.Fatalf("failed to create bucket %q with location %q: %v", bucket, bucketLocation, err)
}
} else {
// Default behaviour (no explicit location).
if err := bh.Create(ctx, projectID, nil); err != nil {
t.Fatalf("failed to create bucket %q: %v", bucket, err)
}
}
logger := logging.NewVaultLogger(log.Trace)
config := map[string]string{
"bucket": bucket,
"ha_enabled": "true",
"bucket": bucket,
"ha_enabled": "true",
"universe_domain": universeDomain,
}
b, err := NewBackend(config, logger)

View file

@ -17,6 +17,7 @@ import (
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/physical"
"google.golang.org/api/googleapi"
"google.golang.org/api/option"
)
func testCleanup(t testing.TB, client *storage.Client, bucket string) {
@ -36,11 +37,18 @@ func TestBackend(t *testing.T) {
t.Skip("GOOGLE_PROJECT_ID not set")
}
universeDomain := os.Getenv("GOOGLE_UNIVERSE_DOMAIN")
r := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
bucket := fmt.Sprintf("vault-gcs-testacc-%d", r)
ctx := context.Background()
client, err := storage.NewClient(ctx)
// Build client options: if a custom universe domain is provided in env, use it.
clientOpts := []option.ClientOption{}
if universeDomain != "" {
clientOpts = append(clientOpts, option.WithUniverseDomain(universeDomain))
}
client, err := storage.NewClient(ctx, clientOpts...)
if err != nil {
t.Fatal(err)
}
@ -49,13 +57,27 @@ func TestBackend(t *testing.T) {
defer testCleanup(t, client, bucket)
b := client.Bucket(bucket)
if err := b.Create(context.Background(), projectID, nil); err != nil {
t.Fatal(err)
// Support minimal for providers that require an explicit Location.
bucketLocation := os.Getenv("GOOGLE_BUCKET_LOCATION")
if bucketLocation != "" {
// Create the bucket with the explicit location required by some universe domains.
if err := b.Create(ctx, projectID, &storage.BucketAttrs{
Location: bucketLocation,
}); err != nil {
t.Fatalf("failed to create bucket %q with location %q: %v", bucket, bucketLocation, err)
}
} else {
// Default behaviour (no explicit location).
if err := b.Create(ctx, projectID, nil); err != nil {
t.Fatalf("failed to create bucket %q: %v", bucket, err)
}
}
backend, err := NewBackend(map[string]string{
"bucket": bucket,
"ha_enabled": "false",
"bucket": bucket,
"ha_enabled": "false",
"universe_domain": universeDomain,
}, logging.NewVaultLogger(log.Trace))
if err != nil {
t.Fatal(err)