From a522bfea593e4b6d45940b076fe86014ba7435dd Mon Sep 17 00:00:00 2001 From: Martin Schuppert Date: Mon, 29 Jan 2024 15:41:16 +0100 Subject: [PATCH] [tlse] tls for Ironic pod configuration Public/Internal service cert secrets and the CA bundle secret can be passed to configure httpd virtual hosts for tls termination. The CA cert get direct mounted as the environment bundle to /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem . The service certificates like config files and copied via kolla to /etc/pki/tls/certs/%s.crt|/etc/pki/tls/private/%s.key . Job deployments for bootstrap/cron get the CA bundle added if configured. Also indexes the named input resources for password, CA bundle, and endpoint secrets to be able to watch them for a change and reconcile. Depends-On: https://github.com/openstack-k8s-operators/lib-common/pull/428 Depends-On: https://github.com/openstack-k8s-operators/tcib/pull/126 Jira: OSPRH-4220 --- .../ironic.openstack.org_ironicapis.yaml | 30 +++ ...ironic.openstack.org_ironicconductors.yaml | 8 + ...ironic.openstack.org_ironicinspectors.yaml | 30 +++ ...nic.openstack.org_ironicneutronagents.yaml | 8 + api/bases/ironic.openstack.org_ironics.yaml | 60 +++++ api/go.mod | 28 +-- api/go.sum | 57 +++-- api/v1beta1/ironicapi_types.go | 6 + api/v1beta1/ironicconductor_types.go | 8 +- api/v1beta1/ironicinspector_types.go | 6 + api/v1beta1/ironicneutronagent_types.go | 5 + api/v1beta1/zz_generated.deepcopy.go | 4 + .../ironic.openstack.org_ironicapis.yaml | 30 +++ ...ironic.openstack.org_ironicconductors.yaml | 8 + ...ironic.openstack.org_ironicinspectors.yaml | 30 +++ ...nic.openstack.org_ironicneutronagents.yaml | 8 + .../bases/ironic.openstack.org_ironics.yaml | 60 +++++ config/default/manager_default_images.yaml | 2 +- config/samples/ironic_v1beta1_ironic_tls.yaml | 31 +++ controllers/funcs.go | 32 +++ controllers/ironic_controller.go | 2 + controllers/ironicapi_controller.go | 178 ++++++++++++- controllers/ironicconductor_controller.go | 100 ++++++++ controllers/ironicinspector_controller.go | 159 +++++++++++- controllers/ironicneutronagent_controller.go | 108 +++++++- go.mod | 40 +-- go.sum | 82 +++--- pkg/ironic/dbsync.go | 18 +- pkg/ironicapi/deployment.go | 49 +++- pkg/ironicconductor/statefulset.go | 26 +- pkg/ironicinspector/statefulset.go | 94 ++++++- pkg/ironicneutronagent/deployment.go | 18 +- templates/ironicapi/bin/api-prep.sh | 3 - .../ironicapi/config/ironic-api-config.json | 22 ++ .../ironicapi/config/ironic-api-httpd.conf | 24 +- templates/ironicapi/config/ssl.conf | 21 ++ .../ironicinspector/config/httpd-config.json | 45 ++++ templates/ironicinspector/config/httpd.conf | 54 ++++ .../ironicinspector/config/inspector.conf | 2 + templates/ironicinspector/config/ssl.conf | 21 ++ tests/functional/base_test.go | 25 +- tests/functional/ironic_controller_test.go | 10 +- tests/functional/ironicapi_controller_test.go | 207 +++++++++++++++- .../ironicconductor_controller_test.go | 111 ++++++++- .../ironicinspector_controller_test.go | 233 ++++++++++++++++++ .../ironicneutronagent_controller_test.go | 81 ++++++ tests/kuttl/common/assert_tls_cert.yaml | 30 +++ tests/kuttl/common/tls_ca_bundle.yaml | 65 +++++ ...ls_cert_ironic-inspector-internal-svc.yaml | 46 ++++ .../tls_cert_ironic-inspector-public-svc.yaml | 45 ++++ .../common/tls_cert_ironic-internal-svc.yaml | 45 ++++ .../common/tls_cert_ironic-public-svc.yaml | 45 ++++ tests/kuttl/tests/deploy_tls/00-assert.yaml | 1 + .../tests/deploy_tls/00-tls_ca_bundle.yaml | 1 + ...ls_cert_ironic-inspector-internal-svc.yaml | 1 + ...-tls_cert_ironic-inspector-public-svc.yaml | 1 + .../00-tls_cert_ironic-internal-svc.yaml | 1 + .../00-tls_cert_ironic-public-svc.yaml | 1 + .../deploy_tls/10-assert-deploy-ironic.yaml | 131 ++++++++++ .../tests/deploy_tls/10-deploy-ironic.yaml | 5 + .../tests/deploy_tls/99-cleanup-ironic.yaml | 1 + .../deploy_tls/99-errors-cleanup-ironic.yaml | 1 + 62 files changed, 2437 insertions(+), 167 deletions(-) create mode 100644 config/samples/ironic_v1beta1_ironic_tls.yaml create mode 100644 templates/ironicapi/config/ssl.conf create mode 100644 templates/ironicinspector/config/httpd-config.json create mode 100644 templates/ironicinspector/config/httpd.conf create mode 100644 templates/ironicinspector/config/ssl.conf create mode 100644 tests/kuttl/common/assert_tls_cert.yaml create mode 100644 tests/kuttl/common/tls_ca_bundle.yaml create mode 100644 tests/kuttl/common/tls_cert_ironic-inspector-internal-svc.yaml create mode 100644 tests/kuttl/common/tls_cert_ironic-inspector-public-svc.yaml create mode 100644 tests/kuttl/common/tls_cert_ironic-internal-svc.yaml create mode 100644 tests/kuttl/common/tls_cert_ironic-public-svc.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-assert.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-tls_ca_bundle.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-internal-svc.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-public-svc.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-internal-svc.yaml create mode 120000 tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-public-svc.yaml create mode 100644 tests/kuttl/tests/deploy_tls/10-assert-deploy-ironic.yaml create mode 100644 tests/kuttl/tests/deploy_tls/10-deploy-ironic.yaml create mode 120000 tests/kuttl/tests/deploy_tls/99-cleanup-ironic.yaml create mode 120000 tests/kuttl/tests/deploy_tls/99-errors-cleanup-ironic.yaml diff --git a/api/bases/ironic.openstack.org_ironicapis.yaml b/api/bases/ironic.openstack.org_ironicapis.yaml index 13a742a6..d1d76525 100644 --- a/api/bases/ironic.openstack.org_ironicapis.yaml +++ b/api/bases/ironic.openstack.org_ironicapis.yaml @@ -373,6 +373,36 @@ spec: default: false description: Whether to deploy a standalone Ironic. type: boolean + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret for + the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + public: + description: Public GenericService - holds the secret for + the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object transportURLSecret: description: Secret containing RabbitMq transport URL type: string diff --git a/api/bases/ironic.openstack.org_ironicconductors.yaml b/api/bases/ironic.openstack.org_ironicconductors.yaml index 2ca8469f..f61a617c 100644 --- a/api/bases/ironic.openstack.org_ironicconductors.yaml +++ b/api/bases/ironic.openstack.org_ironicconductors.yaml @@ -255,6 +255,14 @@ spec: storageRequest: description: StorageRequest type: string + tls: + description: TLS - Parameters related to the TLS + properties: + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object transportURLSecret: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string diff --git a/api/bases/ironic.openstack.org_ironicinspectors.yaml b/api/bases/ironic.openstack.org_ironicinspectors.yaml index 41486800..a6684249 100644 --- a/api/bases/ironic.openstack.org_ironicinspectors.yaml +++ b/api/bases/ironic.openstack.org_ironicinspectors.yaml @@ -430,6 +430,36 @@ spec: storageClass: description: StorageClass type: string + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret for + the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + public: + description: Public GenericService - holds the secret for + the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object type: object status: description: IronicInspectorStatus defines the observed state of IronicInspector diff --git a/api/bases/ironic.openstack.org_ironicneutronagents.yaml b/api/bases/ironic.openstack.org_ironicneutronagents.yaml index a401afcd..203306c7 100644 --- a/api/bases/ironic.openstack.org_ironicneutronagents.yaml +++ b/api/bases/ironic.openstack.org_ironicneutronagents.yaml @@ -173,6 +173,14 @@ spec: description: ServiceUser - optional username used for this service to register in ironic type: string + tls: + description: TLS - Parameters related to the TLS + properties: + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object type: object status: description: IronicNeutronAgentStatus defines the observed state of ML2 diff --git a/api/bases/ironic.openstack.org_ironics.yaml b/api/bases/ironic.openstack.org_ironics.yaml index 6744592a..271a6cf8 100644 --- a/api/bases/ironic.openstack.org_ironics.yaml +++ b/api/bases/ironic.openstack.org_ironics.yaml @@ -375,6 +375,36 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret + for the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + public: + description: Public GenericService - holds the secret + for the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in + a pre-created bundle file + type: string + type: object type: object ironicConductors: description: IronicConductors - Spec definitions for the conductor @@ -889,6 +919,36 @@ spec: storageClass: description: StorageClass type: string + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret + for the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + public: + description: Public GenericService - holds the secret + for the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in + a pre-created bundle file + type: string + type: object type: object ironicNeutronAgent: description: IronicNeutronAgent - Spec definition for the ML2 baremetal diff --git a/api/go.mod b/api/go.mod index c99993d0..02d625ef 100644 --- a/api/go.mod +++ b/api/go.mod @@ -3,13 +3,13 @@ module github.com/openstack-k8s-operators/ironic-operator/api go 1.19 require ( - github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 - github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32 - k8s.io/api v0.26.11 - k8s.io/apimachinery v0.26.11 - k8s.io/client-go v0.26.11 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216 + k8s.io/api v0.26.12 + k8s.io/apimachinery v0.26.12 + k8s.io/client-go v0.26.12 + k8s.io/utils v0.0.0-20240102154912-e7106e64919e sigs.k8s.io/controller-runtime v0.14.7 ) @@ -20,7 +20,7 @@ require ( github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/zapr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect @@ -33,7 +33,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/imdario/mergo v0.3.16 // indirect; indirect // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -51,21 +51,21 @@ require ( github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.26.11 // indirect - k8s.io/component-base v0.26.11 // indirect + k8s.io/apiextensions-apiserver v0.26.12 // indirect + k8s.io/component-base v0.26.12 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/api/go.sum b/api/go.sum index 6ebb367a..bfcd3ca6 100644 --- a/api/go.sum +++ b/api/go.sum @@ -93,8 +93,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -171,8 +171,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -224,14 +224,14 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= -github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 h1:rncLxJBpFGqBztyxCMwNRnMjhhIDOWHJowi6q8G6koI= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32 h1:r24jE5tdacLivcZczb3t6RvbvHp6kXQrW2ECuekzgH8= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32/go.mod h1:xXAuy7HtWN4p7LF5Q+NHLkwAsKVh0KrzpnuPYIG3XaA= +github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216 h1:hDwy0K68UN67kh/XU3iuNPWN0/Zcvtc+kcVPdqTY1So= +github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216/go.mod h1:gW0sefZEues1bO7J8utgMIqbXgs2WUCXNtmixYiN1ak= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -346,7 +346,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -381,8 +380,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -444,12 +443,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -508,8 +507,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -631,22 +630,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.11 h1:hLhTZRdYc3vBBOY4wbEyTLWgMyieOAk2Ws9NG57QqO4= -k8s.io/api v0.26.11/go.mod h1:bSr/A0TKRt5W2OMDdexkM/ER1NxOxiQqNNFXW2nMZrM= -k8s.io/apiextensions-apiserver v0.26.11 h1:6/T0Jm9c+Aw1AYUflPOz2sAsty304/DDSkciTr8+HuE= -k8s.io/apiextensions-apiserver v0.26.11/go.mod h1:xMqWxAB+AvSTdmFRVWlpavY9bJl/3g6yWiPn/fwZbT0= -k8s.io/apimachinery v0.26.11 h1:w//840HHdwSRKqD15j9YX9HLlU6RPlfrvW0xEhLk2+0= -k8s.io/apimachinery v0.26.11/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= -k8s.io/client-go v0.26.11 h1:RjfZr5+vQjjTRmk4oCqHyC0cgrZXPjw+X+ge35sk4GI= -k8s.io/client-go v0.26.11/go.mod h1:+emNszw9va/uRJIM5ALTBtFnlZMTjwBrNjRfEh0iuw8= -k8s.io/component-base v0.26.11 h1:1/JmB6fexefGByfFyIK6aHksZZVtaDskttzXOzmZ6zA= -k8s.io/component-base v0.26.11/go.mod h1:jYNisnoM6iWFRUg51pxaQabzL5fBYTr5CMpsLjUYGp0= +k8s.io/api v0.26.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= +k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= +k8s.io/apiextensions-apiserver v0.26.12 h1:WHfFheB9AM0eHZsz6wu2h/KVmZ8PM7ZAmNDr3smkUzA= +k8s.io/apiextensions-apiserver v0.26.12/go.mod h1:bvr3OVCML7icxP4rq/fJaNBPPiZ9KIi79n/icBbg5Rc= +k8s.io/apimachinery v0.26.12 h1:y+OgufxqLIZtyXIydRhjLBGzrYLF+qwiDdCFXYOjeN4= +k8s.io/apimachinery v0.26.12/go.mod h1:2/HZp0l6coXtS26du1Bk36fCuAEr/lVs9Q9NbpBtd1Y= +k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= +k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/component-base v0.26.12 h1:OyYjCtruv4/Yau5Z1v6e59N+JRDTj8JnW95W9w9AMpg= +k8s.io/component-base v0.26.12/go.mod h1:X98Et5BxJ8i4TcDusUcKS8EYxCujBU1lCL3pc/CUtHQ= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a h1:gmovKNur38vgoWfGtP5QOGNOA7ki4n6qNYoFAgMlNvg= k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/api/v1beta1/ironicapi_types.go b/api/v1beta1/ironicapi_types.go index 914262ff..c5a22e89 100644 --- a/api/v1beta1/ironicapi_types.go +++ b/api/v1beta1/ironicapi_types.go @@ -22,6 +22,7 @@ import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/endpoint" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -37,6 +38,11 @@ type IronicAPITemplate struct { // +kubebuilder:validation:Optional // Override, provides the ability to override the generated manifest of several child resources. Override APIOverrideSpec `json:"override,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // TLS - Parameters related to the TLS + TLS tls.API `json:"tls,omitempty"` } // APIOverrideSpec to override the generated manifest of several child resources. diff --git a/api/v1beta1/ironicconductor_types.go b/api/v1beta1/ironicconductor_types.go index f13715b0..ec07f055 100644 --- a/api/v1beta1/ironicconductor_types.go +++ b/api/v1beta1/ironicconductor_types.go @@ -18,6 +18,7 @@ package v1beta1 import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -50,10 +51,8 @@ type IronicConductorTemplate struct { // +kubebuilder:validation:Optional // DHCPRanges - List of DHCP ranges to use for provisioning DHCPRanges []DHCPRange `json:"dhcpRanges,omitempty"` - } - // IronicConductorSpec defines the desired state of IronicConductor type IronicConductorSpec struct { // Input parameters for the Ironic Conductor service @@ -110,6 +109,11 @@ type IronicConductorSpec struct { // +kubebuilder:validation:Optional // KeystoneEndpoints - Internally used Keystone API endpoints KeystoneEndpoints KeystoneEndpoints `json:"keystoneEndpoints"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // TLS - Parameters related to the TLS + TLS tls.Ca `json:"tls,omitempty"` } // IronicConductorStatus defines the observed state of IronicConductor diff --git a/api/v1beta1/ironicinspector_types.go b/api/v1beta1/ironicinspector_types.go index 751d1a70..f380bb60 100644 --- a/api/v1beta1/ironicinspector_types.go +++ b/api/v1beta1/ironicinspector_types.go @@ -19,6 +19,7 @@ package v1beta1 import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -107,6 +108,11 @@ type IronicInspectorTemplate struct { // +kubebuilder:validation:Optional // Override, provides the ability to override the generated manifest of several child resources. Override InspectorOverrideSpec `json:"override,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // TLS - Parameters related to the TLS + TLS tls.API `json:"tls,omitempty"` } // InspectorOverrideSpec to override the generated manifest of several child resources. diff --git a/api/v1beta1/ironicneutronagent_types.go b/api/v1beta1/ironicneutronagent_types.go index 4fc8cf30..49447bc7 100644 --- a/api/v1beta1/ironicneutronagent_types.go +++ b/api/v1beta1/ironicneutronagent_types.go @@ -18,6 +18,7 @@ package v1beta1 import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -56,6 +57,10 @@ type IronicNeutronAgentSpec struct { // PasswordSelectors - Selectors to identify the ServiceUser password from the Secret PasswordSelectors PasswordSelector `json:"passwordSelectors"` + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // TLS - Parameters related to the TLS + TLS tls.Ca `json:"tls,omitempty"` } // IronicNeutronAgentStatus defines the observed state of ML2 baremetal - ironic-neutron-agent diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index e6e50693..5f9266a8 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -261,6 +261,7 @@ func (in *IronicAPITemplate) DeepCopyInto(out *IronicAPITemplate) { copy(*out, *in) } in.Override.DeepCopyInto(&out.Override) + in.TLS.DeepCopyInto(&out.TLS) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IronicAPITemplate. @@ -338,6 +339,7 @@ func (in *IronicConductorSpec) DeepCopyInto(out *IronicConductorSpec) { in.IronicConductorTemplate.DeepCopyInto(&out.IronicConductorTemplate) out.PasswordSelectors = in.PasswordSelectors out.KeystoneEndpoints = in.KeystoneEndpoints + out.TLS = in.TLS } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IronicConductorSpec. @@ -669,6 +671,7 @@ func (in *IronicInspectorTemplate) DeepCopyInto(out *IronicInspectorTemplate) { copy(*out, *in) } in.Override.DeepCopyInto(&out.Override) + in.TLS.DeepCopyInto(&out.TLS) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IronicInspectorTemplate. @@ -777,6 +780,7 @@ func (in *IronicNeutronAgentSpec) DeepCopyInto(out *IronicNeutronAgentSpec) { *out = *in in.IronicNeutronAgentTemplate.DeepCopyInto(&out.IronicNeutronAgentTemplate) out.PasswordSelectors = in.PasswordSelectors + out.TLS = in.TLS } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IronicNeutronAgentSpec. diff --git a/config/crd/bases/ironic.openstack.org_ironicapis.yaml b/config/crd/bases/ironic.openstack.org_ironicapis.yaml index 13a742a6..d1d76525 100644 --- a/config/crd/bases/ironic.openstack.org_ironicapis.yaml +++ b/config/crd/bases/ironic.openstack.org_ironicapis.yaml @@ -373,6 +373,36 @@ spec: default: false description: Whether to deploy a standalone Ironic. type: boolean + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret for + the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + public: + description: Public GenericService - holds the secret for + the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object transportURLSecret: description: Secret containing RabbitMq transport URL type: string diff --git a/config/crd/bases/ironic.openstack.org_ironicconductors.yaml b/config/crd/bases/ironic.openstack.org_ironicconductors.yaml index 2ca8469f..f61a617c 100644 --- a/config/crd/bases/ironic.openstack.org_ironicconductors.yaml +++ b/config/crd/bases/ironic.openstack.org_ironicconductors.yaml @@ -255,6 +255,14 @@ spec: storageRequest: description: StorageRequest type: string + tls: + description: TLS - Parameters related to the TLS + properties: + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object transportURLSecret: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string diff --git a/config/crd/bases/ironic.openstack.org_ironicinspectors.yaml b/config/crd/bases/ironic.openstack.org_ironicinspectors.yaml index 41486800..a6684249 100644 --- a/config/crd/bases/ironic.openstack.org_ironicinspectors.yaml +++ b/config/crd/bases/ironic.openstack.org_ironicinspectors.yaml @@ -430,6 +430,36 @@ spec: storageClass: description: StorageClass type: string + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret for + the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + public: + description: Public GenericService - holds the secret for + the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for the + service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object type: object status: description: IronicInspectorStatus defines the observed state of IronicInspector diff --git a/config/crd/bases/ironic.openstack.org_ironicneutronagents.yaml b/config/crd/bases/ironic.openstack.org_ironicneutronagents.yaml index a401afcd..203306c7 100644 --- a/config/crd/bases/ironic.openstack.org_ironicneutronagents.yaml +++ b/config/crd/bases/ironic.openstack.org_ironicneutronagents.yaml @@ -173,6 +173,14 @@ spec: description: ServiceUser - optional username used for this service to register in ironic type: string + tls: + description: TLS - Parameters related to the TLS + properties: + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in a pre-created + bundle file + type: string + type: object type: object status: description: IronicNeutronAgentStatus defines the observed state of ML2 diff --git a/config/crd/bases/ironic.openstack.org_ironics.yaml b/config/crd/bases/ironic.openstack.org_ironics.yaml index 6744592a..271a6cf8 100644 --- a/config/crd/bases/ironic.openstack.org_ironics.yaml +++ b/config/crd/bases/ironic.openstack.org_ironics.yaml @@ -375,6 +375,36 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret + for the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + public: + description: Public GenericService - holds the secret + for the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in + a pre-created bundle file + type: string + type: object type: object ironicConductors: description: IronicConductors - Spec definitions for the conductor @@ -889,6 +919,36 @@ spec: storageClass: description: StorageClass type: string + tls: + description: TLS - Parameters related to the TLS + properties: + api: + description: API tls type which encapsulates for API services + properties: + internal: + description: Internal GenericService - holds the secret + for the internal endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + public: + description: Public GenericService - holds the secret + for the public endpoint + properties: + secretName: + description: SecretName - holding the cert, key for + the service + type: string + type: object + type: object + caBundleSecretName: + description: CaBundleSecretName - holding the CA certs in + a pre-created bundle file + type: string + type: object type: object ironicNeutronAgent: description: IronicNeutronAgent - Spec definition for the ML2 baremetal diff --git a/config/default/manager_default_images.yaml b/config/default/manager_default_images.yaml index 4eecc735..ecd8e9f6 100644 --- a/config/default/manager_default_images.yaml +++ b/config/default/manager_default_images.yaml @@ -16,7 +16,7 @@ spec: - name: RELATED_IMAGE_IRONIC_CONDUCTOR_IMAGE_URL_DEFAULT value: quay.io/podified-antelope-centos9/openstack-ironic-conductor:current-podified - name: RELATED_IMAGE_IRONIC_INSPECTOR_IMAGE_URL_DEFAULT - value: quay.io/podified-antelope-centos9/openstack-ironic-inspector:current-podified + value: quay.io/mschuppe/openstack-ironic-inspector:inspector-httpd - name: RELATED_IMAGE_IRONIC_PXE_IMAGE_URL_DEFAULT value: quay.io/podified-antelope-centos9/openstack-ironic-pxe:current-podified - name: RELATED_IMAGE_IRONIC_NEUTRON_AGENT_IMAGE_URL_DEFAULT diff --git a/config/samples/ironic_v1beta1_ironic_tls.yaml b/config/samples/ironic_v1beta1_ironic_tls.yaml new file mode 100644 index 00000000..0d511d80 --- /dev/null +++ b/config/samples/ironic_v1beta1_ironic_tls.yaml @@ -0,0 +1,31 @@ +apiVersion: ironic.openstack.org/v1beta1 +kind: Ironic +metadata: + name: ironic +spec: + serviceUser: ironic + secret: osp-secret + customServiceConfig: | + [DEFAULT] + debug = true + databaseInstance: openstack + storageClass: local-storage + ironicAPI: + tls: + api: + internal: + secretName: cert-ironic-internal-svc + public: + secretName: cert-ironic-public-svc + caBundleSecretName: combined-ca-bundle + ironicConductors: + - storageRequest: 10G + ironicInspector: + tls: + api: + internal: + secretName: cert-ironic-inspector-internal-svc + public: + secretName: cert-ironic-inspector-public-svc + caBundleSecretName: combined-ca-bundle + ironicNeutronAgent: {} diff --git a/controllers/funcs.go b/controllers/funcs.go index ad53d740..cb665614 100644 --- a/controllers/funcs.go +++ b/controllers/funcs.go @@ -20,6 +20,38 @@ import ( rbacv1 "k8s.io/api/rbac/v1" ) +// fields to index to reconcile when change +const ( + passwordSecretField = ".spec.secret" + caBundleSecretNameField = ".spec.tls.caBundleSecretName" + tlsAPIInternalField = ".spec.tls.api.internal.secretName" + tlsAPIPublicField = ".spec.tls.api.public.secretName" +) + +var ( + ironicWatchFields = []string{ + passwordSecretField, + } + ironicAPIWatchFields = []string{ + passwordSecretField, + caBundleSecretNameField, + tlsAPIInternalField, + tlsAPIPublicField, + } + ironicConductorWatchFields = []string{ + passwordSecretField, + caBundleSecretNameField, + } + ironicInspectorWatchFields = []string{ + passwordSecretField, + caBundleSecretNameField, + } + ironicNeutronAgentWatchFields = []string{ + passwordSecretField, + caBundleSecretNameField, + } +) + func getCommonRbacRules() []rbacv1.PolicyRule { return []rbacv1.PolicyRule{ { diff --git a/controllers/ironic_controller.go b/controllers/ironic_controller.go index 3545a511..c23048a8 100644 --- a/controllers/ironic_controller.go +++ b/controllers/ironic_controller.go @@ -739,6 +739,7 @@ func (r *IronicReconciler) conductorDeploymentCreateOrUpdate( DatabaseHostname: instance.Status.DatabaseHostname, TransportURLSecret: instance.Status.TransportURLSecret, KeystoneEndpoints: *keystoneEndpoints, + TLS: instance.Spec.IronicAPI.TLS.Ca, } deployment := &ironicv1.IronicConductor{ ObjectMeta: metav1.ObjectMeta{ @@ -985,6 +986,7 @@ func (r *IronicReconciler) ironicNeutronAgentDeploymentCreateOrUpdate( Secret: instance.Spec.Secret, PasswordSelectors: instance.Spec.PasswordSelectors, ServiceUser: instance.Spec.ServiceUser, + TLS: instance.Spec.IronicAPI.TLS.Ca, } deployment := &ironicv1.IronicNeutronAgent{ ObjectMeta: metav1.ObjectMeta{ diff --git a/controllers/ironicapi_controller.go b/controllers/ironicapi_controller.go index 1808f1ad..743c6d18 100644 --- a/controllers/ironicapi_controller.go +++ b/controllers/ironicapi_controller.go @@ -26,13 +26,18 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" @@ -52,6 +57,7 @@ import ( common_rbac "github.com/openstack-k8s-operators/lib-common/modules/common/rbac" "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "github.com/openstack-k8s-operators/lib-common/modules/common/util" ) @@ -164,6 +170,7 @@ func (r *IronicAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage), condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage), condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage), + condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage), // service account, role, rolebinding conditions condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage), condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage), @@ -241,6 +248,54 @@ func (r *IronicAPIReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Man return nil } + // index passwordSecretField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicAPI{}, passwordSecretField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicAPI) + if cr.Spec.Secret == "" { + return nil + } + return []string{cr.Spec.Secret} + }); err != nil { + return err + } + + // index caBundleSecretNameField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicAPI{}, caBundleSecretNameField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicAPI) + if cr.Spec.TLS.CaBundleSecretName == "" { + return nil + } + return []string{cr.Spec.TLS.CaBundleSecretName} + }); err != nil { + return err + } + + // index tlsAPIInternalField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicAPI{}, tlsAPIInternalField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicAPI) + if cr.Spec.TLS.API.Internal.SecretName == nil { + return nil + } + return []string{*cr.Spec.TLS.API.Internal.SecretName} + }); err != nil { + return err + } + + // index tlsAPIPublicField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicAPI{}, tlsAPIPublicField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicAPI) + if cr.Spec.TLS.API.Public.SecretName == nil { + return nil + } + return []string{*cr.Spec.TLS.API.Public.SecretName} + }); err != nil { + return err + } + return ctrl.NewControllerManagedBy(mgr). For(&ironicv1.IronicAPI{}). Owns(&keystonev1.KeystoneService{}). @@ -254,9 +309,47 @@ func (r *IronicAPIReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Man // watch the config CMs we don't own Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(configMapFn)). + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). Complete(r) } +func (r *IronicAPIReconciler) findObjectsForSrc(src client.Object) []reconcile.Request { + requests := []reconcile.Request{} + + l := log.FromContext(context.Background()).WithName("Controllers").WithName("IronicAPI") + + for _, field := range ironicAPIWatchFields { + crList := &ironicv1.IronicAPIList{} + listOps := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(field, src.GetName()), + Namespace: src.GetNamespace(), + } + err := r.List(context.TODO(), crList, listOps) + if err != nil { + return []reconcile.Request{} + } + + for _, item := range crList.Items { + l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace())) + + requests = append(requests, + reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: item.GetName(), + Namespace: item.GetNamespace(), + }, + }, + ) + } + } + + return requests +} + func (r *IronicAPIReconciler) reconcileDelete(ctx context.Context, instance *ironicv1.IronicAPI, helper *helper.Helper) (ctrl.Result, error) { Log := r.GetLogger(ctx) @@ -412,7 +505,12 @@ func (r *IronicAPIReconciler) reconcileInit( } // create service - end - // TODO: TLS, pass in https as protocol, create TLS cert + // if TLS is enabled + if instance.Spec.TLS.API.Enabled(endpointType) { + // set endpoint protocol to https + data.Protocol = ptr.To(service.ProtocolHTTPS) + } + apiEndpoints[string(endpointType)], err = svc.GetAPIEndpoint( svcOverride.EndpointURL, data.Protocol, data.Path) if err != nil { @@ -576,6 +674,54 @@ func (r *IronicAPIReconciler) reconcileNormal(ctx context.Context, instance *iro instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) + // + // TLS input validation + // + // Validate the CA cert secret if provided + if instance.Spec.TLS.CaBundleSecretName != "" { + hash, ctrlResult, err := tls.ValidateCACertSecret( + ctx, + helper.GetClient(), + types.NamespacedName{ + Name: instance.Spec.TLS.CaBundleSecretName, + Namespace: instance.Namespace, + }, + ) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + + if hash != "" { + configMapVars[tls.CABundleKey] = env.SetValue(hash) + } + } + + // Validate API service certs secrets + certsHash, ctrlResult, err := instance.Spec.TLS.API.ValidateCertSecrets(ctx, helper, instance.Namespace) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + configMapVars[tls.TLSHashName] = env.SetValue(certsHash) + + // all cert input checks out so report InputReady + instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // // Create ConfigMaps required as input for the Service and calculate an overall hash of hashes // @@ -655,7 +801,7 @@ func (r *IronicAPIReconciler) reconcileNormal(ctx context.Context, instance *iro } // Handle service init - ctrlResult, err := r.reconcileInit(ctx, instance, helper, serviceLabels) + ctrlResult, err = r.reconcileInit(ctx, instance, helper, serviceLabels) if err != nil { return ctrlResult, err } else if (ctrlResult != ctrl.Result{}) { @@ -683,8 +829,19 @@ func (r *IronicAPIReconciler) reconcileNormal(ctx context.Context, instance *iro // // Define a new Deployment object + deplDef, err := ironicapi.Deployment(instance, inputHash, serviceLabels, serviceAnnotations) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DeploymentReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.DeploymentReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + depl := deployment.NewDeployment( - ironicapi.Deployment(instance, inputHash, serviceLabels, serviceAnnotations), + deplDef, time.Duration(5)*time.Second, ) @@ -791,6 +948,21 @@ func (r *IronicAPIReconciler) generateServiceConfigMaps( templateParameters["Standalone"] = instance.Spec.Standalone templateParameters["LogPath"] = ironic.LogPath + // create httpd vhost template parameters + httpdVhostConfig := map[string]interface{}{} + for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} { + endptConfig := map[string]interface{}{} + endptConfig["ServerName"] = fmt.Sprintf("%s-%s.%s.svc", ironic.ServiceName, endpt.String(), instance.Namespace) + endptConfig["TLS"] = false // default TLS to false, and set it bellow to true if enabled + if instance.Spec.TLS.API.Enabled(endpt) { + endptConfig["TLS"] = true + endptConfig["SSLCertificateFile"] = fmt.Sprintf("/etc/pki/tls/certs/%s.crt", endpt.String()) + endptConfig["SSLCertificateKeyFile"] = fmt.Sprintf("/etc/pki/tls/private/%s.key", endpt.String()) + } + httpdVhostConfig[endpt.String()] = endptConfig + } + templateParameters["VHosts"] = httpdVhostConfig + cms := []util.Template{ // Scripts ConfigMap { diff --git a/controllers/ironicconductor_controller.go b/controllers/ironicconductor_controller.go index 412d7db8..c7220f60 100644 --- a/controllers/ironicconductor_controller.go +++ b/controllers/ironicconductor_controller.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/types" k8s_types "k8s.io/apimachinery/pkg/types" "github.com/go-logr/logr" @@ -33,10 +35,12 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" @@ -55,6 +59,7 @@ import ( common_rbac "github.com/openstack-k8s-operators/lib-common/modules/common/rbac" "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/statefulset" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "github.com/openstack-k8s-operators/lib-common/modules/common/util" ) @@ -158,6 +163,7 @@ func (r *IronicConductorReconciler) Reconcile(ctx context.Context, req ctrl.Requ condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage), condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage), condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage), + condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage), // service account, role, rolebinding conditions condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage), condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage), @@ -241,6 +247,30 @@ func (r *IronicConductorReconciler) SetupWithManager(ctx context.Context, mgr ct return nil } + // index passwordSecretField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicConductor{}, passwordSecretField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicConductor) + if cr.Spec.Secret == "" { + return nil + } + return []string{cr.Spec.Secret} + }); err != nil { + return err + } + + // index caBundleSecretNameField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicConductor{}, caBundleSecretNameField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicConductor) + if cr.Spec.TLS.CaBundleSecretName == "" { + return nil + } + return []string{cr.Spec.TLS.CaBundleSecretName} + }); err != nil { + return err + } + return ctrl.NewControllerManagedBy(mgr). For(&ironicv1.IronicConductor{}). Owns(&appsv1.StatefulSet{}). @@ -254,9 +284,47 @@ func (r *IronicConductorReconciler) SetupWithManager(ctx context.Context, mgr ct // watch the config CMs we don't own Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(configMapFn)). + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). Complete(r) } +func (r *IronicConductorReconciler) findObjectsForSrc(src client.Object) []reconcile.Request { + requests := []reconcile.Request{} + + l := log.FromContext(context.Background()).WithName("Controllers").WithName("IronicConductor") + + for _, field := range ironicConductorWatchFields { + crList := &ironicv1.IronicConductorList{} + listOps := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(field, src.GetName()), + Namespace: src.GetNamespace(), + } + err := r.List(context.TODO(), crList, listOps) + if err != nil { + return []reconcile.Request{} + } + + for _, item := range crList.Items { + l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace())) + + requests = append(requests, + reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: item.GetName(), + Namespace: item.GetNamespace(), + }, + }, + ) + } + } + + return requests +} + func (r *IronicConductorReconciler) reconcileDelete(ctx context.Context, instance *ironicv1.IronicConductor, helper *helper.Helper) (ctrl.Result, error) { Log := r.GetLogger(ctx) @@ -459,6 +527,38 @@ func (r *IronicConductorReconciler) reconcileNormal(ctx context.Context, instanc instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) + // + // TLS input validation + // + // Validate the CA cert secret if provided + if instance.Spec.TLS.CaBundleSecretName != "" { + hash, ctrlResult, err := tls.ValidateCACertSecret( + ctx, + helper.GetClient(), + types.NamespacedName{ + Name: instance.Spec.TLS.CaBundleSecretName, + Namespace: instance.Namespace, + }, + ) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + + if hash != "" { + configMapVars[tls.CABundleKey] = env.SetValue(hash) + } + } + // all cert input checks out so report InputReady + instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // // Create ConfigMaps required as input for the Service and calculate an overall hash of hashes // diff --git a/controllers/ironicinspector_controller.go b/controllers/ironicinspector_controller.go index 3d54b088..04a93799 100644 --- a/controllers/ironicinspector_controller.go +++ b/controllers/ironicinspector_controller.go @@ -37,13 +37,19 @@ import ( oko_secret "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/service" "github.com/openstack-k8s-operators/lib-common/modules/common/statefulset" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" util "github.com/openstack-k8s-operators/lib-common/modules/common/util" routev1 "github.com/openshift/api/route/v1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/types" k8s_types "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" @@ -61,6 +67,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -203,6 +210,10 @@ func (r *IronicInspectorReconciler) Reconcile( condition.RabbitMqTransportURLReadyCondition, condition.InitReason, condition.RabbitMqTransportURLReadyInitMessage), + condition.UnknownCondition( + condition.TLSInputReadyCondition, + condition.InitReason, + condition.InputReadyInitMessage), // service account, role, rolebinding conditions condition.UnknownCondition( condition.ServiceAccountReadyCondition, @@ -307,6 +318,30 @@ func (r *IronicInspectorReconciler) SetupWithManager( return nil } + // index passwordSecretField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicInspector{}, passwordSecretField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicInspector) + if cr.Spec.Secret == "" { + return nil + } + return []string{cr.Spec.Secret} + }); err != nil { + return err + } + + // index caBundleSecretNameField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicInspector{}, caBundleSecretNameField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicInspector) + if cr.Spec.TLS.CaBundleSecretName == "" { + return nil + } + return []string{cr.Spec.TLS.CaBundleSecretName} + }); err != nil { + return err + } + return ctrl.NewControllerManagedBy(mgr). For(&ironicv1.IronicInspector{}). Owns(&corev1.Secret{}). @@ -315,13 +350,52 @@ func (r *IronicInspectorReconciler) SetupWithManager( Owns(&corev1.ServiceAccount{}). Owns(&rbacv1.Role{}). Owns(&rbacv1.RoleBinding{}). + Owns(&appsv1.StatefulSet{}). // watch the config CMs we don't own Watches( &source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(configMapFn)). + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). Complete(r) } +func (r *IronicInspectorReconciler) findObjectsForSrc(src client.Object) []reconcile.Request { + requests := []reconcile.Request{} + + l := log.FromContext(context.Background()).WithName("Controllers").WithName("IronicInspector") + + for _, field := range ironicInspectorWatchFields { + crList := &ironicv1.IronicInspectorList{} + listOps := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(field, src.GetName()), + Namespace: src.GetNamespace(), + } + err := r.List(context.TODO(), crList, listOps) + if err != nil { + return []reconcile.Request{} + } + + for _, item := range crList.Items { + l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace())) + + requests = append(requests, + reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: item.GetName(), + Namespace: item.GetNamespace(), + }, + }, + ) + } + } + + return requests +} + func (r *IronicInspectorReconciler) reconcileTransportURL( ctx context.Context, instance *ironicv1.IronicInspector, @@ -432,6 +506,54 @@ func (r *IronicInspectorReconciler) reconcileConfigMapsAndSecrets( condition.InputReadyMessage) // run check OpenStack secret - end + // + // TLS input validation + // + // Validate the CA cert secret if provided + if instance.Spec.TLS.CaBundleSecretName != "" { + hash, ctrlResult, err := tls.ValidateCACertSecret( + ctx, + helper.GetClient(), + types.NamespacedName{ + Name: instance.Spec.TLS.CaBundleSecretName, + Namespace: instance.Namespace, + }, + ) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrl.Result{}, "", err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, "", nil + } + + if hash != "" { + configMapVars[tls.CABundleKey] = env.SetValue(hash) + } + } + + // Validate API service certs secrets + certsHash, ctrlResult, err := instance.Spec.TLS.API.ValidateCertSecrets(ctx, helper, instance.Namespace) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrl.Result{}, "", err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, "", nil + } + configMapVars[tls.TLSHashName] = env.SetValue(certsHash) + + // all cert input checks out so report InputReady + instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // // Create ConfigMaps and Secrets required as input for the Service and // calculate an overall hash of hashes @@ -476,7 +598,7 @@ func (r *IronicInspectorReconciler) reconcileConfigMapsAndSecrets( } else if hashChanged { // Hash changed and instance status should be updated (which will be done by main defer func), // so we need to return and reconcile again - return ctrl.Result{}, "", nil + return ctrl.Result{RequeueAfter: time.Second * 5}, "", nil } instance.Status.Conditions.MarkTrue( @@ -503,9 +625,18 @@ func (r *IronicInspectorReconciler) reconcileStatefulSet( } // Define a new StatefulSet object + ssDef, err := ironicinspector.StatefulSet(instance, inputHash, serviceLabels, ingressDomain, serviceAnnotations) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DeploymentReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.DeploymentReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } ss := statefulset.NewStatefulSet( - ironicinspector.StatefulSet( - instance, inputHash, serviceLabels, ingressDomain, serviceAnnotations), + ssDef, time.Duration(5)*time.Second, ) @@ -1004,7 +1135,12 @@ func (r *IronicInspectorReconciler) reconcileExposeService( } // create service - end - // TODO: TLS, pass in https as protocol, create TLS cert + // if TLS is enabled + if instance.Spec.TLS.API.Enabled(endpointType) { + // set endpoint protocol to https + data.Protocol = ptr.To(service.ProtocolHTTPS) + } + apiEndpoints[string(endpointType)], err = svc.GetAPIEndpoint( svcOverride.EndpointURL, data.Protocol, data.Path) if err != nil { @@ -1237,6 +1373,21 @@ func (r *IronicInspectorReconciler) generateServiceConfigMaps( templateParameters["DHCPRanges"] = dhcpRanges templateParameters["Standalone"] = instance.Spec.Standalone + // create httpd vhost template parameters + httpdVhostConfig := map[string]interface{}{} + for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} { + endptConfig := map[string]interface{}{} + endptConfig["ServerName"] = fmt.Sprintf("%s-%s-%s.%s.svc", ironic.ServiceName, ironic.InspectorComponent, endpt.String(), instance.Namespace) + endptConfig["TLS"] = false // default TLS to false, and set it bellow to true if enabled + if instance.Spec.TLS.API.Enabled(endpt) { + endptConfig["TLS"] = true + endptConfig["SSLCertificateFile"] = fmt.Sprintf("/etc/pki/tls/certs/%s.crt", endpt.String()) + endptConfig["SSLCertificateKeyFile"] = fmt.Sprintf("/etc/pki/tls/private/%s.key", endpt.String()) + } + httpdVhostConfig[endpt.String()] = endptConfig + } + templateParameters["VHosts"] = httpdVhostConfig + cms := []util.Template{ // Scripts ConfigMap { diff --git a/controllers/ironicneutronagent_controller.go b/controllers/ironicneutronagent_controller.go index 36e4cc9a..4236a373 100644 --- a/controllers/ironicneutronagent_controller.go +++ b/controllers/ironicneutronagent_controller.go @@ -25,13 +25,20 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" "github.com/go-logr/logr" rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" @@ -40,6 +47,7 @@ import ( "github.com/openstack-k8s-operators/ironic-operator/pkg/ironicneutronagent" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" endpoint "github.com/openstack-k8s-operators/lib-common/modules/common/endpoint" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" @@ -165,6 +173,10 @@ func (r *IronicNeutronAgentReconciler) Reconcile( condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage), + condition.UnknownCondition( + condition.TLSInputReadyCondition, + condition.InitReason, + condition.InputReadyInitMessage), // service account, role, rolebinding conditions condition.UnknownCondition( condition.ServiceAccountReadyCondition, @@ -202,6 +214,30 @@ func (r *IronicNeutronAgentReconciler) Reconcile( func (r *IronicNeutronAgentReconciler) SetupWithManager( mgr ctrl.Manager, ) error { + // index passwordSecretField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicNeutronAgent{}, passwordSecretField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicNeutronAgent) + if cr.Spec.Secret == "" { + return nil + } + return []string{cr.Spec.Secret} + }); err != nil { + return err + } + + // index caBundleSecretNameField + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &ironicv1.IronicNeutronAgent{}, caBundleSecretNameField, func(rawObj client.Object) []string { + // Extract the secret name from the spec, if one is provided + cr := rawObj.(*ironicv1.IronicNeutronAgent) + if cr.Spec.TLS.CaBundleSecretName == "" { + return nil + } + return []string{cr.Spec.TLS.CaBundleSecretName} + }); err != nil { + return err + } + return ctrl.NewControllerManagedBy(mgr). For(&ironicv1.IronicNeutronAgent{}). Owns(&appsv1.Deployment{}). @@ -211,9 +247,47 @@ func (r *IronicNeutronAgentReconciler) SetupWithManager( Owns(&corev1.ServiceAccount{}). Owns(&rbacv1.Role{}). Owns(&rbacv1.RoleBinding{}). + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). Complete(r) } +func (r *IronicNeutronAgentReconciler) findObjectsForSrc(src client.Object) []reconcile.Request { + requests := []reconcile.Request{} + + l := log.FromContext(context.Background()).WithName("Controllers").WithName("IronicNeutronAgent") + + for _, field := range ironicNeutronAgentWatchFields { + crList := &ironicv1.IronicNeutronAgentList{} + listOps := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(field, src.GetName()), + Namespace: src.GetNamespace(), + } + err := r.List(context.TODO(), crList, listOps) + if err != nil { + return []reconcile.Request{} + } + + for _, item := range crList.Items { + l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace())) + + requests = append(requests, + reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: item.GetName(), + Namespace: item.GetNamespace(), + }, + }, + ) + } + } + + return requests +} + func (r *IronicNeutronAgentReconciler) reconcileTransportURL( ctx context.Context, instance *ironicv1.IronicNeutronAgent, @@ -298,6 +372,38 @@ func (r *IronicNeutronAgentReconciler) reconcileConfigMapsAndSecrets( condition.InputReadyMessage) // run check OpenStack secret - end + // + // TLS input validation + // + // Validate the CA cert secret if provided + if instance.Spec.TLS.CaBundleSecretName != "" { + hash, ctrlResult, err := tls.ValidateCACertSecret( + ctx, + helper.GetClient(), + types.NamespacedName{ + Name: instance.Spec.TLS.CaBundleSecretName, + Namespace: instance.Namespace, + }, + ) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, "", err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, "", nil + } + + if hash != "" { + configMapVars[tls.CABundleKey] = env.SetValue(hash) + } + } + // all cert input checks out so report InputReady + instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // // Create ConfigMaps required as input for the Service and calculate an overall hash of hashes // @@ -334,7 +440,7 @@ func (r *IronicNeutronAgentReconciler) reconcileConfigMapsAndSecrets( } else if hashChanged { // Hash changed and instance status should be updated (which will be done by main defer func), // so we need to return and reconcile again - return ctrl.Result{}, "", nil + return ctrl.Result{RequeueAfter: time.Second * 5}, "", nil } instance.Status.Conditions.MarkTrue( condition.ServiceConfigReadyCondition, diff --git a/go.mod b/go.mod index 812a00a1..77d8c081 100644 --- a/go.mod +++ b/go.mod @@ -3,25 +3,25 @@ module github.com/openstack-k8s-operators/ironic-operator go 1.19 require ( - github.com/go-logr/logr v1.3.0 + github.com/go-logr/logr v1.4.1 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 - github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 github.com/openshift/api v3.9.0+incompatible - github.com/openstack-k8s-operators/infra-operator/apis v0.1.1-0.20231001103054-f74a88ed4971 + github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240104150635-c4ffc51e0752 github.com/openstack-k8s-operators/ironic-operator/api v0.1.1-0.20230901035810-610538e222c9 - github.com/openstack-k8s-operators/keystone-operator/api v0.1.1-0.20230925133339-116a3a39cdfa - github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32 - github.com/openstack-k8s-operators/lib-common/modules/test v0.1.2-0.20230927082538-4f614f333d17 + github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240117115727-432678553b37 + github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216 + github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240117103205-2bd91a3da216 github.com/openstack-k8s-operators/mariadb-operator/api v0.3.0 - k8s.io/api v0.26.11 + k8s.io/api v0.26.12 k8s.io/apimachinery v0.27.1 - k8s.io/client-go v0.26.11 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/client-go v0.26.12 + k8s.io/utils v0.0.0-20240102154912-e7106e64919e sigs.k8s.io/controller-runtime v0.14.7 ) -require golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect +require golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect require ( github.com/beorn7/perks v1.0.1 // indirect @@ -42,8 +42,8 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.4.0 - github.com/gophercloud/gophercloud v1.6.0 // indirect + github.com/google/uuid v1.5.0 + github.com/gophercloud/gophercloud v1.7.0 // indirect github.com/imdario/mergo v0.3.16 // indirect; indirect // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -52,7 +52,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20230927082538-4f614f333d17 // indirect + github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20231001084618-12369665b166 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect @@ -61,22 +61,22 @@ require ( github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 - k8s.io/apiextensions-apiserver v0.26.11 // indirect - k8s.io/component-base v0.26.11 // indirect + k8s.io/apiextensions-apiserver v0.26.12 // indirect + k8s.io/component-base v0.26.12 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 7086fb1f..e0777026 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -171,12 +171,12 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gophercloud/gophercloud v1.6.0 h1:JwJN1bauRnWPba5ueWs9IluONHteXPWjjK+MvfM4krY= -github.com/gophercloud/gophercloud v1.6.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EYUh+UNCAs= +github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -228,22 +228,22 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= -github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 h1:rncLxJBpFGqBztyxCMwNRnMjhhIDOWHJowi6q8G6koI= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= -github.com/openstack-k8s-operators/infra-operator/apis v0.1.1-0.20231001103054-f74a88ed4971 h1:5kNS+gseixkgRhYPukQVJyewPTM0lfUOmKP0A03wFFY= -github.com/openstack-k8s-operators/infra-operator/apis v0.1.1-0.20231001103054-f74a88ed4971/go.mod h1:zqFs5MrBKeaE4HQroUgMWwIkBwmmcygg6sghcidSdCA= -github.com/openstack-k8s-operators/keystone-operator/api v0.1.1-0.20230925133339-116a3a39cdfa h1:zKatN2iMa7Ukq7VuRbzt84n6yWZXW8RLuMnyxIN4ggQ= -github.com/openstack-k8s-operators/keystone-operator/api v0.1.1-0.20230925133339-116a3a39cdfa/go.mod h1:Zyp4nHS/JggPqlsMNM8WZN546oYINvGVlHA1NivE3sU= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32 h1:r24jE5tdacLivcZczb3t6RvbvHp6kXQrW2ECuekzgH8= -github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231011150636-e8a0540a3c32/go.mod h1:xXAuy7HtWN4p7LF5Q+NHLkwAsKVh0KrzpnuPYIG3XaA= -github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20230927082538-4f614f333d17 h1:d3HP0nEGNd8cQ088beQbyWzcgdMppD+Zs8HeoMdzRws= -github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20230927082538-4f614f333d17/go.mod h1:+iJZo5alCeOGD/524hWWdlINA6zqY+MjfWT7cDcbvBE= -github.com/openstack-k8s-operators/lib-common/modules/test v0.1.2-0.20230927082538-4f614f333d17 h1:zJguNin+9IwRnGKy1A7ranxASKO1vTvWxoXwkCz8MWw= -github.com/openstack-k8s-operators/lib-common/modules/test v0.1.2-0.20230927082538-4f614f333d17/go.mod h1:YOFHrNK/QqCvZUPlDJYmDyaCkbKIB98V04uyofiC9a8= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240104150635-c4ffc51e0752 h1:RWH5R7RLinnWQOp8MmmlmOy/sIlIsrz5hCRFVO1wZzA= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240104150635-c4ffc51e0752/go.mod h1:y4qeIT1ubUm9SKrvhVTuEYWSm0so38P5Hu3ZpdMJMek= +github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240117115727-432678553b37 h1:8vwif7nsY156TsgqEu+qKUlBXc4pvBDEivap6es5cgI= +github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240117115727-432678553b37/go.mod h1:hzs0LNTIYgkWi/ysd0aAAPti2fT5XZmQPIkiFsDWa7I= +github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216 h1:hDwy0K68UN67kh/XU3iuNPWN0/Zcvtc+kcVPdqTY1So= +github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240117103205-2bd91a3da216/go.mod h1:gW0sefZEues1bO7J8utgMIqbXgs2WUCXNtmixYiN1ak= +github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20231001084618-12369665b166 h1:zOnRGMdgq2XvOCCtF1lY4tFhKx3jXrcrtOiZZ1PR6M8= +github.com/openstack-k8s-operators/lib-common/modules/openstack v0.1.1-0.20231001084618-12369665b166/go.mod h1:LOXXvTQCwhOBNd+0FTlgllpa3wqlkI6Vf3Q5QVRVPlw= +github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240117103205-2bd91a3da216 h1:VTlhT+Epr3YY/I9NKKCv4MWITnNgBUXv684FB7YQT+E= +github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240117103205-2bd91a3da216/go.mod h1:ni4mvKeubWsTjKmcToJ+hIo7pJipM9hwiUv8qhm1R6Y= github.com/openstack-k8s-operators/mariadb-operator/api v0.3.0 h1:FB0xB6whYM6W4XIncYo2mPiOJWkFsIOWtCT+UOtvOaQ= github.com/openstack-k8s-operators/mariadb-operator/api v0.3.0/go.mod h1:xhiz5wFdKWwVM7BF/VYon4TT3NuUPXp/Pyn2hWcp0CE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -300,8 +300,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -341,8 +341,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -363,8 +363,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -400,8 +400,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -463,12 +463,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -527,8 +527,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -650,22 +650,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.11 h1:hLhTZRdYc3vBBOY4wbEyTLWgMyieOAk2Ws9NG57QqO4= -k8s.io/api v0.26.11/go.mod h1:bSr/A0TKRt5W2OMDdexkM/ER1NxOxiQqNNFXW2nMZrM= -k8s.io/apiextensions-apiserver v0.26.11 h1:6/T0Jm9c+Aw1AYUflPOz2sAsty304/DDSkciTr8+HuE= -k8s.io/apiextensions-apiserver v0.26.11/go.mod h1:xMqWxAB+AvSTdmFRVWlpavY9bJl/3g6yWiPn/fwZbT0= +k8s.io/api v0.26.12 h1:jJm3s5ot05SUN3tPGg3b+XWuBE7rO/X0+dnVMhxyd5o= +k8s.io/api v0.26.12/go.mod h1:N+HUXukmtXNOKDngxXrEPbZWggWx01tH/N0nG4nV0oo= +k8s.io/apiextensions-apiserver v0.26.12 h1:WHfFheB9AM0eHZsz6wu2h/KVmZ8PM7ZAmNDr3smkUzA= +k8s.io/apiextensions-apiserver v0.26.12/go.mod h1:bvr3OVCML7icxP4rq/fJaNBPPiZ9KIi79n/icBbg5Rc= k8s.io/apimachinery v0.27.1 h1:EGuZiLI95UQQcClhanryclaQE6xjg1Bts6/L3cD7zyc= k8s.io/apimachinery v0.27.1/go.mod h1:5ikh59fK3AJ287GUvpUsryoMFtH9zj/ARfWCo3AyXTM= -k8s.io/client-go v0.26.11 h1:RjfZr5+vQjjTRmk4oCqHyC0cgrZXPjw+X+ge35sk4GI= -k8s.io/client-go v0.26.11/go.mod h1:+emNszw9va/uRJIM5ALTBtFnlZMTjwBrNjRfEh0iuw8= -k8s.io/component-base v0.26.11 h1:1/JmB6fexefGByfFyIK6aHksZZVtaDskttzXOzmZ6zA= -k8s.io/component-base v0.26.11/go.mod h1:jYNisnoM6iWFRUg51pxaQabzL5fBYTr5CMpsLjUYGp0= +k8s.io/client-go v0.26.12 h1:kPpTpIeFNqwo4UyvoqzNp3DNK2mbGcdGv23eS1U8VMo= +k8s.io/client-go v0.26.12/go.mod h1:V7thEnIFroyNZOU30dKLiiVeqQmJz45shJG1mu7nONQ= +k8s.io/component-base v0.26.12 h1:OyYjCtruv4/Yau5Z1v6e59N+JRDTj8JnW95W9w9AMpg= +k8s.io/component-base v0.26.12/go.mod h1:X98Et5BxJ8i4TcDusUcKS8EYxCujBU1lCL3pc/CUtHQ= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a h1:gmovKNur38vgoWfGtP5QOGNOA7ki4n6qNYoFAgMlNvg= k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/ironic/dbsync.go b/pkg/ironic/dbsync.go index b210b6f7..e28570bd 100644 --- a/pkg/ironic/dbsync.go +++ b/pkg/ironic/dbsync.go @@ -48,6 +48,17 @@ func DbSyncJob( envVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") envVars["KOLLA_BOOTSTRAP"] = env.SetValue("true") + volumes := GetVolumes(ServiceName) + volumeMounts := GetDBSyncVolumeMounts() + initVolumeMounts := GetInitVolumeMounts() + + // add CA cert if defined + if instance.Spec.IronicAPI.TLS.CaBundleSecretName != "" { + volumes = append(volumes, instance.Spec.IronicAPI.TLS.CreateVolume()) + volumeMounts = append(volumeMounts, instance.Spec.IronicAPI.TLS.CreateVolumeMounts(nil)...) + initVolumeMounts = append(initVolumeMounts, instance.Spec.IronicAPI.TLS.CreateVolumeMounts(nil)...) + } + job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: ServiceName + "-db-sync", @@ -71,16 +82,15 @@ func DbSyncJob( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), - VolumeMounts: GetDBSyncVolumeMounts(), + VolumeMounts: volumeMounts, }, }, + Volumes: volumes, }, }, }, } - job.Spec.Template.Spec.Volumes = GetVolumes(ServiceName) - initContainerDetails := APIDetails{ ContainerImage: instance.Spec.Images.Conductor, DatabaseHost: instance.Status.DatabaseHostname, @@ -88,7 +98,7 @@ func DbSyncJob( OSPSecret: instance.Spec.Secret, DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, - VolumeMounts: GetInitVolumeMounts(), + VolumeMounts: initVolumeMounts, } job.Spec.Template.Spec.InitContainers = InitContainer(initContainerDetails) diff --git a/pkg/ironicapi/deployment.go b/pkg/ironicapi/deployment.go index 48c07d29..dea75a71 100644 --- a/pkg/ironicapi/deployment.go +++ b/pkg/ironicapi/deployment.go @@ -21,6 +21,8 @@ import ( common "github.com/openstack-k8s-operators/lib-common/modules/common" affinity "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" env "github.com/openstack-k8s-operators/lib-common/modules/common/env" + "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -39,7 +41,7 @@ func Deployment( configHash string, labels map[string]string, annotations map[string]string, -) *appsv1.Deployment { +) (*appsv1.Deployment, error) { runAsUser := int64(0) livenessProbe := &corev1.Probe{ @@ -81,6 +83,42 @@ func Deployment( Path: "/v1", Port: intstr.IntOrString{Type: intstr.Int, IntVal: int32(ironic.IronicInternalPort)}, } + + if instance.Spec.TLS.API.Enabled(service.EndpointPublic) { + livenessProbe.HTTPGet.Scheme = corev1.URISchemeHTTPS + readinessProbe.HTTPGet.Scheme = corev1.URISchemeHTTPS + } + } + + // create Volume and VolumeMounts + volumes := GetVolumes(instance.Name) + volumeMounts := GetVolumeMounts() + initVolumeMounts := GetInitVolumeMounts() + + // add CA cert if defined + if instance.Spec.TLS.CaBundleSecretName != "" { + volumes = append(volumes, instance.Spec.TLS.CreateVolume()) + volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + initVolumeMounts = append(initVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + } + + for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} { + if instance.Spec.TLS.API.Enabled(endpt) { + var tlsEndptCfg tls.GenericService + switch endpt { + case service.EndpointPublic: + tlsEndptCfg = instance.Spec.TLS.API.Public + case service.EndpointInternal: + tlsEndptCfg = instance.Spec.TLS.API.Internal + } + + svc, err := tlsEndptCfg.ToService() + if err != nil { + return nil, err + } + volumes = append(volumes, svc.CreateVolume(endpt.String())) + volumeMounts = append(volumeMounts, svc.CreateVolumeMounts(endpt.String())...) + } } envVars := map[string]env.Setter{} @@ -135,18 +173,19 @@ func Deployment( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), - VolumeMounts: GetVolumeMounts(), + VolumeMounts: volumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: readinessProbe, LivenessProbe: livenessProbe, }, }, TerminationGracePeriodSeconds: &terminationGracePeriod, + Volumes: volumes, }, }, }, } - deployment.Spec.Template.Spec.Volumes = GetVolumes(instance.Name) + // If possible two pods of the same service should not // run on the same worker node. If this is not possible // the get still created on the same worker node. @@ -169,10 +208,10 @@ func Deployment( TransportURLSecret: instance.Spec.TransportURLSecret, DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, - VolumeMounts: GetInitVolumeMounts(), + VolumeMounts: initVolumeMounts, PxeInit: false, } deployment.Spec.Template.Spec.InitContainers = ironic.InitContainer(initContainerDetails) - return deployment + return deployment, nil } diff --git a/pkg/ironicconductor/statefulset.go b/pkg/ironicconductor/statefulset.go index 77ed1474..686bb2a4 100644 --- a/pkg/ironicconductor/statefulset.go +++ b/pkg/ironicconductor/statefulset.go @@ -173,6 +173,21 @@ func StatefulSet( httpbootEnvVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") httpbootEnvVars["CONFIG_HASH"] = env.SetValue(configHash) + volumes := GetVolumes(instance) + conductorVolumeMounts := GetVolumeMounts("ironic-conductor") + httpbootVolumeMounts := GetVolumeMounts("httpboot") + dnsmasqVolumeMounts := GetVolumeMounts("dnsmasq") + initVolumeMounts := GetInitVolumeMounts() + + // Add the CA bundle + if instance.Spec.TLS.CaBundleSecretName != "" { + volumes = append(volumes, instance.Spec.TLS.CreateVolume()) + conductorVolumeMounts = append(conductorVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + httpbootVolumeMounts = append(httpbootVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + dnsmasqVolumeMounts = append(dnsmasqVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + initVolumeMounts = append(initVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + } + conductorContainer := corev1.Container{ Name: ironic.ServiceName + "-" + ironic.ConductorComponent, Command: []string{ @@ -184,7 +199,7 @@ func StatefulSet( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), - VolumeMounts: GetVolumeMounts("ironic-conductor"), + VolumeMounts: conductorVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: readinessProbe, LivenessProbe: livenessProbe, @@ -201,7 +216,7 @@ func StatefulSet( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, httpbootEnvVars), - VolumeMounts: GetVolumeMounts("httpboot"), + VolumeMounts: httpbootVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: httpbootReadinessProbe, LivenessProbe: httpbootLivenessProbe, @@ -232,7 +247,7 @@ func StatefulSet( }, }, Env: env.MergeEnvs([]corev1.EnvVar{}, dnsmasqEnvVars), - VolumeMounts: GetVolumeMounts("dnsmasq"), + VolumeMounts: dnsmasqVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: dnsmasqReadinessProbe, LivenessProbe: dnsmasqLivenessProbe, @@ -267,11 +282,12 @@ func StatefulSet( ServiceAccountName: instance.RbacResourceName(), Containers: containers, TerminationGracePeriodSeconds: &terminationGracePeriod, + Volumes: volumes, }, }, }, } - statefulset.Spec.Template.Spec.Volumes = GetVolumes(instance) + // If possible two pods of the same service should not // run on the same worker node. If this is not possible // the get still created on the same worker node. @@ -304,7 +320,7 @@ func StatefulSet( TransportURLSecret: instance.Spec.TransportURLSecret, DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, - VolumeMounts: GetInitVolumeMounts(), + VolumeMounts: initVolumeMounts, PxeInit: true, ConductorInit: true, DeployHTTPURL: deployHTTPURL, diff --git a/pkg/ironicinspector/statefulset.go b/pkg/ironicinspector/statefulset.go index ebacafb5..95d88b65 100644 --- a/pkg/ironicinspector/statefulset.go +++ b/pkg/ironicinspector/statefulset.go @@ -21,6 +21,8 @@ import ( common "github.com/openstack-k8s-operators/lib-common/modules/common" affinity "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" env "github.com/openstack-k8s-operators/lib-common/modules/common/env" + "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -31,6 +33,8 @@ import ( const ( // ServiceCommand - ServiceCommand = "/usr/local/bin/kolla_set_configs && /usr/local/bin/kolla_start" + // IronicInspectorHttpdCommand - + IronicInspectorHttpdCommand = "/usr/sbin/httpd -DFOREGROUND" ) // StatefulSet func @@ -40,7 +44,7 @@ func StatefulSet( labels map[string]string, ingressDomain string, annotations map[string]string, -) *appsv1.StatefulSet { +) (*appsv1.StatefulSet, error) { runAsUser := int64(0) livenessProbe := &corev1.Probe{ @@ -53,6 +57,10 @@ func StatefulSet( PeriodSeconds: 5, InitialDelaySeconds: 3, } + startupProbe := &corev1.Probe{ + FailureThreshold: 6, + PeriodSeconds: 10, + } dnsmasqLivenessProbe := &corev1.Probe{ TimeoutSeconds: 10, PeriodSeconds: 30, @@ -87,6 +95,11 @@ func StatefulSet( "/bin/true", }, } + startupProbe.Exec = &corev1.ExecAction{ + Command: []string{ + "/bin/true", + }, + } dnsmasqLivenessProbe.Exec = &corev1.ExecAction{ Command: []string{ "/bin/true", @@ -121,6 +134,15 @@ func StatefulSet( Path: "/v1", Port: intstr.IntOrString{Type: intstr.Int, IntVal: int32(IronicInspectorInternalPort)}, } + startupProbe.HTTPGet = &corev1.HTTPGetAction{ + Path: "/v1", + Port: intstr.IntOrString{Type: intstr.Int, IntVal: int32(IronicInspectorInternalPort)}, + } + if instance.Spec.TLS.API.Enabled(service.EndpointPublic) { + livenessProbe.HTTPGet.Scheme = corev1.URISchemeHTTPS + readinessProbe.HTTPGet.Scheme = corev1.URISchemeHTTPS + startupProbe.HTTPGet.Scheme = corev1.URISchemeHTTPS + } // (TODO): Use http request if we can create a good request path httpbootLivenessProbe.TCPSocket = &corev1.TCPSocketAction{ @@ -142,8 +164,65 @@ func StatefulSet( } } + // create Volume and VolumeMounts + volumes := GetVolumes(ironic.ServiceName + "-" + ironic.InspectorComponent) + httpbootVolumeMounts := GetVolumeMounts("httpboot") + httpdVolumeMounts := GetVolumeMounts("httpd") + inspectorVolumeMounts := GetVolumeMounts("ironic-inspector") + dnsmasqVolumeMounts := GetVolumeMounts("dnsmasq") + initVolumeMounts := GetInitVolumeMounts() + + // add CA cert if defined + if instance.Spec.TLS.CaBundleSecretName != "" { + volumes = append(volumes, instance.Spec.TLS.CreateVolume()) + httpdVolumeMounts = append(httpdVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + inspectorVolumeMounts = append(inspectorVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + httpbootVolumeMounts = append(httpbootVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + dnsmasqVolumeMounts = append(dnsmasqVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + initVolumeMounts = append(initVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + } + + for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} { + if instance.Spec.TLS.API.Enabled(endpt) { + var tlsEndptCfg tls.GenericService + switch endpt { + case service.EndpointPublic: + tlsEndptCfg = instance.Spec.TLS.API.Public + case service.EndpointInternal: + tlsEndptCfg = instance.Spec.TLS.API.Internal + } + + svc, err := tlsEndptCfg.ToService() + if err != nil { + return nil, err + } + volumes = append(volumes, svc.CreateVolume(endpt.String())) + httpdVolumeMounts = append(httpdVolumeMounts, svc.CreateVolumeMounts(endpt.String())...) + } + } + containers := []corev1.Container{} + httpdEnvVars := map[string]env.Setter{} + httpdEnvVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") + httpdEnvVars["CONFIG_HASH"] = env.SetValue(configHash) + httpdContainer := corev1.Container{ + Name: ironic.ServiceName + "-" + ironic.InspectorComponent + "-httpd", + Image: instance.Spec.ContainerImage, + Command: []string{ + "/bin/bash", + }, + Args: args, + SecurityContext: &corev1.SecurityContext{RunAsUser: &runAsUser}, + Env: env.MergeEnvs([]corev1.EnvVar{}, httpdEnvVars), + VolumeMounts: httpdVolumeMounts, + Resources: instance.Spec.Resources, + ReadinessProbe: readinessProbe, + LivenessProbe: livenessProbe, + StartupProbe: startupProbe, + } + containers = append(containers, httpdContainer) + inspectorEnvVars := map[string]env.Setter{} inspectorEnvVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") inspectorEnvVars["CONFIG_HASH"] = env.SetValue(configHash) @@ -156,10 +235,11 @@ func StatefulSet( Args: args, SecurityContext: &corev1.SecurityContext{RunAsUser: &runAsUser}, Env: env.MergeEnvs([]corev1.EnvVar{}, inspectorEnvVars), - VolumeMounts: GetVolumeMounts("ironic-inspector"), + VolumeMounts: inspectorVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: readinessProbe, LivenessProbe: livenessProbe, + StartupProbe: startupProbe, } containers = append(containers, inspectorContainer) @@ -177,7 +257,7 @@ func StatefulSet( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, httpbootEnvVars), - VolumeMounts: GetVolumeMounts("httpboot"), + VolumeMounts: httpbootVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: httpbootReadinessProbe, LivenessProbe: httpbootLivenessProbe, @@ -206,7 +286,7 @@ func StatefulSet( }, }, Env: env.MergeEnvs([]corev1.EnvVar{}, dnsmasqEnvVars), - VolumeMounts: GetVolumeMounts("dnsmasq"), + VolumeMounts: dnsmasqVolumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: dnsmasqReadinessProbe, LivenessProbe: dnsmasqLivenessProbe, @@ -237,11 +317,11 @@ func StatefulSet( ServiceAccountName: instance.RbacResourceName(), Containers: containers, TerminationGracePeriodSeconds: &terminationGracePeriod, + Volumes: volumes, }, }, }, } - statefulset.Spec.Template.Spec.Volumes = GetVolumes(ironic.ServiceName + "-" + ironic.InspectorComponent) // If possible two pods of the same service should not // run on the same worker node. If this is not possible @@ -273,7 +353,7 @@ func StatefulSet( TransportURLSecret: instance.Status.TransportURLSecret, DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, - VolumeMounts: GetInitVolumeMounts(), + VolumeMounts: initVolumeMounts, PxeInit: true, IpaInit: true, InspectorHTTPURL: inspectorHTTPURL, @@ -282,5 +362,5 @@ func StatefulSet( } statefulset.Spec.Template.Spec.InitContainers = InitContainer(initContainerDetails) - return statefulset + return statefulset, nil } diff --git a/pkg/ironicneutronagent/deployment.go b/pkg/ironicneutronagent/deployment.go index cbb4b09b..35e69d29 100644 --- a/pkg/ironicneutronagent/deployment.go +++ b/pkg/ironicneutronagent/deployment.go @@ -80,6 +80,17 @@ func Deployment( envVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") envVars["CONFIG_HASH"] = env.SetValue(configHash) + volumes := GetVolumes(instance.Name) + volumeMounts := GetVolumeMounts() + initVolumeMounts := GetInitVolumeMounts() + + // Add the CA bundle + if instance.Spec.TLS.CaBundleSecretName != "" { + volumes = append(volumes, instance.Spec.TLS.CreateVolume()) + volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + initVolumeMounts = append(initVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + } + // Default oslo.service graceful_shutdown_timeout is 60, so align with that terminationGracePeriod := int64(60) @@ -111,18 +122,19 @@ func Deployment( RunAsUser: &runAsUser, }, Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), - VolumeMounts: GetVolumeMounts(), + VolumeMounts: volumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: readinessProbe, LivenessProbe: livenessProbe, }, }, TerminationGracePeriodSeconds: &terminationGracePeriod, + Volumes: volumes, }, }, }, } - deployment.Spec.Template.Spec.Volumes = GetVolumes(instance.Name) + // If possible two pods of the same service should not // run on the same worker node. If this is not possible // the get still created on the same worker node. @@ -142,7 +154,7 @@ func Deployment( OSPSecret: instance.Spec.Secret, TransportURLSecret: instance.Status.TransportURLSecret, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, - VolumeMounts: GetInitVolumeMounts(), + VolumeMounts: initVolumeMounts, } deployment.Spec.Template.Spec.InitContainers = InitContainer(initContainerDetails) diff --git a/templates/ironicapi/bin/api-prep.sh b/templates/ironicapi/bin/api-prep.sh index eb160fb3..3179ad18 100755 --- a/templates/ironicapi/bin/api-prep.sh +++ b/templates/ironicapi/bin/api-prep.sh @@ -15,9 +15,6 @@ # under the License. set -ex -# Ensure localhost.crt is generated for mod_ssl -/usr/local/bin/kolla_httpd_setup - # TODO(sbaker): remove when https://review.opendev.org/c/openstack/tripleo-common/+/854459 is in the image mkdir -p /var/www/cgi-bin/ironic cp -a /usr/bin/ironic-api-wsgi /var/www/cgi-bin/ironic/app diff --git a/templates/ironicapi/config/ironic-api-config.json b/templates/ironicapi/config/ironic-api-config.json index af5b1159..280cfbfb 100644 --- a/templates/ironicapi/config/ironic-api-config.json +++ b/templates/ironicapi/config/ironic-api-config.json @@ -18,6 +18,28 @@ "dest": "/etc/httpd/conf/httpd.conf", "owner": "root", "perm": "0644" + }, + { + "source": "/var/lib/config-data/merged/ssl.conf", + "dest": "/etc/httpd/conf.d/ssl.conf", + "owner": "root", + "perm": "0644" + }, + { + "source": "/var/lib/config-data/tls/certs/*", + "dest": "/etc/pki/tls/certs/", + "owner": "root", + "perm": "0640", + "optional": true, + "merge": true + }, + { + "source": "/var/lib/config-data/tls/private/*", + "dest": "/etc/pki/tls/private/", + "owner": "root", + "perm": "0600", + "optional": true, + "merge": true } ], "permissions": [ diff --git a/templates/ironicapi/config/ironic-api-httpd.conf b/templates/ironicapi/config/ironic-api-httpd.conf index 34fec686..f9e93bc7 100644 --- a/templates/ironicapi/config/ironic-api-httpd.conf +++ b/templates/ironicapi/config/ironic-api-httpd.conf @@ -22,26 +22,42 @@ SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded CustomLog /dev/stdout combined env=!forwarded CustomLog /dev/stdout proxy env=forwarded - - ServerName undercloud.ctlplane.localdomain +{{ range $endpt, $vhost := .VHosts }} +# {{ $endpt }} vhost {{ $vhost.ServerName }} configuration + + ServerName {{ $vhost.ServerName }} + ## Vhost docroot DocumentRoot "/var/www/cgi-bin/ironic" + ## Directories, there should at least be a declaration for /var/www/cgi-bin/ironic Options -Indexes +FollowSymLinks +MultiViews AllowOverride None Require all granted + ## Logging ErrorLog /dev/stdout + ServerSignature Off SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded CustomLog /dev/stdout combined env=!forwarded CustomLog /dev/stdout proxy env=forwarded +{{- if $vhost.TLS }} + SetEnvIf X-Forwarded-Proto https HTTPS=1 + + ## SSL directives + SSLEngine on + SSLCertificateFile "{{ $vhost.SSLCertificateFile }}" + SSLCertificateKeyFile "{{ $vhost.SSLCertificateKeyFile }}" +{{- end }} + ## WSGI configuration WSGIApplicationGroup %{GLOBAL} - WSGIDaemonProcess ironic display-name=ironic_wsgi group=ironic processes=1 threads=15 user=ironic - WSGIProcessGroup ironic + WSGIDaemonProcess {{ $endpt }} display-name={{ $endpt }} group=ironic processes=1 threads=15 user=ironic + WSGIProcessGroup {{ $endpt }} WSGIScriptAlias / "/var/www/cgi-bin/ironic/app" WSGIPassAuthorization On +{{ end }} diff --git a/templates/ironicapi/config/ssl.conf b/templates/ironicapi/config/ssl.conf new file mode 100644 index 00000000..e3da4ecb --- /dev/null +++ b/templates/ironicapi/config/ssl.conf @@ -0,0 +1,21 @@ + + SSLRandomSeed startup builtin + SSLRandomSeed startup file:/dev/urandom 512 + SSLRandomSeed connect builtin + SSLRandomSeed connect file:/dev/urandom 512 + + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + + SSLPassPhraseDialog builtin + SSLSessionCache "shmcb:/var/cache/mod_ssl/scache(512000)" + SSLSessionCacheTimeout 300 + Mutex default + SSLCryptoDevice builtin + SSLHonorCipherOrder On + SSLUseStapling Off + SSLStaplingCache "shmcb:/run/httpd/ssl_stapling(32768)" + SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!RC4:!3DES + SSLProtocol all -SSLv2 -SSLv3 -TLSv1 + SSLOptions StdEnvVars + diff --git a/templates/ironicinspector/config/httpd-config.json b/templates/ironicinspector/config/httpd-config.json new file mode 100644 index 00000000..0d9313f5 --- /dev/null +++ b/templates/ironicinspector/config/httpd-config.json @@ -0,0 +1,45 @@ +{ + "command": "/usr/sbin/httpd -DFOREGROUND", + "config_files": [ + { + "source": "/var/lib/config-data/merged/httpd.conf", + "dest": "/etc/httpd/conf/httpd.conf", + "owner": "root", + "perm": "0644" + }, + { + "source": "/var/lib/config-data/merged/ssl.conf", + "dest": "/etc/httpd/conf.d/ssl.conf", + "owner": "root", + "perm": "0644" + }, + { + "source": "/var/lib/config-data/tls/certs/*", + "dest": "/etc/pki/tls/certs/", + "owner": "root", + "perm": "0640", + "optional": true, + "merge": true + }, + { + "source": "/var/lib/config-data/tls/private/*", + "dest": "/etc/pki/tls/private/", + "owner": "root", + "perm": "0600", + "optional": true, + "merge": true + } + ], + "permissions": [ + { + "path": "/var/log/ironic-inspector", + "owner": "ironic-inspector:ironic-inspector", + "recurse": true + }, + { + "path": "/var/lib/ironic-inspector", + "owner": "ironic-inspector:ironic-inspector", + "recurse": true + } + ] +} diff --git a/templates/ironicinspector/config/httpd.conf b/templates/ironicinspector/config/httpd.conf new file mode 100644 index 00000000..df74b789 --- /dev/null +++ b/templates/ironicinspector/config/httpd.conf @@ -0,0 +1,54 @@ +ServerTokens Prod +ServerSignature Off +TraceEnable Off +PidFile run/httpd.pid +ServerRoot "/etc/httpd" +ServerName "localhost.localdomain" + +User apache +Group apache + +Listen 5050 + +TypesConfig /etc/mime.types + +Include conf.modules.d/*.conf +Include conf.d/*.conf + +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy + +SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded +CustomLog /dev/stdout combined env=!forwarded +CustomLog /dev/stdout proxy env=forwarded + +{{ range $endpt, $vhost := .VHosts }} +# {{ $endpt }} vhost {{ $vhost.ServerName }} configuration + + ServerName {{ $vhost.ServerName }} + + ## Logging + ErrorLog /dev/stdout + ServerSignature Off + CustomLog /dev/stdout combined + + ## Request header rules + ## as per http://httpd.apache.org/docs/2.2/mod/mod_headers.html#requestheader + RequestHeader set X-Forwarded-Proto "https" + + ## Proxy rules + ProxyRequests Off + ProxyPreserveHost Off + ProxyPass / http://localhost:5051/ retry=10 + ProxyPassReverse / http://localhost:5051/ + +{{- if $vhost.TLS }} + SetEnvIf X-Forwarded-Proto https HTTPS=1 + + ## SSL directives + SSLEngine on + SSLCertificateFile "{{ $vhost.SSLCertificateFile }}" + SSLCertificateKeyFile "{{ $vhost.SSLCertificateKeyFile }}" +{{- end }} + +{{ end }} diff --git a/templates/ironicinspector/config/inspector.conf b/templates/ironicinspector/config/inspector.conf index fd662d7b..ec1283ba 100644 --- a/templates/ironicinspector/config/inspector.conf +++ b/templates/ironicinspector/config/inspector.conf @@ -2,6 +2,8 @@ auth_strategy={{if .Standalone}}noauth{{else}}keystone{{end}} log_file=/dev/stdout transport_url=fake:// +listen_address = 127.0.0.1 +listen_port = 5051 [cors] allowed_origin=* diff --git a/templates/ironicinspector/config/ssl.conf b/templates/ironicinspector/config/ssl.conf new file mode 100644 index 00000000..e3da4ecb --- /dev/null +++ b/templates/ironicinspector/config/ssl.conf @@ -0,0 +1,21 @@ + + SSLRandomSeed startup builtin + SSLRandomSeed startup file:/dev/urandom 512 + SSLRandomSeed connect builtin + SSLRandomSeed connect file:/dev/urandom 512 + + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + + SSLPassPhraseDialog builtin + SSLSessionCache "shmcb:/var/cache/mod_ssl/scache(512000)" + SSLSessionCacheTimeout 300 + Mutex default + SSLCryptoDevice builtin + SSLHonorCipherOrder On + SSLUseStapling Off + SSLStaplingCache "shmcb:/run/httpd/ssl_stapling(32768)" + SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!RC4:!3DES + SSLProtocol all -SSLv2 -SSLv3 -TLSv1 + SSLOptions StdEnvVars + diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index f01fc669..96dded4e 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -41,9 +41,6 @@ const ( ContainerImage = "test://ironic" PxeContainerImage = "test://pxe-image" IronicPythonAgentImage = "test://ipa-image" - IronicInputHash = "n665h595h685hch649h579h9dh55h678hbch5d6h57ch564hd7hbdh5ddhd9h5c6h644h658h677hf9h5bch64bh574h654h5ddh59bh54ch579h56chc9q" - ConductorInputHash = "n58dh5d4h58fh586h566h697h679h5fh68fhddh5c6h594h5f7h7fh594h5f7h88h588hf9hc4h5b6h5dh65ch95h77h5ddh7dh8fh599h579h55dh5fbq" - APIInputHash = "n64fh5cfh9chfdh667hf9h654hd8h56dh568h675h5cfh8dh57h66bhbch5dfhdh5b4h54ch96h94h574h9h54fh649hf4h56bh566h694h664hfdq" ) type IronicNames struct { @@ -60,6 +57,7 @@ type IronicNames struct { APIServiceAccount types.NamespacedName APIRole types.NamespacedName APIRoleBinding types.NamespacedName + APIConfigDataName types.NamespacedName ConductorName types.NamespacedName ConductorServiceAccount types.NamespacedName ConductorRole types.NamespacedName @@ -71,9 +69,13 @@ type IronicNames struct { InspectorRoleBinding types.NamespacedName InspectorDatabaseName types.NamespacedName InspectorDBSyncJobName types.NamespacedName + InspectorConfigDataName types.NamespacedName INAName types.NamespacedName INATransportURLName types.NamespacedName KeystoneServiceName types.NamespacedName + InternalCertSecretName types.NamespacedName + PublicCertSecretName types.NamespacedName + CaBundleSecretName types.NamespacedName } func GetIronicNames( @@ -146,6 +148,10 @@ func GetIronicNames( Namespace: ironicAPI.Namespace, Name: "ironicapi-" + ironicAPI.Name + "-rolebinding", }, + APIConfigDataName: types.NamespacedName{ + Namespace: ironicAPI.Namespace, + Name: "ironic-api-config-data", + }, ConductorName: types.NamespacedName{ Namespace: ironicConductor.Namespace, Name: ironicConductor.Name, @@ -190,6 +196,10 @@ func GetIronicNames( Namespace: ironicInspector.Namespace, Name: ironic_pkg.ServiceName + "-" + ironic_pkg.InspectorComponent + "-db-sync", }, + InspectorConfigDataName: types.NamespacedName{ + Namespace: ironicAPI.Namespace, + Name: "ironic-inspector-config-data", + }, INAName: types.NamespacedName{ Namespace: ironicNeutronAgent.Namespace, Name: ironicNeutronAgent.Name, @@ -198,6 +208,15 @@ func GetIronicNames( Namespace: ironicNeutronAgent.Namespace, Name: ironicNeutronAgent.Name + "-transport", }, + InternalCertSecretName: types.NamespacedName{ + Namespace: ironicName.Namespace, + Name: "internal-tls-certs"}, + PublicCertSecretName: types.NamespacedName{ + Namespace: ironicName.Namespace, + Name: "public-tls-certs"}, + CaBundleSecretName: types.NamespacedName{ + Namespace: ironicName.Namespace, + Name: "combined-ca-bundle"}, } } diff --git a/tests/functional/ironic_controller_test.go b/tests/functional/ironic_controller_test.go index 2c3c9de9..54f42fa5 100644 --- a/tests/functional/ironic_controller_test.go +++ b/tests/functional/ironic_controller_test.go @@ -21,7 +21,6 @@ import ( . "github.com/onsi/gomega" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" - "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" corev1 "k8s.io/api/core/v1" @@ -141,11 +140,10 @@ var _ = Describe("Ironic controller", func() { condition.InputReadyCondition, corev1.ConditionTrue, ) - instance := GetIronic(ironicNames.IronicName) - Expect(instance.Status.Hash).To(Equal( - map[string]string{ - common.InputHashName: IronicInputHash, - })) + Eventually(func(g Gomega) { + instance := GetIronic(ironicNames.IronicName) + g.Expect(instance.Status.Hash).Should(HaveKeyWithValue("input", Not(BeEmpty()))) + }, timeout, interval).Should(Succeed()) th.ExpectCondition( ironicNames.IronicName, ConditionGetterFunc(IronicConditionGetter), diff --git a/tests/functional/ironicapi_controller_test.go b/tests/functional/ironicapi_controller_test.go index c36db228..93e0f857 100644 --- a/tests/functional/ironicapi_controller_test.go +++ b/tests/functional/ironicapi_controller_test.go @@ -21,7 +21,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" - "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" corev1 "k8s.io/api/core/v1" @@ -120,11 +119,10 @@ var _ = Describe("IronicAPI controller", func() { condition.InputReadyCondition, corev1.ConditionTrue, ) - instance := GetIronicAPI(ironicNames.APIName) - Expect(instance.Status.Hash).To(Equal( - map[string]string{ - common.InputHashName: APIInputHash, - })) + Eventually(func(g Gomega) { + instance := GetIronicAPI(ironicNames.APIName) + g.Expect(instance.Status.Hash).Should(HaveKeyWithValue("input", Not(BeEmpty()))) + }, timeout, interval).Should(Succeed()) th.ExpectCondition( ironicNames.APIName, ConditionGetterFunc(IronicAPIConditionGetter), @@ -211,4 +209,201 @@ var _ = Describe("IronicAPI controller", func() { Expect(instance.Status.ReadyCount).To(Equal(int32(1))) }) }) + + When("IronicAPI is created with TLS cert secrets", func() { + BeforeEach(func() { + DeferCleanup( + k8sClient.Delete, + ctx, + CreateIronicSecret(ironicNames.Namespace, SecretName), + ) + DeferCleanup( + k8sClient.Delete, + ctx, + CreateMessageBusSecret(ironicNames.Namespace, MessageBusSecretName), + ) + DeferCleanup( + mariadb.DeleteDBService, + mariadb.CreateDBService( + ironicNames.Namespace, + "openstack", + corev1.ServiceSpec{ + Ports: []corev1.ServicePort{{Port: 3306}}, + }, + ), + ) + DeferCleanup( + keystone.DeleteKeystoneAPI, + keystone.CreateKeystoneAPI(ironicNames.Namespace)) + spec := GetDefaultIronicAPISpec() + spec["rpcTransport"] = "oslo" + spec["transportURLSecret"] = MessageBusSecretName + spec["tls"] = map[string]interface{}{ + "api": map[string]interface{}{ + "internal": map[string]interface{}{ + "secretName": ironicNames.InternalCertSecretName.Name, + }, + "public": map[string]interface{}{ + "secretName": ironicNames.PublicCertSecretName.Name, + }, + }, + "caBundleSecretName": ironicNames.CaBundleSecretName.Name, + } + + DeferCleanup( + th.DeleteInstance, + CreateIronicAPI(ironicNames.APIName, spec)) + }) + + It("reports that the CA secret is missing", func() { + th.ExpectConditionWithDetails( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/combined-ca-bundle not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("reports that the internal cert secret is missing", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + + th.ExpectConditionWithDetails( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/internal-tls-certs not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("reports that the public cert secret is missing", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + + th.ExpectConditionWithDetails( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/public-tls-certs not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("creates a Deployment for ironic-api service with TLS certs attached", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + + th.SimulateDeploymentReplicaReady(ironicNames.IronicName) + keystone.SimulateKeystoneServiceReady(ironicNames.IronicName) + keystone.SimulateKeystoneEndpointReady(ironicNames.IronicName) + + depl := th.GetDeployment(ironicNames.IronicName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(9)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + + // cert deployment volumes + th.AssertVolumeExists(ironicNames.CaBundleSecretName.Name, depl.Spec.Template.Spec.Volumes) + th.AssertVolumeExists(ironicNames.InternalCertSecretName.Name, depl.Spec.Template.Spec.Volumes) + th.AssertVolumeExists(ironicNames.PublicCertSecretName.Name, depl.Spec.Template.Spec.Volumes) + + // httpd container certs + apiContainer := depl.Spec.Template.Spec.Containers[1] + th.AssertVolumeMountExists(ironicNames.InternalCertSecretName.Name, "tls.key", apiContainer.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.InternalCertSecretName.Name, "tls.crt", apiContainer.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.PublicCertSecretName.Name, "tls.key", apiContainer.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.PublicCertSecretName.Name, "tls.crt", apiContainer.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.CaBundleSecretName.Name, "tls-ca-bundle.pem", apiContainer.VolumeMounts) + + Expect(apiContainer.ReadinessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) + Expect(apiContainer.LivenessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) + + configDataMap := th.GetConfigMap(ironicNames.APIConfigDataName) + Expect(configDataMap).ShouldNot(BeNil()) + Expect(configDataMap.Data).Should(HaveKey("ironic-api-httpd.conf")) + Expect(configDataMap.Data).Should(HaveKey("ssl.conf")) + configData := string(configDataMap.Data["ironic-api-httpd.conf"]) + Expect(configData).Should(ContainSubstring("SSLEngine on")) + Expect(configData).Should(ContainSubstring("SSLCertificateFile \"/etc/pki/tls/certs/internal.crt\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateKeyFile \"/etc/pki/tls/private/internal.key\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateFile \"/etc/pki/tls/certs/public.crt\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateKeyFile \"/etc/pki/tls/private/public.key\"")) + }) + + It("TLS Endpoints are created", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + th.SimulateDeploymentReplicaReady(ironicNames.IronicName) + keystone.SimulateKeystoneServiceReady(ironicNames.IronicName) + keystone.SimulateKeystoneEndpointReady(ironicNames.IronicName) + + keystoneEndpoint := keystone.GetKeystoneEndpoint(types.NamespacedName{Namespace: ironicNames.APIName.Namespace, Name: "ironic"}) + endpoints := keystoneEndpoint.Spec.Endpoints + Expect(endpoints).To(HaveKeyWithValue("public", string("https://ironic-public."+ironicNames.APIName.Namespace+".svc:6385"))) + Expect(endpoints).To(HaveKeyWithValue("internal", "https://ironic-internal."+ironicNames.APIName.Namespace+".svc:6385")) + + th.ExpectCondition( + ironicNames.APIName, + ConditionGetterFunc(IronicAPIConditionGetter), + condition.ReadyCondition, + corev1.ConditionTrue, + ) + }) + + It("reconfigures the deployment when CA changes", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + th.SimulateDeploymentReplicaReady(ironicNames.IronicName) + keystone.SimulateKeystoneServiceReady(ironicNames.IronicName) + keystone.SimulateKeystoneEndpointReady(ironicNames.IronicName) + + depl := th.GetDeployment(ironicNames.IronicName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(9)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + + // Grab the current config hash + originalHash := GetEnvVarValue( + depl.Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + Expect(originalHash).NotTo(BeEmpty()) + + // Change the content of the CA secret + th.UpdateSecret(ironicNames.CaBundleSecretName, "tls-ca-bundle.pem", []byte("DifferentCAData")) + + // Assert that the deployment is updated + Eventually(func(g Gomega) { + newHash := GetEnvVarValue( + th.GetDeployment(ironicNames.IronicName).Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + g.Expect(newHash).NotTo(BeEmpty()) + g.Expect(newHash).NotTo(Equal(originalHash)) + }, timeout, interval).Should(Succeed()) + }) + }) }) diff --git a/tests/functional/ironicconductor_controller_test.go b/tests/functional/ironicconductor_controller_test.go index 99dd84a9..bbc0375f 100644 --- a/tests/functional/ironicconductor_controller_test.go +++ b/tests/functional/ironicconductor_controller_test.go @@ -16,11 +16,12 @@ limitations under the License. package functional_test import ( + "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" routev1 "github.com/openshift/api/route/v1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" - "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" corev1 "k8s.io/api/core/v1" @@ -120,11 +121,10 @@ var _ = Describe("IronicConductor controller", func() { condition.InputReadyCondition, corev1.ConditionTrue, ) - instance := GetIronicConductor(ironicNames.ConductorName) - Expect(instance.Status.Hash).To(Equal( - map[string]string{ - common.InputHashName: ConductorInputHash, - })) + Eventually(func(g Gomega) { + instance := GetIronicConductor(ironicNames.ConductorName) + g.Expect(instance.Status.Hash).Should(HaveKeyWithValue("input", Not(BeEmpty()))) + }, timeout, interval).Should(Succeed()) th.ExpectCondition( ironicNames.ConductorName, ConditionGetterFunc(IronicConductorConditionGetter), @@ -184,4 +184,103 @@ var _ = Describe("IronicConductor controller", func() { Expect(instance.Status.ReadyCount).To(Equal(int32(1))) }) }) + + When("IronicConductor is created with TLS cert secrets", func() { + BeforeEach(func() { + DeferCleanup( + k8sClient.Delete, + ctx, + CreateIronicSecret(ironicNames.Namespace, SecretName), + ) + DeferCleanup( + k8sClient.Delete, + ctx, + CreateMessageBusSecret(ironicNames.Namespace, MessageBusSecretName), + ) + DeferCleanup( + mariadb.DeleteDBService, + mariadb.CreateDBService( + ironicNames.Namespace, + "openstack", + corev1.ServiceSpec{ + Ports: []corev1.ServicePort{{Port: 3306}}, + }, + ), + ) + DeferCleanup( + keystone.DeleteKeystoneAPI, + keystone.CreateKeystoneAPI(ironicNames.Namespace)) + spec := GetDefaultIronicConductorSpec() + spec["rpcTransport"] = "oslo" + spec["transportURLSecret"] = MessageBusSecretName + spec["tls"] = map[string]interface{}{ + "caBundleSecretName": ironicNames.CaBundleSecretName.Name, + } + DeferCleanup( + th.DeleteInstance, + CreateIronicConductor(ironicNames.ConductorName, spec)) + }) + + It("reports that the CA secret is missing", func() { + th.ExpectConditionWithDetails( + ironicNames.ConductorName, + ConditionGetterFunc(IronicConductorConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/combined-ca-bundle not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.ConductorName, + ConditionGetterFunc(IronicConductorConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("creates a StatefulSet for ironic-conductor service with TLS CA cert attached", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + th.SimulateStatefulSetReplicaReady(ironicNames.ConductorName) + + depl := th.GetStatefulSet(ironicNames.ConductorName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(7)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + + // cert deployment volumes + th.AssertVolumeExists(ironicNames.CaBundleSecretName.Name, depl.Spec.Template.Spec.Volumes) + + // cert volumeMounts + container := depl.Spec.Template.Spec.Containers[1] + th.AssertVolumeMountExists(ironicNames.CaBundleSecretName.Name, "tls-ca-bundle.pem", container.VolumeMounts) + }) + + It("reconfigures the deployment when CA changes", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + th.SimulateStatefulSetReplicaReady(ironicNames.ConductorName) + + depl := th.GetStatefulSet(ironicNames.ConductorName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(7)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + + // Grab the current config hash + originalHash := GetEnvVarValue( + depl.Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + Expect(originalHash).NotTo(BeEmpty()) + + // Change the content of the CA secret + th.UpdateSecret(ironicNames.CaBundleSecretName, "tls-ca-bundle.pem", []byte("DifferentCAData")) + + // Assert that the deployment is updated + Eventually(func(g Gomega) { + newHash := GetEnvVarValue( + th.GetStatefulSet(ironicNames.ConductorName).Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + g.Expect(newHash).NotTo(BeEmpty()) + g.Expect(newHash).NotTo(Equal(originalHash)) + }, timeout, interval).Should(Succeed()) + }) + }) }) diff --git a/tests/functional/ironicinspector_controller_test.go b/tests/functional/ironicinspector_controller_test.go index aa4434b0..46ff0847 100644 --- a/tests/functional/ironicinspector_controller_test.go +++ b/tests/functional/ironicinspector_controller_test.go @@ -17,6 +17,8 @@ limitations under the License. package functional_test import ( + "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" @@ -175,6 +177,30 @@ var _ = Describe("IronicInspector controller", func() { th.SimulateStatefulSetReplicaReady(ironicNames.InspectorName) keystone.SimulateKeystoneServiceReady(ironicNames.InspectorName) keystone.SimulateKeystoneEndpointReady(ironicNames.InspectorName) + + ss := th.GetStatefulSet(ironicNames.InspectorName) + // Check the resulting deployment fields + Expect(int(*ss.Spec.Replicas)).To(Equal(1)) + Expect(ss.Spec.Template.Spec.Volumes).To(HaveLen(6)) + Expect(ss.Spec.Template.Spec.Containers).To(HaveLen(3)) + + // Check the ironic-inspector-httpd container + container := ss.Spec.Template.Spec.Containers[0] + Expect(container.Name).To(Equal("ironic-inspector-httpd")) + Expect(container.VolumeMounts).To(HaveLen(6)) + + // Check the ironic-inspector container + container = ss.Spec.Template.Spec.Containers[1] + Expect(container.VolumeMounts).To(HaveLen(6)) + Expect(container.Name).To(Equal("ironic-inspector")) + Expect(container.LivenessProbe.HTTPGet.Port.IntVal).To(Equal(int32(5050))) + Expect(container.ReadinessProbe.HTTPGet.Port.IntVal).To(Equal(int32(5050))) + + // Check the ironic-httpboot container + container = ss.Spec.Template.Spec.Containers[2] + Expect(container.VolumeMounts).To(HaveLen(6)) + Expect(container.Name).To(Equal("inspector-httpboot")) + th.ExpectCondition( ironicNames.InspectorName, ConditionGetterFunc(IronicInspectorConditionGetter), @@ -223,4 +249,211 @@ var _ = Describe("IronicInspector controller", func() { Expect(instance.Status.ReadyCount).To(Equal(int32(1))) }) }) + + When("IronicInspector is created with TLS cert secrets", func() { + BeforeEach(func() { + DeferCleanup( + k8sClient.Delete, + ctx, + CreateIronicSecret(ironicNames.Namespace, SecretName), + ) + DeferCleanup( + mariadb.DeleteDBService, + mariadb.CreateDBService( + ironicNames.Namespace, + "openstack", + corev1.ServiceSpec{ + Ports: []corev1.ServicePort{{Port: 3306}}, + }, + ), + ) + DeferCleanup( + keystone.DeleteKeystoneAPI, + keystone.CreateKeystoneAPI(ironicNames.Namespace)) + spec := GetDefaultIronicInspectorSpec() + spec["rpcTransport"] = "oslo" + spec["tls"] = map[string]interface{}{ + "api": map[string]interface{}{ + "internal": map[string]interface{}{ + "secretName": ironicNames.InternalCertSecretName.Name, + }, + "public": map[string]interface{}{ + "secretName": ironicNames.PublicCertSecretName.Name, + }, + }, + "caBundleSecretName": ironicNames.CaBundleSecretName.Name, + } + DeferCleanup( + th.DeleteInstance, + CreateIronicInspector(ironicNames.InspectorName, spec)) + + infra.GetTransportURL(ironicNames.InspectorTransportURLName) + infra.SimulateTransportURLReady(ironicNames.InspectorTransportURLName) + }) + + It("reports that the CA secret is missing", func() { + th.ExpectConditionWithDetails( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/combined-ca-bundle not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("reports that the internal cert secret is missing", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + + th.ExpectConditionWithDetails( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/internal-tls-certs not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("reports that the public cert secret is missing", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + + th.ExpectConditionWithDetails( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/public-tls-certs not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("creates a Deployment for ironic-inspector service with TLS certs attached", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + + mariadb.GetMariaDBDatabase(ironicNames.InspectorDatabaseName) + mariadb.SimulateMariaDBDatabaseCompleted(ironicNames.InspectorDatabaseName) + th.SimulateJobSuccess(ironicNames.InspectorDBSyncJobName) + + th.SimulateStatefulSetReplicaReady(ironicNames.InspectorName) + keystone.SimulateKeystoneServiceReady(ironicNames.InspectorName) + keystone.SimulateKeystoneEndpointReady(ironicNames.InspectorName) + + depl := th.GetStatefulSet(ironicNames.InspectorName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(9)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(3)) + + // cert deployment volumes + th.AssertVolumeExists(ironicNames.CaBundleSecretName.Name, depl.Spec.Template.Spec.Volumes) + th.AssertVolumeExists(ironicNames.InternalCertSecretName.Name, depl.Spec.Template.Spec.Volumes) + th.AssertVolumeExists(ironicNames.PublicCertSecretName.Name, depl.Spec.Template.Spec.Volumes) + + // httpd container certs + container := depl.Spec.Template.Spec.Containers[0] + th.AssertVolumeMountExists(ironicNames.InternalCertSecretName.Name, "tls.key", container.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.InternalCertSecretName.Name, "tls.crt", container.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.PublicCertSecretName.Name, "tls.key", container.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.PublicCertSecretName.Name, "tls.crt", container.VolumeMounts) + th.AssertVolumeMountExists(ironicNames.CaBundleSecretName.Name, "tls-ca-bundle.pem", container.VolumeMounts) + + Expect(container.ReadinessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) + Expect(container.LivenessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) + + configDataMap := th.GetConfigMap(ironicNames.InspectorConfigDataName) + Expect(configDataMap).ShouldNot(BeNil()) + Expect(configDataMap.Data).Should(HaveKey("httpd.conf")) + Expect(configDataMap.Data).Should(HaveKey("ssl.conf")) + configData := string(configDataMap.Data["httpd.conf"]) + Expect(configData).Should(ContainSubstring("SSLEngine on")) + Expect(configData).Should(ContainSubstring("SSLCertificateFile \"/etc/pki/tls/certs/internal.crt\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateKeyFile \"/etc/pki/tls/private/internal.key\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateFile \"/etc/pki/tls/certs/public.crt\"")) + Expect(configData).Should(ContainSubstring("SSLCertificateKeyFile \"/etc/pki/tls/private/public.key\"")) + }) + + It("TLS Endpoints are created", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + + mariadb.GetMariaDBDatabase(ironicNames.InspectorDatabaseName) + mariadb.SimulateMariaDBDatabaseCompleted(ironicNames.InspectorDatabaseName) + th.SimulateJobSuccess(ironicNames.InspectorDBSyncJobName) + + th.SimulateStatefulSetReplicaReady(ironicNames.InspectorName) + keystone.SimulateKeystoneServiceReady(ironicNames.InspectorName) + keystone.SimulateKeystoneEndpointReady(ironicNames.InspectorName) + + keystoneEndpoint := keystone.GetKeystoneEndpoint(ironicNames.InspectorName) + endpoints := keystoneEndpoint.Spec.Endpoints + Expect(endpoints).To(HaveKeyWithValue("public", string("https://ironic-inspector-public."+ironicNames.InspectorName.Namespace+".svc:5050"))) + Expect(endpoints).To(HaveKeyWithValue("internal", "https://ironic-inspector-internal."+ironicNames.InspectorName.Namespace+".svc:5050")) + + th.ExpectCondition( + ironicNames.InspectorName, + ConditionGetterFunc(IronicInspectorConditionGetter), + condition.ReadyCondition, + corev1.ConditionTrue, + ) + }) + + It("reconfigures the deployment when CA changes", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.InternalCertSecretName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(ironicNames.PublicCertSecretName)) + + mariadb.GetMariaDBDatabase(ironicNames.InspectorDatabaseName) + mariadb.SimulateMariaDBDatabaseCompleted(ironicNames.InspectorDatabaseName) + th.SimulateJobSuccess(ironicNames.InspectorDBSyncJobName) + + th.SimulateStatefulSetReplicaReady(ironicNames.InspectorName) + keystone.SimulateKeystoneServiceReady(ironicNames.InspectorName) + keystone.SimulateKeystoneEndpointReady(ironicNames.InspectorName) + + depl := th.GetStatefulSet(ironicNames.InspectorName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(9)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(3)) + + // Grab the current config hash + originalHash := GetEnvVarValue( + depl.Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + Expect(originalHash).NotTo(BeEmpty()) + + // Change the content of the CA secret + th.UpdateSecret(ironicNames.CaBundleSecretName, "tls-ca-bundle.pem", []byte("DifferentCAData")) + + // Assert that the deployment is updated + Eventually(func(g Gomega) { + newHash := GetEnvVarValue( + th.GetStatefulSet(ironicNames.InspectorName).Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + g.Expect(newHash).NotTo(BeEmpty()) + g.Expect(newHash).NotTo(Equal(originalHash)) + }, timeout, interval).Should(Succeed()) + }) + }) }) diff --git a/tests/functional/ironicneutronagent_controller_test.go b/tests/functional/ironicneutronagent_controller_test.go index 781717ba..bcfa324d 100644 --- a/tests/functional/ironicneutronagent_controller_test.go +++ b/tests/functional/ironicneutronagent_controller_test.go @@ -20,6 +20,8 @@ import ( // "encoding/json" // "fmt" + "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" @@ -193,4 +195,83 @@ var _ = Describe("IronicNeutronAgent controller", func() { }) }) + When("IronicNeutronAgent is created with TLS cert secrets", func() { + BeforeEach(func() { + DeferCleanup( + k8sClient.Delete, + ctx, + CreateIronicSecret(ironicNames.Namespace, SecretName), + ) + spec := GetDefaultIronicNeutronAgentSpec() + spec["tls"] = map[string]interface{}{ + "caBundleSecretName": ironicNames.CaBundleSecretName.Name, + } + DeferCleanup(th.DeleteInstance, CreateIronicNeutronAgent(ironicNames.INAName, spec)) + infra.GetTransportURL(ironicNames.INATransportURLName) + infra.SimulateTransportURLReady(ironicNames.INATransportURLName) + DeferCleanup(keystone.DeleteKeystoneAPI, keystone.CreateKeystoneAPI(ironicNames.Namespace)) + }) + + It("reports that the CA secret is missing", func() { + th.ExpectConditionWithDetails( + ironicNames.INAName, + ConditionGetterFunc(INAConditionGetter), + condition.TLSInputReadyCondition, + corev1.ConditionFalse, + condition.ErrorReason, + fmt.Sprintf("TLSInput error occured in TLS sources Secret %s/combined-ca-bundle not found", ironicNames.Namespace), + ) + th.ExpectCondition( + ironicNames.INAName, + ConditionGetterFunc(INAConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + }) + + It("creates a Deployment for ironic-neutronagent service with TLS CA cert attached", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + th.SimulateDeploymentReplicaReady(ironicNames.INAName) + + depl := th.GetDeployment(ironicNames.INAName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(4)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(1)) + + // cert deployment volumes + th.AssertVolumeExists(ironicNames.CaBundleSecretName.Name, depl.Spec.Template.Spec.Volumes) + + // cert volumeMounts + container := depl.Spec.Template.Spec.Containers[0] + th.AssertVolumeMountExists(ironicNames.CaBundleSecretName.Name, "tls-ca-bundle.pem", container.VolumeMounts) + }) + + It("reconfigures the deployment when CA changes", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(ironicNames.CaBundleSecretName)) + th.SimulateDeploymentReplicaReady(ironicNames.INAName) + + depl := th.GetDeployment(ironicNames.INAName) + // Check the resulting deployment fields + Expect(int(*depl.Spec.Replicas)).To(Equal(1)) + Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(4)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(1)) + + // Grab the current config hash + originalHash := GetEnvVarValue( + depl.Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + Expect(originalHash).NotTo(BeEmpty()) + + // Change the content of the CA secret + th.UpdateSecret(ironicNames.CaBundleSecretName, "tls-ca-bundle.pem", []byte("DifferentCAData")) + + // Assert that the deployment is updated + Eventually(func(g Gomega) { + newHash := GetEnvVarValue( + th.GetDeployment(ironicNames.INAName).Spec.Template.Spec.Containers[0].Env, "CONFIG_HASH", "") + g.Expect(newHash).NotTo(BeEmpty()) + g.Expect(newHash).NotTo(Equal(originalHash)) + }, timeout, interval).Should(Succeed()) + }) + }) }) diff --git a/tests/kuttl/common/assert_tls_cert.yaml b/tests/kuttl/common/assert_tls_cert.yaml new file mode 100644 index 00000000..3a0b258c --- /dev/null +++ b/tests/kuttl/common/assert_tls_cert.yaml @@ -0,0 +1,30 @@ +# +# Check for: +# +# - 4 tls cert secrets +# - 1 tls ca bundle secrets + +apiVersion: v1 +kind: Secret +metadata: + name: cert-ironic-internal-svc +--- +apiVersion: v1 +kind: Secret +metadata: + name: cert-ironic-public-svc +--- +apiVersion: v1 +kind: Secret +metadata: + name: cert-ironic-inspector-internal-svc +--- +apiVersion: v1 +kind: Secret +metadata: + name: cert-ironic-inspector-public-svc +--- +apiVersion: v1 +kind: Secret +metadata: + name: combined-ca-bundle diff --git a/tests/kuttl/common/tls_ca_bundle.yaml b/tests/kuttl/common/tls_ca_bundle.yaml new file mode 100644 index 00000000..b8baa3bb --- /dev/null +++ b/tests/kuttl/common/tls_ca_bundle.yaml @@ -0,0 +1,65 @@ +# +# Internal CA created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Issuer +# metadata: +# name: rootca-kuttl-internal +# namespace: openstack +# spec: +# ca: +# secretName: rootca-kuttl-internal +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: rootca-kuttl-internal +# namespace: openstack +# spec: +# commonName: rootca-kuttl-internal +# duration: 87600h0m0s +# isCA: true +# issuerRef: +# name: selfsigned-issuer +# privateKey: +# algorithm: ECDSA +# size: 256 +# secretName: rootca-kuttl-internal +# +# External CA created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Issuer +# metadata: +# name: rootca-kuttl-public +# namespace: openstack +# spec: +# ca: +# secretName: rootca-kuttl-public +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: rootca-kuttl-public +# namespace: openstack +# spec: +# commonName: rootca-kuttl-public +# duration: 87600h0m0s +# isCA: true +# issuerRef: +# name: selfsigned-issuer +# privateKey: +# algorithm: ECDSA +# size: 256 +# secretName: rootca-kuttl-public +# +# Then extracted both CAs and created added them as the bundle: +apiVersion: v1 +data: + tls-ca-bundle.pem: IyByb290Y2EtaW50ZXJuYWwKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmekNDQVNhZ0F3SUJBZ0lRUWxlcTNZcDBtU2kwVDNiTm03Q29UVEFLQmdncWhrak9QUVFEQWpBZ01SNHcKSEFZRFZRUURFeFZ5YjI5MFkyRXRhM1YwZEd3dGFXNTBaWEp1WVd3d0hoY05NalF3TVRFMU1URTBOelUwV2hjTgpNelF3TVRFeU1URTBOelUwV2pBZ01SNHdIQVlEVlFRREV4VnliMjkwWTJFdGEzVjBkR3d0YVc1MFpYSnVZV3d3CldUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTRk9rNHJPUldVUGhoTjUrK09EN1I2MW5Gb1lBY0QKenpvUS91SW93NktjeGhwRWNQTDFxb3ZZUGxUYUJabEh3c2FpNE50VHA4aDA1RHVRSGZKOE9JNXFvMEl3UURBTwpCZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXE3TGtFSk1TCm1MOVpKWjBSOUluKzZkclhycEl3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnVlN1K00ydnZ3QlF3eTJHMVlhdkkKQld2RGtSNlRla0I5U0VqdzJIblRSMWtDSUZSNFNkWGFPQkFGWjVHa2RLWCtSY2IzaDFIZm52eFJEVW96bTl2agphenp3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KIyByb290Y2EtcHVibGljCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCZXpDQ0FTS2dBd0lCQWdJUU5IREdZc0JzNzk4aWJERDdxL28ybGpBS0JnZ3Foa2pPUFFRREFqQWVNUnd3CkdnWURWUVFERXhOeWIyOTBZMkV0YTNWMGRHd3RjSFZpYkdsak1CNFhEVEkwTURFeE5URXdNVFV6TmxvWERUTTAKTURFeE1qRXdNVFV6Tmxvd0hqRWNNQm9HQTFVRUF4TVRjbTl2ZEdOaExXdDFkSFJzTFhCMVlteHBZekJaTUJNRwpCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkQ3OGF2WHFocmhDNXc4czlXa2Q0SXBiZUV1MDNDUitYWFVkCmtEek9SeXhhOXdjY0lkRGl2YkdKakpGWlRUY1ZtYmpxMUJNWXNqcjEyVUlFNUVUM1ZscWpRakJBTUE0R0ExVWQKRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUS0ppeldVSjllVUtpMQpkczBscjZjNnNEN0VCREFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUJJWndZcTYxQnFNSmFCNlVjRm9Sc3hlY3dICjV6L3pNT2RyT3llMG1OaThKZ0lnUUxCNHdES3JwZjl0WDJsb00rMHVUb3BBRFNZSW5yY2ZWdTRGQnVZVTNJZz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= +kind: Secret +metadata: + labels: + combined-ca-bundle: "" + name: combined-ca-bundle +type: Opaque diff --git a/tests/kuttl/common/tls_cert_ironic-inspector-internal-svc.yaml b/tests/kuttl/common/tls_cert_ironic-inspector-internal-svc.yaml new file mode 100644 index 00000000..91b8f519 --- /dev/null +++ b/tests/kuttl/common/tls_cert_ironic-inspector-internal-svc.yaml @@ -0,0 +1,46 @@ +# +# Cert created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: ironic-inspector-kuttl-internal-svc +# namespace: openstack +# spec: +# dnsNames: +# - ironic-inspector-internal.openstack.svc +# - ironic-inspector-internal.ironic-kuttl-tests.svc +# duration: 87600h0m0s +# issuerRef: +# group: cert-manager.io +# kind: Issuer +# name: rootca-kuttl-internal +# secretName: cert-ironic-inspector-internal-svc +# secretTemplate: {} +# usages: +# - key encipherment +# - digital signature +# - server auth +# + +apiVersion: v1 +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmekNDQVNhZ0F3SUJBZ0lRUWxlcTNZcDBtU2kwVDNiTm03Q29UVEFLQmdncWhrak9QUVFEQWpBZ01SNHcKSEFZRFZRUURFeFZ5YjI5MFkyRXRhM1YwZEd3dGFXNTBaWEp1WVd3d0hoY05NalF3TVRFMU1URTBOelUwV2hjTgpNelF3TVRFeU1URTBOelUwV2pBZ01SNHdIQVlEVlFRREV4VnliMjkwWTJFdGEzVjBkR3d0YVc1MFpYSnVZV3d3CldUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTRk9rNHJPUldVUGhoTjUrK09EN1I2MW5Gb1lBY0QKenpvUS91SW93NktjeGhwRWNQTDFxb3ZZUGxUYUJabEh3c2FpNE50VHA4aDA1RHVRSGZKOE9JNXFvMEl3UURBTwpCZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXE3TGtFSk1TCm1MOVpKWjBSOUluKzZkclhycEl3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnVlN1K00ydnZ3QlF3eTJHMVlhdkkKQld2RGtSNlRla0I5U0VqdzJIblRSMWtDSUZSNFNkWGFPQkFGWjVHa2RLWCtSY2IzaDFIZm52eFJEVW96bTl2agphenp3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNyRENDQWxHZ0F3SUJBZ0lSQU5nQ1htQ2FvRnk2a0dJNWs4c0VWeDh3Q2dZSUtvWkl6ajBFQXdJd0lERWUKTUJ3R0ExVUVBeE1WY205dmRHTmhMV3QxZEhSc0xXbHVkR1Z5Ym1Gc01CNFhEVEkwTURFek1URXlOVEF5TTFvWApEVE0wTURFeU9ERXlOVEF5TTFvd0FEQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCCkFMVXoxVVJVdTdrR01lT1I3R1Q3aUQ5dmxkNkJ2UG5lbDdIOUdFUW1rNXJld241bEtWUG9HeTFxUGhqRHhxbloKK09FYnFWVTIzbHorb2xJQUtqVjZaZVA0M01EYW5vZU4zN29TUG1IOVdlRGFpOHhDd2szRFQxQmRLQm42d2t5awp1bkdxWitiTjNwK1E4ckFpd3lGZDkvYXYwSXlqYklpT1BHUm9OUm50bWdyMFdyTDR1T21oci9aZXFtSnhCR2trCnkrL3pRdTM0bVhMT0hDTXhaR2VqUndUSzFRbjZ2SldVdzFwL2NOeG9MMkVnbVlqRG5HeWM3RTR6dUR3SXJaOXgKdmFwdWh4RE1YeUgwWUFTRTRQVHBkdDcvM1V0Z3NMS3pUa3F3SXJLVkcrRExrYlhBZVZPVlhXREIvOWF0dG1Fdwo1U1F4N1dnVVI2TG5oTXZQeE1hcS9wa0NBd0VBQWFPQndEQ0J2VEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEClZSMGxCQXd3Q2dZSUt3WUJCUVVIQXdFd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JTcnN1UVEKa3hLWXYxa2xuUkgwaWY3cDJ0ZXVrakJuQmdOVkhSRUJBZjhFWFRCYmdpZHBjbTl1YVdNdGFXNXpjR1ZqZEc5eQpMV2x1ZEdWeWJtRnNMbTl3Wlc1emRHRmpheTV6ZG1PQ01HbHliMjVwWXkxcGJuTndaV04wYjNJdGFXNTBaWEp1CllXd3VhWEp2Ym1sakxXdDFkSFJzTFhSbGMzUnpMbk4yWXpBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQTdzVG8KclZhNFZKa2NiLzQvSDUweWUxRlRvSVFiSDhSVHdIMzlnK0ZhTTJZQ0lRQ3VwVElCRnRVUi85MTRYSU9EL0QvTwpUTU1EWnZmMDlyWkRIM1lqM3Vza2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdFRQVlJGUzd1UVl4NDVIc1pQdUlQMitWM29HOCtkNlhzZjBZUkNhVG10N0NmbVVwClUrZ2JMV28rR01QR3FkbjQ0UnVwVlRiZVhQNmlVZ0FxTlhwbDQvamN3TnFlaDQzZnVoSStZZjFaNE5xTHpFTEMKVGNOUFVGMG9HZnJDVEtTNmNhcG41czNlbjVEeXNDTERJVjMzOXEvUWpLTnNpSTQ4WkdnMUdlMmFDdlJhc3ZpNAo2YUd2OWw2cVluRUVhU1RMNy9OQzdmaVpjczRjSXpGa1o2TkhCTXJWQ2ZxOGxaVERXbjl3M0dndllTQ1ppTU9jCmJKenNUak80UEFpdG4zRzlxbTZIRU14ZklmUmdCSVRnOU9sMjN2L2RTMkN3c3JOT1NyQWlzcFViNE11UnRjQjUKVTVWZFlNSC8xcTIyWVREbEpESHRhQlJIb3VlRXk4L0V4cXIrbVFJREFRQUJBb0lCQVFDYkZvNEdPZStoNE9kNgpPejcwLzBRUjUxT0NhZEJ3bkUrQmkzbmxlbzhERW4yczZMQ0NuRG9HbU5RbEpnczIvTlRDOW9YcjVWWlVpYXdzCk91L2xiYWtmZ2JTUGE0NGJ2eFlwajh2TTJxYStpTTcyT0gxTlNVanRJNDViRGdDVzBMYXk2b0tiVE1DcUdjbGQKYjZOTFA3NG5hVHM1NC9YVXVzaDl0Nk1iV2YxcU9XRlpaTit4Y3VBaDB6S3JEei9IaHFzaXR3N0g5S3Z6VWNxdApZaTVDVTM0Wmo2VmtpMDlid3J5dHMwd3JXRE5KVkZlQXBROVczaHl6ZTJVUjBQckNPSXJIdXhKbUNIcjRwN1F6CnB2M2l0emhVbFJWT3hsZlNsdW4rRjhaQnd5NEwwNzUxTERtbWNWZjhxM3VYQ1FtWDlVd0dydGZ1NDFNb2hzUTMKRkk0aC9DZXhBb0dCQU5PRktMNXRHM21tUkFSVFNVcjd6TVJGR04xMFhKQkZ2SHAwaHZCTDVFRU1Ea1VTdnVJMApRdFYwSm1CeDZReWhGWnFXTzhPMUI5ei9OR2hoRjhKZmlNQ1ByWE9vOCttQ3YwUFgxK0Z3YmE4RVNQMHBnRVJLCkV3c2NJc0doZ2RmNmhIS1ZNaWxkNUtKeHdUazYxTHd0NWwrM2tIdlFrRTFCUk0wY05XVU5MVXUzQW9HQkFOdE8Ka2tBN0h0djYreEJqYzR1dkVsRkVwY2JOQVJBOXRjdlIvSnNlV1VoQTIySC9PZ0o1VmNMUWRadUg0dnVIcHhqRwpWTHNJbk9BT05SS1F0RGRPZitkNFlSMHZpQ0V6eDFEMGFsSTU5V2VYdzZDdEZBQ1dEVkhJSmRsd0c2VStXbit0CmNQc1RvbU5zdTR5R25RRWlDMlNadzVIcU12ZlRoamVLWlBPL3BxZ3ZBb0dCQUtjMmtHUWgydU9MWmgvSk81cTAKZmtiMm5OYU00NVFHSFI3dE9iT0RPMW1Veno4WnQ1OFpVM0J0RnQyTmozKzFaRi9Gdms5VHNIaXJvMkdVeC9TWQpFNEt1MHA4cGhGRW9WRTJzdDNQM3JpMzZoRHptYndrTlNncXhYbVNXYWhBMGNqb202Zlc3elVBQ0Q0OVBpOWVMCnJhQWpmR3YxRCs2UzEzSVNoNzl2OEV2M0FvR0FKL09aV3hBcUlBTUo1OE5tVWtVVGZqQ1dUckFjQ0h4bGVQc0oKSEswYnNMajMvbE5EbXgzRmpOYnpCZUZzYlV3YUdiNVB3ejdmYlVYSlQxZURMU3dreXVNNE5kdnAzYnFVRGVCbwoyZy9xNy9OSzFTT1NxRVN0cW45ZXZjelpqSEhlaExIeENoeGFrZWhHQm1Tamg0aFBNUVYrQmovM0J3VEd4Nmx6Cm1LQUtXVXNDZ1lBdmdsaTJaczdqRkxlREdYbmwxQWpFK1FqUlh1ZUhMdGduQnBpc2xsallsbGdWVGoreVhDSmkKWXUybDM5RHBabDFhZ3ljZGlTeUVNay95cEl1OXRuM2NITUZSV2N3Z0NBN1VMOGxTRHE4ZjRVRGtsVzBySklESgpEZWFvRXplN05ndmdXdEZvY3hNUkltZmlXQ0Q1cGV4aHBzb00wR0R2ZThrY1Znb2NCMzZEQ2c9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +kind: Secret +metadata: + annotations: + cert-manager.io/alt-names: ironic-inspector-internal.openstack.svc + cert-manager.io/certificate-name: ironic-inspector-kuttl-internal-svc + cert-manager.io/common-name: "" + cert-manager.io/ip-sans: "" + cert-manager.io/issuer-group: cert-manager.io + cert-manager.io/issuer-kind: Issuer + cert-manager.io/issuer-name: rootca-kuttl-internal + cert-manager.io/uri-sans: "" + creationTimestamp: "2024-01-31T08:04:05Z" + labels: + controller.cert-manager.io/fao: "true" + name: cert-ironic-inspector-internal-svc +type: kubernetes.io/tls diff --git a/tests/kuttl/common/tls_cert_ironic-inspector-public-svc.yaml b/tests/kuttl/common/tls_cert_ironic-inspector-public-svc.yaml new file mode 100644 index 00000000..50735051 --- /dev/null +++ b/tests/kuttl/common/tls_cert_ironic-inspector-public-svc.yaml @@ -0,0 +1,45 @@ +# +# Cert created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: kuttl-ironic-inspector-public-svc +# namespace: openstack +# spec: +# dnsNames: +# - ironic-inspector-public.openstack.svc +# - ironic-inspector-public.ironic-kuttl-tests.svc +# duration: 87600h0m0s +# issuerRef: +# group: cert-manager.io +# kind: Issuer +# name: rootca-kuttl-public +# secretName: cert-ironic-inspector-public-svc +# secretTemplate: {} +# usages: +# - key encipherment +# - digital signature +# - server auth + +apiVersion: v1 +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlekNDQVNLZ0F3SUJBZ0lRTkhER1lzQnM3OThpYkREN3EvbzJsakFLQmdncWhrak9QUVFEQWpBZU1Sd3cKR2dZRFZRUURFeE55YjI5MFkyRXRhM1YwZEd3dGNIVmliR2xqTUI0WERUSTBNREV4TlRFd01UVXpObG9YRFRNMApNREV4TWpFd01UVXpObG93SGpFY01Cb0dBMVVFQXhNVGNtOXZkR05oTFd0MWRIUnNMWEIxWW14cFl6QlpNQk1HCkJ5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRDc4YXZYcWhyaEM1dzhzOVdrZDRJcGJlRXUwM0NSK1hYVWQKa0R6T1J5eGE5d2NjSWREaXZiR0pqSkZaVFRjVm1ianExQk1Zc2pyMTJVSUU1RVQzVmxxalFqQkFNQTRHQTFVZApEd0VCL3dRRUF3SUNwREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlRLSml6V1VKOWVVS2kxCmRzMGxyNmM2c0Q3RUJEQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQklad1lxNjFCcU1KYUI2VWNGb1JzeGVjd0gKNXovek1PZHJPeWUwbU5pOEpnSWdRTEI0d0RLcnBmOXRYMmxvTSswdVRvcEFEU1lJbnJjZlZ1NEZCdVlVM0lnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwVENDQWtxZ0F3SUJBZ0lRZDM2L2cxSkYyUzhqN2xWTlE5dUxxVEFLQmdncWhrak9QUVFEQWpBZU1Sd3cKR2dZRFZRUURFeE55YjI5MFkyRXRhM1YwZEd3dGNIVmliR2xqTUI0WERUSTBNREV6TVRFeU5UQXdObG9YRFRNMApNREV5T0RFeU5UQXdObG93QURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTXRUCktaT1pQekVCMG4vbG9FZDliaE5xODVwYnlpWFFuMkFZb2J5SDRQZDNJdlhVMUMyTlZ2cFFqd2lNS1ZIUllKNDQKaE0ram5FbG1hZ0Mzc1Nqc3Zid3grbXpVMUZSV0haY002cmtOYW9QTi9peXFaZ0c5c1c4aDA2Nm1LMVByRmxjWApDeHh3Y0xtRTB6amZZVXV6WG8wYzU3cmFYYldPNDhXcmh6WGJsVDZYQng2cVk5OEkzQjYyQTEyOENqUTNha04yCkFQMFhHdGJHRDA1RzRsV2NuSXhqaWVZZFhVN3hnZWkrSk13d25UQm8wdkVGejBYeXpiY3dwRW5BNGl6V3M0MGEKb2JYdkw2ZGdFQkNqUWZacFZtaURMeTdEYUNjREhLcmt4WlE4eUNNYUw2WEtQbm9Xa2ZXVnFvbWo3OXlxclV1TQpxTDNSL2IyNFMwOUtLL2VjTWNrQ0F3RUFBYU9CdkRDQnVUQU9CZ05WSFE4QkFmOEVCQU1DQmFBd0V3WURWUjBsCkJBd3dDZ1lJS3dZQkJRVUhBd0V3REFZRFZSMFRBUUgvQkFJd0FEQWZCZ05WSFNNRUdEQVdnQlRLSml6V1VKOWUKVUtpMWRzMGxyNmM2c0Q3RUJEQmpCZ05WSFJFQkFmOEVXVEJYZ2lWcGNtOXVhV010YVc1emNHVmpkRzl5TFhCMQpZbXhwWXk1dmNHVnVjM1JoWTJzdWMzWmpnaTVwY205dWFXTXRhVzV6Y0dWamRHOXlMWEIxWW14cFl5NXBjbTl1CmFXTXRhM1YwZEd3dGRHVnpkSE11YzNaak1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRHk2a1d1VTBHTG9jYW4KVndoYk1PdUR0SG1pM1paMEgyeWYyVCt3Z2dRUy9BSWhBTU5uUFRYWWpmb3FUQldpTFRTZDROUGp5QXdkQ3FDbwp4aUFKbVRTTmhrbDgKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeTFNcGs1ay9NUUhTZitXZ1IzMXVFMnJ6bWx2S0pkQ2ZZQmlodklmZzkzY2k5ZFRVCkxZMVcrbENQQ0l3cFVkRmduamlFejZPY1NXWnFBTGV4S095OXZESDZiTlRVVkZZZGx3enF1UTFxZzgzK0xLcG0KQWIyeGJ5SFRycVlyVStzV1Z4Y0xISEJ3dVlUVE9OOWhTN05lalJ6bnV0cGR0WTdqeGF1SE5kdVZQcGNISHFwagozd2pjSHJZRFhid0tORGRxUTNZQS9SY2Exc1lQVGtiaVZaeWNqR09KNWgxZFR2R0I2TDRrekRDZE1HalM4UVhQClJmTE50ekNrU2NEaUxOYXpqUnFodGU4dnAyQVFFS05COW1sV2FJTXZMc05vSndNY3F1VEZsRHpJSXhvdnBjbysKZWhhUjlaV3FpYVB2M0txdFM0eW92ZEg5dmJoTFQwb3I5NXd4eVFJREFRQUJBb0lCQVFDNUtjUU1RWncxb2lZMApDVWM4czdLaUJsMVFibFVhdVBIYlRyTkVBUzVUenZCTWxnU2djejRKZVlHNDFBUHhHYzkyWjV3emlCa1ZFeXBuCit1RmdsckIzaWNBNGlsM1BiQmxJYlIvNVpJbGkvUjZEU0s3YTJRaVVYMmJxZnpPb0djaGZpWUc1NVlBU3d5NmsKZFhHaXdmZlNaTWQzOTlNdE83S2NXb2dvK1E3aVRvQThockJZS1ZKYkRMdW90SmNsZkNvT3p2WFR6RzBmQ29rdQprcUx1MU5HczlEeE52cTFwTWZSbFBBOGVUYXZpTDZsSkl6SUYwaGsrUW9ESGN6NkRYWkpJaWJKNk5BdTg2UnZNCnV0Zk9hTnVibDdvakhKZjlYTEVDUmJRcGU2cktoblhFdHZ1YWVLQ2FFdGlJZGFYc05Tdm1tZnRYVCs3QlhZSnIKUnRqNzVTUUJBb0dCQVB2cW56eUVvbjZtb0YyZUdxY3VHUGxWeDZzbVpNWlAyWm90Q1dtVkVzYzhDRG5Oejd0eQpnNnRlSUV1MWFuM3NnMHV1c2N2TTVSdHVJYWJVU3dZWE1WN01yYkRWcGkzMlMvbUQ4aStlWklVdFY1TGVIYjlnCkVsd0VhRldCRlZIelRuOWovcTJZNFlTcE1kenZCN21YanpBcWRraUk2akl5UDZ1QUorVVZjeUJKQW9HQkFNNmUKNWs4WEVVSWhzRU1JTllZUlFLOU82bXY2RjA5VnYzdWovUHZYTHM2blRsbHpOaHZpYVQzY3JIMkJoZmx6ZS83NAppRkk4M0YrSG92d1BpcU1xdGRuTUxzUmNwTGltSDhwbHhIN24ySUlyRlh6R3Vxd1ovZVhTWW1IdW5rNFBLRFpjCnRBVThBTFJsRDJaQVVzYnNnK0xqNTZrMXM3dzN2eVJKTStlb080V0JBb0dBVXZGN0lHZmpRS1FJSlFyTFo4UUwKd1B4M1UyaSt3WFRGQnJoUll3d01OTUVWVEVMeFpKeGRzZXk1NFhPSDdwSVM0TFpTSC9JRWRUV2JxdHczSDNnLwpieUVoQnhveEx1enJNdW80c1drTFc3WUVJWDAwZWpCZG15SndYOGF5aUZyOXUzL20rSzFmZzFoWjdJNWZFc0pPCkNPUFNNaXV5UUhpKzhlNnVOQVVOOU5FQ2dZRUFyZCtOMDlTSGsyMGlGT2Fkay9xRXdvSFlSNUVuZUgyaUszdXUKY29kOFBpOFFnYm13T1Byb3NVUTRhMDFKM3NkTit4eE9LMVpINUtRUmhhZldkTVNHVDRmQmUwQ3k1U2YyN0syRApFNEFxOUM4cFg5MGtUWnQ1eTZLbFkrQVhtM3lwekVWcXdGVGtDdXBZY1NXRUF4NFpSaCtmWFFkeC90dXluK2h5CkkybXczUUVDZ1lBZUN5Q3cyMG1VV3hxUnRQR0haZHVQb2puRnlTOEFGbEJqUkZSTE9tb3JtMDAyc2k3SngrbUMKRW9jZkhSbGhxS1pYZWJCNjJoU3dQeHI5cFc0a0k5QTMvbG40UUFLbUZMd3JuYkc3MGxreDFDT2w5dmxxMEp6MApaTmRxcE1ZWGdBYXlXcnBDUFF5bUwvYXR3bStjQ3YxKzMvbGhXOGYxcVdWdVB0MDAwOUQxQXc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +kind: Secret +metadata: + annotations: + cert-manager.io/alt-names: ironic-inspector-public.openstack.svc + cert-manager.io/certificate-name: ironic-inspector-kuttl-public-svc + cert-manager.io/common-name: "" + cert-manager.io/ip-sans: "" + cert-manager.io/issuer-group: cert-manager.io + cert-manager.io/issuer-kind: Issuer + cert-manager.io/issuer-name: rootca-kuttl-public + cert-manager.io/uri-sans: "" + creationTimestamp: "2024-01-31T08:04:05Z" + labels: + controller.cert-manager.io/fao: "true" + name: cert-ironic-inspector-public-svc +type: kubernetes.io/tls diff --git a/tests/kuttl/common/tls_cert_ironic-internal-svc.yaml b/tests/kuttl/common/tls_cert_ironic-internal-svc.yaml new file mode 100644 index 00000000..9343d3c8 --- /dev/null +++ b/tests/kuttl/common/tls_cert_ironic-internal-svc.yaml @@ -0,0 +1,45 @@ +# +# Cert created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: ironic-kuttl-internal-svc +# namespace: openstack +# spec: +# dnsNames: +# - ironic-internal.openstack.svc +# - ironic-internal.ironic-kuttl-tests.svc +# duration: 87600h0m0s +# issuerRef: +# group: cert-manager.io +# kind: Issuer +# name: rootca-kuttl-internal +# secretName: cert-ironic-internal-svc +# secretTemplate: {} +# usages: +# - key encipherment +# - digital signature +# - server auth +# + +apiVersion: v1 +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmekNDQVNhZ0F3SUJBZ0lRUWxlcTNZcDBtU2kwVDNiTm03Q29UVEFLQmdncWhrak9QUVFEQWpBZ01SNHcKSEFZRFZRUURFeFZ5YjI5MFkyRXRhM1YwZEd3dGFXNTBaWEp1WVd3d0hoY05NalF3TVRFMU1URTBOelUwV2hjTgpNelF3TVRFeU1URTBOelUwV2pBZ01SNHdIQVlEVlFRREV4VnliMjkwWTJFdGEzVjBkR3d0YVc1MFpYSnVZV3d3CldUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTRk9rNHJPUldVUGhoTjUrK09EN1I2MW5Gb1lBY0QKenpvUS91SW93NktjeGhwRWNQTDFxb3ZZUGxUYUJabEh3c2FpNE50VHA4aDA1RHVRSGZKOE9JNXFvMEl3UURBTwpCZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXE3TGtFSk1TCm1MOVpKWjBSOUluKzZkclhycEl3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnVlN1K00ydnZ3QlF3eTJHMVlhdkkKQld2RGtSNlRla0I5U0VqdzJIblRSMWtDSUZSNFNkWGFPQkFGWjVHa2RLWCtSY2IzaDFIZm52eFJEVW96bTl2agphenp3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNsekNDQWoyZ0F3SUJBZ0lSQUx1d1JPTm9RZjRveFhVNTEvUENWZG93Q2dZSUtvWkl6ajBFQXdJd0lERWUKTUJ3R0ExVUVBeE1WY205dmRHTmhMV3QxZEhSc0xXbHVkR1Z5Ym1Gc01CNFhEVEkwTURFek1URXlORFUwT0ZvWApEVE0wTURFeU9ERXlORFUwT0Zvd0FEQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCCkFKWWlKYkJYNzd1Y251QTVadTlUdVZweVZMRmJvaU13eU0vL29DeExHU01WUnhJaEIxdWFUQW8zaWplVVlxd24KczFVMjZRNUw4ekxwTUtHZkR5MURFQXZlZlNHK0VOWTlBTGo2QnhsN0NjN3dEUHd0cXBTMjJaRE53bTdMb1BabApraW14WC9PRXpEVHk2MThLZndkUi9yNUpOWThITGgvRWVJK0NSVTRjaDFEem1zVk8xd2ZjSTBaUkZWQU0zbjlzCjlzMlpEdkxEalkyMVlucHJhcWVUL1JNMnNQWXhvNTVKeW1XQ2pZNmdST3B1QU9GbFNjc0FvN29MZVRQYWRrZDIKck1iUHBMbTlnU2cvemJUcHAraXUraFZRZElGdVRXblRQSnY3amdJYnY0QmlhRnRwTndqVXdIbHR4SWhXMWRBMwp5cnMrUHZwdGRDNU9aUm9UR2gxanpUa0NBd0VBQWFPQnJEQ0JxVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEClZSMGxCQXd3Q2dZSUt3WUJCUVVIQXdFd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JTcnN1UVEKa3hLWXYxa2xuUkgwaWY3cDJ0ZXVrakJUQmdOVkhSRUJBZjhFU1RCSGdoMXBjbTl1YVdNdGFXNTBaWEp1WVd3dQpiM0JsYm5OMFlXTnJMbk4yWTRJbWFYSnZibWxqTFdsdWRHVnlibUZzTG1seWIyNXBZeTFyZFhSMGJDMTBaWE4wCmN5NXpkbU13Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnQTFrb3dYR1lQVytTTmJWQ3pXNHkvcVBNTEVPZ3p6elcKYnhHUUtiankrTFVDSVFEdm80TlBPeVY5RERtRVZ3M29UZ0lEbDUvZFV4MGlHcmdVR2RtQnBCMlh6Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBbGlJbHNGZnZ1NXllNERsbTcxTzVXbkpVc1Z1aUl6REl6LytnTEVzWkl4VkhFaUVIClc1cE1DamVLTjVSaXJDZXpWVGJwRGt2ek11a3dvWjhQTFVNUUM5NTlJYjRRMWowQXVQb0hHWHNKenZBTS9DMnEKbExiWmtNM0Nic3VnOW1XU0tiRmY4NFRNTlBMclh3cC9CMUgrdmtrMWp3Y3VIOFI0ajRKRlRoeUhVUE9heFU3WApCOXdqUmxFVlVBemVmMnoyelprTzhzT05qYlZpZW10cXA1UDlFemF3OWpHam5rbktaWUtOanFCRTZtNEE0V1ZKCnl3Q2p1Z3Q1TTlwMlIzYXN4cytrdWIyQktEL050T21uNks3NkZWQjBnVzVOYWRNOG0vdU9BaHUvZ0dKb1cyazMKQ05UQWVXM0VpRmJWMERmS3V6NCsrbTEwTGs1bEdoTWFIV1BOT1FJREFRQUJBb0lCQUJZQ0JYSlhRYTVINUVaTQpROW1iZFZWYjR5eG9tVmo5UXNLeTMwRCs5VDFlVmgvRE5iZm80M0t2OTVQMExZNjg5eDNyd2JnMXkvM1BqekJ5CkI2Q0Q3eXMrUHl1ZUdBdS92NFplS0lKRXRnaGV5aGlCZlRyMW51a0tNSkZiU2tvMFUzdkhJNkNuKytOYkpNTzIKM3k0c2grSlBDd25mYkpSOWtZcS85dmJmV2JxMDhhUjhHMHRib1QxL2RLaHdva0FuNkRsVU9YVzJuZkUvM1E1WQpsd0ZvQ1FGTnNld3c4L0hvYXBSaExyeWpiNC9DN2Fvc2F0TEpUZk83eDRjWGxackFqNzBRSlRDUFNzdW5oODcvCjdnU256aDI0WWNTT0h6Y2M0cEcrOHM4aHVrbHN4M0IxTGxmUjNuMXRxOG1naEw0QnJlS1Vwc0E1RFViWS9iQncKc1BGSWZxMENnWUVBd1VGSnVwcDV3aFBoRndIbHNQMVpZbjJreUhlVEN2MVMxanIvWE0xSDhJUFJVUU1XQ1VPawpNdjZyT2N3Y052QjNyK2lHUXhGK29FRmM3VFdZSEZLeUorWUlkRGg0QnVHWjU0V2tFWEVyY1hpWGR2b2dLdVc5Ck00aEhEKytuREU1OFUzdVdXeSs3ME9iS0hCMjVOcWp4Y1lJOHNCYnVXODY1S0ZFVndhRlNTQThDZ1lFQXh1QzcKZlpqdGl0RU15QlM0Y0tvdEpvdkt2T2MzSUxFNE1uNklQTTRsRkhCT2dXVWJweEdMT1d3ZnBRbm1NT2ZiQzNregp2T2dIMFBsUXNEWFEwTXM0WGovaW1rMW5MVXNraW9mYXJiYmI1dWNid2phbG43TEx4ekF0V1h1NWk1ZlNteVMzCmhpYUhVN3RhR3hKVFJCektqR0RoK092ZWM4MSs1SXRzcEJWaWpqY0NnWUVBdHk5VjNnWVRxRDREdlRWVkxvSFkKT3AzeWx2dVJiSGRZRUMzNFpWVkkvZGxWamo4b29qdDE1OGl6TWFRaWtvazZTb3BVeWpwSkYwc2Q5TlE2alk1dAp4Wmd0SjAxbnFNNHNmdU9VODl1Y1hJRDh3aEN5Y1RjNE15TFlpV2lYcGZpM3JNS1hjWFE3eWZjYVdiQnJJajdlCkxzUlBGbk9HR1l4SXdzaXBvTk4wRlUwQ2dZQTlybG00SElRZjk3SkZJOWdJYVY5VGd5dS81dDQ4TDNyRWZtWDIKcGVEdU05N0ZWdng2bG9CZHNPRW5xS2hTSnJiVEdpWW53cmNaNHhsWmJYZDBLbk16R0JGSjFoUFlBbVEwNnVteAowdkxrN0d5NWtZVlF3SDFmSzl3RTB0QzdNTDFMRE5vMnF5QnhvYnZTaFo1NWs0eG1lVzNjYkJzMFExbkZ2RkJYCm02SlRoUUtCZ0NkSWF6NmhSSFNaSi9QalpwSmJrWHZuQ3ZCcDRaU0dXTHR2L1lUalh3YjJoWDVFL1ZJc0w3UDYKajRVd1l6THlZZzRHUldjaDc3S0dHb2hlZ1dsQThva0JreGRTTVY1ZHhUa3JUU1BwYUtjNndLQnZ6cElDQzNoVApCekVlTlJxNW1wMks0ekR6MVFraGVDNENUQUlJLzNFSVNySWFxNXFxSko0bkFFQzA1cmtQCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== +kind: Secret +metadata: + annotations: + cert-manager.io/alt-names: ironic-internal.openstack.svc + cert-manager.io/certificate-name: ironic-kuttl-internal-svc + cert-manager.io/common-name: "" + cert-manager.io/ip-sans: "" + cert-manager.io/issuer-group: cert-manager.io + cert-manager.io/issuer-kind: Issuer + cert-manager.io/issuer-name: rootca-kuttl-internal + cert-manager.io/uri-sans: "" + labels: + controller.cert-manager.io/fao: "true" + name: cert-ironic-internal-svc +type: kubernetes.io/tls diff --git a/tests/kuttl/common/tls_cert_ironic-public-svc.yaml b/tests/kuttl/common/tls_cert_ironic-public-svc.yaml new file mode 100644 index 00000000..4fa83391 --- /dev/null +++ b/tests/kuttl/common/tls_cert_ironic-public-svc.yaml @@ -0,0 +1,45 @@ +# +# Cert created with: +# +# apiVersion: cert-manager.io/v1 +# kind: Certificate +# metadata: +# name: kuttl-ironic-public-svc +# namespace: openstack +# spec: +# dnsNames: +# - ironic-public.openstack.svc +# - ironic-public.ironic-kuttl-tests.svc +# duration: 87600h0m0s +# issuerRef: +# group: cert-manager.io +# kind: Issuer +# name: rootca-kuttl-public +# secretName: cert-ironic-public-svc +# secretTemplate: {} +# usages: +# - key encipherment +# - digital signature +# - server auth + +apiVersion: v1 +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlekNDQVNLZ0F3SUJBZ0lRTkhER1lzQnM3OThpYkREN3EvbzJsakFLQmdncWhrak9QUVFEQWpBZU1Sd3cKR2dZRFZRUURFeE55YjI5MFkyRXRhM1YwZEd3dGNIVmliR2xqTUI0WERUSTBNREV4TlRFd01UVXpObG9YRFRNMApNREV4TWpFd01UVXpObG93SGpFY01Cb0dBMVVFQXhNVGNtOXZkR05oTFd0MWRIUnNMWEIxWW14cFl6QlpNQk1HCkJ5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRDc4YXZYcWhyaEM1dzhzOVdrZDRJcGJlRXUwM0NSK1hYVWQKa0R6T1J5eGE5d2NjSWREaXZiR0pqSkZaVFRjVm1ianExQk1Zc2pyMTJVSUU1RVQzVmxxalFqQkFNQTRHQTFVZApEd0VCL3dRRUF3SUNwREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlRLSml6V1VKOWVVS2kxCmRzMGxyNmM2c0Q3RUJEQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQklad1lxNjFCcU1KYUI2VWNGb1JzeGVjd0gKNXovek1PZHJPeWUwbU5pOEpnSWdRTEI0d0RLcnBmOXRYMmxvTSswdVRvcEFEU1lJbnJjZlZ1NEZCdVlVM0lnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNqekNDQWphZ0F3SUJBZ0lRTlZpR1hYdnlsNUhZd1gzZnd5S0JRREFLQmdncWhrak9QUVFEQWpBZU1Sd3cKR2dZRFZRUURFeE55YjI5MFkyRXRhM1YwZEd3dGNIVmliR2xqTUI0WERUSTBNREV6TVRFeU5EZzBOVm9YRFRNMApNREV5T0RFeU5EZzBOVm93QURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTFVmCkVKUE1tTEJHNVZ1dlJDT0RCcFNhV0RnN0dJN0JZZGZpM2RERHROc1dpRHhycnN4V3NTNm9CUjF6OGtrNUFBQ04KdmtFSXAxVHdHZUZtMkcxNStnTHdEMWFwSWZVVUtmRmxXZ3h0enpEZHdLRmNIQWJKVFFURE1KNzNLeElIbzNsUgoyS1JOckFyK0FXdDdQazF0dzNOOFFBMWxDZFJCWFdpd0QrUk5hazBmc0oyUTU1TXFPclNyRzVHcldra3ppVGlCCnRGWDF4eWJoNHVCMzZhVHJodUE3TkdHayt1ckhoZEdYaHdZSExHVFZOVHBBbXlGVXJGbml5VjdyZGJxSVdQdHAKanBrdDhJMDdmSW53a0lnK1IzNzFPUm9tUXlKOUxjaHJGT2FqUVNTdDdDcENsV3NWYndNeU1Cc2VQTWNpWnB2bQoyL3BnWHFlQnJDVXF6dmIyRmZrQ0F3RUFBYU9CcURDQnBUQU9CZ05WSFE4QkFmOEVCQU1DQmFBd0V3WURWUjBsCkJBd3dDZ1lJS3dZQkJRVUhBd0V3REFZRFZSMFRBUUgvQkFJd0FEQWZCZ05WSFNNRUdEQVdnQlRLSml6V1VKOWUKVUtpMWRzMGxyNmM2c0Q3RUJEQlBCZ05WSFJFQkFmOEVSVEJEZ2h0cGNtOXVhV010Y0hWaWJHbGpMbTl3Wlc1egpkR0ZqYXk1emRtT0NKR2x5YjI1cFl5MXdkV0pzYVdNdWFYSnZibWxqTFd0MWRIUnNMWFJsYzNSekxuTjJZekFLCkJnZ3Foa2pPUFFRREFnTkhBREJFQWlBS09MQlVXckVxNytMaVZGemcwbzErR2pKUFdVbUIrUUloaEwxdVZlZUcKRmdJZ2FTb3V2YlloMFJXd1NBeWx2Q2xwcnJmSWNra2p6VzZoK3doU0dnT2MrMWs9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdFI4UWs4eVlzRWJsVzY5RUk0TUdsSnBZT0RzWWpzRmgxK0xkME1PMDJ4YUlQR3V1CnpGYXhMcWdGSFhQeVNUa0FBSTIrUVFpblZQQVo0V2JZYlhuNkF2QVBWcWtoOVJRcDhXVmFERzNQTU4zQW9Wd2MKQnNsTkJNTXdudmNyRWdlamVWSFlwRTJzQ3Y0QmEzcytUVzNEYzN4QURXVUoxRUZkYUxBUDVFMXFUUit3blpEbgpreW82dEtzYmthdGFTVE9KT0lHMFZmWEhKdUhpNEhmcHBPdUc0RHMwWWFUNjZzZUYwWmVIQmdjc1pOVTFPa0NiCklWU3NXZUxKWHV0MXVvaFkrMm1PbVMzd2pUdDhpZkNRaUQ1SGZ2VTVHaVpESW4wdHlHc1U1cU5CSkszc0trS1YKYXhWdkF6SXdHeDQ4eHlKbW0rYmIrbUJlcDRHc0pTck85dllWK1FJREFRQUJBb0lCQURreG1ST0MvUWhWS3VJYgo0MkZ2WTZtVFg1NUtFd1FwVHROVVlZVWw5N3RqVHh2OVNSSmZvYzNBNHZTZEEzcFoxSVZZUFNiZUs3RG5yTlIvCm5JSmRqVFJXU0JHdWtQbUtKNENCNThDYkFGMUcrU2c3Sk9LRHVKMXpZYXdoRXVtN25jU1dzdG1YYVdlRE5FR1QKaG1YKzdrUk9qUTl0dzMvU01FUDVyTnNFRXpoTTY2ZGlWbkQxSW5TKzljdlpYRUpJSTNrRlI0OVk5ZkNwcHNjNgppRnB4VDk1MnpEZFNlNmlPSEc2VmRINHo1UTFORWJrbzQzeXg0Q2o0K2IrRDRjSy9Ga2ZkL2NhNUJBckxmTzdyCjNzbS8rYlhQUGVHbDRadGhCUzY0Nkh5QXphVzJKckY0bDZQSnNrREQxVVo2YTNCb2ZQbkZYc1lxMTYwbVpVRkoKRGhZV09ERUNnWUVBOE92dlczNjNVTGRuTHI4WE1GMllwRmk0aW1GanVJSkpPTlpOVUxWVHRzOUVXM29KQlQwSgo2UVZEWXVyNjZhZDF0WnV3U2hSV3JpVGU1bVM0TnpjempKdmdDUFhKbTBMRFR1Q3dFNkJMMlM5d0RXdVF2VHVaCkZRYmlIWE00aGQ3Zmw5QWhvOGpwbHg2eHFYa2VRVER5N2Z5d3ZsVGEvQTlZUnBPWlRjOFhiRjBDZ1lFQXdIVUIKVG53OVZYWnB6dUIzN3dyN3NZTHA4eTliL3dNQ29qeFN6amJpNGgzNEtaZjVWNU5TSnp4ejkreDdYYnFjN2FZZwpidDR4QWwyR2xLR1Z5QUwrTWRWb3E5MlNQZDA4RE95NGw5cFh2Nzd6ZEVpZXRmNXBSMjZFbGNJL2k2ZFZxb29iCjRoUmJHTVNzTVNhOE80ZXdRNm1DN1hoNVJ0WDhuS0hPZU9wY2xrMENnWUVBMVVKRDBsM01yeXBwcjd0L0wxVHEKZFRBRHlwcUN4eVNzNUI3dXVXNkk5OTFveVFDeFUyM0FoQUFnc2tNR2NDWEgwRVpNT29iZVk3QkhqdkhCRHo5Ugo1amxraXdubXVBVFZGZEZXaTBqdFd3YmV6VUpXRU92Y2lmeFowMi9Xck1tb2FwM1Y2VUZEWkgzTERoVWtidGlCCmNhQ29ZeEtCOVhVdjB1bDhYcC9lUUJFQ2dZRUFyR05oNHpwMytlaFNTR05hS24xdERBaldvK1RGQTd4ZmpKQjYKSDRxY1dhdzhrSTAzWkJGcTRnaE5YRUt3RWpuSXZUbzBEUHJyYlZIMjdZVjdVNmdTcHZLZ2ltbXl4OFUyTitHRwpTMGJobUxoaSs4TGNudW9leFVRaWNMNkpDdis5UlQvbVQvQ3AxSnErSGx5eStLUEc2Q1NiU1RqRGNRYlYranNaClpjZVBYWFVDZ1lCeGFkdC9tWWhnbklZRGp0QXlnZngra1ZndE5GYWtQdEMxaUNwbXB6SWxCYWJHYVdnNEtJMXQKS1FKUnlVd3hHcG5lQTBFbVVXNXdWcFBXQUVSUTBpRHRodFRXY1N3OTE0ZWthTFpxbnBJTXRpY3MzNkwyTFplTgpuaGcza1hEdUx0Y1BSU284UmhGbkFQTjBxZU9LMTVNQlhGWlVFZ3Raa1N4MlJ2c0tiM253S1E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +kind: Secret +metadata: + annotations: + cert-manager.io/alt-names: ironic-public.openstack.svc + cert-manager.io/certificate-name: ironic-kuttl-public-svc + cert-manager.io/common-name: "" + cert-manager.io/ip-sans: "" + cert-manager.io/issuer-group: cert-manager.io + cert-manager.io/issuer-kind: Issuer + cert-manager.io/issuer-name: rootca-kuttl-public + cert-manager.io/uri-sans: "" + creationTimestamp: "2024-01-31T07:56:49Z" + labels: + controller.cert-manager.io/fao: "true" + name: cert-ironic-public-svc +type: kubernetes.io/tls diff --git a/tests/kuttl/tests/deploy_tls/00-assert.yaml b/tests/kuttl/tests/deploy_tls/00-assert.yaml new file mode 120000 index 00000000..4e080a30 --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-assert.yaml @@ -0,0 +1 @@ +../../common/assert_tls_cert.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/00-tls_ca_bundle.yaml b/tests/kuttl/tests/deploy_tls/00-tls_ca_bundle.yaml new file mode 120000 index 00000000..2e45b874 --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-tls_ca_bundle.yaml @@ -0,0 +1 @@ +../../common/tls_ca_bundle.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-internal-svc.yaml b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-internal-svc.yaml new file mode 120000 index 00000000..52d5e360 --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-internal-svc.yaml @@ -0,0 +1 @@ +../../common/tls_cert_ironic-inspector-internal-svc.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-public-svc.yaml b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-public-svc.yaml new file mode 120000 index 00000000..9b44b8db --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-inspector-public-svc.yaml @@ -0,0 +1 @@ +../../common/tls_cert_ironic-inspector-public-svc.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-internal-svc.yaml b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-internal-svc.yaml new file mode 120000 index 00000000..c4fbdb46 --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-internal-svc.yaml @@ -0,0 +1 @@ +../../common/tls_cert_ironic-internal-svc.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-public-svc.yaml b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-public-svc.yaml new file mode 120000 index 00000000..9b78b980 --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/00-tls_cert_ironic-public-svc.yaml @@ -0,0 +1 @@ +../../common/tls_cert_ironic-public-svc.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/10-assert-deploy-ironic.yaml b/tests/kuttl/tests/deploy_tls/10-assert-deploy-ironic.yaml new file mode 100644 index 00000000..8b14a04f --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/10-assert-deploy-ironic.yaml @@ -0,0 +1,131 @@ +# +# Check for: +# +# Ironic +# IronicAPI +# IronicConductor +# IronicInspector +# IronicNeutronAgent +# Registered TLS endpoints for api and inspector +# + +apiVersion: ironic.openstack.org/v1beta1 +kind: Ironic +metadata: + name: ironic +spec: + databaseInstance: openstack + ironicAPI: + replicas: 1 + tls: + api: + internal: + secretName: cert-ironic-internal-svc + public: + secretName: cert-ironic-public-svc + caBundleSecretName: combined-ca-bundle + ironicConductors: + - replicas: 1 + ironicInspector: + replicas: 1 + tls: + api: + internal: + secretName: cert-ironic-inspector-internal-svc + public: + secretName: cert-ironic-inspector-public-svc + caBundleSecretName: combined-ca-bundle + ironicNeutronAgent: + replicas: 1 +status: + databaseHostname: openstack + ironicAPIReadyCount: 1 + ironicConductorReadyCount: + null_conductor_group_null: 1 + ironicInspectorReadyCount: 1 + ironicNeutronAgentReadyCount: 1 +--- +apiVersion: ironic.openstack.org/v1beta1 +kind: IronicAPI +metadata: + name: ironic-api +spec: + replicas: 1 + tls: + api: + internal: + secretName: cert-ironic-internal-svc + public: + secretName: cert-ironic-public-svc + caBundleSecretName: combined-ca-bundle +status: + readyCount: 1 +--- +apiVersion: ironic.openstack.org/v1beta1 +kind: IronicConductor +metadata: + name: ironic-conductor +spec: + replicas: 1 + tls: + caBundleSecretName: combined-ca-bundle +status: + readyCount: 1 +--- +apiVersion: ironic.openstack.org/v1beta1 +kind: IronicInspector +metadata: + name: ironic-inspector +spec: + replicas: 1 + tls: + api: + internal: + secretName: cert-ironic-inspector-internal-svc + public: + secretName: cert-ironic-inspector-public-svc + caBundleSecretName: combined-ca-bundle +status: + databaseHostname: openstack + readyCount: 1 +--- +apiVersion: ironic.openstack.org/v1beta1 +kind: IronicNeutronAgent +metadata: + name: ironic-ironic-neutron-agent +spec: + replicas: 1 + tls: + caBundleSecretName: combined-ca-bundle +status: + readyCount: 1 +--- +# the actual addresses of the api endpoints are platform specific, so we can't rely on +# kuttl asserts to check them. This short script gathers the addresses and checks that +# the two endpoints are defined and their addresses follow the default pattern +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + template='{{.spec.endpoints.internal}}{{":"}}{{.spec.endpoints.public}}{{"\n"}}' + regex="https:\/\/ironic-internal.$NAMESPACE.*:https:\/\/ironic-public.$NAMESPACE.*" + apiEndpoints=$(oc get -n $NAMESPACE KeystoneEndpoint ironic -o go-template="$template") + matches=$(echo "$apiEndpoints" | sed -e "s?$regex??") + if [[ -n "$matches" ]]; then + exit 1 + fi +--- +# the actual addresses of the api endpoints are platform specific, so we can't rely on +# kuttl asserts to check them. This short script gathers the addresses and checks that +# the two endpoints are defined and their addresses follow the default pattern +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + template='{{.spec.endpoints.internal}}{{":"}}{{.spec.endpoints.public}}{{"\n"}}' + regex="https:\/\/ironic-inspector-internal.$NAMESPACE.*:https:\/\/ironic-inspector-public.$NAMESPACE.*" + apiEndpoints=$(oc get -n $NAMESPACE KeystoneEndpoint ironic-inspector -o go-template="$template") + matches=$(echo "$apiEndpoints" | sed -e "s?$regex??") + if [[ -n "$matches" ]]; then + exit 1 + fi diff --git a/tests/kuttl/tests/deploy_tls/10-deploy-ironic.yaml b/tests/kuttl/tests/deploy_tls/10-deploy-ironic.yaml new file mode 100644 index 00000000..f6c3878e --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/10-deploy-ironic.yaml @@ -0,0 +1,5 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: | + oc apply -n $NAMESPACE -f ../../../../config/samples/ironic_v1beta1_ironic_tls.yaml diff --git a/tests/kuttl/tests/deploy_tls/99-cleanup-ironic.yaml b/tests/kuttl/tests/deploy_tls/99-cleanup-ironic.yaml new file mode 120000 index 00000000..5b96dace --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/99-cleanup-ironic.yaml @@ -0,0 +1 @@ +../../common/cleanup-ironic.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/deploy_tls/99-errors-cleanup-ironic.yaml b/tests/kuttl/tests/deploy_tls/99-errors-cleanup-ironic.yaml new file mode 120000 index 00000000..e8c1833b --- /dev/null +++ b/tests/kuttl/tests/deploy_tls/99-errors-cleanup-ironic.yaml @@ -0,0 +1 @@ +../../common/errors-cleanup-ironic.yaml \ No newline at end of file