A Kubernetes operator that bridges Hardware Security Module (HSM) data storage with Kubernetes Secrets, providing true secret portability th
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

try and fix delete

+53 -16
+1 -1
Makefile
··· 3 3 # To re-generate a bundle for another specific version without changing the standard setup, you can: 4 4 # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) 5 5 # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) 6 - VERSION ?= 0.6.37 6 + VERSION ?= 0.6.38 7 7 8 8 # CHANNELS define the bundle channels used in the bundle. 9 9 # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
+2 -2
helm/hsm-secrets-operator/Chart.yaml
··· 2 2 name: hsm-secrets-operator 3 3 description: A Kubernetes operator that bridges Pico HSM binary data storage with Kubernetes Secrets 4 4 type: application 5 - version: 0.6.37 6 - appVersion: v0.6.37 5 + version: 0.6.38 6 + appVersion: v0.6.38 7 7 icon: https://raw.githubusercontent.com/cncf/artwork/master/projects/kubernetes/icon/color/kubernetes-icon-color.svg 8 8 home: https://github.com/evanjarrett/hsm-secrets-operator 9 9 sources:
+39 -12
internal/hsm/pkcs11_cgo.go
··· 316 316 317 317 obj, err := session.ctx.CreateObject(session.session, template) 318 318 if err != nil { 319 - return 0, fmt.Errorf("failed to create data object: %w", err) 319 + // Enhanced error message with context 320 + oidStatus := "none" 321 + if derOID != nil { 322 + oidStatus = fmt.Sprintf("%v (DER len=%d)", oid, len(derOID)) 323 + } 324 + return 0, fmt.Errorf("failed to create data object (label=%s, dataType=%s, oid=%s, valueLen=%d): %w", 325 + label, dataType, oidStatus, len(value), err) 320 326 } 321 327 322 328 return obj, nil ··· 345 351 return fmt.Errorf("failed to find objects: %w", err) 346 352 } 347 353 348 - // Delete each object that matches our path 349 - deletedCount := 0 354 + // CRITICAL: Collect object handles to delete WHILE in search mode 355 + // We must call FindObjectsFinal BEFORE destroying objects 356 + type objectToDelete struct { 357 + handle ObjectHandle 358 + label string 359 + } 360 + objectsToDelete := make([]objectToDelete, 0) 361 + 350 362 for _, obj := range objs { 351 363 // Get the label to check if this object matches our path 352 364 labelAttr, err := session.ctx.GetAttributeValue(session.session, obj, []*pkcs11.Attribute{ ··· 361 373 } 362 374 363 375 label := string(labelAttr[0].Value) 364 - // Only delete objects that match our path 376 + // Only collect objects that match our path 365 377 if !strings.HasPrefix(label, path) { 366 378 continue 367 379 } 368 380 369 - if err := session.ctx.DestroyObject(session.session, obj); err != nil { 370 - // Log error but continue with other objects 371 - continue 381 + objectsToDelete = append(objectsToDelete, objectToDelete{ 382 + handle: obj, 383 + label: label, 384 + }) 385 + } 386 + 387 + // CRITICAL: Must call FindObjectsFinal to exit search mode BEFORE destroying objects 388 + // DestroyObject requires the session to be in normal mode, not search mode 389 + if err := session.ctx.FindObjectsFinal(session.session); err != nil { 390 + return fmt.Errorf("failed to finalize object search (session may be in invalid state): %w", err) 391 + } 392 + 393 + // Now destroy the collected objects (session is in normal mode) 394 + deletedCount := 0 395 + var deleteErrors []string 396 + for _, obj := range objectsToDelete { 397 + if err := session.ctx.DestroyObject(session.session, obj.handle); err != nil { 398 + deleteErrors = append(deleteErrors, fmt.Sprintf("%s: %v", obj.label, err)) 399 + } else { 400 + deletedCount++ 372 401 } 373 - deletedCount++ 374 402 } 375 403 376 - // CRITICAL: Must call FindObjectsFinal to release search operation 377 - // If this fails, the session remains in search mode and CreateObject will fail 378 - if err := session.ctx.FindObjectsFinal(session.session); err != nil { 379 - return fmt.Errorf("failed to finalize object search after deleting %d objects (session may be in invalid state): %w", deletedCount, err) 404 + // Report any delete failures 405 + if len(deleteErrors) > 0 { 406 + return fmt.Errorf("failed to delete %d of %d objects: %s", len(deleteErrors), len(objectsToDelete), strings.Join(deleteErrors, "; ")) 380 407 } 381 408 382 409 return nil
+11 -1
internal/hsm/pkcs11_client.go
··· 234 234 // First, delete any existing objects for this path to avoid duplicates 235 235 // IMPORTANT: Do not ignore errors here - if FindObjectsFinal fails in delete, 236 236 // the session will be in an invalid state and CreateObject will fail 237 + c.logger.V(1).Info("Deleting existing objects before write", "path", path) 237 238 if err := deleteSecretObjectsPKCS11(c.session, path); err != nil { 238 239 return fmt.Errorf("failed to prepare HSM for write (delete existing objects): %w", err) 239 240 } 241 + c.logger.V(1).Info("Successfully deleted existing objects", "path", path) 240 242 241 243 // Create data objects for each key-value pair 242 244 for key, value := range data { ··· 277 279 // Create metadata object label 278 280 metadataLabel := path + metadataKeySuffix 279 281 282 + c.logger.V(1).Info("Creating metadata object", 283 + "path", path, 284 + "label", metadataLabel, 285 + "metadataSize", len(metadataJSON)) 286 + 280 287 // Create the metadata object via helper 281 288 handle, err := createObjectPKCS11(c.session, metadataLabel, metadataJSON) 282 289 if err != nil { ··· 286 293 // Cache the metadata object handle 287 294 c.dataObjects[metadataLabel] = handle 288 295 289 - c.logger.V(2).Info("Created metadata object", "path", path, "label", metadataLabel) 296 + c.logger.V(1).Info("Successfully created metadata object", 297 + "path", path, 298 + "label", metadataLabel, 299 + "handle", handle) 290 300 return nil 291 301 } 292 302