Running GCP KMS & Secret Manager locally with the native SDK: gRPC vs HTTPS
Google's client libraries are excellent — and by default they talk gRPC. For most
services that's invisible. But for Cloud KMS and Secret Manager, two things line
up that make local development hard: the default transport is gRPC, and Google ships no emulator
for either (unlike Pub/Sub or Firestore). This is how we kept the native
google-cloud-kms / google-cloud-secretmanager SDKs working as-is
against a local appliance by using a transport they already support — HTTPS — and what that
costs.
1. The wall — gRPC
The native google-cloud-kms and google-cloud-secretmanager SDKs default to
gRPC against *.googleapis.com. Serving gRPC ourselves means standing up
HTTP/2 with protobuf framing, trailers, and a faithful
re-implementation of each service's exact .proto contract — a heavy build for what is, here, two
services. And unlike Pub/Sub and Firestore, Google publishes no local emulator for KMS or Secret
Manager, so there's nothing official to lean on.
So the naive options are both bad: re-implement gRPC service-by-service, or fake it and return a green that the real SDK would never have produced.
2. The tech choice — build around HTTPS
The key insight: these are the same SDKs, and they already expose a REST (HTTPS)
transport. Google's gax layer ships an HttpJson channel; the client settings expose a
newHttpJsonBuilder(). Point that at the appliance's HTTPS endpoint with NoCredentials,
and the unmodified native client does real encrypt/decrypt and secret access over plain HTTPS —
backed by a Vault-transit engine the SDK never sees.
// Native google-cloud-kms — same client classes & calls as production.
// One transport line changed: REST (HttpJson) instead of the default gRPC.
KeyManagementServiceSettings settings =
KeyManagementServiceSettings.newHttpJsonBuilder()
.setEndpoint(System.getenv("GCP_REST_ENDPOINT")) // appliance HTTPS (caddy), host:port
.setCredentialsProvider(NoCredentialsProvider.create()) // appliance ignores auth
.build();
try (KeyManagementServiceClient client = KeyManagementServiceClient.create(settings)) {
CryptoKeyName keyName = CryptoKeyName.of(project, location, "my-ring", "my-key");
EncryptResponse enc = client.encrypt(keyName, ByteString.copyFromUtf8("top-secret"));
DecryptResponse dec = client.decrypt(keyName, enc.getCiphertext());
assert dec.getPlaintext().toStringUtf8().equals("top-secret"); // real round-trip
}
Secret Manager is the identical pattern — SecretManagerServiceSettings.newHttpJsonBuilder() — for
createSecret → addSecretVersion → accessSecretVersion → deleteSecret. This is exactly the spirit of
AWS's endpointOverride: still the native SDK, just configured to a
transport and endpoint it natively supports.
3. The trade-off, stated plainly
Driving the REST channel instead of gRPC has real, concrete implications — and they're all about transport, not about your business logic:
- gax builds HTTPS URLs, so you target the appliance's caddy host:port, and the
cert must be trusted by the JVM (add it to your truststore — same as any private TLS
endpoint). gRPC-to-an-
http://-endpoint won't work here; the REST channel is HTTPS. - No channel pooling. The HttpJson transport doesn't multiplex like gRPC; for local dev and CI that's a non-issue.
- protojson encoding. Request/response must match Google's canonical protojson mapping — which the SDK and the appliance both honour, so it's transparent to you.
- What you give up vs gRPC: bidirectional streaming and some deadline/retry nuances — none of which apply to KMS encrypt/decrypt or secret access.
4. SDK conformance
The snippet is the whole guarantee: same client classes, same method calls as the code you
deploy to GCP. Exactly one line changes the transport (newHttpJsonBuilder() and an
endpoint). There's no Vyomi SDK and no wrapper; the Vault-transit backing behind KMS is invisible and swappable.
Drop the HttpJson settings and point the default client at real GCP, and the identical encrypt/decrypt code runs
against the cloud.
5. What is guaranteed (KMS / Secrets)
- Guaranteed: the official
google-cloud-kms/google-cloud-secretmanagerSDKs, unmodified, config-only (REST transport + endpoint); a real encrypt → decrypt round-trip and secret create → access → delete; portable code; backing tech (Vault) invisible and swappable. - Not guaranteed (said out loud): gRPC-specific transport behaviours (streaming, channel multiplexing, some deadline semantics); cloud-scale latency, quotas, and billing. You also supply the JVM trust for the local TLS cert — a one-time setup, not a code change.
Part of the Vyomi Knowledge Center series on native-SDK conformance. Companion:
“AMQP vs HTTPS” — Azure messaging.
Verified on a live appliance (2026-06-22): native google-cloud-kms / secretmanager over
HttpJson, encrypt→decrypt and secret round-trips green (11/12 overall).