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

Support complex scenarios for the Behaviormodeling mode #163

Merged
merged 22 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf683d3
Add StorageType field in the ArmorProfileModelData structure
Danny-Wei Jan 26, 2025
ddab0a8
feat: Save the behavior data and profiles into a local file when the …
Danny-Wei Jan 26, 2025
01b3bbe
Authorize varmor-manager to create subjectaccessreviews
Danny-Wei Feb 6, 2025
a767c9b
feat: Support export the complete ArmorProfileModel object from the m…
Danny-Wei Feb 6, 2025
7323030
fix: Validate the file name that comes from client
Danny-Wei Feb 6, 2025
4f9abd8
Add the storageType field of ArmorProfileModel to the additional prin…
Danny-Wei Feb 6, 2025
bb858db
Always validate the permission of the client
Danny-Wei Feb 6, 2025
b2e4ffe
refactor: Add the apm internal package
Danny-Wei Feb 6, 2025
39b06fd
feat: load profiles from the local file if the StorageType field of A…
Danny-Wei Feb 6, 2025
7da5281
Refactor: Adjust the location of the StatusService interface
Danny-Wei Feb 7, 2025
b979de8
refactor: Move the storageType field outside of the ArmorProfileModel…
Danny-Wei Feb 7, 2025
eab090e
Return directly if the profiles are too large to create or update the…
Danny-Wei Feb 7, 2025
49a9900
fix: Access to classifier through the varmor-classifier-svc service w…
Danny-Wei Feb 8, 2025
6522d93
Mount a data volume when the behavior modeling feature is enabled
Danny-Wei Feb 8, 2025
cb7e35c
fix: Correct ArmorProfileModelPath namespace spelling to plural
Danny-Wei Feb 8, 2025
da05d02
Fix unit test
Danny-Wei Feb 8, 2025
1c94b0c
Persist the object into the backend storage if RPC resource is exhausted
Danny-Wei Feb 8, 2025
22d3436
feat: Optimize the handling logic for request size errors during Armo…
Danny-Wei Feb 9, 2025
37688b7
docs: Document the support for the Behaviormodeling feature in comple…
Danny-Wei Feb 10, 2025
efda4a5
Fix typo
Danny-Wei Feb 10, 2025
f8b9ae4
feat: Cache audit data in an emptyDir volume during modeling
Danny-Wei Feb 11, 2025
2a186e8
Fix unit test
Danny-Wei Feb 11, 2025
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
17 changes: 13 additions & 4 deletions apis/varmor/v1beta1/armorprofilemodel_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,16 @@ type DynamicResult struct {
type StaticResult struct {
}

type StorageType string

// ArmorProfileModelData defines the behavior model and the profile
type ArmorProfileModelData struct {
// DynamicResult stores the behavior data that has been collected with the BehaviorModeling mode.
DynamicResult DynamicResult `json:"dynamicResult,omitempty"`
StaticResult StaticResult `json:"staticResult,omitempty"`
Profile Profile `json:"profile,omitempty"`
// StaticResult stores the static analysis data.
StaticResult StaticResult `json:"staticResult,omitempty"`
// Profile stores the AppArmor and Seccomp profiles that are generate from the DynamicResult and StaticResult.
Profile Profile `json:"profile,omitempty"`
}

type ArmorProfileModelConditionType string
Expand Down Expand Up @@ -113,6 +118,7 @@ type ArmorProfileModelStatus struct {
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="STORAGE-TYPE",type=string,JSONPath=`.storageType`
//+kubebuilder:printcolumn:name="DESIRED",type=integer,JSONPath=`.status.desiredNumber`
//+kubebuilder:printcolumn:name="COMPLETED",type=integer,JSONPath=`.status.completedNumber`
//+kubebuilder:printcolumn:name="READY",type=boolean,JSONPath=`.status.ready`
Expand All @@ -123,8 +129,11 @@ type ArmorProfileModel struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Data ArmorProfileModelData `json:"data"`
Status ArmorProfileModelStatus `json:"status,omitempty"`
// StorageType indicates which storage type to use to save the DynamicResult, StaticResult and profiles.
// Possible values: CRDInternal, LocalDisk
StorageType StorageType `json:"storageType,omitempty"`
Data ArmorProfileModelData `json:"data"`
Status ArmorProfileModelStatus `json:"status,omitempty"`
}

//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
1 change: 1 addition & 0 deletions cmd/varmor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ func main() {
kubeClient.AppsV1(),
varmorClient.CrdV1beta1(),
kubeClient.AuthenticationV1(),
kubeClient.AuthorizationV1(),
statusUpdateCycle,
metricsModule,
log.Log.WithName("STATUS-SERVICE"),
Expand Down
13 changes: 13 additions & 0 deletions config/crds/crd.varmor.org_armorprofilemodels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ spec:
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .storageType
name: STORAGE-TYPE
type: string
- jsonPath: .status.desiredNumber
name: DESIRED
type: integer
Expand Down Expand Up @@ -43,6 +46,8 @@ spec:
profile
properties:
dynamicResult:
description: DynamicResult stores the behavior data that has been
collected with the BehaviorModeling mode.
properties:
apparmor:
properties:
Expand Down Expand Up @@ -140,6 +145,8 @@ spec:
type: object
type: object
profile:
description: Profile stores the AppArmor and Seccomp profiles that
are generate from the DynamicResult and StaticResult.
properties:
bpfContent:
properties:
Expand Down Expand Up @@ -303,6 +310,7 @@ spec:
- name
type: object
staticResult:
description: StaticResult stores the static analysis data.
type: object
type: object
kind:
Expand Down Expand Up @@ -355,6 +363,11 @@ spec:
required:
- ready
type: object
storageType:
description: 'StorageType indicates which storage type to use to save
the DynamicResult, StaticResult and profiles. Possible values: CRDInternal,
LocalDisk'
type: string
required:
- data
type: object
Expand Down
6 changes: 6 additions & 0 deletions config/k8s-resource/rbac/manager-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,9 @@ rules:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
7 changes: 7 additions & 0 deletions config/manifest/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,10 @@ spec:
- containerPort: 8080
name: status
protocol: TCP
volumeMounts:
- mountPath: /var/log/varmor/data
name: data-volume
volumes:
- emptyDir:
sizeLimit: 500Mi
name: data-volume
164 changes: 164 additions & 0 deletions docs/guides/policies_and_rules/policy_modes/behavior_modeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
English | [简体中文](behavior_modeling.zh_CN.md)

## Introduction

The BehaviorModeling mode is an experimental feature. You can utilize the BehaviorModeling mode to gather behavior data of the target workloads over a specified duration. Once the modeling is completed, vArmor will generate an [ArmorProfileModel](https://github.com/bytedance/vArmor/blob/main/apis/varmor/v1beta1/armorprofilemodel_types.go) object to store the model of the target workloads.

The model generated by the BehaviorModeling mode can also be used to analyze which built-in rules can be applied to harden the target application. Or guide to minimize the securityContext configurations of workload.
Expand All @@ -16,7 +17,11 @@ vArmor currently leverages a built-in BPF tracer and the Linux audit system to c
The requirements for the BehaviorModeling mode are as follows.

1. containerd v1.6.0 and above.

2. BTF (BPF Type Format) must be enabled.

In general, when a node has a file `/sys/kernel/btf/vmlinux`, it means that the system supports BTF.

3. Upgrade vArmor
* Enable the BehaviorModeling feature with `--set behaviorModeling.enabled=true`

Expand Down Expand Up @@ -44,8 +49,165 @@ The requirements for the BehaviorModeling mode are as follows.
memory: 500Mi
```

## Usage Instructions

### Basic Usage

The basic steps to use the BehaviorModeling feature are as follows.

**1. Create a policy with BehaviorModeling mode**

You can set the modeling duration through the `.spec.policy.modelingOptions.duration` field and adjust it as needed before the modeling is completed. You can also set whether to roll restart target workloads through the `.spec.updateExistingWorkloads` field (only target workloads of Deployment, DaemonSet, StatefulSet types are supported) to start behavioral modeling immediately.

```yaml
apiVersion: crd.varmor.org/v1beta1
kind: VarmorPolicy
metadata:
name: demo-4
namespace: demo
spec:
# Perform a rolling update on existing workloads.
# It's disabled by default.
updateExistingWorkloads: true
target:
kind: Deployment
selector:
matchLabels:
app: demo-4
policy:
enforcer: AppArmorSeccomp
# Note: Switching the mode from BehaviorModeling to others is prohibited, and vice versa.
# You need recraete the policy to switch the mode from BehaviorModeling to DefenseInDepth.
# mode: DefenseInDepth
mode: BehaviorModeling
modelingOptions:
# The duration in minutes to modeling
duration: 3
```

**2. Create target workloads**

You can skip this step if `updateExistingWorkloads=true` and the target workload type is not Pod. Otherwise, you should create a new target workloads.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-4
namespace: demo
labels:
app: demo-4
# This label is required with target workloads.
# You can disable the feature with --set 'manager.args={--webhookMatchLabel=}'
sandbox.varmor.org/enable: "true"
spec:
replicas: 2
selector:
matchLabels:
app: demo-4
template:
metadata:
labels:
app: demo-4
annotations:
# Use these annotation to explicitly disable the protection for the container named c0.
# It always takes precedence over the '.spec.target.containers' field of VarmorPolicy
# or VarmorClusterPolicy object.
container.apparmor.security.beta.varmor.org/c0: unconfined
container.seccomp.security.beta.varmor.org/c0: unconfined
spec:
shareProcessNamespace: true
containers:
- name: c0
image: curlimages/curl:7.87.0
command: ["/bin/sh", "-c", "sleep infinity"]
imagePullPolicy: IfNotPresent
- name: c1
image: debian:10
command: ["/bin/sh", "-c", "sleep infinity"]
imagePullPolicy: IfNotPresent
```

**3. Update modeling duration (on demand)**

You can modify the modeling duration as needed by updating the ".spec.policy.modelingOptions.duration" field of the policy. For example, change it to 1 to end the modeling prematurely.

```bash
kubectl patch vpol -n demo demo-4 --type='json' -p='[{"op": "replace", "path": "/spec/policy/modelingOptions/duration", "value":1}]'
```

**4. Wait for the modeling to complete**

```bash
$ kubectl get vpol -n demo
NAME ENFORCER MODE TARGET-KIND TARGET-NAME TARGET-SELECTOR PROFILE-NAME READY STATUS AGE
demo-4 AppArmorSeccomp BehaviorModeling Deployment {"matchLabels":{"app":"demo-4"}} varmor-demo-demo-4 true Modeling 2s

$ kubectl get vpol -n demo
NAME ENFORCER MODE TARGET-KIND TARGET-NAME TARGET-SELECTOR PROFILE-NAME READY STATUS AGE
demo-4 AppArmorSeccomp BehaviorModeling Deployment {"matchLabels":{"app":"demo-4"}} varmor-demo-demo-4 true Completed 30m
```

After the modeling is complete, the agent preprocesses the behavioral data collected in the node (only for the target workload) and sends it to the manager. The manager will analyze the data collected by all nodes and save it in the `.data.dynamicResult` field of the [ArmorProfileModel](https://github.com/bytedance/vArmor/blob/main/apis/varmor/v1beta1/armorprofilemodel_types.go) object in the corresponding namespace.

After the manager has processed the behavioral data for all nodes, it generates an AppArmor or Seccomp Profile for the target workload in an allowlist fashion (Deny-by-Default) and saves it in the `.data.profile.content` and `.data.profile.seccompContent` fields of the ArmorProfileModel object (encoded in base64).

When the amount of data is too large to be saved in the CRD object, the manager saves it locally. You can determine how the behavioral data and profiles are stored by using the `.storageType` field of the ArmorProfileModel object.

```bash
$ kubectl get ArmorProfileModel -A
NAMESPACE NAME STORAGE-TYPE DESIRED COMPLETED READY AGE
demo varmor-cluster-demo-demo-4 CRDInternal 2 2 true 23h
```

### Points to Note

* The target workload needs to have a `sandbox.varmor.org/enable="true"` label. You can turn this off via the [Set matching tags for webhooks](../../../getting_started/installation.md#set-the-match-label-of-webhook) configuration option.
* Switching policies in BehaviorModeling mode to others and vice versa is not supported. You need to delete the policy and recreate the policy to switch.
* After the modeling is completed, it is not supported to modify the modeling duration of the policy. You need to delete the policy and recreate the policy before you can start modeling again, but the existing behavioral data will be preserved.

### Data Export

You can export the behavior data and profiles of the target workloads for other purposes. For example, use [Policy Advisor](../../policy_advisor.md) to analyze which built-in rules can be used to enforce the target workloads, guide users to minimize permissions for the security context of the workload based on the behavior data, etc.

Different storage types have different methods for exporting ArmorProfileModel objects:

* **CRDInternal**

- Export directly using kubectl

```bash
kubectl get ArmorProfileModel -n demo varmor-demo-demo-4 -o json > varmor-demo-demo-4.json
```

* **LocalDisk**

- Forward local port 8080 to port 8080 of the cluster varmor-state-svc Service

```bash
kubectl port-forward -n varmor service/varmor-status-svc 8080:8080
```

- Request a ServiceAccount token of varmor-manager

```bash
token=$(kubectl create token varmor-manager -n varmor)
```

- Access the `/apis/crd.varmor.org/v1beta1/namespaces/{namespace}/armorprofilemodels/{name}` interface to export data

```bash
curl -k -X GET \
-H 'Authorization: Bearer $token' \
https://localhost:8080/apis/crd.varmor.org/v1beta1/namespaces/demo/armorprofilemodels/varmor-demo-demo-4 > varmor-demo-demo-4.json
```

## Use Case

### 1. Deploy target workloads

Create target workloads in the defalut and demo namespaces.

```yaml
cat << EOF | kubectl create -f -
apiVersion: apps/v1
Expand Down Expand Up @@ -118,6 +280,7 @@ EOF
```

### 2. Create a policy to model

Create a policy with BehaviorModeling mode. You can set the modeling duration in the `.spec.policy.modelingOptions.duration` field.

The target workloads will be updated once the policy is created. You can also create a policy before deploying target workloads.
Expand Down Expand Up @@ -150,6 +313,7 @@ EOF
```

### 3. Inspect the status

Check out the policy object. If anything is working right, the policy will be ready and in the `Modeling` status as shown below.

```bash
Expand Down
Loading