Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow sidecar sensor to customize namespace #537

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/falcon/v1alpha1/falconcontainer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ type FalconContainerSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Namespace where the Falcon Sensor should be installed.
// For best security practices, this should be a dedicated namespace that is not used for any other purpose.
// It also should not be the same namespace where the Falcon Operator, or other Falcon resources are deployed.
// +kubebuilder:default:=falcon-system
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=1,xDescriptors={"urn:alm:descriptor:io.kubernetes:Namespace"}
InstallNamespace string `json:"installNamespace,omitempty"`

// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon Sensor Configuration",order=1
Falcon FalconSensor `json:"falcon,omitempty"`
// FalconAPI configures connection from your local Falcon operator to CrowdStrike Falcon platform.
Expand Down
8 changes: 8 additions & 0 deletions config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,14 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
installNamespace:
default: falcon-system
description: Namespace where the Falcon Sensor should be installed.
For best security practices, this should be a dedicated namespace
that is not used for any other purpose. It also should not be the
same namespace where the Falcon Operator, or other Falcon resources
are deployed.
type: string
registry:
description: Registry configures container image registry to which
the Falcon Container image will be pushed
Expand Down
8 changes: 8 additions & 0 deletions deploy/falcon-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2437,6 +2437,14 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
installNamespace:
default: falcon-system
description: Namespace where the Falcon Sensor should be installed.
For best security practices, this should be a dedicated namespace
that is not used for any other purpose. It also should not be the
same namespace where the Falcon Operator, or other Falcon resources
are deployed.
type: string
registry:
description: Registry configures container image registry to which
the Falcon Container image will be pushed
Expand Down
1 change: 1 addition & 0 deletions docs/deployment/openshift/resources/container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ spec:
#### Sidecar Injection Configuration Settings
| Spec | Description |
| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| installNamespace | (optional) Override the default namespace of falcon-sidecar |
| image | (optional) Leverage a Falcon Container Sensor image that is not managed by the operator; typically used with custom repositories; overrides all registry settings; might require injector.imagePullSecretName to be set |
| version | (optional) Enforce particular Falcon Container version to be installed (example: "6.31", "6.31.0", "6.31.0-1409") |
| registry.type | Registry to mirror Falcon Container (allowed values: acr, ecr, crowdstrike, gcr, openshift) |
Expand Down
1 change: 1 addition & 0 deletions docs/resources/container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ spec:
#### Sidecar Injection Configuration Settings
| Spec | Description |
| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| installNamespace | (optional) Override the default namespace of falcon-sidecar |
| image | (optional) Leverage a Falcon Container Sensor image that is not managed by the operator; typically used with custom repositories; overrides all registry settings; might require injector.imagePullSecretName to be set |
| version | (optional) Enforce particular Falcon Container version to be installed (example: "6.31", "6.31.0", "6.31.0-1409") |
| registry.type | Registry to mirror Falcon Container (allowed values: acr, ecr, crowdstrike, gcr, openshift) |
Expand Down
1 change: 1 addition & 0 deletions docs/src/resources/container.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ spec:
#### Sidecar Injection Configuration Settings
| Spec | Description |
| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| installNamespace | (optional) Override the default namespace of falcon-sidecar |
| image | (optional) Leverage a Falcon Container Sensor image that is not managed by the operator; typically used with custom repositories; overrides all registry settings; might require injector.imagePullSecretName to be set |
| version | (optional) Enforce particular Falcon Container version to be installed (example: "6.31", "6.31.0", "6.31.0-1409") |
| registry.type | Registry to mirror Falcon Container (allowed values: acr, ecr, crowdstrike, gcr, openshift) |
Expand Down
8 changes: 4 additions & 4 deletions internal/controller/falcon_container/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (r *FalconContainerReconciler) reconcileGenericConfigMap(name string, genFu
return configMap, fmt.Errorf("unable to render expected configmap: %v", err)
}
existingConfigMap := &corev1.ConfigMap{}
err = r.Client.Get(ctx, types.NamespacedName{Name: name, Namespace: r.Namespace()}, existingConfigMap)
err = r.Client.Get(ctx, types.NamespacedName{Name: name, Namespace: falconContainer.Spec.InstallNamespace}, existingConfigMap)
if err != nil {
if errors.IsNotFound(err) {
if err = ctrl.SetControllerReference(falconContainer, configMap, r.Scheme); err != nil {
Expand All @@ -55,14 +55,14 @@ func (r *FalconContainerReconciler) newCABundleConfigMap(ctx context.Context, lo
if falconContainer.Spec.Registry.TLS.CACertificate != "" {
data["tls.crt"] = string(common.DecodeBase64Interface(falconContainer.Spec.Registry.TLS.CACertificate))

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

func (r *FalconContainerReconciler) newConfigMap(ctx context.Context, log logr.Logger, falconContainer *falconv1alpha1.FalconContainer) (*corev1.ConfigMap, error) {
data := common.MakeSensorEnvMap(falconContainer.Spec.Falcon)
data["CP_NAMESPACE"] = r.Namespace()
data["CP_NAMESPACE"] = falconContainer.Spec.InstallNamespace
data["FALCON_INJECTOR_LISTEN_PORT"] = strconv.Itoa(int(*falconContainer.Spec.Injector.ListenPort))

imageUri, err := r.imageUri(ctx, falconContainer)
Expand Down Expand Up @@ -117,5 +117,5 @@ func (r *FalconContainerReconciler) newConfigMap(ctx context.Context, log logr.L
}
}

return assets.SensorConfigMap(injectorConfigMapName, r.Namespace(), common.FalconSidecarSensor, data), nil
return assets.SensorConfigMap(injectorConfigMapName, falconContainer.Spec.InstallNamespace, common.FalconSidecarSensor, data), nil
}
22 changes: 20 additions & 2 deletions internal/controller/falcon_container/falconcontainer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ func (r *FalconContainerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
}
}

validate, err := k8sutils.CheckRunningPodLabels(r.Client, ctx, falconContainer.Spec.InstallNamespace, common.CRLabels("deployment", injectorName, common.FalconSidecarSensor))
if err != nil {
return ctrl.Result{}, err
}
if !validate {
err = r.StatusUpdate(ctx, req, log, falconContainer,
falconv1alpha1.ConditionFailed,
metav1.ConditionFalse,
falconv1alpha1.ReasonReqNotMet,
"FalconContainer must not be installed in a namespace with other workloads running. Please change the namespace in the CR configuration.",
)
if err != nil {
return ctrl.Result{}, err
}
log.Error(nil, "FalconContainer is attempting to install in a namespace with existing pods. Please update the CR configuration to a namespace that does not have workoads already running.", "namespace", falconContainer.Spec.InstallNamespace, "labels", common.CRLabels("deployment", falconContainer.Name, common.FalconSidecarSensor))
return ctrl.Result{}, nil
}

if falconContainer.Status.Version != version.Get() {
falconContainer.Status.Version = version.Get()
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
Expand Down Expand Up @@ -250,7 +268,7 @@ func (r *FalconContainerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
return ctrl.Result{}, fmt.Errorf("failed to reconcile injector Service: %v", err)
}

pod, err := k8sutils.GetReadyPod(r.Client, ctx, r.Namespace(), map[string]string{common.FalconComponentKey: common.FalconSidecarSensor})
pod, err := k8sutils.GetReadyPod(r.Client, ctx, falconContainer.Spec.InstallNamespace, map[string]string{common.FalconComponentKey: common.FalconSidecarSensor})
if err != nil && err.Error() != "No webhook service pod found in a Ready state" {
err = r.StatusUpdate(ctx, req, log, falconContainer, falconv1alpha1.ConditionFailed, metav1.ConditionFalse, "Reconciling", fmt.Sprintf("failed to find Ready injector pod: %v", err))
if err != nil {
Expand All @@ -259,7 +277,7 @@ func (r *FalconContainerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
return ctrl.Result{}, fmt.Errorf("failed to find Ready injector pod: %v", err)
}
if pod.Name == "" {
log.Info("Looking for a Ready injector pod", "namespace", r.Namespace())
log.Info("Looking for a Ready injector pod", "namespace", falconContainer.Spec.InstallNamespace)
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/controller/falcon_container/image_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func (r *FalconContainerReconciler) imageNamespace(falconContainer *falconv1alph
// is shared and images pushed there can be referenced by deployments in other namespaces
return "openshift"
}
return r.Namespace()
return falconContainer.Spec.InstallNamespace
}

func (r *FalconContainerReconciler) falconApiConfig(ctx context.Context, falconContainer *falconv1alpha1.FalconContainer) *falcon.ApiConfig {
Expand Down
14 changes: 7 additions & 7 deletions internal/controller/falcon_container/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const (

func (r *FalconContainerReconciler) reconcileInjectorTLSSecret(ctx context.Context, log logr.Logger, falconContainer *falconv1alpha1.FalconContainer) (*corev1.Secret, error) {
existingInjectorTLSSecret := &corev1.Secret{}
err := r.Client.Get(ctx, types.NamespacedName{Name: injectorTLSSecretName, Namespace: r.Namespace()}, existingInjectorTLSSecret)
err := r.Client.Get(ctx, types.NamespacedName{Name: injectorTLSSecretName, Namespace: falconContainer.Spec.InstallNamespace}, existingInjectorTLSSecret)
if err != nil {
if errors.IsNotFound(err) {
validity := 3650
Expand All @@ -38,11 +38,11 @@ func (r *FalconContainerReconciler) reconcileInjectorTLSSecret(ctx context.Conte
}

certInfo := tls.CertInfo{
CommonName: fmt.Sprintf("%s.%s.svc", injectorName, r.Namespace()),
DNSNames: []string{fmt.Sprintf("%s.%s.svc", injectorName, r.Namespace()), fmt.Sprintf("%s.%s.svc.cluster.local", injectorName, r.Namespace())},
CommonName: fmt.Sprintf("%s.%s.svc", injectorName, falconContainer.Spec.InstallNamespace),
DNSNames: []string{fmt.Sprintf("%s.%s.svc", injectorName, falconContainer.Spec.InstallNamespace), fmt.Sprintf("%s.%s.svc.cluster.local", injectorName, falconContainer.Spec.InstallNamespace)},
}

c, k, b, err := tls.CertSetup(r.Namespace(), validity, certInfo)
c, k, b, err := tls.CertSetup(falconContainer.Spec.InstallNamespace, validity, certInfo)
if err != nil {
return &corev1.Secret{}, fmt.Errorf("failed to generate Falcon Container PKI: %v", err)
}
Expand All @@ -51,7 +51,7 @@ func (r *FalconContainerReconciler) reconcileInjectorTLSSecret(ctx context.Conte
"tls.key": k,
"ca.crt": b,
}
injectorTLSSecret := assets.Secret(injectorTLSSecretName, r.Namespace(), common.FalconSidecarSensor, secretData, corev1.SecretTypeTLS)
injectorTLSSecret := assets.Secret(injectorTLSSecretName, falconContainer.Spec.InstallNamespace, common.FalconSidecarSensor, secretData, corev1.SecretTypeTLS)
if err = ctrl.SetControllerReference(falconContainer, injectorTLSSecret, r.Scheme); err != nil {
return &corev1.Secret{}, fmt.Errorf("unable to set controller reference on injector TLS Secret%s: %v", injectorTLSSecret.ObjectMeta.Name, err)
}
Expand All @@ -71,7 +71,7 @@ func (r *FalconContainerReconciler) reconcileDeployment(ctx context.Context, log
return &appsv1.Deployment{}, fmt.Errorf("unable to determine falcon container image URI: %v", err)
}

deployment := assets.SideCarDeployment(injectorName, r.Namespace(), common.FalconSidecarSensor, imageUri, falconContainer)
deployment := assets.SideCarDeployment(injectorName, falconContainer.Spec.InstallNamespace, common.FalconSidecarSensor, imageUri, falconContainer)
existingDeployment := &appsv1.Deployment{}

if len(proxy.ReadProxyVarsFromEnv()) > 0 {
Expand All @@ -80,7 +80,7 @@ func (r *FalconContainerReconciler) reconcileDeployment(ctx context.Context, log
}
}

err = r.Client.Get(ctx, types.NamespacedName{Name: injectorName, Namespace: r.Namespace()}, existingDeployment)
err = r.Client.Get(ctx, types.NamespacedName{Name: injectorName, Namespace: falconContainer.Spec.InstallNamespace}, existingDeployment)
if err != nil {
if errors.IsNotFound(err) {
if err = ctrl.SetControllerReference(falconContainer, deployment, r.Scheme); err != nil {
Expand Down
24 changes: 8 additions & 16 deletions internal/controller/falcon_container/ns.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,55 +14,47 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
)

const (
injectorNamespace = "falcon-system"
)

var (
namespaceLabels = map[string]string{
common.FalconContainerInjection: "disabled",
"kubernetes.io/metadata.name": "falcon-system",
}
)

func (r *FalconContainerReconciler) Namespace() string {
return injectorNamespace
}

func (r *FalconContainerReconciler) NamespaceLabels() map[string]string {
nsLabels := common.CRLabels("namespace", r.Namespace(), common.FalconSidecarSensor)
func (r *FalconContainerReconciler) NamespaceLabels(falconContainer *falconv1alpha1.FalconContainer) map[string]string {
nsLabels := common.CRLabels("namespace", falconContainer.Spec.InstallNamespace, common.FalconSidecarSensor)
for k, v := range namespaceLabels {
nsLabels[k] = v
}
return nsLabels
}

func (r *FalconContainerReconciler) reconcileNamespace(ctx context.Context, log logr.Logger, falconContainer *falconv1alpha1.FalconContainer) (*corev1.Namespace, error) {
namespace := r.newNamespace()
namespace := r.newNamespace(falconContainer)
existingNamespace := &corev1.Namespace{}
err := r.Client.Get(ctx, types.NamespacedName{Name: r.Namespace()}, existingNamespace)
err := r.Client.Get(ctx, types.NamespacedName{Name: falconContainer.Spec.InstallNamespace}, existingNamespace)
if err != nil {
if errors.IsNotFound(err) {
if err = ctrl.SetControllerReference(falconContainer, namespace, r.Scheme); err != nil {
return &corev1.Namespace{}, fmt.Errorf("unable to set controller reference on namespace %s: %v", namespace.ObjectMeta.Name, err)
}
return namespace, r.Create(ctx, log, falconContainer, namespace)
}
return &corev1.Namespace{}, fmt.Errorf("unable to query existing namespace %s: %v", r.Namespace(), err)
return &corev1.Namespace{}, fmt.Errorf("unable to query existing namespace %s: %v", falconContainer.Spec.InstallNamespace, err)
}

return existingNamespace, nil
}

func (r *FalconContainerReconciler) newNamespace() *corev1.Namespace {
func (r *FalconContainerReconciler) newNamespace(falconContainer *falconv1alpha1.FalconContainer) *corev1.Namespace {
return &corev1.Namespace{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: r.Namespace(),
Labels: r.NamespaceLabels(),
Name: falconContainer.Spec.InstallNamespace,
Labels: r.NamespaceLabels(falconContainer),
},
}
}
6 changes: 3 additions & 3 deletions internal/controller/falcon_container/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (r *FalconContainerReconciler) reconcileServiceAccount(ctx context.Context,
update := false
serviceAccount := r.newServiceAccount(falconContainer)
existingServiceAccount := &corev1.ServiceAccount{}
err := r.Client.Get(ctx, types.NamespacedName{Name: common.SidecarServiceAccountName, Namespace: r.Namespace()}, existingServiceAccount)
err := r.Client.Get(ctx, types.NamespacedName{Name: common.SidecarServiceAccountName, Namespace: falconContainer.Spec.InstallNamespace}, existingServiceAccount)
if err != nil {
if errors.IsNotFound(err) {
if err = ctrl.SetControllerReference(falconContainer, serviceAccount, r.Scheme); err != nil {
Expand Down Expand Up @@ -94,7 +94,7 @@ func (r *FalconContainerReconciler) newServiceAccount(falconContainer *falconv1a
},
ObjectMeta: metav1.ObjectMeta{
Name: common.SidecarServiceAccountName,
Namespace: r.Namespace(),
Namespace: falconContainer.Spec.InstallNamespace,
Labels: common.CRLabels("serviceaccount", common.SidecarServiceAccountName, common.FalconSidecarSensor),
Annotations: falconContainer.Spec.Injector.ServiceAccount.Annotations,
},
Expand All @@ -115,7 +115,7 @@ func (r *FalconContainerReconciler) newClusterRoleBinding(falconContainer *falco
Subjects: []rbacv1.Subject{{
Kind: "ServiceAccount",
Name: common.SidecarServiceAccountName,
Namespace: r.Namespace(),
Namespace: falconContainer.Spec.InstallNamespace,
}},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Expand Down
Loading
Loading