[keymanager/wsd] Add /keys:destroy Go KOL handler with KEM + binding key destruction#651
Conversation
60466aa to
cff8e70
Compare
4d76482 to
87f6a9f
Compare
|
|
||
| // NewServer creates a new WSD server with the given dependencies. | ||
| func NewServer(bindingGen BindingKeyGenerator, kemGen KEMKeyGenerator) *Server { | ||
| func NewServer(bindingGen BindingKeyGenerator, kemGen KEMKeyGenerator, kemKeyDestroyer KEMKeyDestroyer, bindingKeyDestroyer BindingKeyDestroyer) *Server { |
There was a problem hiding this comment.
this will need change after #678 is merged.
May have to rebase over that
…struction
Implement the Go KOL handler for POST /keys:destroy that orchestrates
the full key destruction flow:
1. Workload sends {kemKeyHandle} to WSD
2. WSD looks up binding UUID from KEM-to-binding map
3. WSD calls KPS DestroyKEMKey to destroy the KEM key
4. WSD calls WSD KCC DestroyBindingKey to destroy the binding key
5. WSD removes the KEM→Binding mapping
6. Returns 204 No Content
Changes:
- C headers: add key_manager_destroy_kem_key (KPS) and
key_manager_destroy_binding_key (WSD) declarations
- CGO bridges: add DestroyKEMKey and DestroyBindingKey Go wrappers
- KPS service: extend with DestroyKEMKey method and KEMKeyDestroyer
interface
- WSD server: add KEMKeyDestroyer/BindingKeyDestroyer interfaces,
DestroyRequest type, handleDestroy handler, /keys:destroy route
- Tests: 7 new destroy handler tests + 2 new KPS service tests
Remove DecapAndSeal and Open from KPS and WSD
87f6a9f to
dcac4cd
Compare
| // KEMKeyGenerator generates KEM keypairs linked to a binding public key. | ||
|
|
||
| // KEMKeyDestroyer destroys a KEM key by UUID. | ||
| type KEMKeyDestroyer interface { |
There was a problem hiding this comment.
Similar comment to PR #650: https://github.com/google/go-tpm-tools/pull/650/changes#r2872752692
| kemUUIDs[0], binding1, kemUUIDs[1], binding2) | ||
| } | ||
|
|
||
| func TestIntegrationDestroyKey(t *testing.T) { |
There was a problem hiding this comment.
Should we also add an integration test to validate the auto-destroy mechanism with this PR? And also verify that calling a destroy on a auto-destroyed key will not cause problems (since the kem to binding mapping will still exist in the KOL layer).
There was a problem hiding this comment.
Done! I have added a new integration test TestIntegrationAutoDestroy
I also verified the behavior offline: when the KEM key and binding key expire and are auto-destroyed in the Rust KCC layer, an explicit call to /v1/keys:destroy does not cause any problems. The Rust backend returns success, allowing the Go KOL to cleanly remove the stale mapping from its kemToBindingMap and return an HTTP 204 No Content. The new integration test ensures this behavior won't regress.
|
|
||
| // Step 4: Remove the mapping. | ||
| s.mu.Lock() | ||
| delete(s.kemToBindingMap, kemUUID) |
There was a problem hiding this comment.
I am wondering if we should try to remove the kemUUID from the kemToBindingMap even in case of errors. For example, if for some reason DestroyKEMKey or DestroyBindingKey fails the delete call will not go through. A subsequent decap call on the same key will pass through since the mapping exist and fail in the Rust layer. Which is okay, but would it better to try to delete the mapping to avoid such a situation?
There was a problem hiding this comment.
That makes sense.
I have updated the logic to ensure that both KEM and Binding keys are always attempted for destruction, and the mapping is always deleted from the map, regardless of individual failure outcomes. I've also updated server_test.go to explicitly verify this behavior.
Even if delete fails for some reason, the reaper would eventually delete expired keys right?
| func DestroyKEMKey(kemUUID uuid.UUID) error { | ||
| uuidBytes := kemUUID[:] | ||
| rc := C.key_manager_destroy_kem_key( | ||
| (*C.uint8_t)(unsafe.Pointer(&uuidBytes[0])), |
# Conflicts: # keymanager/key_protection_service/service.go # keymanager/workload_service/server.go # keymanager/workload_service/server_test.go
102c4f4 to
29cacc6
Compare
9080eeb to
830a9ee
Compare
- fix: fix handleDestroy to prevent resource and memory leaks by always clearing the KeyManager mapping. - test: update handleDestroy tests to assert mapping deletion. - test: add integration test for auto-destroy mechanism.
830a9ee to
c45988c
Compare
| kemUUIDs[0], binding1, kemUUIDs[1], binding2) | ||
| } | ||
|
|
||
| func TestIntegrationDestroyKey(t *testing.T) { |
| errKps := s.keyProtectionService.DestroyKEMKey(kemUUID) | ||
| errWs := s.workloadService.DestroyBindingKey(bindingUUID) | ||
|
|
||
| // Step 4: Remove the mapping. |
There was a problem hiding this comment.
I think this is Step 2 now
There was a problem hiding this comment.
Removed Step from the comment as this comment pattern isn't used in our codebase
| if errKps != nil { | ||
| writeError(w, fmt.Sprintf("failed to destroy KEM key: %v", errKps), http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| if errWs != nil { | ||
| writeError(w, fmt.Sprintf("failed to destroy binding key: %v", errWs), http.StatusInternalServerError) | ||
| return | ||
| } |
There was a problem hiding this comment.
This works, but if the errKps fails, errWs is ignored. We can use errors.Join() to join the errors, so that both or either of them are surfaced.
- removed `Step <x>` comments - used errors.Join to collectively check of either KPS or WS destroy failed
Implements the Go orchestration layer (KOL) for
POST /v1/keys:destroy, the key destruction endpoint that allows workloads to explicitly destroy a key pair.Flow:
{key_handle: {handle: ...}}to WSDDestroyKEMKey— destroys the KEM key from the registryDestroyBindingKey— destroys the binding key from the registry204 No ContentChanges:
key_manager_destroy_kem_key(KPS) andkey_manager_destroy_binding_key(WSD) declarationsDestroyKEMKey()andDestroyBindingKey()Go wrappers for the Rust FFI functionsServicewithDestroyKEMKeymethod andKEMKeyDestroyerinterfaceKEMKeyDestroyer/BindingKeyDestroyerinterfaces,DestroyRequesttype,handleDestroyhandler,/v1/keys:destroyroute registrationTestIntegrationDestroyKeyDependencies
This PR is built on top of:
key_manager_destroy_ffi) — Rust FFI changes (Base commit:d1d6bad)wsd_generate_key_go) — Included via merge (Commit:d7f52c6)What to review
Please review the following commits:
d1d6bad—feat(keymanager): Add manual FFI headers for destroy(C headers for destroy)60466aa—[keymanager/wsd] Add /keys:destroy endpoint with KEM + binding key destruction(Go implementation)All other commits are from dependencies (PRs #647, #652) that are not yet merged to main but required for this build.
Verification
Automated Tests
go test ./keymanager/workload_service/...(Passed)go test -tags=integration ./keymanager/workload_service/...(Passed)Manual Verification (Curl)
Manually verified the destruction workflow locally:
POST /v1/keys:generate_kem-> Returns Handle.POST /v1/keys:destroy-> Returns 204.POST /v1/keys:destroy-> Returns 404 (Key mapping removed).