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.

fixes

+74 -8
+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.5.25 6 + VERSION ?= 0.5.26 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.5.25 6 - appVersion: v0.5.25 5 + version: 0.5.26 6 + appVersion: v0.5.26 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:
+60 -2
internal/agent/grpc_server.go
··· 160 160 pbData[key] = value 161 161 } 162 162 163 + s.logger.V(1).Info("Successfully read secret", "path", req.Path, "keys_count", len(pbData)) 164 + 163 165 return &hsmv1.ReadSecretResponse{ 164 166 SecretData: &hsmv1.SecretData{Data: pbData}, 165 167 }, nil ··· 190 192 return nil, status.Errorf(codes.Internal, "failed to write secret: %v", err) 191 193 } 192 194 195 + s.logger.V(1).Info("Successfully wrote secret", "path", req.Path, "keys_count", len(hsmData)) 193 196 return &hsmv1.WriteSecretResponse{}, nil 194 197 } 195 198 ··· 231 234 return nil, status.Errorf(codes.Internal, "failed to write secret with metadata: %v", err) 232 235 } 233 236 237 + s.logger.V(1).Info("Successfully wrote secret with metadata", "path", req.Path, "keys_count", len(hsmData)) 234 238 return &hsmv1.WriteSecretWithMetadataResponse{}, nil 235 239 } 236 240 ··· 282 286 return nil, status.Errorf(codes.Internal, "failed to delete secret: %v", err) 283 287 } 284 288 289 + s.logger.V(1).Info("Successfully deleted secret", "path", req.Path) 285 290 return &hsmv1.DeleteSecretResponse{}, nil 286 291 } 287 292 ··· 297 302 return nil, status.Errorf(codes.Internal, "failed to list secrets: %v", err) 298 303 } 299 304 305 + s.logger.V(1).Info("Successfully listed secrets", "prefix", req.Prefix, "count", len(paths)) 300 306 return &hsmv1.ListSecretsResponse{ 301 307 Paths: paths, 302 308 }, nil ··· 389 395 func (s *GRPCServer) loggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 390 396 start := time.Now() 391 397 398 + // Extract request-specific details 399 + logFields := []interface{}{ 400 + "method", info.FullMethod, 401 + "device", s.deviceName, 402 + } 403 + 404 + // Add request-specific fields based on the method 405 + switch r := req.(type) { 406 + case *hsmv1.ReadSecretRequest: 407 + logFields = append(logFields, "path", r.Path) 408 + case *hsmv1.WriteSecretRequest: 409 + logFields = append(logFields, "path", r.Path) 410 + if r.SecretData != nil { 411 + logFields = append(logFields, "keys_count", len(r.SecretData.Data)) 412 + } 413 + case *hsmv1.WriteSecretWithMetadataRequest: 414 + logFields = append(logFields, "path", r.Path) 415 + if r.SecretData != nil { 416 + logFields = append(logFields, "keys_count", len(r.SecretData.Data)) 417 + } 418 + case *hsmv1.DeleteSecretRequest: 419 + logFields = append(logFields, "path", r.Path) 420 + case *hsmv1.ListSecretsRequest: 421 + logFields = append(logFields, "prefix", r.Prefix) 422 + case *hsmv1.GetChecksumRequest: 423 + logFields = append(logFields, "path", r.Path) 424 + case *hsmv1.ReadMetadataRequest: 425 + logFields = append(logFields, "path", r.Path) 426 + } 427 + 428 + s.logger.Info("gRPC request started", logFields...) 429 + 392 430 resp, err := handler(ctx, req) 393 431 394 432 duration := time.Since(start) 395 433 code := codes.OK 434 + errorMsg := "" 396 435 if err != nil { 397 436 if st, ok := status.FromError(err); ok { 398 437 code = st.Code() 438 + errorMsg = st.Message() 399 439 } else { 400 440 code = codes.Unknown 441 + errorMsg = err.Error() 401 442 } 402 443 } 403 444 404 - s.logger.Info("gRPC request", 405 - "method", info.FullMethod, 445 + // Log completion with result details 446 + resultFields := append(logFields, 406 447 "code", code.String(), 407 448 "duration", duration, 449 + "success", err == nil, 408 450 ) 451 + 452 + if err != nil { 453 + resultFields = append(resultFields, "error", errorMsg) 454 + s.logger.Error(err, "gRPC request failed", resultFields...) 455 + } else { 456 + // Add response-specific fields for successful requests 457 + switch r := resp.(type) { 458 + case *hsmv1.ReadSecretResponse: 459 + if r.SecretData != nil { 460 + resultFields = append(resultFields, "keys_returned", len(r.SecretData.Data)) 461 + } 462 + case *hsmv1.ListSecretsResponse: 463 + resultFields = append(resultFields, "secrets_count", len(r.Paths)) 464 + } 465 + s.logger.Info("gRPC request completed", resultFields...) 466 + } 409 467 410 468 return resp, err 411 469 }
+1 -1
internal/controller/hsmsecret_controller.go
··· 163 163 164 164 // Connect to first available device 165 165 deviceName := devices[0] 166 - grpcClient, err := r.AgentManager.CreateGRPCClient(ctx, deviceName, hsmSecret.Namespace, logger) 166 + grpcClient, err := r.AgentManager.CreateGRPCClient(ctx, deviceName, r.OperatorNamespace, logger) 167 167 if err != nil { 168 168 logger.Error(err, "Failed to create gRPC client", "device", deviceName) 169 169 return ctrl.Result{RequeueAfter: time.Minute * 2}, nil
+10 -2
internal/modes/manager/manager.go
··· 349 349 setupLog.Info("starting device-scoped HSM mirroring", "interval", "30s") 350 350 351 351 // Wait for agents to be ready before starting mirroring 352 + setupLog.Info("waiting for HSM agents to be ready before starting mirroring") 352 353 ctx := context.Background() 353 354 ready, err := mirrorManager.WaitForAgentsReady(ctx, 5*time.Minute) 354 355 if err != nil { ··· 359 360 setupLog.Info("no agents became ready within timeout, disabling mirroring") 360 361 return 361 362 } 363 + setupLog.Info("HSM agents are ready, starting mirroring cycle") 362 364 363 365 for range mirrorTicker.C { 366 + setupLog.Info("starting device-scoped mirroring cycle") 364 367 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) 365 368 result, err := mirrorManager.MirrorAllSecrets(ctx) 366 369 cancel() 367 370 368 371 if err != nil { 369 372 setupLog.Error(err, "device-scoped mirroring failed") 370 - } else if result.SecretsProcessed > 0 { 373 + } else { 371 374 setupLog.Info("device-scoped mirroring completed", 372 375 "secretsProcessed", result.SecretsProcessed, 373 376 "secretsUpdated", result.SecretsUpdated, 374 377 "secretsCreated", result.SecretsCreated, 375 - "errors", len(result.Errors)) 378 + "metadataRestored", result.MetadataRestored, 379 + "errors", len(result.Errors), 380 + "success", result.Success) 381 + if len(result.Errors) > 0 { 382 + setupLog.Info("mirroring errors details", "errors", result.Errors) 383 + } 376 384 } 377 385 } 378 386 }()