You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Rename 'current_key_id' to `key_id`
- Rename metadata to annotations in proto
- Use byes for annotations value instead of string
- Make beta/GA requirements as TBD
Signed-off-by: Anish Ramasekar <[email protected]>
Copy file name to clipboardExpand all lines: keps/sig-auth/3299-kms-v2-improvements/README.md
+35-36Lines changed: 35 additions & 36 deletions
Original file line number
Diff line number
Diff line change
@@ -92,11 +92,11 @@ Performance, Health Check, Observability and Rotation:
92
92
- Support key hierarchy in KMS plugin that generates local KEK
93
93
- Expand `EncryptionConfiguration` to support a new KMSv2 configuration
94
94
- Add v2alpha1 `KeyManagementService` proto service contract in Kubernetes to include
95
-
-`current_key_id` and metadata to support key rotation
96
-
-`current_key_id`: the KMS Key ID, stable identifier, changed to trigger key rotation and storage migration
97
-
-metadata: structured data, can contain the encrypted local KEK, can be used for debugging, recovery, opaque to API server, stored unencrypted, etc. Validation similar to how K8s labels are validated today. Labels have good size limits and restrictions today.
98
-
- A status request and response periodically (order of minutes) returns `version`, `healthz`, and `current_key_id`
99
-
- The `current_key_id` in status can be used on decrypt operations to compare and validate the key ID stored in the DEK cache and the latest `EncryptResponse``current_key_id` to detect if an object is stale in terms of storage migration
95
+
-`key_id` and additional metadata in `annotations` to support key rotation
96
+
-`key_id`: the KMS Key ID, stable identifier, changed to trigger key rotation and storage migration
97
+
-`annotations`: structured data, can contain the encrypted local KEK, can be used for debugging, recovery, opaque to API server, stored unencrypted, etc. Validation similar to how K8s labels are validated today. Labels have good size limits and restrictions today.
98
+
- A status request and response periodically (order of minutes) returns `version`, `healthz`, and `key_id`
99
+
- The `key_id` in status can be used on decrypt operations to compare and validate the key ID stored in the DEK cache and the latest `EncryptResponse``key_id` to detect if an object is stale in terms of storage migration
100
100
- Generate a new UID for each envelope operation in kube-apiserver
101
101
- Add a new UID field to `EncryptRequest` and `DecryptRequest`
102
102
- Add support for hot reload of the `EncryptionConfiguration`:
@@ -149,7 +149,7 @@ index d7d68d2584d..84c1fa6546f 100644
149
149
+}
150
150
```
151
151
152
-
Support key hierarchy in KMS plugin that generates local KEK and add v2alpha1 `KeyManagementService` proto service contract in Kubernetes to include `current_key_id`, `metadata`, and `status`.
152
+
Support key hierarchy in KMS plugin that generates local KEK and add v2alpha1 `KeyManagementService` proto service contract in Kubernetes to include `key_id`, `annotations`, and `status`.
153
153
154
154
Key Hierarchy in KMS plugin (reference implementation):
Since key hierarchy is implemented at the KMS plugin level, it should be seamless for the kube-apiserver. So whether the plugin is using a key hierarchy or not, the kube-apiserver should behave the same.
165
165
166
-
What is required of the kube-apiserver is to be able to tell the KMS plugin which KEK (local KEK or KMS KEK) it should use to decrypt the incoming DEK. To do so, upon encryption, the KMS plugin could provide the encrypted local KEK as part of the `metadata` field in the `EncryptResponse`. The kube-apiserver would then store it in etcd next to the DEK. Upon decryption, the kube-apiserver provides the encrypted local KEK in `metadata` and `observed_key_id` from the last encryption when calling Decrypt. In case no encrypted local KEK is provided in the `metadata`, then we can assume key hierarchy is not used. The KMS plugin would query the external KMS to use the remote KEK to decrypt the DEK (same behavior as today). No state coordination is required between different instances of the KMS plugin.
166
+
What is required of the kube-apiserver is to be able to tell the KMS plugin which KEK (local KEK or KMS KEK) it should use to decrypt the incoming DEK. To do so, upon encryption, the KMS plugin could provide the encrypted local KEK as part of the `annotations` field in the `EncryptResponse`. The kube-apiserver would then store it in etcd next to the DEK. Upon decryption, the kube-apiserver provides the encrypted local KEK in `annotations` and `observed_key_id` from the last encryption when calling Decrypt. In case no encrypted local KEK is provided in the `annotations`, then we can assume key hierarchy is not used. The KMS plugin would query the external KMS to use the remote KEK to decrypt the DEK (same behavior as today). No state coordination is required between different instances of the KMS plugin.
167
167
168
-
For the reference KMS plugin, the encrypted local KEK is stored in etcd via the `metadata` field, and once decrypted, it can be stored in memory as part of the KMS plugin cache to be used for encryption and decryption of DEKs. The encrypted local KEK is used as the key and the decrypted local KEK is stored as the value.
168
+
For the reference KMS plugin, the encrypted local KEK is stored in etcd via the `annotations` field, and once decrypted, it can be stored in memory as part of the KMS plugin cache to be used for encryption and decryption of DEKs. The encrypted local KEK is used as the key and the decrypted local KEK is stored as the value.
169
169
170
170
```proto
171
171
message EncryptResponse {
172
172
// The encrypted data.
173
173
bytes ciphertext = 1;
174
174
// The KMS key ID used for encryption operations.
175
175
// This can be used to drive rotation.
176
-
string current_key_id = 2;
176
+
string key_id = 2;
177
177
// Additional metadata to be stored with the encrypted data.
178
-
// This metadata can contain the encrypted local KEK that was used to encrypt the DEK.
178
+
// The annotations can contain the encrypted local KEK that was used to encrypt the DEK.
179
179
// Stored unencrypted in etcd.
180
-
map<string, string> metadata = 3;
180
+
map<string, bytes> annotations = 3;
181
181
}
182
182
```
183
183
184
-
The `DecryptRequest` passes the same `current_key_id` and `metadata` returned by the previous `EncryptResponse` of this data as its `observed_key_id` and `metadata` for the decryption request.
184
+
The `DecryptRequest` passes the same `key_id` and `annotations` returned by the previous `EncryptResponse` of this data as its `observed_key_id` and `metadata` for the decryption request.
185
185
186
186
```proto
187
187
message DecryptRequest {
188
188
// The data to be decrypted.
189
-
bytes ciphertext = 2;
189
+
bytes ciphertext = 1;
190
190
// UID is a unique identifier for the request.
191
-
string uid = 3;
191
+
string uid = 2;
192
192
// The keyID that was provided to the apiserver during encryption.
193
193
// This represents the KMS KEK that was used to encrypt the data.
194
-
string observed_key_id = 4;
194
+
string observed_key_id = 3;
195
195
// Additional metadata that was sent by the KMS plugin during encryption.
196
-
map<string, string> metadata = 5;
196
+
map<string, bytes> annotations = 4;
197
197
}
198
198
199
199
message DecryptResponse {
200
200
// The decrypted data.
201
201
bytes plaintext = 1;
202
202
// The KMS key ID used to decrypt the data.
203
-
string current_key_id = 2;
203
+
string key_id = 2;
204
204
// Additional metadata that was sent by the KMS plugin.
205
-
map<string, string> metadata = 3;
205
+
map<string, bytes> annotations = 3;
206
206
}
207
207
208
208
message EncryptRequest {
209
209
// The data to be encrypted.
210
-
bytes plaintext = 2;
210
+
bytes plaintext = 1;
211
211
// UID is a unique identifier for the request.
212
-
string uid = 3;
212
+
string uid = 2;
213
213
}
214
214
```
215
215
@@ -248,11 +248,11 @@ message StatusResponse {
248
248
string healthz = 2;
249
249
250
250
// the current write key, can be used to trigger rotation
251
-
string current_key_id = 3;
251
+
string key_id = 3;
252
252
}
253
253
```
254
254
255
-
The `current_key_id` may be funneled into the storage version status as another field that API servers can attempt to gain consensus on:
255
+
The `key_id` may be funneled into the storage version status as another field that API servers can attempt to gain consensus on:
kubeapiserver->>etcd: store encrypt response and encrypted DEK
317
317
```
@@ -323,9 +323,9 @@ sequenceDiagram
323
323
participant kubeapiserver
324
324
participant kmsplugin
325
325
participant externalkms
326
-
%% if local KEK in metadata, then using hierarchy
327
-
alt encrypted local KEK is in metadata
328
-
kubeapiserver->>kmsplugin: decrypt request <br/> {"ciphertext": "<encrypted DEK>", observed_key_id: "<current_key_id gotten as part of EncryptResponse>", <br/> "metadata": {"kms.kubernetes.io/local-kek": "<encrypted local KEK>"}}
326
+
%% if local KEK in annotations, then using hierarchy
327
+
alt encrypted local KEK is in annotations
328
+
kubeapiserver->>kmsplugin: decrypt request <br/> {"ciphertext": "<encrypted DEK>", observed_key_id: "<key_id gotten as part of EncryptResponse>", <br/> "annotations": {"kms.kubernetes.io/local-kek": "<encrypted local KEK>"}}
0 commit comments