Skip to content

Commit

Permalink
Merge pull request #190 from mauricioharley/luna_functional_tests
Browse files Browse the repository at this point in the history
Functional tests for HSM Support
  • Loading branch information
openshift-merge-bot[bot] authored Jan 6, 2025
2 parents 02efac8 + 09d7f3d commit 1482a31
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 1 deletion.
180 changes: 180 additions & 0 deletions tests/functional/barbican_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
. "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers"

barbicanv1beta1 "github.com/openstack-k8s-operators/barbican-operator/api/v1beta1"
controllers "github.com/openstack-k8s-operators/barbican-operator/controllers"
"github.com/openstack-k8s-operators/barbican-operator/pkg/barbican"
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
mariadb_test "github.com/openstack-k8s-operators/mariadb-operator/api/test/helpers"
Expand Down Expand Up @@ -431,6 +432,185 @@ var _ = Describe("Barbican controller", func() {
})
})

When("A Barbican with HSM is created", func() {
BeforeEach(func() {
DeferCleanup(k8sClient.Delete, ctx, CreateHSMLoginSecret(barbicanTest.Instance.Namespace, HSMLoginSecret))
DeferCleanup(k8sClient.Delete, ctx, CreateHSMCertsSecret(barbicanTest.Instance.Namespace, HSMCertsSecret))

DeferCleanup(th.DeleteInstance, CreateBarbican(barbicanTest.Instance, GetHSMBarbicanSpec()))
DeferCleanup(k8sClient.Delete, ctx, CreateBarbicanMessageBusSecret(barbicanTest.Instance.Namespace, barbicanTest.RabbitmqSecretName))
infra.SimulateTransportURLReady(barbicanTest.BarbicanTransportURL)
DeferCleanup(k8sClient.Delete, ctx, CreateKeystoneAPISecret(barbicanTest.Instance.Namespace, SecretName))
DeferCleanup(
mariadb.DeleteDBService,
mariadb.CreateDBService(
barbicanTest.Instance.Namespace,
GetBarbican(barbicanTest.Instance).Spec.DatabaseInstance,
corev1.ServiceSpec{
Ports: []corev1.ServicePort{{Port: 3306}},
},
),
)
mariadb.SimulateMariaDBAccountCompleted(barbicanTest.BarbicanDatabaseAccount)
mariadb.SimulateMariaDBDatabaseCompleted(barbicanTest.BarbicanDatabaseName)
DeferCleanup(keystone.DeleteKeystoneAPI, keystone.CreateKeystoneAPI(barbicanTest.Instance.Namespace))
th.SimulateJobSuccess(barbicanTest.BarbicanDBSync)
DeferCleanup(th.DeleteInstance, CreateBarbicanAPI(barbicanTest.Instance, GetHSMBarbicanAPISpec()))
th.SimulateJobSuccess(barbicanTest.BarbicanP11Prep)
})

It("Creates BarbicanAPI", func() {
keystone.SimulateKeystoneEndpointReady(barbicanTest.BarbicanKeystoneEndpoint)

th.ExpectCondition(
barbicanTest.Instance,
ConditionGetterFunc(BarbicanAPIConditionGetter),
condition.TLSInputReadyCondition,
corev1.ConditionTrue,
)

BarbicanAPIExists(barbicanTest.Instance)

d := th.GetDeployment(barbicanTest.BarbicanAPI)
// Check the resulting deployment fields
Expect(int(*d.Spec.Replicas)).To(Equal(1))

Expect(d.Spec.Template.Spec.Volumes).To(HaveLen(4))
Expect(d.Spec.Template.Spec.Containers).To(HaveLen(2))

container := d.Spec.Template.Spec.Containers[1]

Expect(container.ReadinessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTP))
Expect(container.LivenessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTP))

// Checking the HSM container
Expect(container.Name).To(Equal(barbican.ComponentAPI))
foundMount := false
indexMount := 0
for index, volumeMount := range container.VolumeMounts {
if volumeMount.Name == barbican.LunaVolume {
foundMount = true
indexMount = index
break
}
}
Expect(foundMount).To(BeTrue())
Expect(container.VolumeMounts[indexMount].MountPath).To(Equal(HSMCertificatesMountPoint))
})

It("Verifies the PKCS11 struct is in good shape", func() {
Barbican := GetBarbican(barbicanTest.Instance)
Expect(Barbican.Spec.EnabledSecretStores).Should(Equal([]barbicanv1beta1.SecretStore{"pkcs11"}))
Expect(Barbican.Spec.GlobalDefaultSecretStore).Should(Equal(barbicanv1beta1.SecretStore("pkcs11")))

pkcs11 := Barbican.Spec.PKCS11
Expect(pkcs11.SlotId).Should(Equal(HSMSlotID))
Expect(pkcs11.LibraryPath).Should(Equal(HSMLibraryPath))
Expect(pkcs11.CertificatesMountPoint).Should(Equal(HSMCertificatesMountPoint))
Expect(pkcs11.LoginSecret).Should(Equal(HSMLoginSecret))
Expect(pkcs11.CertificatesSecret).Should(Equal(HSMCertsSecret))
Expect(pkcs11.MKEKLabel).Should(Equal(HSMMKEKLabel))
Expect(pkcs11.HMACLabel).Should(Equal(HSMHMACLabel))
Expect(pkcs11.ServerAddress).Should(Equal(HSMServerAddress))
Expect(pkcs11.ClientAddress).Should(Equal(HSMClientAddress))
Expect(pkcs11.Type).Should(Equal(HSMType))
})

It("Checks if the two relevant secrets have the right contents", func() {
hsmSecret := th.GetSecret(barbicanTest.BarbicanHSMLoginSecret)
Expect(hsmSecret).ShouldNot(BeNil())
confHSM := hsmSecret.Data["hsmLogin"]
Expect(confHSM).To(
ContainSubstring("12345678"))

certsSecret := th.GetSecret(barbicanTest.BarbicanHSMCertsSecret)
Expect(certsSecret).ShouldNot(BeNil())
confCA := certsSecret.Data["CACert.pem"]
Expect(confCA).To(
ContainSubstring("dummy-data"))
confServer := certsSecret.Data[HSMServerAddress+"Server.pem"]
Expect(confServer).To(
ContainSubstring("dummy-data"))

confClient := certsSecret.Data[HSMClientAddress+"Client.pem"]
Expect(confClient).To(
ContainSubstring("dummy-data"))
confKey := certsSecret.Data[HSMClientAddress+"Client.key"]
Expect(confKey).To(
ContainSubstring("dummy-data"))
})

It("Verifies if 00-default.conf, barbican-api-config.json and Chrystoki.conf have the right contents.", func() {
confSecret := th.GetSecret(barbicanTest.BarbicanConfigSecret)
Expect(confSecret).ShouldNot(BeNil())

conf := confSecret.Data["Chrystoki.conf"]
Expect(conf).To(
ContainSubstring("Chrystoki2"))
Expect(conf).To(
ContainSubstring("LunaSA Client"))
Expect(conf).To(
ContainSubstring("ProtectedAuthenticationPathFlagStatus = 0"))
Expect(conf).To(
ContainSubstring("ClientPrivKeyFile = " + HSMCertificatesMountPoint + "/" + HSMClientAddress + "Key.pem"))
Expect(conf).To(
ContainSubstring("ClientCertFile = " + HSMCertificatesMountPoint + "/" + HSMClientAddress + ".pem"))
Expect(conf).To(
ContainSubstring("ServerCAFile = " + HSMCertificatesMountPoint + "/CACert.pem"))

conf = confSecret.Data["00-default.conf"]
Expect(conf).To(
ContainSubstring("[secretstore:pkcs11]"))
Expect(conf).To(
ContainSubstring("plugin_name = PKCS11"))
Expect(conf).To(
ContainSubstring("slot_id = " + HSMSlotID))

conf = confSecret.Data["barbican-api-config.json"]
Expect(conf).To(
ContainSubstring("/var/lib/config-data/default/Chrystoki.conf"))
Expect(conf).To(
ContainSubstring("/usr/local/luna/Chrystoki.conf"))
})

It("Checks if the P11PreJob successfully executed", func() {
BarbicanExists(barbicanTest.Instance)

th.ExpectCondition(
barbicanTest.Instance,
ConditionGetterFunc(BarbicanConditionGetter),
controllers.P11PrepReadyCondition,
corev1.ConditionTrue,
)

// Checking if both, the volume mount name and its mount path match the specified values.
var elemLuna, elemScript = 0, 0
for index, mount := range th.GetJob(barbicanTest.BarbicanP11Prep).Spec.Template.Spec.Containers[0].VolumeMounts {
if mount.Name == barbican.LunaVolume {
elemLuna = index
} else if mount.Name == barbican.ScriptVolume {
elemScript = index
}
}

volume := th.GetJob(barbicanTest.BarbicanP11Prep).Spec.Template.Spec.Containers[0].VolumeMounts[elemLuna].Name
mountPath := th.GetJob(barbicanTest.BarbicanP11Prep).Spec.Template.Spec.Containers[0].VolumeMounts[elemLuna].MountPath

Eventually(func(g Gomega) {
g.Expect(volume).To(Equal(barbican.LunaVolume))
g.Expect(mountPath).To(Equal(HSMCertificatesMountPoint))
}, timeout, interval).Should(Succeed())

volume = th.GetJob(barbicanTest.BarbicanP11Prep).Spec.Template.Spec.Containers[0].VolumeMounts[elemScript].Name
mountPath = th.GetJob(barbicanTest.BarbicanP11Prep).Spec.Template.Spec.Containers[0].VolumeMounts[elemScript].MountPath

Eventually(func(g Gomega) {
g.Expect(volume).To(Equal(barbican.ScriptVolume))
g.Expect(mountPath).To(Equal(P11PrepMountPoint))
}, timeout, interval).Should(Succeed())
})
})

// Run MariaDBAccount suite tests. these are pre-packaged ginkgo tests
// that exercise standard account create / update patterns that should be
// common to all controllers that ensure MariaDBAccount CRs.
Expand Down
17 changes: 17 additions & 0 deletions tests/functional/barbican_test_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type BarbicanTestData struct {
BarbicanDatabaseName types.NamespacedName
BarbicanDatabaseAccount types.NamespacedName
BarbicanDBSync types.NamespacedName
BarbicanP11Prep types.NamespacedName
BarbicanAPI types.NamespacedName
BarbicanRole types.NamespacedName
BarbicanRoleBinding types.NamespacedName
Expand All @@ -65,6 +66,8 @@ type BarbicanTestData struct {
BarbicanServiceInternal types.NamespacedName
BarbicanConfigSecret types.NamespacedName
BarbicanAPIConfigSecret types.NamespacedName
BarbicanHSMLoginSecret types.NamespacedName
BarbicanHSMCertsSecret types.NamespacedName
BarbicanConfigScripts types.NamespacedName
BarbicanConfigMapData types.NamespacedName
BarbicanScheduler types.NamespacedName
Expand Down Expand Up @@ -97,6 +100,10 @@ func GetBarbicanTestData(barbicanName types.NamespacedName) BarbicanTestData {
Namespace: barbicanName.Namespace,
Name: fmt.Sprintf("%s-db-sync", barbicanName.Name),
},
BarbicanP11Prep: types.NamespacedName{
Namespace: barbicanName.Namespace,
Name: fmt.Sprintf("%s-p11-prep", barbicanName.Name),
},
BarbicanAPI: types.NamespacedName{
Namespace: barbicanName.Namespace,
Name: fmt.Sprintf("%s-api-api", barbicanName.Name),
Expand Down Expand Up @@ -142,6 +149,16 @@ func GetBarbicanTestData(barbicanName types.NamespacedName) BarbicanTestData {
Namespace: barbicanName.Namespace,
Name: fmt.Sprintf("%s-%s", barbicanName.Name, "api-config-data"),
},
// This secret stores the password to connect to the HSM.
BarbicanHSMLoginSecret: types.NamespacedName{
Namespace: barbicanName.Namespace,
Name: "hsm-login",
},
// This secret stores the certificates used to interact with the HSM.
BarbicanHSMCertsSecret: types.NamespacedName{
Namespace: barbicanName.Namespace,
Name: "hsm-certs",
},
BarbicanConfigScripts: types.NamespacedName{
Namespace: barbicanName.Namespace,
Name: fmt.Sprintf("%s-%s", barbicanName.Name, "scripts"),
Expand Down
61 changes: 60 additions & 1 deletion tests/functional/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,14 @@ func BarbicanKeystoneListenerNotExists(name types.NamespacedName) {
}, timeout, interval).Should(Succeed())
}

// ========== TLS Stuff ==============
func BarbicanExists(name types.NamespacedName) {
Consistently(func(g Gomega) {
instance := &barbicanv1.Barbican{}
err := k8sClient.Get(ctx, name, instance)
g.Expect(k8s_errors.IsNotFound(err)).To(BeFalse())
}, timeout, interval).Should(Succeed())
}

func BarbicanAPIConditionGetter(name types.NamespacedName) condition.Conditions {
instance := GetBarbicanAPI(name)
return instance.Status.Conditions
Expand All @@ -145,6 +152,7 @@ func GetBarbicanAPI(name types.NamespacedName) *barbicanv1.BarbicanAPI {
return instance
}

// ========== TLS Stuff ==============
func GetTLSBarbicanSpec() map[string]interface{} {
return map[string]interface{}{
"databaseInstance": "openstack",
Expand Down Expand Up @@ -172,6 +180,57 @@ func GetTLSBarbicanAPISpec() map[string]interface{} {
return spec
}

// ========== End of TLS Stuff ============

// ========== HSM Stuff ============
func GetHSMBarbicanSpec() map[string]interface{} {
spec := GetDefaultBarbicanSpec()
maps.Copy(spec, map[string]interface{}{
"enabledSecretStores": []string{"pkcs11"},
"globalDefaultSecretStore": "pkcs11",
"pkcs11": map[string]interface{}{
"slotId": HSMSlotID,
"libraryPath": HSMLibraryPath,
"certificatesMountPoint": HSMCertificatesMountPoint,
"loginSecret": HSMLoginSecret,
"certificatesSecret": HSMCertsSecret,
"MKEKLabel": HSMMKEKLabel,
"HMACLabel": HSMHMACLabel,
"serverAddress": HSMServerAddress,
"clientAddress": HSMClientAddress,
"type": HSMType,
},
})
return spec
}

func GetHSMBarbicanAPISpec() map[string]interface{} {
return GetDefaultBarbicanAPISpec()
}

func CreateHSMLoginSecret(namespace string, name string) *corev1.Secret {
return th.CreateSecret(
types.NamespacedName{Namespace: namespace, Name: name},
map[string][]byte{
"hsmLogin": []byte("12345678"),
},
)
}

func CreateHSMCertsSecret(namespace string, name string) *corev1.Secret {
return th.CreateSecret(
types.NamespacedName{Namespace: namespace, Name: name},
map[string][]byte{
"CACert.pem": []byte("dummy-data"),
HSMServerAddress + "Server.pem": []byte("dummy-data"),
HSMClientAddress + "Client.pem": []byte("dummy-data"),
HSMClientAddress + "Client.key": []byte("dummy-data"),
},
)
}

// ========== End of HSM Stuff ============

func GetDefaultBarbicanAPISpec() map[string]interface{} {
return map[string]interface{}{
"secret": SecretName,
Expand Down
13 changes: 13 additions & 0 deletions tests/functional/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ const (
SecretName = "test-osp-secret"

interval = time.Millisecond * 200

// HSM Constants
HSMType = "luna" // Using them Luna model without any specific selection criteria.
HSMLibraryPath = "/usr/local/luna/libs/64/libCryptoki2.so"
HSMCertificatesMountPoint = "/usr/local/luna/config/certs"
HSMSlotID = "1"
HSMMKEKLabel = "MKEKLabel"
HSMHMACLabel = "HMACLabel"
HSMServerAddress = "192.168.0.1"
HSMClientAddress = "192.168.0.2"
HSMLoginSecret = "hsm-login"
HSMCertsSecret = "hsm-certs"
P11PrepMountPoint = "/usr/local/bin/container-scripts"
)

func TestAPIs(t *testing.T) {
Expand Down

0 comments on commit 1482a31

Please sign in to comment.