-
Notifications
You must be signed in to change notification settings - Fork 11
Experiment files documentation #13
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # Experiments | ||
|
|
||
| **secops-chaos** experiments are driven by **experiment** files, they all follow a common format, made up of a `metadata` and `parameters` section. | ||
|
|
||
| ``` yaml | ||
| experiments: | ||
| - metadata: | ||
| name: my-experiment # A meaningful name for your experiment | ||
| type: prvileged_container # The type of experiment, see table below for a list of valid types | ||
| namespace: my-namespace # What namespace to apply the experiment to | ||
| parameters: # Parameters holds the settings for your experiment, tweak them to suit your needs. | ||
| host_pid: true | ||
| ``` | ||
|
|
||
|
|
||
| ## Available Experiments | ||
|
|
||
| | Type | Description | Framework | | ||
| |-------------------------------------------------------|-------------------------------------------------------------------------------------|-----------| | ||
| | [privileged_container](run_privileged_container.yaml) | This experiment attempts to run a privileged container in a namespace | MITRE | | ||
| | [host_path_mount](host_path_volume.yaml) | This experiment attempts to mount a sensitive host filesystem path into a container | MITRE | | ||
|
|
||
|
|
||
| ## Implementing a new Experiment | ||
|
|
||
| Each experiment within `secops-chaos` adheres to a shared interface, this allows for a common set of functionality to be used across all experiments. | ||
|
|
||
| When implementing a new experiment you should create a new file starting with `experiment_` within the [internal/experiments](https://github.com/OperantAI/secops-chaos/blob/main/internal/experiments/) directory, and implement the `Experiment` interface. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could also add an example of the config model saying that every experiment would need to define its own config model like the PrivilegedContainerConfig and add in an example of one of the experiments
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should now be added, have a read through when you have a sec. |
||
|
|
||
| ```go | ||
| type Experiment interface { | ||
| // Type returns the type of the experiment | ||
| Type() string | ||
| // Description describes the experiment in a brief sentence | ||
| Description() string | ||
| // Framework returns the attack framework e.g., MITRE/OWASP | ||
| Framework() string | ||
| // Tactic returns the attack tactic category | ||
| Tactic() string | ||
| // Technique returns the attack method | ||
| Technique() string | ||
| // Run runs the experiment, returning an error if it fails | ||
| Run(ctx context.Context, client *kubernetes.Clientset, experimentConfig *ExperimentConfig) error | ||
| // Verify verifies the experiment, returning an error if it fails | ||
| Verify(ctx context.Context, client *kubernetes.Clientset, experimentConfig *ExperimentConfig) (*Outcome, error) | ||
| // Cleanup cleans up the experiment, returning an error if it fails | ||
| Cleanup(ctx context.Context, client *kubernetes.Clientset, experimentConfig *ExperimentConfig) error | ||
| } | ||
| ``` | ||
|
|
||
| Additionally, you need some way of configuring your experiment, this is done via the `ExperimentConfig` struct, which is passed to the `Run`, `Verify` and `Cleanup` methods for your experiment. | ||
|
|
||
| ```go | ||
| type ExperimentsConfig struct { | ||
| ExperimentConfigs []ExperimentConfig `yaml:"experiments"` | ||
| } | ||
|
|
||
| type ExperimentConfig struct { | ||
| // Metadata for the experiment | ||
| Metadata ExperimentMetadata `yaml:"metadata"` | ||
| // Parameters for the experiment | ||
| Parameters interface{} `yaml:"parameters"` | ||
| } | ||
|
|
||
| type ExperimentMetadata struct { | ||
| // Name of the experiment | ||
| Name string `yaml:"name"` | ||
| // Namespace to apply the experiment to | ||
| Namespace string `yaml:"namespace"` | ||
| // Type of the experiment | ||
| Type string `yaml:"type"` | ||
| } | ||
| ``` | ||
|
|
||
| Inside your experiment file, you also need to add Parameter configuration as parameters will differ per experiment. These params get parsed into the `Parameters` field of the `ExperimentConfig` struct. | ||
|
|
||
| ``` go | ||
| type HostPathMountExperimentConfig struct { | ||
| Metadata ExperimentMetadata `yaml:"metadata"` | ||
| Parameters HostPathMount `yaml:"parameters"` | ||
| } | ||
|
|
||
| type HostPathMount struct { | ||
| HostPath HostPath `yaml:"host_path"` | ||
| } | ||
|
|
||
| type HostPath struct { | ||
| Path string `yaml:"path"` | ||
| } | ||
|
|
||
| func (p *HostPathMountExperimentConfig) Run(ctx context.Context, client *kubernetes.Clientset, experimentConfig *ExperimentConfig) error { | ||
| var hostPathMountExperimentConfig HostPathMountExperimentConfig | ||
| yamlObj, _ := yaml.Marshal(experimentConfig) | ||
| err := yaml.Unmarshal(yamlObj, &hostPathMountExperimentConfig) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| params := hostPathMountExperimentConfig.Parameters | ||
| ...rest of your experiment implementation... | ||
| } | ||
| ``` | ||
|
|
||
| `Verify`, and `Clean` also follow the same pattern, and are passed the same `ExperimentConfig` struct. | ||
|
|
||
| Finally, add your Experiment to the Experiment registry in [internal/experiments/registry.go](https://github.com/operantai/secops-chaos/blob/main/internal/experiments/registry.go), and create a new experiment file in the [experiments](https://github.com/operantai/secops-chaos/blob/main/experiments) directory. | ||
|
|
||
| Now you're set to cause some chaos! 🎉 | ||
|
|
||
| ``` go | ||
| secops-chaos run -f experiments/my-experiment.yaml | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package experiments | ||
|
|
||
| // ExperimentsRegistry is a list of all experiments | ||
| var ExperimentsRegistry = []Experiment{ | ||
| &PrivilegedContainerExperimentConfig{}, | ||
| &HostPathMountExperimentConfig{}, | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.