Skip to content

Commit

Permalink
Merge pull request #415 from kubevirt-bot/cherry-pick-408-to-release-…
Browse files Browse the repository at this point in the history
…v0.16

[release-v0.16] Support cluster-wide crypto policy
  • Loading branch information
kubevirt-bot committed Sep 5, 2022
2 parents 7ad7fe2 + 1df5bd5 commit 456a26a
Show file tree
Hide file tree
Showing 21 changed files with 1,990 additions and 121 deletions.
14 changes: 1 addition & 13 deletions controllers/services_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package controllers
import (
"context"
"fmt"
"io/ioutil"
"strings"

"github.com/go-logr/logr"
apps "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -119,7 +117,7 @@ func getOperatorDeployment(namespace string, apiReader client.Reader) (*apps.Dep

func newServiceReconciler(mgr ctrl.Manager) (*serviceReconciler, error) {
logger := ctrl.Log.WithName("controllers").WithName("Resources")
namespace, err := getOperatorNamespace(logger)
namespace, err := common.GetOperatorNamespace(logger)
if err != nil {
return nil, fmt.Errorf("in newServiceReconciler: %w", err)
}
Expand All @@ -139,16 +137,6 @@ func newServiceReconciler(mgr ctrl.Manager) (*serviceReconciler, error) {
return reconciler, nil
}

func getOperatorNamespace(logger logr.Logger) (string, error) {
nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return "", fmt.Errorf("in getOperatorNamespace failed in call to downward API: %w", err)
}
ns := strings.TrimSpace(string(nsBytes))
logger.Info("Found namespace", "Namespace", ns)
return ns, nil
}

func (r *serviceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
r.log.Info("Starting service reconciliation...", "request", req.String())
service := ServiceObject(req.Namespace)
Expand Down
12 changes: 12 additions & 0 deletions controllers/ssp_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package controllers
import (
"context"
"fmt"
"os"
"reflect"
"strconv"

Expand Down Expand Up @@ -143,6 +144,7 @@ func (r *sspReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ct
return ctrl.Result{}, err
}

r.restartIfNeeded(instance)
r.clearCacheIfNeeded(instance)

sspRequest := &common.Request{
Expand Down Expand Up @@ -219,6 +221,16 @@ func (r *sspReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ct
return ctrl.Result{}, nil
}

func (r *sspReconciler) restartIfNeeded(sspObj *ssp.SSP) {
if reflect.DeepEqual(r.lastSspSpec, ssp.SSPSpec{}) {
return
}
if !reflect.DeepEqual(r.lastSspSpec.TLSSecurityProfile, sspObj.Spec.TLSSecurityProfile) {
r.log.Info("TLSSecurityProfile changed, restarting")
os.Exit(0)
}
}

func (r *sspReconciler) clearCacheIfNeeded(sspObj *ssp.SSP) {
if !reflect.DeepEqual(r.lastSspSpec, sspObj.Spec) {
r.subresourceCache = common.VersionCache{}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/onsi/gomega v1.19.0
github.com/openshift/api v0.0.0-20220124143425-d74727069f6f // release-4.10
github.com/openshift/custom-resource-status v1.1.2
github.com/openshift/library-go v0.0.0-20220630204433-c71d40c7de49
github.com/operator-framework/api v0.14.0
github.com/operator-framework/operator-lib v0.10.0
github.com/pkg/errors v0.9.1
Expand Down Expand Up @@ -98,6 +99,7 @@ require (
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiserver v0.24.2 // indirect
k8s.io/component-base v0.24.2 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ github.com/openshift/api v0.0.0-20220124143425-d74727069f6f/go.mod h1:F/eU6jgr6Q
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4=
github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA=
github.com/openshift/library-go v0.0.0-20220630204433-c71d40c7de49 h1:m849kE1Ylw7ssU6SbIOFtvJo4NF6ZCtjNRTpIDMDzqo=
github.com/openshift/library-go v0.0.0-20220630204433-c71d40c7de49/go.mod h1:6AmNM4N4nHftckybV/U7bQW+5AvK5TW81ndSI6KEidw=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/operator-framework/api v0.14.0 h1:5nk8fQL8l+dDxi11hZi0T7nqhhoIQLn+qL2DhMEGnoE=
github.com/operator-framework/api v0.14.0/go.mod h1:r/erkmp9Kc1Al4dnxmRkJYc0uCtD5FohN9VuJ5nTxz0=
Expand Down Expand Up @@ -1002,6 +1004,7 @@ k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFY
k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM=
k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apiserver v0.24.2 h1:orxipm5elPJSkkFNlwH9ClqaKEDJJA3yR2cAAlCnyj4=
k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI=
k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA=
k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
Expand Down
128 changes: 128 additions & 0 deletions internal/common/crypto_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package common

import (
"context"
"crypto/tls"
"fmt"

"github.com/go-logr/logr"
ocpv1 "github.com/openshift/api/config/v1"
"github.com/openshift/library-go/pkg/crypto"
"kubevirt.io/ssp-operator/api/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type SSPTLSOptions struct {
MinTLSVersion string
OpenSSLCipherNames []string
}

func (s *SSPTLSOptions) IsEmpty() bool {
return len(s.OpenSSLCipherNames) == 0 && s.MinTLSVersion == ""
}

func (s *SSPTLSOptions) MinTLSVersionId() (uint16, error) {
switch s.MinTLSVersion {
case "":
return tls.VersionTLS10, nil
case "1.0":
return tls.VersionTLS10, nil
case "1.1":
return tls.VersionTLS11, nil
case "1.2":
return tls.VersionTLS12, nil
case "1.3":
return tls.VersionTLS13, nil
default:
return 0, fmt.Errorf("invalid TLSMinVersion %v: expects 1.0, 1.1, 1.2, 1.3 or empty", s.MinTLSVersion)
}
}

func NewSSPTLSOptions(tlsSecurityProfile *ocpv1.TLSSecurityProfile, logger *logr.Logger) (*SSPTLSOptions, error) {
ciphers, tlsProfile := selectCipherSuitesAndMinTLSVersion(tlsSecurityProfile)

if logger != nil {
logger.Info("Got Ciphers and tlsProfile:", "ciphers: ", ciphers, "tlsProfile: ", tlsProfile)
}

minVersion, err := tlsVersionToHumanReadable(tlsProfile)
if err != nil {
return nil, err
}
return &SSPTLSOptions{
MinTLSVersion: minVersion,
OpenSSLCipherNames: ciphers,
}, nil
}

func (s *SSPTLSOptions) CipherIDs() (cipherSuites []uint16) {
for _, cipherName := range crypto.OpenSSLToIANACipherSuites(s.OpenSSLCipherNames) {
for _, knownCipher := range tls.CipherSuites() {
if knownCipher.Name == cipherName {
cipherSuites = append(cipherSuites, knownCipher.ID)
continue
}
}
}
return
}

func GetSspTlsOptions() (*SSPTLSOptions, error) {
setupLog := ctrl.Log.WithName("setup")
restConfig := ctrl.GetConfigOrDie()
apiReader, err := client.New(restConfig, client.Options{Scheme: Scheme})
if err != nil {
return nil, err
}

namespace, err := GetOperatorNamespace(setupLog)
if err != nil {
return nil, err
}

var sspList v1beta1.SSPList
if err := apiReader.List(context.TODO(), &sspList, &client.ListOptions{Namespace: namespace}); err != nil {
return nil, err
}

if len(sspList.Items) == 0 {
return &SSPTLSOptions{}, nil
}

ssp := sspList.Items[0]

sspTLSOptions, err := NewSSPTLSOptions(ssp.Spec.TLSSecurityProfile, &setupLog)
if err != nil {
return nil, err
}
return sspTLSOptions, nil
}

func selectCipherSuitesAndMinTLSVersion(profile *ocpv1.TLSSecurityProfile) ([]string, ocpv1.TLSProtocolVersion) {
if profile == nil {
return nil, ""
}
if profile.Custom != nil {
return profile.Custom.TLSProfileSpec.Ciphers, profile.Custom.TLSProfileSpec.MinTLSVersion
}
tlsProfileSpec := ocpv1.TLSProfiles[profile.Type]
return tlsProfileSpec.Ciphers, tlsProfileSpec.MinTLSVersion
}

func tlsVersionToHumanReadable(version ocpv1.TLSProtocolVersion) (string, error) {
switch version {
case "":
return "", nil
case ocpv1.VersionTLS10:
return "1.0", nil
case ocpv1.VersionTLS11:
return "1.1", nil
case ocpv1.VersionTLS12:
return "1.2", nil
case ocpv1.VersionTLS13:
return "1.3", nil
default:
return "", fmt.Errorf("invalid ocpv1.VersionTLS %v", version)
}
}
14 changes: 14 additions & 0 deletions internal/common/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package common

import (
"context"
"fmt"
"io/ioutil"
"os"
"strings"

"github.com/go-logr/logr"
osconfv1 "github.com/openshift/api/config/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -37,3 +41,13 @@ func GetInfrastructureTopology(c client.Reader) (osconfv1.TopologyMode, error) {

return infraConfig.Status.InfrastructureTopology, nil
}

func GetOperatorNamespace(logger logr.Logger) (string, error) {
nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return "", fmt.Errorf("in getOperatorNamespace failed in call to downward API: %w", err)
}
ns := strings.TrimSpace(string(nsBytes))
logger.Info("Found namespace", "Namespace", ns)
return ns, nil
}
8 changes: 7 additions & 1 deletion internal/operands/template-validator/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,13 @@ func reconcileDeployment(request *common.Request) (common.ReconcileResult, error
if request.IsSingleReplicaTopologyMode() && (numberOfReplicas > 1) {
numberOfReplicas = 1
}
deployment := newDeployment(request.Namespace, numberOfReplicas, image)

sspTLSOptions, err := common.NewSSPTLSOptions(request.Instance.Spec.TLSSecurityProfile, nil)
if err != nil {
return common.ReconcileResult{}, err
}

deployment := newDeployment(request.Namespace, numberOfReplicas, image, sspTLSOptions)
injectPlacementMetadata(&deployment.Spec.Template.Spec, &validatorSpec)
return common.CreateOrUpdate(request).
NamespacedResource(deployment).
Expand Down
7 changes: 4 additions & 3 deletions internal/operands/template-validator/reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
)

var log = logf.Log.WithName("validator_operand")
var emptySSPTLSConfig = &common.SSPTLSOptions{}

var _ = Describe("Template validator operand", func() {
const (
Expand Down Expand Up @@ -85,7 +86,7 @@ var _ = Describe("Template validator operand", func() {
ExpectResourceExists(newServiceAccount(namespace), request)
ExpectResourceExists(newClusterRoleBinding(namespace), request)
ExpectResourceExists(newService(namespace), request)
ExpectResourceExists(newDeployment(namespace, replicas, "test-img"), request)
ExpectResourceExists(newDeployment(namespace, replicas, "test-img", emptySSPTLSConfig), request)
ExpectResourceExists(newValidatingWebhook(namespace), request)
ExpectResourceExists(newPrometheusService(namespace), request)
})
Expand Down Expand Up @@ -153,7 +154,7 @@ var _ = Describe("Template validator operand", func() {
Expect(err).ToNot(HaveOccurred())

// Set status for deployment
key := client.ObjectKeyFromObject(newDeployment(namespace, replicas, "test-img"))
key := client.ObjectKeyFromObject(newDeployment(namespace, replicas, "test-img", emptySSPTLSConfig))
updateDeployment(key, &request, func(deployment *apps.Deployment) {
deployment.Status.Replicas = replicas
deployment.Status.ReadyReplicas = 0
Expand Down Expand Up @@ -381,7 +382,7 @@ var _ = Describe("Template validator operand", func() {
_, err := operand.Reconcile(&request)
Expect(err).ToNot(HaveOccurred())
deployment := &apps.Deployment{}
key := client.ObjectKeyFromObject(newDeployment(namespace, replicas, "test-img"))
key := client.ObjectKeyFromObject(newDeployment(namespace, replicas, "test-img", emptySSPTLSConfig))
Expect(request.Client.Get(request.Context, key, deployment)).To(Succeed())
Expect(deployment.Spec.Template.Spec.Affinity.NodeAffinity).To(Equal(expectedNodeAffinity))
Expect(deployment.Spec.Template.Spec.Affinity.PodAffinity).To(Equal(expectedPodAffinity))
Expand Down
15 changes: 13 additions & 2 deletions internal/operands/template-validator/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template_validator

import (
"fmt"
"strings"

templatev1 "github.com/openshift/api/template/v1"
admission "k8s.io/api/admissionregistration/v1"
Expand All @@ -18,6 +19,7 @@ import (
"kubevirt.io/ssp-operator/internal/common"
common_templates "kubevirt.io/ssp-operator/internal/operands/common-templates"
metrics "kubevirt.io/ssp-operator/internal/operands/metrics"
"kubevirt.io/ssp-operator/internal/template-validator/tlsinfo"
webhook "kubevirt.io/ssp-operator/internal/template-validator/webhooks"
)

Expand Down Expand Up @@ -142,7 +144,7 @@ func newPodAntiAffinity(key, topologyKey string, operator metav1.LabelSelectorOp
}
}

func newDeployment(namespace string, replicas int32, image string) *apps.Deployment {
func newDeployment(namespace string, replicas int32, image string, sspTLSOptions *common.SSPTLSOptions) *apps.Deployment {
const volumeName = "tls"
const certMountPath = "/etc/webhook/certs"
trueVal := true
Expand All @@ -152,7 +154,6 @@ func newDeployment(namespace string, replicas int32, image string) *apps.Deploym
podLabels[PrometheusLabel] = "true"
podLabels["name"] = DeploymentName
podAntiAffinity := newPodAntiAffinity(KubevirtIo, kubernetesHostnameTopologyKey, metav1.LabelSelectorOpIn, []string{VirtTemplateValidator})

return &apps.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: DeploymentName,
Expand Down Expand Up @@ -195,6 +196,16 @@ func newDeployment(namespace string, replicas int32, image string) *apps.Deploym
fmt.Sprintf("--port=%d", ContainerPort),
fmt.Sprintf("--cert-dir=%s", certMountPath),
},
Env: []core.EnvVar{
{
Name: tlsinfo.CiphersEnvName,
Value: strings.Join(sspTLSOptions.OpenSSLCipherNames, ","),
},
{
Name: tlsinfo.TLSMinVersionEnvName,
Value: sspTLSOptions.MinTLSVersion,
},
},
VolumeMounts: []core.VolumeMount{{
Name: volumeName,
MountPath: certMountPath,
Expand Down
Loading

0 comments on commit 456a26a

Please sign in to comment.