mirror of
https://github.com/kairos-io/kcrypt-challenger.git
synced 2025-09-26 13:04:30 +00:00
643 lines
21 KiB
Go
643 lines
21 KiB
Go
// [✓] Setup a cluster
|
|
// [✓] install crds on it
|
|
// - run the server locally
|
|
// - make requests to the server to see if we can get passphrases back
|
|
package challenger
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
|
|
"github.com/go-logr/logr"
|
|
"github.com/google/go-attestation/attest"
|
|
keyserverv1alpha1 "github.com/kairos-io/kairos-challenger/api/v1alpha1"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("challenger", func() {
|
|
Describe("findSecretFor", func() {
|
|
var requestData PassphraseRequestData
|
|
var volumeList *keyserverv1alpha1.SealedVolumeList
|
|
|
|
BeforeEach(func() {
|
|
requestData = PassphraseRequestData{
|
|
TPMHash: "1234",
|
|
DeviceName: "/dev/sda1",
|
|
UUID: "sda1_uuid",
|
|
Label: "COS_PERSISTENT",
|
|
}
|
|
})
|
|
|
|
When("a sealedvolume matching the label exists", func() {
|
|
BeforeEach(func() {
|
|
volumeList = volumeListWithPartitionSpec(
|
|
keyserverv1alpha1.PartitionSpec{
|
|
Label: requestData.Label,
|
|
DeviceName: "not_matching",
|
|
UUID: "not_matching",
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "the_secret",
|
|
Path: "the_path",
|
|
}})
|
|
})
|
|
|
|
It("returns the sealed volume data", func() {
|
|
volumeData, _ := findVolumeFor(requestData, volumeList)
|
|
Expect(volumeData).ToNot(BeNil())
|
|
Expect(volumeData.Quarantined).To(BeFalse())
|
|
Expect(volumeData.SecretName).To(Equal("the_secret"))
|
|
Expect(volumeData.SecretPath).To(Equal("the_path"))
|
|
})
|
|
})
|
|
|
|
When("a sealedvolume with empty field exists", func() {
|
|
BeforeEach(func() {
|
|
volumeList = volumeListWithPartitionSpec(
|
|
keyserverv1alpha1.PartitionSpec{
|
|
Label: "",
|
|
DeviceName: "not_matching",
|
|
UUID: "not_matching",
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "the_secret",
|
|
Path: "the_path",
|
|
}})
|
|
|
|
requestData = PassphraseRequestData{
|
|
TPMHash: "1234",
|
|
Label: "",
|
|
DeviceName: "/dev/sda1",
|
|
UUID: "sda1_uuid",
|
|
}
|
|
})
|
|
|
|
It("doesn't match a request with an empty field", func() {
|
|
volumeData, _ := findVolumeFor(requestData, volumeList)
|
|
Expect(volumeData).To(BeNil())
|
|
})
|
|
})
|
|
|
|
When("a sealedvolume matching the device name exists", func() {
|
|
BeforeEach(func() {
|
|
volumeList = volumeListWithPartitionSpec(
|
|
keyserverv1alpha1.PartitionSpec{
|
|
Label: "not_matching",
|
|
DeviceName: requestData.DeviceName,
|
|
UUID: "not_matching",
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "the_secret",
|
|
Path: "the_path",
|
|
}})
|
|
})
|
|
|
|
It("returns the sealed volume data", func() {
|
|
volumeData, _ := findVolumeFor(requestData, volumeList)
|
|
Expect(volumeData).ToNot(BeNil())
|
|
Expect(volumeData.Quarantined).To(BeFalse())
|
|
Expect(volumeData.SecretName).To(Equal("the_secret"))
|
|
Expect(volumeData.SecretPath).To(Equal("the_path"))
|
|
})
|
|
})
|
|
|
|
When("a sealedvolume matching the UUID exists", func() {
|
|
BeforeEach(func() {
|
|
volumeList = volumeListWithPartitionSpec(
|
|
keyserverv1alpha1.PartitionSpec{
|
|
Label: "not_matching",
|
|
DeviceName: "not_matching",
|
|
UUID: requestData.UUID,
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "the_secret",
|
|
Path: "the_path",
|
|
}})
|
|
})
|
|
|
|
It("returns the sealed volume data", func() {
|
|
volumeData, _ := findVolumeFor(requestData, volumeList)
|
|
Expect(volumeData).ToNot(BeNil())
|
|
Expect(volumeData.Quarantined).To(BeFalse())
|
|
Expect(volumeData.SecretName).To(Equal("the_secret"))
|
|
Expect(volumeData.SecretPath).To(Equal("the_path"))
|
|
})
|
|
})
|
|
|
|
When("a matching sealedvolume doesn't exist", func() {
|
|
BeforeEach(func() {
|
|
volumeList = volumeListWithPartitionSpec(
|
|
keyserverv1alpha1.PartitionSpec{
|
|
Label: "not_matching",
|
|
DeviceName: "not_matching",
|
|
UUID: "not_matching",
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "the_secret",
|
|
Path: "the_path",
|
|
}})
|
|
})
|
|
|
|
It("returns nil sealedVolumeData", func() {
|
|
volumeData, _ := findVolumeFor(requestData, volumeList)
|
|
Expect(volumeData).To(BeNil())
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("Selective Enrollment Mode", func() {
|
|
var logger logr.Logger
|
|
|
|
BeforeEach(func() {
|
|
logger = logr.Discard()
|
|
})
|
|
|
|
Describe("verifyAKMatch with selective enrollment", func() {
|
|
var currentAK *attest.AttestationParameters
|
|
var expectedAKPEM string
|
|
const mockAKPublicKey = "mock-ak-public-key"
|
|
|
|
BeforeEach(func() {
|
|
// Mock current AK parameters - in real implementation this would come from TPM
|
|
currentAK = &attest.AttestationParameters{
|
|
Public: []byte(mockAKPublicKey),
|
|
UseTCSDActivationFormat: false,
|
|
CreateData: []byte("mock-create-data"),
|
|
CreateAttestation: []byte("mock-create-attestation"),
|
|
CreateSignature: []byte("mock-create-signature"),
|
|
}
|
|
|
|
// Generate the expected PEM encoding from the plain text constant
|
|
var err error
|
|
expectedAKPEM, err = encodeAKToPEM(currentAK)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
When("stored AK is empty (re-enrollment mode)", func() {
|
|
It("should store the current AK value during re-enrollment", func() {
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
AKPublicKey: "", // Empty = re-enrollment mode
|
|
}
|
|
|
|
// Before re-enrollment: AK should be empty
|
|
Expect(attestation.AKPublicKey).To(Equal(""))
|
|
|
|
// Re-enrollment should store the current AK
|
|
err := updateAttestationDataSelective(attestation, currentAK, nil, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// After re-enrollment: AK should contain the exact expected PEM value
|
|
Expect(attestation.AKPublicKey).To(Equal(expectedAKPEM))
|
|
})
|
|
|
|
It("should accept any AK, store it during re-enrollment, then enforce exact match", func() {
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
AKPublicKey: "", // Start in re-enrollment mode
|
|
}
|
|
sealedVolume := &keyserverv1alpha1.SealedVolume{
|
|
Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
Attestation: attestation,
|
|
},
|
|
}
|
|
|
|
// Step 1: Verification should pass with any AK (re-enrollment mode)
|
|
err := verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 2: Re-enroll - store the AK
|
|
err = updateAttestationDataSelective(attestation, currentAK, nil, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 3: Now we should be in enforcement mode - same AK should pass
|
|
err = verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 4: Different AK should now fail (enforcement mode)
|
|
differentAK := &attest.AttestationParameters{
|
|
Public: []byte("different-ak-key"),
|
|
}
|
|
err = verifyAKMatchSelective(sealedVolume, differentAK, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("AK public key does not match"))
|
|
})
|
|
})
|
|
|
|
When("stored AK is set (enforcement mode)", func() {
|
|
It("should enforce exact match", func() {
|
|
// Create a specific AK PEM that won't match our mock
|
|
storedAKPEM := "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtest\n-----END PUBLIC KEY-----"
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
AKPublicKey: storedAKPEM,
|
|
}
|
|
sealedVolume := &keyserverv1alpha1.SealedVolume{
|
|
Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
Attestation: attestation,
|
|
},
|
|
}
|
|
|
|
err := verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("AK public key does not match"))
|
|
})
|
|
})
|
|
|
|
When("no attestation data exists", func() {
|
|
It("should return error", func() {
|
|
sealedVolume := &keyserverv1alpha1.SealedVolume{
|
|
Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
Attestation: nil,
|
|
},
|
|
}
|
|
|
|
err := verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("no attestation data"))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("verifyPCRValuesSelective", func() {
|
|
var currentPCRs *keyserverv1alpha1.PCRValues
|
|
const expectedPCR0 = "abc123def456"
|
|
const expectedPCR7 = "ghi789jkl012"
|
|
const expectedPCR11 = "mno345pqr678"
|
|
|
|
BeforeEach(func() {
|
|
currentPCRs = &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": expectedPCR0,
|
|
"7": expectedPCR7,
|
|
"11": expectedPCR11,
|
|
},
|
|
}
|
|
})
|
|
|
|
When("stored PCR values are empty (re-enrollment mode)", func() {
|
|
It("should accept any PCR values during verification", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "", // Empty = re-enrollment mode
|
|
"7": "", // Empty = re-enrollment mode
|
|
"11": "", // Empty = re-enrollment mode
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
It("should store the current PCR values during re-enrollment", func() {
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
PCRValues: &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "", // Empty = re-enrollment mode
|
|
"7": "", // Empty = re-enrollment mode
|
|
"11": "", // Empty = re-enrollment mode
|
|
},
|
|
},
|
|
}
|
|
|
|
// Before re-enrollment: PCRs should be empty
|
|
Expect(attestation.PCRValues.PCRs["0"]).To(Equal(""))
|
|
Expect(attestation.PCRValues.PCRs["7"]).To(Equal(""))
|
|
Expect(attestation.PCRValues.PCRs["11"]).To(Equal(""))
|
|
|
|
// Re-enrollment should store the current PCR values
|
|
err := updateAttestationDataSelective(attestation, nil, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// After re-enrollment: PCRs should be stored with exact expected values
|
|
Expect(attestation.PCRValues.PCRs["0"]).To(Equal(expectedPCR0))
|
|
Expect(attestation.PCRValues.PCRs["7"]).To(Equal(expectedPCR7))
|
|
Expect(attestation.PCRValues.PCRs["11"]).To(Equal(expectedPCR11))
|
|
})
|
|
|
|
It("should transition from re-enrollment mode to enforcement mode", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "", // Start in re-enrollment mode
|
|
},
|
|
}
|
|
|
|
// Create a limited current PCR set (only PCR0) to test selective enrollment
|
|
limitedCurrentPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": expectedPCR0, // Only provide PCR0
|
|
},
|
|
}
|
|
|
|
// Step 1: Should accept any PCR values (re-enrollment mode)
|
|
err := verifyPCRValuesSelective(storedPCRs, limitedCurrentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 2: Re-enroll - store the PCR value (should only update the empty PCR0)
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
PCRValues: storedPCRs,
|
|
}
|
|
err = updateAttestationDataSelective(attestation, nil, limitedCurrentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Verify PCR0 was enrolled and no other PCRs were added
|
|
Expect(storedPCRs.PCRs["0"]).To(Equal(expectedPCR0))
|
|
Expect(storedPCRs.PCRs).To(HaveLen(1)) // Should still only have PCR0
|
|
|
|
// Step 3: Now should be in enforcement mode - same PCR should pass
|
|
err = verifyPCRValuesSelective(storedPCRs, limitedCurrentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 4: Different PCR should now fail (enforcement mode)
|
|
differentPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "different_value",
|
|
},
|
|
}
|
|
err = verifyPCRValuesSelective(storedPCRs, differentPCRs, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("PCR0 changed"))
|
|
})
|
|
})
|
|
|
|
When("stored PCR values are set (enforcement mode)", func() {
|
|
It("should enforce exact match for set values", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "abc123def456", // Matches current
|
|
"7": "different_value", // Different from current
|
|
"11": "mno345pqr678", // Matches current
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, currentPCRs, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("PCR7 changed"))
|
|
})
|
|
|
|
It("should pass when all set values match", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "abc123def456", // Matches current
|
|
"7": "ghi789jkl012", // Matches current
|
|
"11": "mno345pqr678", // Matches current
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
})
|
|
|
|
When("PCR fields are omitted (skip verification)", func() {
|
|
It("should skip verification for omitted PCRs entirely", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "abc123def456", // Present and matches
|
|
"7": "ghi789jkl012", // Present and matches
|
|
// "11" is omitted entirely = skip verification
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
})
|
|
|
|
When("mixed selective and enforcement mode", func() {
|
|
It("should handle combination of empty, set, and omitted PCRs", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "", // Empty = re-enrollment mode
|
|
"7": "ghi789jkl012", // Set = enforcement mode (matches)
|
|
"14": "any_value", // Set but PCR14 not in current (should fail)
|
|
// "11" omitted = skip verification
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, currentPCRs, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("PCR14"))
|
|
})
|
|
})
|
|
|
|
When("no stored PCR values exist", func() {
|
|
It("should accept any current PCR values", func() {
|
|
err := verifyPCRValuesSelective(nil, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
})
|
|
|
|
When("no current PCR values provided", func() {
|
|
It("should pass if no stored values either", func() {
|
|
err := verifyPCRValuesSelective(nil, nil, logger)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
It("should fail if stored values expect specific PCRs", func() {
|
|
storedPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "abc123def456",
|
|
},
|
|
}
|
|
|
|
err := verifyPCRValuesSelective(storedPCRs, nil, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("no current PCR values"))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("updateAttestationData for selective enrollment", func() {
|
|
It("should update empty fields with current values", func() {
|
|
currentAK := &attest.AttestationParameters{
|
|
Public: []byte("new-ak-public-key"),
|
|
}
|
|
currentPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "new_pcr0_value",
|
|
"7": "new_pcr7_value",
|
|
"11": "new_pcr11_value",
|
|
},
|
|
}
|
|
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
AKPublicKey: "", // Empty = should be updated
|
|
PCRValues: &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "", // Empty = should be updated
|
|
"7": "fixed_pcr7_value", // Set = should NOT be updated
|
|
"11": "", // Empty = should be updated
|
|
},
|
|
},
|
|
}
|
|
|
|
err := updateAttestationDataSelective(attestation, currentAK, currentPCRs, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// AK should be updated
|
|
Expect(attestation.AKPublicKey).ToNot(BeEmpty())
|
|
|
|
// PCR0 should be updated (was empty)
|
|
Expect(attestation.PCRValues.PCRs["0"]).To(Equal("new_pcr0_value"))
|
|
|
|
// PCR7 should NOT be updated (was set)
|
|
Expect(attestation.PCRValues.PCRs["7"]).To(Equal("fixed_pcr7_value"))
|
|
|
|
// PCR11 should be updated (was empty)
|
|
Expect(attestation.PCRValues.PCRs["11"]).To(Equal("new_pcr11_value"))
|
|
})
|
|
|
|
It("should demonstrate AK re-enrollment workflow", func() {
|
|
// Step 1: Start with empty AK (re-enrollment mode)
|
|
originalAK := ""
|
|
attestation := &keyserverv1alpha1.AttestationSpec{
|
|
AKPublicKey: originalAK, // Empty = re-enrollment mode
|
|
}
|
|
|
|
// Step 2: Current AK from client
|
|
currentAK := &attest.AttestationParameters{
|
|
Public: []byte("client-provided-ak-key"),
|
|
}
|
|
|
|
// Step 3: Verification should pass (empty stored AK accepts any)
|
|
sealedVolume := &keyserverv1alpha1.SealedVolume{
|
|
Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
Attestation: attestation,
|
|
},
|
|
}
|
|
err := verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 4: Update should store the new AK (this is the re-enrollment)
|
|
err = updateAttestationDataSelective(attestation, currentAK, nil, logger)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Step 5: Verify the AK was actually enrolled (stored)
|
|
Expect(attestation.AKPublicKey).ToNot(BeEmpty())
|
|
Expect(attestation.AKPublicKey).ToNot(Equal(originalAK))
|
|
|
|
// Step 6: Future verification should now require exact match
|
|
err = verifyAKMatchSelective(sealedVolume, currentAK, logger)
|
|
Expect(err).To(BeNil()) // Should still pass with same AK
|
|
|
|
// Step 7: Different AK should now fail (enforcement mode)
|
|
differentAK := &attest.AttestationParameters{
|
|
Public: []byte("different-ak-key"),
|
|
}
|
|
err = verifyAKMatchSelective(sealedVolume, differentAK, logger)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("AK public key does not match"))
|
|
})
|
|
})
|
|
|
|
Describe("Initial TOFU Enrollment behavior", func() {
|
|
It("should store ALL provided PCRs during initial enrollment", func() {
|
|
clientPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"0": "pcr0_value",
|
|
"1": "pcr1_value",
|
|
"2": "pcr2_value",
|
|
"7": "pcr7_value",
|
|
"11": "pcr11_value",
|
|
"14": "pcr14_value",
|
|
},
|
|
}
|
|
|
|
attestation := createInitialTOFUAttestation(nil, clientPCRs, logger)
|
|
|
|
// All provided PCRs should be stored
|
|
Expect(attestation.PCRValues).ToNot(BeNil())
|
|
Expect(attestation.PCRValues.PCRs).To(HaveLen(6))
|
|
Expect(attestation.PCRValues.PCRs["0"]).To(Equal("pcr0_value"))
|
|
Expect(attestation.PCRValues.PCRs["1"]).To(Equal("pcr1_value"))
|
|
Expect(attestation.PCRValues.PCRs["2"]).To(Equal("pcr2_value"))
|
|
Expect(attestation.PCRValues.PCRs["7"]).To(Equal("pcr7_value"))
|
|
Expect(attestation.PCRValues.PCRs["11"]).To(Equal("pcr11_value"))
|
|
Expect(attestation.PCRValues.PCRs["14"]).To(Equal("pcr14_value"))
|
|
})
|
|
|
|
It("should not filter or omit any PCRs during TOFU", func() {
|
|
// Test that even "sensitive" PCRs like PCR11 are stored
|
|
clientPCRs := &keyserverv1alpha1.PCRValues{
|
|
PCRs: map[string]string{
|
|
"11": "kernel_pcr_value", // Previously filtered out
|
|
"12": "other_pcr_value",
|
|
},
|
|
}
|
|
|
|
attestation := createInitialTOFUAttestation(nil, clientPCRs, logger)
|
|
|
|
Expect(attestation.PCRValues.PCRs).To(HaveKey("11"))
|
|
Expect(attestation.PCRValues.PCRs).To(HaveKey("12"))
|
|
Expect(attestation.PCRValues.PCRs["11"]).To(Equal("kernel_pcr_value"))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("handleTPMAttestation functions", func() {
|
|
Describe("establishAttestationConnection", func() {
|
|
var mockResponseWriter *httptest.ResponseRecorder
|
|
var mockRequest *http.Request
|
|
var logger logr.Logger
|
|
|
|
BeforeEach(func() {
|
|
logger = logr.Discard()
|
|
mockResponseWriter = httptest.NewRecorder()
|
|
mockRequest = httptest.NewRequest("GET", "/test", nil)
|
|
|
|
// Set partition headers
|
|
mockRequest.Header.Set("label", "COS_PERSISTENT")
|
|
mockRequest.Header.Set("name", "/dev/sda1")
|
|
mockRequest.Header.Set("uuid", "test-uuid-123")
|
|
})
|
|
|
|
It("should return error when WebSocket upgrade fails", func() {
|
|
// This test checks the error behavior when WebSocket upgrade fails
|
|
conn, partition, err := establishAttestationConnection(mockResponseWriter, mockRequest, logger)
|
|
|
|
// WebSocket upgrade should fail with regular HTTP request
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("upgrade"))
|
|
Expect(conn).To(BeNil())
|
|
|
|
// When upgrade fails, partition info is not extracted (function returns early)
|
|
Expect(partition.Label).To(Equal(""))
|
|
Expect(partition.DeviceName).To(Equal(""))
|
|
Expect(partition.UUID).To(Equal(""))
|
|
})
|
|
})
|
|
|
|
})
|
|
})
|
|
|
|
func volumeListWithPartitionSpec(partitionSpec keyserverv1alpha1.PartitionSpec) *keyserverv1alpha1.SealedVolumeList {
|
|
return &keyserverv1alpha1.SealedVolumeList{
|
|
Items: []keyserverv1alpha1.SealedVolume{
|
|
{Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
TPMHash: "1234",
|
|
Partitions: []keyserverv1alpha1.PartitionSpec{
|
|
partitionSpec,
|
|
},
|
|
Quarantined: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func volumeListWithAttestationSpec(tpmHash string, attestation *keyserverv1alpha1.AttestationSpec) *keyserverv1alpha1.SealedVolumeList {
|
|
return &keyserverv1alpha1.SealedVolumeList{
|
|
Items: []keyserverv1alpha1.SealedVolume{
|
|
{Spec: keyserverv1alpha1.SealedVolumeSpec{
|
|
TPMHash: tpmHash,
|
|
Partitions: []keyserverv1alpha1.PartitionSpec{
|
|
{
|
|
Label: "COS_PERSISTENT",
|
|
Secret: &keyserverv1alpha1.SecretSpec{
|
|
Name: "test-secret",
|
|
Path: "pass",
|
|
},
|
|
},
|
|
},
|
|
Quarantined: false,
|
|
Attestation: attestation,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|