Skip to content

Commit

Permalink
Merge pull request #453 from redhatrises/admission_finalization
Browse files Browse the repository at this point in the history
feat: update falconadmission resource
  • Loading branch information
redhatrises authored Oct 31, 2023
2 parents fa5141f + a3a274a commit cb3ab58
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 190 deletions.
88 changes: 88 additions & 0 deletions controllers/admission/configmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package controllers

import (
"context"
"fmt"
"reflect"

falconv1alpha1 "github.com/crowdstrike/falcon-operator/api/falcon/v1alpha1"
"github.com/crowdstrike/falcon-operator/internal/controller/assets"
k8sutils "github.com/crowdstrike/falcon-operator/internal/controller/common"
"github.com/crowdstrike/falcon-operator/pkg/common"
"github.com/crowdstrike/falcon-operator/pkg/falcon_api"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
types "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
)

func (r *FalconAdmissionReconciler) reconcileRegistryCABundleConfigMap(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
return r.reconcileGenericConfigMap(falconAdmission.Name+"-registry-certs", r.newCABundleConfigMap, ctx, req, log, falconAdmission)
}

func (r *FalconAdmissionReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
return r.reconcileGenericConfigMap(falconAdmission.Name+"-config", r.newConfigMap, ctx, req, log, falconAdmission)
}

func (r *FalconAdmissionReconciler) reconcileGenericConfigMap(name string, genFunc func(context.Context, string, *falconv1alpha1.FalconAdmission) (*corev1.ConfigMap, error), ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
cm, err := genFunc(ctx, name, falconAdmission)
if err != nil {
return false, err
}

existingCM := &corev1.ConfigMap{}
err = r.Get(ctx, types.NamespacedName{Name: name, Namespace: falconAdmission.Spec.InstallNamespace}, existingCM)
if err != nil && apierrors.IsNotFound(err) {
err = k8sutils.Create(r.Client, r.Scheme, ctx, req, log, falconAdmission, &falconAdmission.Status, cm)
if err != nil {
return false, err
}

return false, nil
} else if err != nil {
log.Error(err, "Failed to get FalconAdmission ConfigMap")
return false, err
}

if !reflect.DeepEqual(cm.Data, existingCM.Data) {
existingCM.Data = cm.Data
if err := k8sutils.Update(r.Client, ctx, req, log, falconAdmission, &falconAdmission.Status, existingCM); err != nil {
return false, err
}
return true, nil
}

return false, nil

}

func (r *FalconAdmissionReconciler) newCABundleConfigMap(ctx context.Context, name string, falconAdmission *falconv1alpha1.FalconAdmission) (*corev1.ConfigMap, error) {
data := make(map[string]string)
if falconAdmission.Spec.Registry.TLS.CACertificate != "" {
data["tls.crt"] = string(common.DecodeBase64Interface(falconAdmission.Spec.Registry.TLS.CACertificate))

return assets.SensorConfigMap(name, falconAdmission.Spec.InstallNamespace, common.FalconSidecarSensor, data), nil
}
return &corev1.ConfigMap{}, fmt.Errorf("unable to determine contents of Registry TLS CACertificate attribute")
}

func (r *FalconAdmissionReconciler) newConfigMap(ctx context.Context, name string, falconAdmission *falconv1alpha1.FalconAdmission) (*corev1.ConfigMap, error) {
var err error
data := common.MakeSensorEnvMap(falconAdmission.Spec.Falcon)

cid := ""
if falconAdmission.Spec.Falcon.CID != nil {
cid = *falconAdmission.Spec.Falcon.CID
}

if cid == "" && falconAdmission.Spec.FalconAPI != nil {
cid, err = falcon_api.FalconCID(ctx, falconAdmission.Spec.FalconAPI.CID, falconAdmission.Spec.FalconAPI.ApiConfig())
if err != nil {
return &corev1.ConfigMap{}, err
}
}
data["FALCONCTL_OPT_CID"] = cid

return assets.SensorConfigMap(name, falconAdmission.Spec.InstallNamespace, common.FalconAdmissionController, data), nil
}
78 changes: 27 additions & 51 deletions controllers/admission/falconadmission_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
k8sutils "github.com/crowdstrike/falcon-operator/internal/controller/common"
"github.com/crowdstrike/falcon-operator/pkg/aws"
"github.com/crowdstrike/falcon-operator/pkg/common"
"github.com/crowdstrike/falcon-operator/pkg/falcon_api"
"github.com/crowdstrike/falcon-operator/pkg/registry/pulltoken"
"github.com/crowdstrike/falcon-operator/pkg/tls"
"github.com/crowdstrike/falcon-operator/version"
Expand Down Expand Up @@ -142,11 +141,11 @@ func (r *FalconAdmissionReconciler) Reconcile(ctx context.Context, req ctrl.Requ
// Image being set will override other image based settings
if falconAdmission.Spec.Image != "" {
if _, err := r.setImageTag(ctx, falconAdmission); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to set Falcon Container Image version: %v", err)
return ctrl.Result{}, fmt.Errorf("failed to set Falcon Admission Image version: %v", err)
}
} else if os.Getenv("RELATED_IMAGE_ADMISSION_CONTROLLER") != "" && falconAdmission.Spec.FalconAPI == nil {
if _, err := r.setImageTag(ctx, falconAdmission); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to set Falcon Container Image version: %v", err)
return ctrl.Result{}, fmt.Errorf("failed to set Falcon Admission Image version: %v", err)
}
} else {
switch falconAdmission.Spec.Registry.Type {
Expand All @@ -164,17 +163,27 @@ func (r *FalconAdmissionReconciler) Reconcile(ctx context.Context, req ctrl.Requ
}
}

// Create a CA Bundle ConfigMap if CACertificate attribute is set; overridden by the presence of a CACertificateConfigMap value
if falconAdmission.Spec.Registry.TLS.CACertificateConfigMap == "" && falconAdmission.Spec.Registry.TLS.CACertificate != "" {
if _, err := r.reconcileRegistryCABundleConfigMap(ctx, req, log, falconAdmission); err != nil {
if err != nil {
return ctrl.Result{}, err
}

}
}

if r.imageMirroringEnabled(falconAdmission) {
if err := r.PushImage(ctx, log, falconAdmission); err != nil {
return ctrl.Result{}, fmt.Errorf("cannot refresh Falcon Container image: %v", err)
return ctrl.Result{}, fmt.Errorf("cannot refresh Falcon Admission image: %v", err)
}
} else {
updated, err = r.verifyCrowdStrike(ctx, log, falconAdmission)
if updated {
return ctrl.Result{}, nil
}
if err != nil {
log.Error(err, "Failed to verify CrowdStrike Container Image Registry access")
log.Error(err, "Failed to verify CrowdStrike Admission Image Registry access")
time.Sleep(time.Second * 5)
return ctrl.Result{RequeueAfter: 5 * time.Second}, err
}
Expand Down Expand Up @@ -341,50 +350,6 @@ func (r *FalconAdmissionReconciler) reconcileTLSSecret(ctx context.Context, req
return &corev1.Secret{}, nil
}

func (r *FalconAdmissionReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
existingCM := &corev1.ConfigMap{}
var err error
data := common.MakeSensorEnvMap(falconAdmission.Spec.Falcon)
name := falconAdmission.Name + "-config"

cid := ""
if falconAdmission.Spec.Falcon.CID != nil {
cid = *falconAdmission.Spec.Falcon.CID
}

if cid == "" && falconAdmission.Spec.FalconAPI != nil {
cid, err = falcon_api.FalconCID(ctx, falconAdmission.Spec.FalconAPI.CID, falconAdmission.Spec.FalconAPI.ApiConfig())
if err != nil {
return false, err
}
}
data["FALCONCTL_OPT_CID"] = cid

cm := assets.SensorConfigMap(name, falconAdmission.Spec.InstallNamespace, common.FalconAdmissionController, data)
err = r.Get(ctx, types.NamespacedName{Name: name, Namespace: falconAdmission.Spec.InstallNamespace}, existingCM)
if err != nil && apierrors.IsNotFound(err) {
err = k8sutils.Create(r.Client, r.Scheme, ctx, req, log, falconAdmission, &falconAdmission.Status, cm)
if err != nil {
return false, err
}

return false, nil
} else if err != nil {
log.Error(err, "Failed to get FalconAdmission ConfigMap")
return false, err
}

if !reflect.DeepEqual(cm.Data, existingCM.Data) {
existingCM.Data = cm.Data
if err := k8sutils.Update(r.Client, ctx, req, log, falconAdmission, &falconAdmission.Status, existingCM); err != nil {
return false, err
}
return true, nil
}

return false, nil
}

func (r *FalconAdmissionReconciler) reconcileService(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
existingService := &corev1.Service{}
selector := map[string]string{common.FalconComponentKey: common.FalconAdmissionController}
Expand Down Expand Up @@ -576,6 +541,16 @@ func (r *FalconAdmissionReconciler) reconcileAdmissionDeployment(ctx context.Con
existingDeployment.Spec.Template.Spec.Containers[i].Resources = containers.Resources
updated = true
}

if !reflect.DeepEqual(containers.LivenessProbe.ProbeHandler.HTTPGet.Port, existingDeployment.Spec.Template.Spec.Containers[i].LivenessProbe.ProbeHandler.HTTPGet.Port) {
existingDeployment.Spec.Template.Spec.Containers[i].LivenessProbe.ProbeHandler.HTTPGet.Port = containers.LivenessProbe.ProbeHandler.HTTPGet.Port
updated = true
}

if !reflect.DeepEqual(containers.StartupProbe.ProbeHandler.HTTPGet.Port, existingDeployment.Spec.Template.Spec.Containers[i].StartupProbe.ProbeHandler.HTTPGet.Port) {
existingDeployment.Spec.Template.Spec.Containers[i].StartupProbe.ProbeHandler.HTTPGet.Port = containers.StartupProbe.ProbeHandler.HTTPGet.Port
updated = true
}
}

if updated {
Expand Down Expand Up @@ -622,10 +597,11 @@ func (r *FalconAdmissionReconciler) reconcileRegistrySecret(ctx context.Context,

func (r *FalconAdmissionReconciler) reconcileImageStream(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (*imagev1.ImageStream, error) {
const imageStreamName = "falcon-admission-controller"
imageStream := assets.ImageStream(imageStreamName, falconAdmission.Spec.InstallNamespace, common.FalconAdmissionController)
namespace := r.imageNamespace(falconAdmission)
imageStream := assets.ImageStream(imageStreamName, namespace, common.FalconAdmissionController)
existingImageStream := &imagev1.ImageStream{}

err := r.Get(ctx, types.NamespacedName{Name: imageStreamName, Namespace: falconAdmission.Spec.InstallNamespace}, existingImageStream)
err := r.Get(ctx, types.NamespacedName{Name: imageStreamName, Namespace: namespace}, existingImageStream)
if err != nil && apierrors.IsNotFound(err) {
err = k8sutils.Create(r.Client, r.Scheme, ctx, req, log, falconAdmission, &falconAdmission.Status, imageStream)
if err != nil {
Expand Down
87 changes: 69 additions & 18 deletions controllers/admission/image_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import (
"context"
"fmt"
"os"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

falconv1alpha1 "github.com/crowdstrike/falcon-operator/api/falcon/v1alpha1"
"github.com/crowdstrike/falcon-operator/internal/controller/image"
"github.com/crowdstrike/falcon-operator/pkg/aws"
"github.com/crowdstrike/falcon-operator/pkg/common"
"github.com/crowdstrike/falcon-operator/pkg/gcp"
"github.com/crowdstrike/falcon-operator/pkg/k8s_utils"
"github.com/crowdstrike/falcon-operator/pkg/registry/auth"
"github.com/crowdstrike/falcon-operator/pkg/registry/falcon_registry"
"github.com/crowdstrike/falcon-operator/pkg/registry/pushtoken"
"github.com/crowdstrike/gofalcon/falcon"
"github.com/go-logr/logr"
imagev1 "github.com/openshift/api/image/v1"
"k8s.io/apimachinery/pkg/api/meta"
)

Expand All @@ -25,6 +30,11 @@ func (r *FalconAdmissionReconciler) PushImage(ctx context.Context, log logr.Logg
return err
}

// If we have version locking enabled (as it is by default), use the already configured version if present
if r.versionLock(falconAdmission) {
return nil
}

pushAuth, err := r.pushAuth(ctx, falconAdmission)
if err != nil {
return err
Expand All @@ -34,22 +44,17 @@ func (r *FalconAdmissionReconciler) PushImage(ctx context.Context, log logr.Logg
image := image.NewImageRefresher(ctx, log, r.falconApiConfig(ctx, falconAdmission), pushAuth, falconAdmission.Spec.Registry.TLS.InsecureSkipVerify)
version := falconAdmission.Spec.Version

// If we have version locking enabled (as it is by default), use the already configured version if present
if r.versionLock(falconAdmission) {
return nil
}

tag, err := image.Refresh(registryUri, common.SensorTypeKac, version)
if err != nil {
return fmt.Errorf("Cannot push Falcon Container Image: %v", err)
return fmt.Errorf("Cannot push Falcon Admission Image: %v", err)
}

log.Info("Falcon Container Image pushed successfully", "Image.Tag", tag)
log.Info("Falcon Admission Controller Image pushed successfully", "Image.Tag", tag)
falconAdmission.Status.Sensor = &tag

imageUri, err := r.imageUri(ctx, falconAdmission)
if err != nil {
return fmt.Errorf("Cannot identify Falcon Container Image: %v", err)
return fmt.Errorf("Cannot identify Falcon Admission Image: %v", err)
}

meta.SetStatusCondition(&falconAdmission.Status.Conditions, metav1.Condition{
Expand Down Expand Up @@ -77,7 +82,7 @@ func (r *FalconAdmissionReconciler) verifyCrowdStrike(ctx context.Context, log l
return false, nil
}

log.Info("Skipping push of Falcon Container image to local registry. Remote CrowdStrike registry will be used.")
log.Info("Skipping push of Falcon Admission image to local registry. Remote CrowdStrike registry will be used.")
meta.SetStatusCondition(&falconAdmission.Status.Conditions, metav1.Condition{
Status: metav1.ConditionTrue,
Reason: falconv1alpha1.ReasonDiscovered,
Expand All @@ -90,12 +95,49 @@ func (r *FalconAdmissionReconciler) verifyCrowdStrike(ctx context.Context, log l
}

func (r *FalconAdmissionReconciler) registryUri(ctx context.Context, falconAdmission *falconv1alpha1.FalconAdmission) (string, error) {
cloud, err := falconAdmission.Spec.FalconAPI.FalconCloud(ctx)
if err != nil {
return "", err
}
switch falconAdmission.Spec.Registry.Type {
case falconv1alpha1.RegistryTypeOpenshift:
imageStream := &imagev1.ImageStream{}
err := r.Get(ctx, types.NamespacedName{Name: "falcon-admission-controller", Namespace: r.imageNamespace(falconAdmission)}, imageStream)
if err != nil {
return "", err
}

return falcon_registry.SensorImageURI(cloud, common.SensorTypeKac), nil
if imageStream.Status.DockerImageRepository == "" {
return "", fmt.Errorf("Unable to find route to OpenShift on-cluster registry. Please verify that OpenShift on-cluster registry is up and running.")
}

return imageStream.Status.DockerImageRepository, nil
case falconv1alpha1.RegistryTypeGCR:
projectId, err := gcp.GetProjectID()
if err != nil {
return "", fmt.Errorf("Cannot get GCP Project ID: %v", err)
}

return "gcr.io/" + projectId + "/falcon-kac", nil
case falconv1alpha1.RegistryTypeECR:
repo, err := aws.UpsertECRRepo(ctx, "falcon-kac")
if err != nil {
return "", fmt.Errorf("Cannot get target docker URI for ECR repository: %v", err)
}

return *repo.RepositoryUri, nil
case falconv1alpha1.RegistryTypeACR:
if falconAdmission.Spec.Registry.AcrName == nil {
return "", fmt.Errorf("Cannot push Falcon Image locally to ACR. acr_name was not specified")
}

return fmt.Sprintf("%s.azurecr.io/falcon-kac", *falconAdmission.Spec.Registry.AcrName), nil
case falconv1alpha1.RegistryTypeCrowdStrike:
cloud, err := falconAdmission.Spec.FalconAPI.FalconCloud(ctx)
if err != nil {
return "", err
}

return falcon_registry.SensorImageURI(cloud, common.SensorTypeKac), nil
default:
return "", fmt.Errorf("Unrecognized registry type: %s", falconAdmission.Spec.Registry.Type)
}
}

func (r *FalconAdmissionReconciler) imageUri(ctx context.Context, falconAdmission *falconv1alpha1.FalconAdmission) (string, error) {
Expand All @@ -115,7 +157,7 @@ func (r *FalconAdmissionReconciler) imageUri(ctx context.Context, falconAdmissio

imageTag, err := r.setImageTag(ctx, falconAdmission)
if err != nil {
return "", fmt.Errorf("failed to set Falcon Container Image version: %v", err)
return "", fmt.Errorf("failed to set Falcon Admission Image version: %v", err)
}

return fmt.Sprintf("%s:%s", registryUri, imageTag), nil
Expand All @@ -126,7 +168,7 @@ func (r *FalconAdmissionReconciler) getImageTag(ctx context.Context, falconAdmis
return *falconAdmission.Status.Sensor, nil
}

return "", fmt.Errorf("Unable to get falcon container version")
return "", fmt.Errorf("Unable to get falcon admission container image version")
}

func (r *FalconAdmissionReconciler) setImageTag(ctx context.Context, falconAdmission *falconv1alpha1.FalconAdmission) (string, error) {
Expand Down Expand Up @@ -167,10 +209,19 @@ func (r *FalconAdmissionReconciler) setImageTag(ctx context.Context, falconAdmis

func (r *FalconAdmissionReconciler) pushAuth(ctx context.Context, falconAdmission *falconv1alpha1.FalconAdmission) (auth.Credentials, error) {
return pushtoken.GetCredentials(ctx, falconAdmission.Spec.Registry.Type,
k8s_utils.QuerySecretsInNamespace(r.Client, falconAdmission.Spec.InstallNamespace),
k8s_utils.QuerySecretsInNamespace(r.Client, r.imageNamespace(falconAdmission)),
)
}

func (r *FalconAdmissionReconciler) imageNamespace(falconAdmission *falconv1alpha1.FalconAdmission) string {
if falconAdmission.Spec.Registry.Type == falconv1alpha1.RegistryTypeOpenshift {
// Within OpenShift, ImageStreams are separated by namespaces. The "openshift" namespace
// is shared and images pushed there can be referenced by deployments in other namespaces
return "openshift"
}
return falconAdmission.Spec.InstallNamespace
}

func (r *FalconAdmissionReconciler) falconApiConfig(ctx context.Context, falconAdmission *falconv1alpha1.FalconAdmission) *falcon.ApiConfig {
cfg := falconAdmission.Spec.FalconAPI.ApiConfig()
cfg.Context = ctx
Expand All @@ -183,5 +234,5 @@ func (r *FalconAdmissionReconciler) imageMirroringEnabled(falconAdmission *falco
}

func (r *FalconAdmissionReconciler) versionLock(falconAdmission *falconv1alpha1.FalconAdmission) bool {
return falconAdmission.Spec.Version != nil && falconAdmission.Status.Sensor != nil && *falconAdmission.Spec.Version == *falconAdmission.Status.Sensor
return (falconAdmission.Spec.Version != nil && falconAdmission.Status.Sensor != nil && strings.Contains(*falconAdmission.Status.Sensor, *falconAdmission.Spec.Version)) || (falconAdmission.Spec.Version == nil && falconAdmission.Status.Sensor != nil)
}
Loading

0 comments on commit cb3ab58

Please sign in to comment.