Skip to content

Commit

Permalink
Merge pull request #580 from CrowdStrike/mhyson/auto-sensor-update
Browse files Browse the repository at this point in the history
feat: automatic sensor updates
  • Loading branch information
mhyson-cs authored Aug 28, 2024
2 parents 012c124 + 7561a39 commit fe047cd
Show file tree
Hide file tree
Showing 33 changed files with 1,068 additions and 110 deletions.
3 changes: 0 additions & 3 deletions UNSAFE.md

This file was deleted.

6 changes: 0 additions & 6 deletions api/falcon/v1alpha1/falconadmission_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ type FalconAdmissionSpec struct {
// Falcon Admission Controller Version. The latest version will be selected when version specifier is missing. Example: 6.31, 6.31.0, 6.31.0-1409, etc.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon Admission Controller Version",order=8
Version *string `json:"version,omitempty"`

// FalconUnsafe configures various options that go against industry practices or are otherwise not recommended for use.
// Adjusting these settings may result in incorrect or undesirable behavior. Proceed at your own risk.
// For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon Admission Controller Unsafe Settings"
Unsafe FalconUnsafe `json:"unsafe,omitempty"`
}

type FalconAdmissionRQSpec struct {
Expand Down
43 changes: 43 additions & 0 deletions api/falcon/v1alpha1/unsafe.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
package v1alpha1

import "strings"

const (
Force = "force"
Normal = "normal"
Off = "off"
)

// FalconUnsafe configures various options that go against industry practices or are otherwise not recommended for use.
// Adjusting these settings may result in incorrect or undesirable behavior. Proceed at your own risk.
// For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
type FalconUnsafe struct {
// UpdatePolicy is the name of a sensor update policy configured and enabled in Falcon UI. It is ignored when Image and/or Version are set.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon Sensor Update Policy",order=1
UpdatePolicy *string `json:"updatePolicy,omitempty"`

// AutoUpdate determines whether to install new versions of the sensor as they become available. Defaults to "off" and is ignored if FalconAPI is not set.
// Setting this to "force" causes the reconciler to run on every polling cycle, even if a new sensor version is not available.
// Setting it to "normal" only reconciles when a new version is detected.
// +kubebuilder:validation:Enum=off;normal;force
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon Sensor Automatic Updates",order=2
AutoUpdate *string `json:"autoUpdate,omitempty"`
}

func (notSafe FalconUnsafe) GetUpdatePolicy() string {
if notSafe.UpdatePolicy == nil {
return ""
}

return strings.TrimSpace(*notSafe.UpdatePolicy)
}

func (notSafe FalconUnsafe) HasUpdatePolicy() bool {
return notSafe.GetUpdatePolicy() != ""
}

func (notSafe FalconUnsafe) IsAutoUpdating() bool {
if notSafe.AutoUpdate == nil {
return false
}

return *notSafe.AutoUpdate != "off"
}

func (notSafe FalconUnsafe) IsAutoUpdatingForced() bool {
if notSafe.AutoUpdate == nil {
return false
}

return *notSafe.AutoUpdate == "force"
}
6 changes: 5 additions & 1 deletion api/falcon/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,6 @@ func (in *FalconAdmissionSpec) DeepCopyInto(out *FalconAdmissionSpec) {
*out = new(string)
**out = **in
}
in.Unsafe.DeepCopyInto(&out.Unsafe)
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FalconAdmissionSpec.
Expand Down Expand Up @@ -1209,6 +1208,11 @@ func (in *FalconUnsafe) DeepCopyInto(out *FalconUnsafe) {
*out = new(string)
**out = **in
}
if in.AutoUpdate != nil {
in, out := &in.AutoUpdate, &out.AutoUpdate
*out = new(string)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FalconUnsafe.
Expand Down
16 changes: 13 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (

falconv1alpha1 "github.com/crowdstrike/falcon-operator/api/falcon/v1alpha1"
admissioncontroller "github.com/crowdstrike/falcon-operator/internal/controller/admission"
"github.com/crowdstrike/falcon-operator/internal/controller/common/sensorversion"
containercontroller "github.com/crowdstrike/falcon-operator/internal/controller/falcon_container"
imageanalyzercontroller "github.com/crowdstrike/falcon-operator/internal/controller/falcon_image_analyzer"
nodecontroller "github.com/crowdstrike/falcon-operator/internal/controller/falcon_node"
Expand All @@ -48,6 +49,8 @@ import (
// +kubebuilder:scaffold:imports
)

const defaultSensorAutoUpdateInterval = time.Hour * 24

var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
Expand All @@ -70,6 +73,7 @@ func main() {
var enableProfiling bool
var ver bool
var err error
var sensorAutoUpdateInterval time.Duration

flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
Expand All @@ -79,6 +83,7 @@ func main() {
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&ver, "version", false, "Print version")
flag.DurationVar(&sensorAutoUpdateInterval, "sensor-auto-update-interval", defaultSensorAutoUpdateInterval, "The rate at which the Falcon API is queried for new sensor versions")

if env := os.Getenv("ARGS"); env != "" {
os.Args = append(os.Args, strings.Split(env, " ")...)
Expand Down Expand Up @@ -182,18 +187,21 @@ func main() {
setupLog.Info("cert-manager installation not found")
}

ctx := ctrl.SetupSignalHandler()
tracker := sensorversion.NewTracker(ctx, sensorAutoUpdateInterval)

if err = (&containercontroller.FalconContainerReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
RestConfig: mgr.GetConfig(),
}).SetupWithManager(mgr); err != nil {
}).SetupWithManager(mgr, tracker); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "FalconContainer")
os.Exit(1)
}
if err = (&nodecontroller.FalconNodeSensorReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
}).SetupWithManager(mgr, tracker); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "FalconNodeSensor")
os.Exit(1)
}
Expand Down Expand Up @@ -240,8 +248,10 @@ func main() {
}()
}

go tracker.StartTracking()

setupLog.Info("starting manager", "version", version.Get(), "go version", version.GoVersion)
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
if err := mgr.Start(ctx); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
Expand Down
12 changes: 0 additions & 12 deletions config/crd/bases/falcon.crowdstrike.com_falconadmissions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -450,18 +450,6 @@ spec:
can be created in the namespace.
type: string
type: object
unsafe:
description: FalconUnsafe configures various options that go against
industry practices or are otherwise not recommended for use. Adjusting
these settings may result in incorrect or undesirable behavior.
Proceed at your own risk. For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when Image
and/or Version are set.
type: string
type: object
version:
description: 'Falcon Admission Controller Version. The latest version
will be selected when version specifier is missing. Example: 6.31,
Expand Down
12 changes: 12 additions & 0 deletions config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,18 @@ spec:
these settings may result in incorrect or undesirable behavior.
Proceed at your own risk. For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
autoUpdate:
description: AutoUpdate determines whether to install new versions
of the sensor as they become available. Defaults to "off" and
is ignored if FalconAPI is not set. Setting this to "force"
causes the reconciler to run on every polling cycle, even if
a new sensor version is not available. Setting it to "normal"
only reconciles when a new version is detected.
enum:
- "off"
- normal
- force
type: string
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when Image
Expand Down
12 changes: 12 additions & 0 deletions config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,18 @@ spec:
behavior. Proceed at your own risk. For more information, please
see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
autoUpdate:
description: AutoUpdate determines whether to install new
versions of the sensor as they become available. Defaults
to "off" and is ignored if FalconAPI is not set. Setting
this to "force" causes the reconciler to run on every polling
cycle, even if a new sensor version is not available. Setting
it to "normal" only reconciles when a new version is detected.
enum:
- "off"
- normal
- force
type: string
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when
Expand Down
36 changes: 24 additions & 12 deletions deploy/falcon-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -464,18 +464,6 @@ spec:
can be created in the namespace.
type: string
type: object
unsafe:
description: FalconUnsafe configures various options that go against
industry practices or are otherwise not recommended for use. Adjusting
these settings may result in incorrect or undesirable behavior.
Proceed at your own risk. For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when Image
and/or Version are set.
type: string
type: object
version:
description: 'Falcon Admission Controller Version. The latest version
will be selected when version specifier is missing. Example: 6.31,
Expand Down Expand Up @@ -2497,6 +2485,18 @@ spec:
these settings may result in incorrect or undesirable behavior.
Proceed at your own risk. For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
autoUpdate:
description: AutoUpdate determines whether to install new versions
of the sensor as they become available. Defaults to "off" and
is ignored if FalconAPI is not set. Setting this to "force"
causes the reconciler to run on every polling cycle, even if
a new sensor version is not available. Setting it to "normal"
only reconciles when a new version is detected.
enum:
- "off"
- normal
- force
type: string
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when Image
Expand Down Expand Up @@ -3534,6 +3534,18 @@ spec:
behavior. Proceed at your own risk. For more information, please
see https://github.com/CrowdStrike/falcon-operator/blob/main/UNSAFE.md.
properties:
autoUpdate:
description: AutoUpdate determines whether to install new
versions of the sensor as they become available. Defaults
to "off" and is ignored if FalconAPI is not set. Setting
this to "force" causes the reconciler to run on every polling
cycle, even if a new sensor version is not available. Setting
it to "normal" only reconciles when a new version is detected.
enum:
- "off"
- normal
- force
type: string
updatePolicy:
description: UpdatePolicy is the name of a sensor update policy
configured and enabled in Falcon UI. It is ignored when
Expand Down
29 changes: 29 additions & 0 deletions docs/UNSAFE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Unsafe Settings

Some of the operator's configurable settings involve features that conflict with established industry norms. These options are disabled by default as they carry a certain amount of risk, but they can be enabled in the `unsafe` section of each resource spec. What follows is a brief overview of the issues surrounding their use.

## The Golden Rule of Kubernetes

A fundamental principle underlying all Kubernetes operation is repeatability. Any given configuration should always produce the same result regardless of when or where it is applied or by whom. Another way of saying this is that a cluster should only ever do something because somebody explicitly called for it to happen. Anything that has variable behavior introduces uncertainty into the environment, and this can lead to problems that are difficult to diagnose.

A common example is the use of image tags. These operate like pointers with many of the same concerns. The image they refer to can change without warning, and that can cause trouble.

Consider a container spec that uses `nginx:latest`. What exactly will this deploy? Some version of nginx, presumably, but which version? What if it's not the version expected by the rest of the system? What if it's incompatible with other things in the cluster? Maybe everything works fine today, but what if tomorrow the container is moved to a different node? This tears down the old one and launches a new one. What if `latest` has changed to something new that breaks everything? There's no way to detect this beforehand.

It is for these reasons and others that such practices are discouraged. A better approach given the above scenario is to use explicit image hashes. Instead of `nginx:latest`, one could use `nginx@sha256:447a8665...`. This uniquely identifies a particular version and package of nginx. It will never be anything else. All of the questions raised above become irrelevant. It is known what version will be deployed. It is known it will be the expected version. It is known new containers won't use anything else. It is safe.

## Falcon's Unsafe Options

Only some of the resources provided by the operator have unsafe properties. Each keeps them in slightly different places:

* `spec.unsafe` for FalconContainer
* `spec.node.unsafe` for FalconNodeSensor

Any options that go against recommended practices can be found here. Presently, that includes settings that affect the selection of Falcon sensor versions, which brings all of the issues of image tags described above. Details on these settings can be found in the respective resource documents.

## More Information

The issues around unsafe settings can be quite involved. The following are other resources that go into greater depth:

* [Attack of the Mutant Tags! Or Why Tag Mutability is a Real Security Threat](https://sysdig.com/blog/toctou-tag-mutability/)
* [How to Ensure Consistent Kubernetes Container Versions](https://www.gremlin.com/blog/kubernetes-container-image-version-uniformity)
11 changes: 11 additions & 0 deletions docs/deployment/openshift/resources/container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ spec:
| falcon.tags | (optional) Configure Falcon Sensor Grouping Tags; comma-delimited |
| falcon.trace | (optional) Configure Falcon Sensor Trace Logging Level (none, err, warn, info, debug) |

#### Unsafe Settings
The following settings provide an alternative means to select which version of Falcon sensor is deployed. Their use is not recommended. Instead, an explicit SHA256 hash should be configured using the `image` property above.

See `docs/UNSAFE.md` for more details.

| Spec | Default Value | Description |
| :- | :- | :- |
| unsafe.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:<ul><li>`force` -- Reconciles the resource after every check for a new version</li><li>`normal` -- Reconciles the resource whenever a new version is detected</li><li>`off` -- No automatic updates</li></ul>
| unsafe.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |

#### Status Conditions
| Status | Description |
| :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| conditions.["NamespaceReady"] | Displays the most recent reconciliation operation for the Namespace used by the Falcon Container Sensor (Created, Updated, Deleted) |
Expand Down
10 changes: 10 additions & 0 deletions docs/deployment/openshift/resources/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ spec:
| falcon.tags | (optional) Sensor grouping tags are optional, user-defined identifiers that can used to group and filter hosts. Allowed characters: all alphanumerics, '/', '-', and '_'. |
| falcon.trace | (optional) Set sensor trace level. |

#### Unsafe Settings
The following settings provide an alternative means to select which version of Falcon sensor is deployed. Their use is not recommended. Instead, an explicit SHA256 hash should be configured using the `node.image` property above.

See `docs/UNSAFE.md` for more details.

| Spec | Default Value | Description |
| :- | :- | :- |
| node.unsafe.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:<ul><li>`force` -- Reconciles the resource after every check for a new version</li><li>`normal` -- Reconciles the resource whenever a new version is detected</li><li>`off` -- No automatic updates</li></ul>
| node.unsafe.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |

> [!IMPORTANT]
> All arguments are optional, but successful deployment requires either **client_id and falcon_secret or the Falcon cid and image**. When deploying using the CrowdStrike Falcon API, the container image and CID will be fetched from CrowdStrike Falcon API. While in the latter case, the CID and image location is explicitly specified by the user.

Expand Down
Loading

0 comments on commit fe047cd

Please sign in to comment.