···310310apiVersion: hsm.j5t.io/v1alpha1
311311kind: HSMSecret
312312metadata:
313313- name: appname-secret
313313+ name: appname-secret # HSM path automatically set to this name
314314 namespace: appnamespace
315315spec:
316316- hsmPath: "secrets/appnamespace/appname-secret" # Path on Pico HSM
317316 secretName: "appname-secret" # Target K8s Secret name (optional)
318317 autoSync: true # Enable bidirectional sync (default: true)
319318 secretType: "Opaque" # Kubernetes Secret type (default: Opaque)
···658657- Implement secure key storage and retrieval
659658- Support HSM-specific error handling
660659660660+### PKCS#11 Library Compatibility
661661+662662+**⚠️ Important: Use OpenSC Library for Pico HSM**
663663+664664+The Pico HSM requires the **OpenSC PKCS#11 library** (`/usr/lib/opensc-pkcs11.so`) instead of the default CardContact library for proper data object support.
665665+666666+**Library Configuration:**
667667+```yaml
668668+# HSMDevice CRD configuration
669669+spec:
670670+ pkcs11:
671671+ libraryPath: "/usr/lib/opensc-pkcs11.so" # Use OpenSC instead of libsc-hsm-pkcs11.so
672672+ slotId: 0
673673+ pinSecret:
674674+ name: "hsm-pin"
675675+ key: "pin"
676676+```
677677+678678+**Key Differences:**
679679+- **CardContact Library** (`libsc-hsm-pkcs11.so`): Cryptographic operations only, no data object support
680680+- **OpenSC Library** (`opensc-pkcs11.so`): Full PKCS#11 compliance with data object support
681681+682682+### Manual HSM Access with pkcs11-tool
683683+684684+**⚠️ Authentication Required**: HSM secrets created by the operator are marked as **private objects** and require PIN authentication to view.
685685+686686+**Common Operations:**
687687+688688+```bash
689689+# List all secrets (requires PIN authentication)
690690+pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" \
691691+ --login --pin="YOUR_PIN" \
692692+ --list-objects --type=data
693693+694694+# List public objects only (no PIN required)
695695+pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" \
696696+ --list-objects --type=data
697697+698698+# Read a specific secret component
699699+pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" \
700700+ --login --pin="YOUR_PIN" \
701701+ --read-object --type=data --label="secret-name/api_key"
702702+703703+# Get HSM info
704704+pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" -I
705705+706706+# List all object types
707707+pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" \
708708+ --login --pin="YOUR_PIN" \
709709+ --list-objects
710710+```
711711+712712+**Secret Storage Structure:**
713713+- Each API secret becomes **multiple PKCS#11 data objects**
714714+- Object naming: `secret-name/key-name` (e.g., `user-credentials/api_key`)
715715+- Private objects: `flags: modifiable private` (require authentication)
716716+- Public objects: `flags: modifiable` (visible without authentication)
717717+718718+**Emergency Access without Kubernetes:**
719719+```bash
720720+# Backup all secrets from pod
721721+kubectl exec HSM_AGENT_POD -- sh -c '
722722+ pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" \
723723+ --login --pin="$PKCS11_PIN" \
724724+ --list-objects --type=data > /tmp/hsm-backup.txt
725725+'
726726+727727+# Copy backup file
728728+kubectl cp HSM_AGENT_POD:/tmp/hsm-backup.txt ./hsm-secrets-backup.txt
729729+```
730730+661731### Kubernetes Integration
662732- Standard Secret object management
663733- RBAC for Secret read/write operations
···778848kubectl get hsmpool pico-hsm-discovery-pool -o jsonpath='{.status.reportingPods[*].podName}'
779849```
780850781781-This operator design provides a secure, hardware-backed secret management solution that integrates seamlessly with Kubernetes while maintaining the security benefits of HSM-based storage.851851+This operator design provides a secure, hardware-backed secret management solution that integrates seamlessly with Kubernetes while maintaining the security benefits of HSM-based storage.
852852+853853+## Quick Reference: Pico HSM + OpenSC
854854+855855+### API Testing (Recommended)
856856+```bash
857857+# Test API functionality with working HSM
858858+cd /home/data/hsm-secrets-operator/examples/api
859859+860860+# Create a secret (HSM path = secret name)
861861+./create-secret.sh my-test-secret
862862+863863+# List all secrets
864864+./list-secrets.sh
865865+866866+# Get specific secret via curl
867867+curl http://localhost:8090/api/v1/hsm/secrets/my-test-secret | jq '.'
868868+```
869869+870870+### Direct PKCS#11 Access
871871+```bash
872872+# Get agent pod name
873873+AGENT_POD=$(kubectl get pods -l app.kubernetes.io/name=hsm-agent -o jsonpath='{.items[0].metadata.name}')
874874+875875+# List all secrets (requires authentication)
876876+kubectl exec $AGENT_POD -- sh -c 'pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" --login --pin="$PKCS11_PIN" --list-objects --type=data'
877877+878878+# Read specific secret component
879879+kubectl exec $AGENT_POD -- sh -c 'pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" --login --pin="$PKCS11_PIN" --read-object --type=data --label="my-test-secret/api_key"'
880880+881881+# HSM device info
882882+kubectl exec $AGENT_POD -- pkcs11-tool --module="/usr/lib/opensc-pkcs11.so" -I
883883+```
884884+885885+### Troubleshooting
886886+- **API works, pkcs11-tool doesn't see objects**: Use `--login --pin` for private objects
887887+- **`CKR_DEVICE_REMOVED` errors**: Restart agent pod to reset PKCS#11 session
888888+- **`CKR_TEMPLATE_INCONSISTENT` errors**: Switch from CardContact to OpenSC library
889889+- **Agent crash loop**: Check library path and PIN secret configuration
-5
api/v1alpha1/hsmsecret_types.go
···26262727// HSMSecretSpec defines the desired state of HSMSecret.
2828type HSMSecretSpec struct {
2929- // HSMPath is the path on the Pico HSM where the secret data is stored
3030- // Example: "secrets/appnamespace/appname-secret"
3131- HSMPath string `json:"hsmPath"`
3232-3329 // SecretName is the name of the Kubernetes Secret object to create/update
3430 // Defaults to the HSMSecret name if not specified
3531 // +optional
···10096// +kubebuilder:object:root=true
10197// +kubebuilder:subresource:status
10298// +kubebuilder:resource:shortName=hsmsec
103103-// +kubebuilder:printcolumn:name="HSM Path",type=string,JSONPath=`.spec.hsmPath`
10499// +kubebuilder:printcolumn:name="Secret Name",type=string,JSONPath=`.spec.secretName`
105100// +kubebuilder:printcolumn:name="Sync Status",type=string,JSONPath=`.status.syncStatus`
106101// +kubebuilder:printcolumn:name="Last Sync",type=date,JSONPath=`.status.lastSyncTime`
-10
config/crd/bases/hsm.j5t.io_hsmsecrets.yaml
···1717 scope: Namespaced
1818 versions:
1919 - additionalPrinterColumns:
2020- - jsonPath: .spec.hsmPath
2121- name: HSM Path
2222- type: string
2320 - jsonPath: .spec.secretName
2421 name: Secret Name
2522 type: string
···6259 description: AutoSync enables bidirectional synchronization between
6360 HSM and Kubernetes Secret
6461 type: boolean
6565- hsmPath:
6666- description: |-
6767- HSMPath is the path on the Pico HSM where the secret data is stored
6868- Example: "secrets/appnamespace/appname-secret"
6969- type: string
7062 secretName:
7163 description: |-
7264 SecretName is the name of the Kubernetes Secret object to create/update
···8476 Only applies when AutoSync is true
8577 format: int32
8678 type: integer
8787- required:
8888- - hsmPath
8979 type: object
9080 status:
9181 description: HSMSecretStatus defines the observed state of HSMSecret.
···77 name: hsmsecret-sample
88 namespace: default
99spec:
1010- # HSM path where the secret is stored
1111- hsmPath: "secrets/default/test-secret"
1010+ # HSM path is automatically set to the metadata.name (hsmsecret-sample)
12111312 # Name of the Kubernetes Secret to create (defaults to HSMSecret name if not specified)
1413 secretName: "database-credentials"
···6464 tier: database
6565spec:
6666 # Path on HSM where secret is stored
6767- hsmPath: "secrets/production/database/credentials"
68676968 # Name of Kubernetes Secret to create/sync
7069 secretName: "database-credentials"
-1
examples/basic/api-keys.yaml
···1010 hsm.j5t.io/description: "API keys for external services (Stripe, AWS, etc.)"
1111spec:
1212 # Path on the HSM where API keys are stored
1313- hsmPath: "secrets/api-keys/external-services"
14131514 # Name of the Secret containing API keys
1615 secretName: "external-api-keys"
-1
examples/basic/database-secret.yaml
···1111 hsm.j5t.io/description: "PostgreSQL database credentials for production"
1212spec:
1313 # Path on the HSM where the secret is stored
1414- hsmPath: "secrets/production/database-credentials"
15141615 # Name of the Kubernetes Secret to create/maintain
1716 secretName: "database-credentials"
-1
examples/basic/tls-certificate.yaml
···1010 hsm.j5t.io/description: "TLS certificate and key for webapp.example.com"
1111spec:
1212 # Path on the HSM where the TLS cert/key is stored
1313- hsmPath: "secrets/tls/webapp-example-com"
14131514 # Name of the TLS Secret to create
1615 secretName: "webapp-tls"