Skip to content

Commit bb5e250

Browse files
committed
feat(gcpkms): add SOPS_GCP_KMS_ENDPOINT and SOPS_GCP_KMS_UNIVERSE_DOMAIN env vars
Allow overriding the GCP KMS endpoint and universe domain via environment variables. This enables use of sovereign cloud environments that expose a GCP-compatible KMS API at a non-standard endpoint (e.g. S3NS/Thales TPC with cloudkms.s3nsapis.fr).
1 parent 020e84f commit bb5e250

3 files changed

Lines changed: 56 additions & 0 deletions

File tree

README.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,21 @@ switch to the REST client by setting the ``SOPS_GCP_KMS_CLIENT_TYPE`` environmen
325325
$ export SOPS_GCP_KMS_CLIENT_TYPE=rest # Use REST client
326326
$ export SOPS_GCP_KMS_CLIENT_TYPE=grpc # Use gRPC client (default)
327327
328+
For sovereign cloud environments that expose a GCP-compatible KMS API at a
329+
non-standard endpoint (e.g. S3NS/Thales TPC: ``cloudkms.s3nsapis.fr``),
330+
you can override the endpoint or the universe domain:
331+
332+
.. code:: sh
333+
334+
# Override the KMS endpoint directly
335+
$ export SOPS_GCP_KMS_ENDPOINT=cloudkms.example.com:443
336+
337+
# Or derive the endpoint from the universe domain (cloudkms.<domain>:443)
338+
$ export SOPS_GCP_KMS_UNIVERSE_DOMAIN=example.com
339+
340+
Note: ``SOPS_GCP_KMS_ENDPOINT`` takes precedence over
341+
``SOPS_GCP_KMS_UNIVERSE_DOMAIN`` if both are set.
342+
328343
Encrypting/decrypting with GCP KMS requires a KMS ResourceID. You can use the
329344
cloud console the get the ResourceID or you can create one using the gcloud
330345
sdk:

gcpkms/keysource.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ const (
3030
// SopsGCPKMSClientTypeEnv is the environment variable used to specify the
3131
// GCP KMS client type. Valid values are "grpc" (default) and "rest".
3232
SopsGCPKMSClientTypeEnv = "SOPS_GCP_KMS_CLIENT_TYPE"
33+
// SopsGCPKMSEndpointEnv overrides the GCP KMS endpoint URL. Useful for
34+
// sovereign cloud environments that expose a GCP-compatible KMS API at a
35+
// non-standard endpoint (e.g. S3NS/Thales TPC: cloudkms.s3nsapis.fr).
36+
SopsGCPKMSEndpointEnv = "SOPS_GCP_KMS_ENDPOINT"
37+
// SopsGCPKMSUniverseDomainEnv sets the universe domain for the GCP KMS
38+
// client, which derives the endpoint as cloudkms.{UNIVERSE_DOMAIN}:443.
39+
// Example: "s3nsapis.fr" for S3NS/Thales TPC.
40+
SopsGCPKMSUniverseDomainEnv = "SOPS_GCP_KMS_UNIVERSE_DOMAIN"
3341
// KeyTypeIdentifier is the string used to identify a GCP KMS MasterKey.
3442
KeyTypeIdentifier = "gcp_kms"
3543
)
@@ -321,6 +329,13 @@ func (key *MasterKey) newKMSClient(ctx context.Context) (*kms.KeyManagementClien
321329
// Add extra options.
322330
opts = append(opts, key.clientOpts...)
323331

332+
if endpoint := os.Getenv(SopsGCPKMSEndpointEnv); endpoint != "" {
333+
opts = append(opts, option.WithEndpoint(endpoint))
334+
}
335+
if ud := os.Getenv(SopsGCPKMSUniverseDomainEnv); ud != "" {
336+
opts = append(opts, option.WithUniverseDomain(ud))
337+
}
338+
324339
// Select client type based on inputs.
325340
clientType := strings.ToLower(os.Getenv(SopsGCPKMSClientTypeEnv))
326341
var client *kms.KeyManagementClient

gcpkms/keysource_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,32 @@ func TestMasterKey_createCloudKMSService_withoutCredentials(t *testing.T) {
189189
assert.ErrorContains(t, err, "credentials: could not find default credentials")
190190
}
191191

192+
func TestMasterKey_createCloudKMSService_withEndpointEnv(t *testing.T) {
193+
t.Setenv(SopsGCPKMSEndpointEnv, "cloudkms.example.com:443")
194+
t.Setenv(SopsGoogleCredentialsOAuthTokenEnv, "token")
195+
196+
masterKey := MasterKey{
197+
ResourceID: testResourceID,
198+
}
199+
200+
_, err := masterKey.newKMSClient(context.Background())
201+
202+
assert.NoError(t, err)
203+
}
204+
205+
func TestMasterKey_createCloudKMSService_withUniverseDomainEnv(t *testing.T) {
206+
t.Setenv(SopsGCPKMSUniverseDomainEnv, "example.com")
207+
t.Setenv(SopsGoogleCredentialsOAuthTokenEnv, "token")
208+
209+
masterKey := MasterKey{
210+
ResourceID: testResourceID,
211+
}
212+
213+
_, err := masterKey.newKMSClient(context.Background())
214+
215+
assert.NoError(t, err)
216+
}
217+
192218
func newGRPCServer(port string) *grpc.ClientConn {
193219
serv := grpc.NewServer()
194220
kmspb.RegisterKeyManagementServiceServer(serv, &mockKeyManagement)

0 commit comments

Comments
 (0)