* kms plugin version: `v1beta1`
In response to procedure call Version, a compatible KMS plugin should return `v1beta1` as `VersionResponse.version`.
* message version: `v1beta1`
All messages from KMS provider have the version field set to `v1beta1`.
* protocol: UNIX domain socket (`unix`)
The plugin is implemented as a gRPC server that listens at UNIX domain socket. The plugin deployment should create a file on the file system to run the gRPC unix domain socket connection. The API server (gRPC client) is configured with the KMS provider (gRPC server) unix domain socket endpoint in order to communicate with it. An abstract Linux socket may be used by starting the endpoint with `/@`, i.e. `unix:///@foo`. Care must be taken when using this type of socket as they do not have concept of ACL (unlike traditional file based sockets). However, they are subject to Linux networking namespace, so will only be accessible to containers within the same pod unless host networking is used.
##### KMS v2 {#developing-a-kms-plugin-gRPC-server-notes-kms-v2}
* KMS plugin version: `v2`
In response to the `Status` remote procedure call, a compatible KMS plugin should return its KMS compatibility
version as `StatusResponse.version`. That status response should also include
"ok" as `StatusResponse.healthz` and a `key_id` (remote KMS KEK ID) as `StatusResponse.key_id`.
The Kubernetes project recommends you make your plugin
compatible with the stable `v2` KMS API. Kubernetes {{< skew currentVersion >}} also supports the
`v2beta1` API for KMS; future Kubernetes releases are likely to continue supporting that beta version.
The API server polls the `Status` procedure call approximately every minute when everything is healthy,
and every 10 seconds when the plugin is not healthy. Plugins must take care to optimize this call as it will be
under constant load.
* Encryption
The `EncryptRequest` procedure call provides the plaintext and a UID for logging purposes. The response must include
the ciphertext, the `key_id` for the KEK used, and, optionally, any metadata that the KMS plugin needs to aid in
future `DecryptRequest` calls (via the `annotations` field). The plugin must guarantee that any distinct plaintext
results in a distinct response `(ciphertext, key_id, annotations)`.
If the plugin returns a non-empty `annotations` map, all map keys must be fully qualified domain names such as
`example.com`. An example use case of `annotation` is `{"kms.example.io/remote-kms-auditid":"<audit ID used by the remote KMS>"}`
The API server does not perform the `EncryptRequest` procedure call at a high rate. Plugin implementations should
still aim to keep each request's latency at under 100 milliseconds.
* Decryption
The `DecryptRequest` procedure call provides the `(ciphertext, key_id, annotations)` from `EncryptRequest` and a UID
for logging purposes. As expected, it is the inverse of the `EncryptRequest` call. Plugins must verify that the
`key_id` is one that they understand - they must not attempt to decrypt data unless they are sure that it was
encrypted by them at an earlier time.
The API server may perform thousands of `DecryptRequest` procedure calls on startup to fill its watch cache. Thus
plugin implementations must perform these calls as quickly as possible, and should aim to keep each request's latency
at under 10 milliseconds.
* Understanding `key_id` and Key Rotation
The `key_id` is the public, non-secret name of the remote KMS KEK that is currently in use. It may be logged
during regular operation of the API server, and thus must not contain any private data. Plugin implementations
are encouraged to use a hash to avoid leaking any data. The KMS v2 metrics take care to hash this value before
exposing it via the `/metrics` endpoint.
The API server considers the `key_id` returned from the `Status` procedure call to be authoritative. Thus, a change
to this value signals to the API server that the remote KEK has changed, and data encrypted with the old KEK should