mirror of
https://github.com/kairos-io/kcrypt-challenger.git
synced 2025-09-24 12:39:51 +00:00
This will make debugging easier both while developing and in production. No need to use it through the kcrypt binary anymore, because we might not actually care about decrypting the disks but rather about getting the passphrase from the KMS. Signed-off-by: Dimitris Karakasilis <dimitris@karakasilis.me>
399 lines
13 KiB
Go
399 lines
13 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/kairos-io/kairos-sdk/kcrypt/bus"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
func TestCLI(t *testing.T) {
|
|
RegisterFailHandler(Fail)
|
|
RunSpecs(t, "Discovery CLI Suite")
|
|
}
|
|
|
|
var _ = Describe("CLI Interface", func() {
|
|
BeforeEach(func() {
|
|
// Clean up any previous log files
|
|
_ = os.Remove("/tmp/kcrypt-challenger-client.log")
|
|
})
|
|
|
|
AfterEach(func() {
|
|
// Clean up log files
|
|
_ = os.Remove("/tmp/kcrypt-challenger-client.log")
|
|
})
|
|
|
|
Context("CLI help and version", func() {
|
|
It("should show help when --help is used", func() {
|
|
exitCode := RunCLIMode([]string{"--help"})
|
|
|
|
Expect(exitCode).To(Equal(0))
|
|
// We can't easily test the output content without complex output capture,
|
|
// but we can verify the function executes and returns the correct exit code
|
|
})
|
|
|
|
It("should show version when --version is used", func() {
|
|
exitCode := RunCLIMode([]string{"--version"})
|
|
|
|
Expect(exitCode).To(Equal(0))
|
|
// We can't easily test the output content without complex output capture,
|
|
// but we can verify the function executes and returns the correct exit code
|
|
})
|
|
})
|
|
|
|
Context("Input validation", func() {
|
|
It("should require all partition parameters", func() {
|
|
exitCode := RunCLIMode([]string{"--partition-name=/dev/sda2"})
|
|
|
|
Expect(exitCode).To(Equal(1))
|
|
// Should exit with error code 1 when required parameters are missing
|
|
})
|
|
|
|
It("should validate that all required fields are provided", func() {
|
|
// Test missing UUID
|
|
exitCode := RunCLIMode([]string{"--partition-name=/dev/sda2", "--partition-label=test"})
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Test missing label
|
|
exitCode = RunCLIMode([]string{"--partition-name=/dev/sda2", "--partition-uuid=12345"})
|
|
Expect(exitCode).To(Equal(1))
|
|
})
|
|
|
|
It("should handle invalid flags gracefully", func() {
|
|
exitCode := RunCLIMode([]string{"--invalid-flag"})
|
|
|
|
Expect(exitCode).To(Equal(1))
|
|
// FlagSet should handle the error and return exit code 1
|
|
})
|
|
})
|
|
|
|
Context("Flow detection and backend integration", func() {
|
|
It("should attempt to get passphrase with valid parameters", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid-12345",
|
|
"--partition-label=test-label",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// We expect this to fail since there's no server, but it should reach the backend logic
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Should show flow detection in the log (if created)
|
|
logContent, readErr := os.ReadFile("/tmp/kcrypt-challenger-client.log")
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should contain flow detection message
|
|
Expect(logStr).To(ContainSubstring("flow"))
|
|
}
|
|
})
|
|
|
|
It("should use the correct backend client logic", func() {
|
|
// Test that the CLI mode uses the same GetPassphrase method
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail but attempt to use the client
|
|
Expect(exitCode).To(Equal(1))
|
|
// The important thing is that it reaches the backend and doesn't crash
|
|
})
|
|
})
|
|
|
|
Context("Event validation", func() {
|
|
It("should correctly identify valid events", func() {
|
|
// Test that discovery.password is recognized as a valid event
|
|
Expect(isEventDefined("discovery.password")).To(BeTrue())
|
|
Expect(isEventDefined(string(bus.EventDiscoveryPassword))).To(BeTrue())
|
|
})
|
|
|
|
It("should reject invalid events", func() {
|
|
// Test that invalid events are rejected
|
|
Expect(isEventDefined("invalid.event")).To(BeFalse())
|
|
Expect(isEventDefined("")).To(BeFalse())
|
|
Expect(isEventDefined(123)).To(BeFalse())
|
|
})
|
|
|
|
It("should route to plugin mode for valid events", func() {
|
|
// This would be the behavior when called with discovery.password
|
|
isValid := isEventDefined("discovery.password")
|
|
Expect(isValid).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("Configuration overrides with debug logging", func() {
|
|
var tempDir string
|
|
var originalLogFile string
|
|
var testLogFile string
|
|
var configDir string
|
|
|
|
BeforeEach(func() {
|
|
// Create a temporary directory for this test
|
|
var err error
|
|
tempDir, err = os.MkdirTemp("", "kcrypt-test-*")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// Use /tmp/oem since it's already in confScanDirs
|
|
configDir = "/tmp/oem"
|
|
err = os.MkdirAll(configDir, 0755)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// Create a test configuration file with known values
|
|
configContent := `kcrypt:
|
|
challenger:
|
|
challenger_server: "https://default-server.com:8080"
|
|
mdns: false
|
|
certificate: "/default/path/to/cert.pem"
|
|
nv_index: "0x1500000"
|
|
c_index: "0x1400000"
|
|
tpm_device: "/dev/tpm0"
|
|
`
|
|
configFile := filepath.Join(configDir, "kairos.yaml")
|
|
err = os.WriteFile(configFile, []byte(configContent), 0644)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// Override the log file location for testing
|
|
originalLogFile = os.Getenv("KAIROS_LOG_FILE")
|
|
testLogFile = filepath.Join(tempDir, "kcrypt-discovery-challenger.log")
|
|
os.Setenv("KAIROS_LOG_FILE", testLogFile)
|
|
})
|
|
|
|
AfterEach(func() {
|
|
// Restore original log file setting
|
|
if originalLogFile != "" {
|
|
os.Setenv("KAIROS_LOG_FILE", originalLogFile)
|
|
} else {
|
|
os.Unsetenv("KAIROS_LOG_FILE")
|
|
}
|
|
|
|
// Clean up config file
|
|
_ = os.RemoveAll(configDir)
|
|
|
|
// Clean up temporary directory
|
|
_ = os.RemoveAll(tempDir)
|
|
})
|
|
|
|
It("should read and use original configuration values without overrides", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--debug",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail at passphrase retrieval but config parsing should work
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check that original configuration values are logged
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should show original configuration values from the file
|
|
Expect(logStr).To(ContainSubstring("Original configuration"))
|
|
Expect(logStr).To(ContainSubstring("https://default-server.com:8080"))
|
|
Expect(logStr).To(ContainSubstring("false")) // mdns value
|
|
Expect(logStr).To(ContainSubstring("/default/path/to/cert.pem"))
|
|
// Should also show final configuration (which should be the same as original)
|
|
Expect(logStr).To(ContainSubstring("Final configuration"))
|
|
// Should NOT contain any override messages since no flags were provided
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding server URL"))
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding MDNS setting"))
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding certificate"))
|
|
}
|
|
})
|
|
|
|
It("should show configuration file values being overridden by CLI flags", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--challenger-server=https://overridden-server.com:9999",
|
|
"--mdns=true",
|
|
"--certificate=/overridden/cert.pem",
|
|
"--debug",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail at passphrase retrieval but config parsing and overrides should work
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check that both original and overridden values are logged
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should show original configuration values from the file
|
|
Expect(logStr).To(ContainSubstring("Original configuration"))
|
|
Expect(logStr).To(ContainSubstring("https://default-server.com:8080"))
|
|
Expect(logStr).To(ContainSubstring("/default/path/to/cert.pem"))
|
|
|
|
// Should show override messages
|
|
Expect(logStr).To(ContainSubstring("Overriding server URL"))
|
|
Expect(logStr).To(ContainSubstring("https://default-server.com:8080 -> https://overridden-server.com:9999"))
|
|
Expect(logStr).To(ContainSubstring("Overriding MDNS setting"))
|
|
Expect(logStr).To(ContainSubstring("false -> true"))
|
|
Expect(logStr).To(ContainSubstring("Overriding certificate"))
|
|
|
|
// Should show final configuration with overridden values
|
|
Expect(logStr).To(ContainSubstring("Final configuration"))
|
|
Expect(logStr).To(ContainSubstring("https://overridden-server.com:9999"))
|
|
Expect(logStr).To(ContainSubstring("/overridden/cert.pem"))
|
|
}
|
|
})
|
|
|
|
It("should apply CLI flag overrides and log configuration changes", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--challenger-server=https://custom-server.com:8082",
|
|
"--mdns=true",
|
|
"--certificate=/path/to/cert.pem",
|
|
"--debug",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail at passphrase retrieval but flag parsing should work
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check if debug log exists and contains configuration information
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should contain debug information about configuration overrides
|
|
Expect(logStr).To(ContainSubstring("Overriding server URL"))
|
|
Expect(logStr).To(ContainSubstring("https://custom-server.com:8082"))
|
|
Expect(logStr).To(ContainSubstring("Overriding MDNS setting"))
|
|
Expect(logStr).To(ContainSubstring("Overriding certificate"))
|
|
}
|
|
})
|
|
|
|
It("should show original vs final configuration in debug mode", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--challenger-server=https://override-server.com:9999",
|
|
"--debug",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail but debug information should be logged
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check for original and final configuration logging
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
Expect(logStr).To(ContainSubstring("Original configuration"))
|
|
Expect(logStr).To(ContainSubstring("Final configuration"))
|
|
Expect(logStr).To(ContainSubstring("https://override-server.com:9999"))
|
|
}
|
|
})
|
|
|
|
It("should log partition details in debug mode", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/custom-partition",
|
|
"--partition-uuid=custom-uuid-123",
|
|
"--partition-label=custom-label-456",
|
|
"--debug",
|
|
"--attempts=2",
|
|
})
|
|
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check for partition details in debug log
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
Expect(logStr).To(ContainSubstring("Partition details"))
|
|
Expect(logStr).To(ContainSubstring("/dev/custom-partition"))
|
|
Expect(logStr).To(ContainSubstring("custom-uuid-123"))
|
|
Expect(logStr).To(ContainSubstring("custom-label-456"))
|
|
Expect(logStr).To(ContainSubstring("Attempts: 2"))
|
|
}
|
|
})
|
|
|
|
It("should not log debug information without debug flag", func() {
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--attempts=1",
|
|
})
|
|
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Debug log should not exist or should not contain detailed debug info
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should not contain debug-level details
|
|
Expect(logStr).NotTo(ContainSubstring("Original configuration"))
|
|
Expect(logStr).NotTo(ContainSubstring("Partition details"))
|
|
}
|
|
})
|
|
|
|
It("should handle missing configuration file gracefully and show defaults", func() {
|
|
// Remove the config file to test default behavior
|
|
_ = os.RemoveAll(configDir)
|
|
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/test",
|
|
"--partition-uuid=test-uuid",
|
|
"--partition-label=test-label",
|
|
"--debug",
|
|
"--attempts=1",
|
|
})
|
|
|
|
// Should fail at passphrase retrieval but not due to config parsing
|
|
Expect(exitCode).To(Equal(1))
|
|
|
|
// Check that default/empty configuration values are logged
|
|
logContent, readErr := os.ReadFile(testLogFile)
|
|
if readErr == nil {
|
|
logStr := string(logContent)
|
|
// Should show original configuration (which should be empty/defaults)
|
|
Expect(logStr).To(ContainSubstring("Original configuration"))
|
|
Expect(logStr).To(ContainSubstring("Final configuration"))
|
|
// Should NOT contain override messages since no flags were provided
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding server URL"))
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding MDNS setting"))
|
|
Expect(logStr).NotTo(ContainSubstring("Overriding certificate"))
|
|
}
|
|
})
|
|
})
|
|
|
|
Context("CLI argument parsing", func() {
|
|
It("should parse all arguments correctly", func() {
|
|
// This will fail at the client creation/server connection,
|
|
// but should successfully parse all arguments
|
|
exitCode := RunCLIMode([]string{
|
|
"--partition-name=/dev/custom",
|
|
"--partition-uuid=custom-uuid-999",
|
|
"--partition-label=custom-label",
|
|
"--attempts=5",
|
|
})
|
|
|
|
Expect(exitCode).To(Equal(1)) // Fails due to no server
|
|
// The important thing is that flag parsing worked and it reached the backend
|
|
})
|
|
|
|
It("should handle boolean flags correctly", func() {
|
|
// Test help flag
|
|
exitCode := RunCLIMode([]string{"-help"})
|
|
Expect(exitCode).To(Equal(0))
|
|
|
|
// Test version flag
|
|
exitCode = RunCLIMode([]string{"-version"})
|
|
Expect(exitCode).To(Equal(0))
|
|
})
|
|
})
|
|
})
|