diff --git a/pkg/asset/installconfig/gcp/client.go b/pkg/asset/installconfig/gcp/client.go index ee7bbe27a41..a7adb72e732 100644 --- a/pkg/asset/installconfig/gcp/client.go +++ b/pkg/asset/installconfig/gcp/client.go @@ -720,7 +720,11 @@ func (c *Client) GetNamespacedTagValue(ctx context.Context, tagNamespacedName st } func (c *Client) getKeyManagementClient(ctx context.Context) (*kms.KeyManagementClient, error) { - kmsClient, err := kms.NewKeyManagementClient(ctx, option.WithCredentials(c.ssn.Credentials)) + opts, err := CredentialOptions(c.ssn) + if err != nil { + return nil, fmt.Errorf("failed to get credential options: %w", err) + } + kmsClient, err := kms.NewKeyManagementClient(ctx, opts...) if err != nil { return nil, fmt.Errorf("failed to create kms key management client: %w", err) } diff --git a/pkg/asset/installconfig/gcp/services.go b/pkg/asset/installconfig/gcp/services.go index 38185f135e6..915b6951bdf 100644 --- a/pkg/asset/installconfig/gcp/services.go +++ b/pkg/asset/installconfig/gcp/services.go @@ -59,17 +59,34 @@ func CreateEndpointOption(endpointName string, service ServiceNameGCP) option.Cl return option.WithEndpoint(endpoint) } +// CredentialOptions returns the client options for authenticating with GCP, +// including universe domain support for Google Cloud Dedicated. +// When credential JSON is available, it is passed via WithCredentialsJSON so +// the client library can use self-signed JWTs for non-default universe +// domains (where the OAuth2 token endpoint is unavailable). Falls back to +// WithCredentials for metadata-based credentials that have no JSON. +func CredentialOptions(ssn *Session) ([]option.ClientOption, error) { + ud, err := ssn.Credentials.GetUniverseDomain() + if err != nil { + return nil, fmt.Errorf("failed to get universe domain: %w", err) + } + var opts []option.ClientOption + if len(ssn.Credentials.JSON) > 0 { + opts = append(opts, option.WithCredentialsJSON(ssn.Credentials.JSON)) + } else { + opts = append(opts, option.WithCredentials(ssn.Credentials)) + } + opts = append(opts, option.WithUniverseDomain(ud)) + return opts, nil +} + // getOptions creates the options for use during service creation. func getOptions(ctx context.Context) ([]option.ClientOption, error) { ssn, err := GetSession(ctx) if err != nil { return nil, fmt.Errorf("failed to get session: %w", err) } - - options := []option.ClientOption{ - option.WithCredentials(ssn.Credentials), - } - return options, nil + return CredentialOptions(ssn) } // GetComputeService creates the compute service. The service is created with credentials and any service diff --git a/pkg/clusterapi/system.go b/pkg/clusterapi/system.go index f991d0f54ab..0e07d683750 100644 --- a/pkg/clusterapi/system.go +++ b/pkg/clusterapi/system.go @@ -311,6 +311,17 @@ func (c *system) Run(ctx context.Context) error { //nolint:gocyclo logrus.Infof("setting %q to %s for capg infrastructure controller", gAppCredEnvVar, v) } + // Google Cloud Dedicated support: detect universe domain from + // credentials and pass it to the CAPG controller via env var. + ud, err := session.Credentials.GetUniverseDomain() + if err != nil { + return fmt.Errorf("failed to get universe domain from gcp credentials: %w", err) + } + if ud != "googleapis.com" { + capgEnvVars["GOOGLE_CLOUD_UNIVERSE_DOMAIN"] = ud + logrus.Infof("setting GOOGLE_CLOUD_UNIVERSE_DOMAIN to %q for capg infrastructure controller", ud) + } + controllers = append(controllers, c.getInfrastructureController( &GCP, diff --git a/pkg/quota/gcp/gcp.go b/pkg/quota/gcp/gcp.go index 552c2b266c8..1baf81ebaed 100644 --- a/pkg/quota/gcp/gcp.go +++ b/pkg/quota/gcp/gcp.go @@ -2,6 +2,7 @@ package gcp import ( "context" + "fmt" "net/http" "sort" "strings" @@ -35,7 +36,10 @@ func Load(ctx context.Context, project string, endpoint *gcptypes.PSCEndpoint, s if err != nil { return nil, errors.Wrap(err, "failed to create services svc") } - metricsOptions := []option.ClientOption{option.WithCredentials(ssn.Credentials)} + metricsOptions, err := gcpconfig.CredentialOptions(ssn) + if err != nil { + return nil, fmt.Errorf("failed to get credential options: %w", err) + } metricsSvc, err := monitoring.NewMetricClient(ctx, metricsOptions...) if err != nil { return nil, errors.Wrap(err, "failed to create metrics svc")