mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
Merge commit 'da5c03f89df3007088b27fc84b08827170e16eda' into 345_support_usergroup_info
# Conflicts: # test/scenarios/samples/best_practices/add_safe_to_evict2.yaml
This commit is contained in:
commit
45dc0bd358
91 changed files with 752 additions and 892 deletions
62
README.md
62
README.md
|
@ -6,9 +6,9 @@
|
|||
|
||||
Kyverno is a policy engine designed for Kubernetes.
|
||||
|
||||
Kubernetes supports declarative management of objects using configurations written in YAML or JSON. Often, parts of the configuration will need to vary based on the runtime environment. For portability, and for separation of concerns, its best to maintain environment specific configurations separately from workload configurations.
|
||||
Kubernetes supports declarative validation, mutation, and generation of resource configurations using policies written as Kubernetes resources.
|
||||
|
||||
Kyverno allows cluster adminstrators to manage environment specific configurations independently of workload configurations and enforce configuration best practices for their clusters.
|
||||
Kyverno can be used to scan existing workloads for best practices, or can be used to enforce best practices by blocking or mutating API requests.Kyverno allows cluster adminstrators to manage environment specific configurations independently of workload configurations and enforce configuration best practices for their clusters.
|
||||
|
||||
Kyverno policies are Kubernetes resources that can be written in YAML or JSON. Kyverno policies can validate, mutate, and generate any Kubernetes resources.
|
||||
|
||||
|
@ -115,29 +115,7 @@ spec:
|
|||
|
||||
### 4. More examples
|
||||
|
||||
Refer to a list of curated of [kyverno policies](/samples/README.md) to follow kubernetes best practices.
|
||||
|
||||
## License
|
||||
|
||||
[Apache License 2.0](https://github.com/nirmata/kyverno/blob/master/LICENSE)
|
||||
|
||||
## Status
|
||||
|
||||
*Kyverno is under active development and not ready for production use. Key components and policy definitions are likely to change as we complete core features.*
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Open Policy Agent
|
||||
|
||||
[Open Policy Agent (OPA)](https://www.openpolicyagent.org/) is a general-purpose policy engine that can be used as a Kubernetes admission controller. It supports a large set of use cases. Policies are written using [Rego](https://www.openpolicyagent.org/docs/latest/how-do-i-write-policies#what-is-rego) a custom query language.
|
||||
|
||||
### Polaris
|
||||
|
||||
[Polaris](https://github.com/reactiveops/polaris) validates configurations for best practices. It includes several checks across health, networking, security, etc. Checks can be assigned a severity. A dashboard reports the overall score.
|
||||
|
||||
### External configuration management tools
|
||||
|
||||
Tools like [Kustomize](https://github.com/kubernetes-sigs/kustomize) can be used to manage variations in configurations outside of clusters. There are several advantages to this approach when used to produce variations of the same base configuration. However, such solutions cannot be used to validate or enforce configurations.
|
||||
Refer to a list of curated of ***[sample policies](/samples/README.md)*** that can be applied to your cluster.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
@ -149,15 +127,35 @@ Tools like [Kustomize](https://github.com/kubernetes-sigs/kustomize) can be used
|
|||
* [Testing Policies](documentation/testing-policies.md)
|
||||
* [Using kubectl](documentation/testing-policies.md#Test-using-kubectl)
|
||||
* [Using the Kyverno CLI](documentation/testing-policies.md#Test-using-the-Kyverno-CLI)
|
||||
* [Sample Policies](/samples/README.md)
|
||||
|
||||
## License
|
||||
|
||||
[Apache License 2.0](https://github.com/nirmata/kyverno/blob/master/LICENSE)
|
||||
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Open Policy Agent
|
||||
|
||||
[Open Policy Agent (OPA)](https://www.openpolicyagent.org/) is a general-purpose policy engine that can be used as a Kubernetes admission controller. It supports a large set of use cases. Policies are written using [Rego](https://www.openpolicyagent.org/docs/latest/how-do-i-write-policies#what-is-rego) a custom query language.
|
||||
|
||||
### k-rail
|
||||
|
||||
[k-rail](https://github.com/cruise-automation/k-rail/) provides several ready to use policies for security and multi-tenancy. The policies are written in Golang. Several of the [Kyverno sample policies](/samples/README.md) were inspired by k-rail policies.
|
||||
|
||||
### Polaris
|
||||
|
||||
[Polaris](https://github.com/reactiveops/polaris) validates configurations for best practices. It includes several checks across health, networking, security, etc. Checks can be assigned a severity. A dashboard reports the overall score.
|
||||
|
||||
### External configuration management tools
|
||||
|
||||
Tools like [Kustomize](https://github.com/kubernetes-sigs/kustomize) can be used to manage variations in configurations outside of clusters. There are several advantages to this approach when used to produce variations of the same base configuration. However, such solutions cannot be used to validate or enforce configurations.
|
||||
|
||||
|
||||
## Roadmap
|
||||
|
||||
Here are some the major features we plan on completing before a 1.0 release:
|
||||
|
||||
* [Events](https://github.com/nirmata/kyverno/issues/14)
|
||||
* [Policy Violations](https://github.com/nirmata/kyverno/issues/24)
|
||||
* [Conditionals on existing resources](https://github.com/nirmata/kyverno/issues/57)
|
||||
* [Extend CLI to operate on cluster resources ](https://github.com/nirmata/kyverno/issues/164)
|
||||
See [Milestones](https://github.com/nirmata/kyverno/milestones) and [Issues](https://github.com/nirmata/kyverno/issues).
|
||||
|
||||
## Getting help
|
||||
|
||||
|
@ -166,7 +164,7 @@ Here are some the major features we plan on completing before a 1.0 release:
|
|||
|
||||
## Contributing
|
||||
|
||||
Welcome to our community and thanks for contributing!
|
||||
Thanks for your interest in contributing!
|
||||
|
||||
* Please review and agree to abide with the [Code of Conduct](/CODE_OF_CONDUCT.md) before contributing.
|
||||
* See the [Wiki](https://github.com/nirmata/kyverno/wiki) for developer documentation.
|
||||
|
|
|
@ -2,17 +2,23 @@
|
|||
|
||||
# Mutate Configurations
|
||||
|
||||
The ```mutate``` rule contains actions that will be applied to matching resource before their creation. A mutate rule can be written as a JSON Patch or as an overlay. By using a ```patch``` in the (JSONPatch - RFC 6902)[http://jsonpatch.com/] format, you can make precise changes to the resource being created. Using an ```overlay``` is convenient for describing the desired state of the resource.
|
||||
The ```mutate``` rule contains actions that will be applied to matching resources. A mutate rule can be written as a JSON Patch or as an overlay.
|
||||
|
||||
By using a ```patch``` in the (JSONPatch - RFC 6902)[http://jsonpatch.com/] format, you can make precise changes to the resource being created. Using an ```overlay``` is convenient for describing the desired state of the resource.
|
||||
|
||||
Resource mutation occurs before validation, so the validation rules should not contradict the changes performed by the mutation section.
|
||||
|
||||
## Anchors
|
||||
| Anchor | Tag | Behavior |
|
||||
|------------- |----- |--------------------------------------------- |
|
||||
| Conditional | () | Add the specified tag |
|
||||
| Add | +() | Add if the tag if not specified |
|
||||
|
||||
## Patches
|
||||
## JSON Patch
|
||||
|
||||
A JSON Patch rule provides an alternate way to mutate resources.
|
||||
|
||||
[JSONPatch](http://jsonpatch.com/) supports the following operations (in the 'op' field):
|
||||
* **add**
|
||||
* **replace**
|
||||
* **remove**
|
||||
|
||||
With Kyverno, the add and replace have the same behavior i.e. both operations will add or replace the target element.
|
||||
|
||||
This patch adds an init container to all deployments.
|
||||
|
||||
|
@ -37,14 +43,9 @@ spec :
|
|||
name: "init-secrets"
|
||||
|
||||
````
|
||||
[JSONPatch](http://jsonpatch.com/) supports the following operations (in the 'op' field):
|
||||
* **add**
|
||||
* **replace**
|
||||
* **remove**
|
||||
|
||||
With Kyverno, the add and replace have the same behavior i.e. both operations will add or replace the target element.
|
||||
|
||||
Here is the example of a patch that removes a label from the secret:
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : ClusterPolicy
|
||||
|
@ -65,9 +66,11 @@ spec :
|
|||
|
||||
Note, that if **remove** operation cannot be applied, then this **remove** operation will be skipped with no error.
|
||||
|
||||
## Overlay
|
||||
## Mutate Overlay
|
||||
|
||||
A mutation overlay describes the desired form of resource. The existing resource values are replaced with the values specified in the overlay. If a value is specified in the overlay but not present in the target resource, then it will be added to the resource. The overlay cannot be used to delete values in a resource: use **patches** for this purpose.
|
||||
A mutation overlay describes the desired form of resource. The existing resource values are replaced with the values specified in the overlay. If a value is specified in the overlay but not present in the target resource, then it will be added to the resource.
|
||||
|
||||
The overlay cannot be used to delete values in a resource: use **patches** for this purpose.
|
||||
|
||||
The following mutation overlay will add (or replace) the memory request and limit to 10Gi for every Pod with a label ```memory: high```:
|
||||
|
||||
|
@ -124,9 +127,26 @@ spec:
|
|||
````
|
||||
|
||||
|
||||
|
||||
### Conditional logic using anchors
|
||||
|
||||
An **anchor** field, marked by parentheses, allows conditional processing of configurations. Processing stops when the anchor value does not match. Once processing stops, any child elements or any remaining siblings in a list, will not be processed.
|
||||
An **anchor** field, marked by parentheses and an optional preceeding character, allows conditional processing for mutations.
|
||||
|
||||
The mutate overlay rules support two types of anchors:
|
||||
|
||||
| Anchor | Tag | Behavior |
|
||||
|--------------------|----- |----------------------------------------------------- |
|
||||
| Conditional | () | Use the tag and value as an "if" condition |
|
||||
| Add if not present | +() | Add the tag value, if the tag is not already present |
|
||||
|
||||
|
||||
The **anchors** values support **wildcards**:
|
||||
1. `*` - matches zero or more alphanumeric characters
|
||||
2. `?` - matches a single alphanumeric character
|
||||
|
||||
#### Conditional anchor
|
||||
|
||||
A `conditional anchor` evaluates to `true` if the anchor tag exists and if the value matches the specified value. Processing stops if a tag does not exist or when the value does not match. Once processing stops, any child elements or any remaining siblings in a list, will not be processed.
|
||||
|
||||
For example, this overlay will add or replace the value 6443 for the port field, for all ports with a name value that starts with "secure":
|
||||
|
||||
|
@ -150,16 +170,15 @@ spec :
|
|||
port: 6443
|
||||
````
|
||||
|
||||
The **anchors** values support **wildcards**:
|
||||
1. `*` - matches zero or more alphanumeric characters
|
||||
2. `?` - matches a single alphanumeric character
|
||||
If the anchor tag value is an object or array, the entire object or array must match. In other words, the entire object or array becomes part of the "if" clause. Nested `conditional anchor` tags are not supported.
|
||||
|
||||
### Add if not present anchor
|
||||
|
||||
### Add if not present
|
||||
A variation of an anchor, is to add a field value if it is not already defined. This is done by using the `add anchor` (short for `add if not present anchor`) with the notation ````+(...)```` for the tag.
|
||||
|
||||
A variation of an anchor, is to add a field value if it is not already defined. This is done by using the ````+(...)```` notation for the field.
|
||||
An `add anchor` is processed as part of applying the mutation. Typically, every non-anchor tag-value is applied as part of the mutation. If the `add anchor` is set on a tag, the tag and value are only applied if they do not exist in the resource.
|
||||
|
||||
For example, this overlay will set the port to 6443, if a port is not already defined:
|
||||
For example, this overlay will set the port to 6443, if a port is not already defined:
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
|
@ -180,6 +199,15 @@ spec :
|
|||
+(port): 6443
|
||||
````
|
||||
|
||||
#### Anchor processing flow
|
||||
|
||||
The anchor processing behavior for mutate conditions is as follows:
|
||||
|
||||
1. First, all conditional anchors are processed. Processing stops when the first conditional anchor return a `false`. Mutation proceeds only of all conditional anchors return a `true`. Note that for `conditional anchor` tags with complex (object or array) values the entire value (child) object is treated as part of the condition, as explained above.
|
||||
|
||||
2. Next, all tag-values without anchors and all `add anchor` tags are processed to apply the mutation.
|
||||
|
||||
|
||||
## Additional Details
|
||||
|
||||
Additional details on mutation overlay behaviors are available on the wiki: [Mutation Overlay](https://github.com/nirmata/kyverno/wiki/Mutation-Overlay)
|
||||
|
|
|
@ -10,68 +10,56 @@ func Test_Mutate_Validate_qos(t *testing.T) {
|
|||
testScenario(t, "/test/scenarios/other/scenario_mutate_validate_qos.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_deny_runasrootuser(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_deny_runasrootuser.yaml")
|
||||
func Test_disallow_root_user(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_root_user.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_priviledgedprivelegesecalation(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_priviledged_privelegesecalation.yaml")
|
||||
func Test_disallow_priviledged(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_priviledged.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_healthChecks(t *testing.T) {
|
||||
testScenario(t, "/test/scenarios/other/scenario_validate_healthChecks.yaml")
|
||||
}
|
||||
|
||||
func Test_generate_networkPolicy(t *testing.T) {
|
||||
testScenario(t, "/test/scenarios/samples/best_practices/scenario_generate_networkPolicy.yaml")
|
||||
func Test_add_networkPolicy(t *testing.T) {
|
||||
testScenario(t, "/test/scenarios/samples/best_practices/add_networkPolicy.yaml")
|
||||
}
|
||||
|
||||
// namespace is blank, not "default" as testrunner evaulates the policyengine, but the "default" is added by kubeapiserver
|
||||
|
||||
func Test_validate_require_image_tag_not_latest_deny(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_valiadate_require_image_tag_not_latest_deny.yaml")
|
||||
func Test_validate_disallow_latest_tag(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_latest_tag.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_require_image_tag_not_latest_pass(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_valiadate_require_image_tag_not_latest_pass.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_automoutingapicred_pass(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_automountingapicred.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_latest_tag_pass.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_default_namespace(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_default_namespace.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_default_namespace.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_host_network_port(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_host_network_hostport.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_host_network_port.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_hostPID_hostIPC(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_hostpid_hostipc.yaml")
|
||||
func Test_validate_host_PID_IPC(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_host_pid_ipc.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_not_readonly_rootfilesystem(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_require_readonly_rootfilesystem.yaml")
|
||||
func Test_validate_ro_rootfs(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/require_ro_rootfs.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_require_namespace_quota(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_require_namespace_quota.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_node_port(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_node_port.yaml")
|
||||
func Test_add_ns_quota(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/add_ns_quota.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_default_serviceaccount(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/other/scenario_validate_disallow_default_serviceaccount.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_fsgroup(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/scenario_validate_fsgroup.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_selinux_context(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/other/scenario_validate_selinux_context.yaml")
|
||||
}
|
||||
|
@ -80,61 +68,66 @@ func Test_validate_proc_mount(t *testing.T) {
|
|||
testScenario(t, "test/scenarios/other/scenario_validate_default_proc_mount.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_container_capabilities(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/scenario_validate_container_capabilities.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_sysctl(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/scenario_validate_sysctl_configs.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_volume_whitelist(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/other/scenario_validate_volume_whiltelist.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_trusted_image_registries(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_trusted_image_registries.yaml")
|
||||
}
|
||||
|
||||
func Test_require_pod_requests_limits(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_require_pod_requests_limits.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/require_pod_requests_limits.yaml")
|
||||
}
|
||||
|
||||
func Test_require_probes(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_probes.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/require_probes.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_host_filesystem_fail(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_host_filesystem.yaml")
|
||||
func Test_validate_disallow_bind_mounts_fail(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_bind_mounts_fail.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_host_filesystem_pass(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_host_filesystem_pass.yaml")
|
||||
func Test_validate_disallow_bind_mounts_pass(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_bind_mounts_pass.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_new_capabilities(t *testing.T) {
|
||||
testScenario(t, "/test/scenarios/samples/best_practices/scenario_validate_disallow_new_capabilities.yaml")
|
||||
testScenario(t, "/test/scenarios/samples/best_practices/disallow_new_capabilities.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_docker_sock_mount(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_docker_sock_mount.yaml")
|
||||
func Test_disallow_sysctls(t *testing.T) {
|
||||
testScenario(t, "/test/scenarios/samples/best_practices/disallow_sysctls.yaml")
|
||||
}
|
||||
|
||||
func Test_disallow_docker_sock_mount(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/disallow_docker_sock_mount.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_disallow_helm_tiller(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_disallow_helm_tiller.yaml")
|
||||
}
|
||||
|
||||
func Test_add_safe_to_evict_annotation(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_mutate_safe-to-evict.yaml")
|
||||
func Test_add_safe_to_evict(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/add_safe_to_evict.yaml")
|
||||
}
|
||||
|
||||
func Test_add_safe_to_evict_annotation2(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_mutate_safe-to-evict2.yaml")
|
||||
testScenario(t, "test/scenarios/samples/best_practices/add_safe_to_evict2.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_restrict_automount_sa_token_pass(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/restrict_automount_sa_token.yaml")
|
||||
}
|
||||
|
||||
func Test_restrict_node_port(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/restrict_node_port.yaml")
|
||||
}
|
||||
|
||||
func Test_validate_restrict_image_registries(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/more/restrict_image_registries.yaml")
|
||||
}
|
||||
|
||||
func Test_known_ingress(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_known_ingress_class.yaml")
|
||||
testScenario(t, "test/scenarios/samples/more/restrict_ingress_classes.yaml")
|
||||
}
|
||||
|
||||
func Test_unknown_ingress(t *testing.T) {
|
||||
testScenario(t, "test/scenarios/samples/best_practices/scenario_validate_unknown_ingress_class.yaml")
|
||||
testScenario(t, "test/scenarios/samples/more/unknown_ingress_class.yaml")
|
||||
}
|
||||
|
|
33
samples/AddDefaultNetworkPolicy.md
Normal file
33
samples/AddDefaultNetworkPolicy.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Default deny all ingress traffic
|
||||
|
||||
By default, Kubernetes allows communications across all pods within a cluster. Network policies and, a CNI that supports network policies, must be used to restrict communinications.
|
||||
|
||||
A default `NetworkPolicy` should be configured for each namespace to default deny all ingress traffic to the pods in the namespace. Application teams can then configure additional `NetworkPolicy` resources to allow desired traffic to application pods from select sources.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[add_network_policy.yaml](best_practices/add_network_policy.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-networkpolicy
|
||||
spec:
|
||||
rules:
|
||||
- name: "default-deny-ingress"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
name: "*"
|
||||
generate:
|
||||
kind: NetworkPolicy
|
||||
name: default-deny-ingress
|
||||
data:
|
||||
spec:
|
||||
# select all pods in the namespace
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
````
|
|
@ -8,23 +8,23 @@ To limit the number of resources like CPU and memory, as well as objects that ma
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[require_namespace_quota.yaml](best_practices/require_namespace_quota.yaml)
|
||||
[add_ns_quota.yaml](best_practices/add_ns_quota.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-namespace-quota
|
||||
name: add-ns-quota
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-namespace-quota
|
||||
- name: generate-resourcequota
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
generate:
|
||||
kind: ResourceQuota
|
||||
name: "defaultresourcequota"
|
||||
name: "default-resourcequota"
|
||||
data:
|
||||
spec:
|
||||
hard:
|
|
@ -10,16 +10,16 @@ This policy matches and mutates pods with `emptyDir` and `hostPath` volumes, to
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[add_safe_to_evict_annotation.yaml](best_practices/add_safe-to-evict_annotation.yaml)
|
||||
[add_safe_to_evict_annotation.yaml](best_practices/add_safe_to_evict.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: "kyverno.io/v1alpha1"
|
||||
kind: "ClusterPolicy"
|
||||
metadata:
|
||||
name: "annotate-emptydir-hostpath"
|
||||
name: "add-safe-to-evict"
|
||||
spec:
|
||||
rules:
|
||||
- name: "empty-dir-add-safe-to-evict"
|
||||
- name: "annotate-empty-dir"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
@ -32,7 +32,7 @@ spec:
|
|||
spec:
|
||||
volumes:
|
||||
- (emptyDir): {}
|
||||
- name: "host-path-add-safe-to-evict"
|
||||
- name: "annotate-host-path"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
|
@ -1,34 +0,0 @@
|
|||
# Assign Linux capabilities
|
||||
|
||||
Linux divides the privileges traditionally associated with superuser into distinct units, known as capabilities, which can be independently enabled or disabled by listing them in `securityContext.capabilites`.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[policy_validate_container_capabilities.yaml](more/policy_validate_container_capabilities.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-container-capablities
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-container-capablities
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Allow certain linux capability"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"]
|
||||
|
||||
````
|
||||
|
||||
## Additional Information
|
||||
|
||||
* [List of linux capabilities](https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h)
|
|
@ -1,34 +0,0 @@
|
|||
# Configure kernel parameters
|
||||
|
||||
The Sysctl interface allows to modify kernel parameters at runtime and in the pod can be specified under `securityContext.sysctls`. If kernel parameters in the pod are to be modified, should be handled cautiously, and policy with rules restricting these options will be helpful. We can control minimum and maximum port that a network connection can use as its source(local) port by checking net.ipv4.ip_local_port_range
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[policy_validate_sysctl_configs.yaml](more/policy_validate_sysctl_configs.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-allow-portrange-with-sysctl
|
||||
spec:
|
||||
rules:
|
||||
- name: allow-portrange-with-sysctl
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Allowed port range is from 1024 to 65535"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
sysctls:
|
||||
- name: net.ipv4.ip_local_port_range
|
||||
value: "1024 65535"
|
||||
````
|
||||
|
||||
|
||||
## Additional Information
|
||||
|
||||
* [List of supported namespaced sysctl interfaces](https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/)
|
|
@ -1,33 +0,0 @@
|
|||
# Default deny all ingress traffic
|
||||
|
||||
By default, Kubernetes allows all ingress and egress traffic to and from pods within a cluster.
|
||||
|
||||
A "default" `NetworkPolicy` should be configured for each namespace to default deny all ingress traffic to the pods in that namespace. Later, the application team can configure additional `NetworkPolicy` resources to allow desired traffic to application pods from select sources.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[require_default_network_policy.yaml](best_practices/require_default_network_policy.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: default-deny-ingress-networkpolicy
|
||||
spec:
|
||||
rules:
|
||||
- name: "default-deny-ingress"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
name: "*"
|
||||
generate:
|
||||
kind: NetworkPolicy
|
||||
name: default-deny-ingress
|
||||
data:
|
||||
spec:
|
||||
# select all pods in the namespace
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
````
|
|
@ -1,30 +0,0 @@
|
|||
# Disallow automount of Service Account credentials
|
||||
|
||||
Kubernetes automounts default service account credentials in each pod. To restrict access, opt out of automounting credentials by setting `automountServiceAccountToken` to `false`.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_automountingapicred.yaml](best_practices/disallow_automountingapicred.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-disallow-automoutingapicred
|
||||
spec:
|
||||
rules:
|
||||
- name: disallow-automoutingapicred
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Deny automounting API credentials"
|
||||
pattern:
|
||||
spec:
|
||||
=(serviceAccountName): "*"
|
||||
automountServiceAccountToken: false
|
||||
````
|
||||
|
||||
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
# Disallow use of bind mounts (`hostPath` volumes)
|
||||
|
||||
The volume of type `hostPath` allows pods to use host bind mounts (i.e. directories and volumes mounted to a host path) in containers. Using host resources can be used to access shared data or escalate priviliges. Also, this couples pods to a specific host and data persisted in the `hostPath` volume is coupled to the life of the node leading to potential pod scheduling failures. It is highly recommeded that applications are designed to be decoupled from the underlying infrstructure (in this case, nodes).
|
||||
The volume of type `hostPath` allows pods to use host bind mounts (i.e. directories and volumes mounted to a host path) in containers. Using host resources can be used to access shared data or escalate privileges. Also, this couples pods to a specific host and data persisted in the `hostPath` volume is coupled to the life of the node leading to potential pod scheduling failures. It is highly recommended that applications are designed to be decoupled from the underlying infrastructure (in this case, nodes).
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_host_filesystem.yaml](best_practices/disallow_host_filesystem.yaml)
|
||||
[disallow_bind_mounts.yaml](best_practices/disallow_bind_mounts.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: "kyverno.io/v1alpha1"
|
||||
kind: "ClusterPolicy"
|
||||
metadata:
|
||||
name: "deny-use-of-host-fs"
|
||||
name: "disallow-bind-mounts"
|
||||
spec:
|
||||
rules:
|
||||
- name: "deny-use-of-host-fs"
|
||||
- name: "validate-hostPath"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- "Pod"
|
||||
validate:
|
||||
message: "Host path is not allowed"
|
||||
message: "Host path volumes are not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
volumes:
|
|
@ -1,6 +1,6 @@
|
|||
# Disallow use of default namespace
|
||||
|
||||
Kubernetes namespaces provide a way to segment and isolate cluster resources across multiple applictaions and users. It is recommended that each workload be isolated in its own namespace and that use of the default namespace be not allowed.
|
||||
Kubernetes namespaces are an optional feature that provide a way to segment and isolate cluster resources across multiple applications and users. As a best practice, workloads should be isolated with namespaces. Namespaces should be required and the default (empty) namespace should not be used.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
|
@ -10,20 +10,20 @@ Kubernetes namespaces provide a way to segment and isolate cluster resources acr
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-namespace
|
||||
name: disallow-default-namespace
|
||||
spec:
|
||||
rules:
|
||||
- name: check-default-namespace
|
||||
- name: validate-namespace
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Using 'default' namespace is restricted"
|
||||
message: "Using 'default' namespace is not allowed"
|
||||
pattern:
|
||||
metadata:
|
||||
namespace: "!default"
|
||||
- name: check-namespace-exist
|
||||
- name: require-namespace
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -13,11 +13,6 @@ apiVersion: kyverno.io/v1alpha1
|
|||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-docker-sock-mount
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: The Docker socket bind mount allows access to the
|
||||
Docker daemon on the node. This access can be used for privilege escalation and
|
||||
to manage containers outside of Kubernetes, and hence should not be allowed.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-docker-sock-mount
|
||||
|
|
|
@ -4,14 +4,13 @@ Tiller has known security challenges. It requires adminstrative privileges and a
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_helm_tiller.yaml](best_practices/disallow_helm_tiller.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-helm-tiller
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description:
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-helm-tiller
|
||||
|
|
|
@ -5,23 +5,23 @@ Using `hostPort` and `hostNetwork` allows pods to share the host networking stac
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_host_network_hostport.yaml](best_practices/disallow_host_network_hostport.yaml)
|
||||
[disallow_host_network_port.yaml](best_practices/disallow_host_network_port.yaml)
|
||||
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-host-network-hostport
|
||||
name: disallow-host-network-port
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-host-network-hostport
|
||||
- name: validate-host-network-port
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Defining hostNetwork and hostPort are not allowed"
|
||||
message: "Using host networking is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
(hostNetwork): false
|
||||
|
|
|
@ -6,23 +6,17 @@ To avoid pod container from having visibility to host process space, validate th
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_hostpid_hostipc.yaml](best_practices/disallow_hostpid_hostipc.yaml)
|
||||
[disallow_host_pid_ipc.yaml](best_practices/disallow_host_pid_ipc.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-host-pid-ipc
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: Sharing the host's PID namespace allows visibility of process
|
||||
on the host, potentially exposing process information. Sharing the host's IPC namespace allows
|
||||
the container process to communicate with processes on the host. To avoid pod container from
|
||||
having visibility to host process space, validate that 'hostPID' and 'hostIPC' are set to 'false'.
|
||||
name: disallow-host-pid-ipc
|
||||
spec:
|
||||
validationFailureAction: enforce
|
||||
validationFailureAction: audit
|
||||
rules:
|
||||
- name: validate-host-pid-ipc
|
||||
- name: validate-hostPID-hostIPC
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -4,36 +4,37 @@ The `:latest` tag is mutable and can lead to unexpected errors if the upstream i
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[require_image_tag_not_latest.yaml](best_practices/require_image_tag_not_latest.yaml)
|
||||
[disallow_latest_tag.yaml](best_practices/disallow_latest_tag.yaml)
|
||||
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-image-tag
|
||||
name: disallow-latest-tag
|
||||
spec:
|
||||
rules:
|
||||
- name: image-tag-notspecified
|
||||
- name: require-tag
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Image tag not specified"
|
||||
message: "An image tag is required"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- image: "*:*"
|
||||
- name: image-tag-not-latest
|
||||
- name: validate-tag
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Using 'latest' image tag is restricted. Set image tag to a specific version"
|
||||
message: "Using a mutable image tag e.g. 'latest' is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- image: "!*:latest"
|
||||
|
||||
````
|
||||
|
|
|
@ -14,23 +14,16 @@ default capabilities.
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-new-capabilities
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/description: Linux allows defining fine-grained permissions using
|
||||
capabilities. With Kubernetes, it is possible to add capabilities that escalate the
|
||||
level of kernel access and allow other potentially dangerous behaviors. This policy
|
||||
enforces that pods cannot add new capabilities. Other policies can be used to set
|
||||
default capabilities.
|
||||
name: disallow-new-capabilities
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-new-capabilities
|
||||
- name: validate-add-capabilities
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Capabilities cannot be added"
|
||||
message: "New capabilities cannot be added"
|
||||
anyPattern:
|
||||
- spec:
|
||||
=(securityContext):
|
||||
|
@ -42,4 +35,5 @@ spec:
|
|||
=(securityContext):
|
||||
=(capabilities):
|
||||
X(add): null
|
||||
|
||||
````
|
||||
|
|
|
@ -1,36 +1,50 @@
|
|||
# Disable privileged containers
|
||||
# Diallow privileged containers
|
||||
|
||||
Privileged containers are defined as any container where the container uid 0 is mapped to the host’s uid 0. A process within a privileged container can get unrestricted host access. With `securityContext.allowPrivilegeEscalation` enabled, a process can gain privileges from its parent.
|
||||
|
||||
To disallow privileged containers and the privilege escalation it is recommended to run pod containers with `securityContext.priveleged` set to `false` and `allowPrivilegeEscalation` set to `false`.
|
||||
To disallow privileged containers and privilege escalation, run pod containers with `securityContext.privileged` set to `false` and `securityContext.allowPrivilegeEscalation` set to `false`.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_priviledged_priviligedescalation.yaml](best_practices/disallow_priviledged_priviligedescalation.yaml)
|
||||
[disallow_privileged.yaml](best_practices/disallow_privileged.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-deny-privileged-priviligedescalation
|
||||
name: disallow-privileged
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-privileged-priviligedescalation
|
||||
- name: validate-privileged
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false"
|
||||
message: "Privileged mode is not allowed. Set privileged to false"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
- spec:
|
||||
containers:
|
||||
- name: "*"
|
||||
securityContext:
|
||||
privileged: false
|
||||
- name: validate-allowPrivilegeEscalation
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Privileged mode is not allowed. Set allowPrivilegeEscalation to false"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
- spec:
|
||||
containers:
|
||||
- name: "*"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
````
|
|
@ -8,16 +8,17 @@ By default, all processes in a container run as the root user (uid 0). To preven
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[deny_runasrootuser.yaml](best_practices/deny_runasrootuser.yaml)
|
||||
[disallow_root_user.yaml](best_practices/disallow_root_user.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-deny-runasrootuser
|
||||
name: disallow-root-user
|
||||
annotations:
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-runasrootuser
|
||||
- name: validate-runAsNonRoot
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
32
samples/DisallowSysctls.md
Normal file
32
samples/DisallowSysctls.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Disallow changes to kernel parameters
|
||||
|
||||
The Sysctl interface allows modifications to kernel parameters at runtime. In a Kubernetes pod these parameters can be specified under `securityContext.sysctls`. Kernel parameter modifications can be used for exploits and should be restricted.
|
||||
|
||||
## Additional Information
|
||||
|
||||
* [List of supported namespaced sysctl interfaces](https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/)
|
||||
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_sysctls.yaml](best_practices/disallow_sysctls.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-sysctls
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-sysctls
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Changes to kernel paramaters are not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
X(sysctls): null
|
||||
````
|
|
@ -1,32 +0,0 @@
|
|||
# Require a known ingress class
|
||||
|
||||
It can be useful to restrict Ingress resources to use a known ingress class that are allowed in the cluster.
|
||||
|
||||
You can customize this policy to allow ingress classes that are configured in the cluster.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[known_ingress.yaml](best_practices/known_ingress.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: known-ingress
|
||||
annotations:
|
||||
policies.kyverno.io/category: Ingress
|
||||
policies.kyverno.io/description:
|
||||
spec:
|
||||
rules:
|
||||
- name: known-ingress
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Ingress
|
||||
validate:
|
||||
message: "Unknown ingress class"
|
||||
pattern:
|
||||
metadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "F5 | nginx"
|
||||
````
|
|
@ -1,6 +1,43 @@
|
|||
# Sample Policies
|
||||
|
||||
Sample policies are designed to be applied to your Kubernetes clusters with minimal changes. To apply these policies to your cluster, install Kyverno and import the policies as follows:
|
||||
Sample policies are designed to be applied to your Kubernetes clusters with minimal changes.
|
||||
|
||||
The policies are mostly validation rules in `audit` mode i.e. your existing workloads will not be impacted, but will be audited for policy complaince.
|
||||
|
||||
## Best Practice Policies
|
||||
|
||||
These policies are highly recommended.
|
||||
|
||||
1. [Disallow root user](DisallowRootUser.md)
|
||||
2. [Disallow privileged containers](DisallowPrivilegedContainers.md)
|
||||
3. [Disallow new capabilities](DisallowNewCapabilities.md)
|
||||
4. [Disallow kernel parameter changes](DisallowSysctls.md)
|
||||
5. [Disallow use of bind mounts (`hostPath` volumes)](DisallowBindMounts.md)
|
||||
6. [Disallow docker socket bind mount](DisallowDockerSockMount.md)
|
||||
7. [Disallow `hostNetwork` and `hostPort`](DisallowHostNetworkPort.md)
|
||||
8. [Disallow `hostPID` and `hostIPC`](DisallowHostPIDIPC.md)
|
||||
9. [Disallow use of default namespace](DisallowDefaultNamespace.md)
|
||||
10. [Disallow latest image tag](DisallowLatestTag.md)
|
||||
11. [Disallow Helm Tiller](DisallowHelmTiller.md)
|
||||
12. [Require read-only root filesystem](RequireReadOnlyRootFS.md)
|
||||
13. [Require pod resource requests and limits](RequirePodRequestsLimits.md)
|
||||
14. [Require pod `livenessProbe` and `readinessProbe`](RequirePodProbes.md)
|
||||
15. [Add default network policy](AddDefaultNetworkPolicy.md)
|
||||
16. [Add namespace resource quotas](AddNamespaceResourceQuota.md)
|
||||
17. [Add `safe-to-evict` for pods with `emptyDir` and `hostPath` volumes](AddSafeToEvict.md)
|
||||
|
||||
## Additional Policies
|
||||
|
||||
These policies provide additional best practices and are worthy of close consideration. These policies may require specific changes for your workloads and environments.
|
||||
|
||||
17. [Restrict image registries](RestrictImageRegistries.md)
|
||||
18. [Restrict `NodePort` services](RestrictNodePort.md)
|
||||
19. [Restrict auto-mount of service account credentials](RestrictAutomountSAToken.md)
|
||||
20. [Restrict ingress classes](RestrictIngressClasses.md)
|
||||
|
||||
## Applying the sample policies
|
||||
|
||||
To apply these policies to your cluster, install Kyverno and import the policies as follows:
|
||||
|
||||
**Install Kyverno**
|
||||
|
||||
|
@ -30,36 +67,3 @@ Import addition policies from [here](more):
|
|||
kubectl create -f samples/more/
|
||||
````
|
||||
|
||||
The policies are mostly validation rules in `audit` mode i.e. your existing workloads will not be impacted, but will be audited for policy complaince.
|
||||
|
||||
## Best Practice Policies
|
||||
|
||||
These policies are highly recommended.
|
||||
|
||||
1. [Run as non-root user](RunAsNonRootUser.md)
|
||||
2. [Disable privileged containers and disallow privilege escalation](DisablePrivilegedContainers.md)
|
||||
3. [Disallow new capabilities](DisallowNewCapabilities.md)
|
||||
4. [Require read-only root filesystem](RequireReadOnlyFS.md)
|
||||
5. [Disallow use of bind mounts (`hostPath` volumes)](DisallowHostFS.md)
|
||||
6. [Disallow docker socket bind mount](DisallowDockerSockMount.md)
|
||||
7. [Disallow `hostNetwork` and `hostPort`](DisallowHostNetworkPort.md)
|
||||
8. [Disallow `hostPID` and `hostIPC`](DisallowHostPIDIPC.md)
|
||||
9. [Disallow unknown image registries](DisallowUnknownRegistries.md)
|
||||
10. [Disallow latest image tag](DisallowLatestTag.md)
|
||||
11. [Disallow use of default namespace](DisallowDefaultNamespace.md)
|
||||
12. [Require namespace limits and quotas](RequireNSLimitsQuotas.md)
|
||||
13. [Require pod resource requests and limits](RequirePodRequestsLimits.md)
|
||||
14. [Require pod `livenessProbe` and `readinessProbe`](RequirePodProbes.md)
|
||||
15. [Default deny all ingress traffic](DefaultDenyAllIngress.md)
|
||||
16. [Disallow Helm Tiller](DisallowHelmTiller.md)
|
||||
17. [Add `safe-to-evict` for pods with `emptyDir` and `hostPath` volumes](MutateSafeToEvict.md)
|
||||
|
||||
## Additional Policies
|
||||
|
||||
The policies provide additional best practices and are worthy of close consideration. These policies may require workload specific changes.
|
||||
|
||||
18. [Limit use of `NodePort` services](LimitNodePort.md)
|
||||
19. [Limit automount of Service Account credentials](DisallowAutomountSACredentials.md)
|
||||
20. [Configure Linux Capabilities](AssignLinuxCapabilities.md)
|
||||
21. [Limit Kernel parameter access](ConfigureKernelParmeters.md)
|
||||
22. [Restrict ingress class](KnownIngressClass.md)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Require `livenessProbe` and `readinessProbe`
|
||||
|
||||
For each pod, a `livenessProbe` is carried out by the kubelet to determine if containers are running and when to restart the pod. A `readinessProbe` is used by services and deployments to determine if the pod is ready to recieve network traffic.
|
||||
Liveness and readiness probes need to be configured to correctly manage a pods lifecycle during deployments, restarts, and upgrades.
|
||||
|
||||
Both liveness and readiness probes need to be configured to manage the pod lifecycle during restarts and upgrades.
|
||||
For each pod, a periodic `livenessProbe` is performed by the kubelet to determine if the pod's containers are running or need to be restarted. A `readinessProbe` is used by services and deployments to determine if the pod is ready to receive network traffic.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
|
@ -12,10 +12,10 @@ Both liveness and readiness probes need to be configured to manage the pod lifec
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-probes
|
||||
name: require-pod-probes
|
||||
spec:
|
||||
rules:
|
||||
- name: check-probes
|
||||
- name: validate-livenessProbe-readinessProbe
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -12,11 +12,11 @@ If a namespace level request or limit is specified, defaults will automatically
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: check-resource
|
||||
name: require-pod-requests-limits
|
||||
spec:
|
||||
validationFailureAction: "audit"
|
||||
rules:
|
||||
- name: check-resource-request-limit
|
||||
- name: validate-resources
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
# Require Read-only root filesystem
|
||||
# Require read-only root filesystem
|
||||
|
||||
A read-only root file system helps to enforce an immutable infrastructure strategy; the container only needs to write on mounted volumes that can persist state even if the container exits. An immutable root filesystem can also prevent malicious binaries from writing to the host system.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[require_readonly_rootfilesystem.yaml](best_practices/require_readonly_rootfilesystem.yaml)
|
||||
[require_ro_rootfs.yaml](best_practices/require_ro_rootfs.yaml)
|
||||
|
||||
|
||||
````yaml
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-readonly-rootfilesystem
|
||||
name: require-ro-rootfs
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-readonly-rootfilesystem
|
||||
- name: validate-readOnlyRootFilesystem
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Container require read-only rootfilesystem"
|
||||
message: "Root filesystem must be read-only"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
````
|
||||
````
|
29
samples/RestrictAutomountSAToken.md
Normal file
29
samples/RestrictAutomountSAToken.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Restrict auto-mount of Service Account tokens
|
||||
|
||||
Kubernetes automatically mounts service account credentials in each pod. The service account may be assigned roles allowing pods to access API resources. To restrict access, opt out of auto-mounting tokens by setting `automountServiceAccountToken` to `false`.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[restrict_automount_sa_token.yaml](more/restrict_automount_sa_token.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: restrict-automount-sa-token
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-automountServiceAccountToken
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Deny automounting API credentials"
|
||||
pattern:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
````
|
||||
|
||||
|
||||
|
|
@ -6,16 +6,16 @@ You can customize this policy to allow image registries that you trust.
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[trusted_image_registries.yaml](best_practices/trusted_image_registries.yaml)
|
||||
[restrict_image_registries.yaml](more/restrict_image_registries.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: trusted-registries
|
||||
name: restrict-image-registries
|
||||
spec:
|
||||
rules:
|
||||
- name: trusted-registries
|
||||
- name: validate-registries
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
27
samples/RestrictIngressClasses.md
Normal file
27
samples/RestrictIngressClasses.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Restrict ingress classes
|
||||
|
||||
It can be useful to restrict Ingress resources to a set of known ingress classes that are allowed in the cluster. You can customize this policy to allow ingress classes that are configured in the cluster.
|
||||
|
||||
## Policy YAML
|
||||
|
||||
[restrict_ingress_classes.yaml](more/restrict_ingress_classes.yaml)
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: restrict-ingress-classes
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-ingress
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Ingress
|
||||
validate:
|
||||
message: "Unknown ingress class"
|
||||
pattern:
|
||||
metadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "F5 | nginx"
|
||||
````
|
|
@ -1,4 +1,4 @@
|
|||
# Limit `NodePort` services
|
||||
# Restrict use of `NodePort` services
|
||||
|
||||
A Kubernetes service of type `NodePort` uses a host port (on every node in the cluster) to receive traffic from any source.
|
||||
|
||||
|
@ -8,23 +8,23 @@ Although NodePort services can be useful, their use should be limited to service
|
|||
|
||||
## Policy YAML
|
||||
|
||||
[disallow_node_port.yaml](best_practices/disallow_node_port.yaml)
|
||||
[restrict_node_port.yaml](more/restrict_node_port.yaml)
|
||||
|
||||
````yaml
|
||||
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-node-port
|
||||
name: restrict-node-port
|
||||
spec:
|
||||
rules:
|
||||
- name: disallow-node-port
|
||||
- name: validate-node-port
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Service
|
||||
validate:
|
||||
message: "Disallow service of type NodePort"
|
||||
message: "Service of type NodePort is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
type: "!NodePort"
|
29
samples/best_practices/add_network_policy.yaml
Normal file
29
samples/best_practices/add_network_policy.yaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-networkpolicy
|
||||
annotations:
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: By default, Kubernetes allows communications across
|
||||
all pods within a cluster. Network policies and, a CNI that supports network policies,
|
||||
must be used to restrict communinications. A default NetworkPolicy should be configured
|
||||
for each namespace to default deny all ingress traffic to the pods in the namespace.
|
||||
Application teams can then configure additional NetworkPolicy resources to allow
|
||||
desired traffic to application pods from select sources.
|
||||
spec:
|
||||
rules:
|
||||
- name: "default-deny-ingress"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
name: "*"
|
||||
generate:
|
||||
kind: NetworkPolicy
|
||||
name: default-deny-ingress
|
||||
data:
|
||||
spec:
|
||||
# select all pods in the namespace
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
26
samples/best_practices/add_ns_quota.yaml
Normal file
26
samples/best_practices/add_ns_quota.yaml
Normal file
|
@ -0,0 +1,26 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-ns-quota
|
||||
annotations:
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: To limit the number of objects, as well as the
|
||||
total amount of compute that may be consumed by a single namespace, create
|
||||
a default resource quota for each namespace.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-resourcequota
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
generate:
|
||||
kind: ResourceQuota
|
||||
name: "default-resourcequota"
|
||||
data:
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: '4'
|
||||
requests.memory: '16Gi'
|
||||
limits.cpu: '4'
|
||||
limits.memory: '16Gi'
|
|
@ -1,15 +1,15 @@
|
|||
apiVersion: "kyverno.io/v1alpha1"
|
||||
kind: "ClusterPolicy"
|
||||
metadata:
|
||||
name: "annotate-emptydir-hostpath"
|
||||
name: "add-safe-to-evict"
|
||||
annotations:
|
||||
policies.kyverno.io/category: AutoScaling
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: The Kubernetes cluster autoscaler does not evict pods that
|
||||
use hostPath or emptyDir volumes. To allow eviction of these pods, the annotation
|
||||
cluster-autoscaler.kubernetes.io/safe-to-evict=true must be added to the pods.
|
||||
spec:
|
||||
rules:
|
||||
- name: "empty-dir-add-safe-to-evict"
|
||||
- name: "annotate-empty-dir"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
@ -22,7 +22,7 @@ spec:
|
|||
spec:
|
||||
volumes:
|
||||
- (emptyDir): {}
|
||||
- name: "host-path-add-safe-to-evict"
|
||||
- name: "annotate-host-path"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
|
@ -1,21 +0,0 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-disallow-automoutingapicred
|
||||
annotations:
|
||||
policies.kyverno.io/category: API Server Access Control
|
||||
policies.kyverno.io/description: Kubernetes automounts default service account credentials in each pod.
|
||||
To restrict access, opt out of automounting credentials by setting 'automountServiceAccountToken' to 'false'.
|
||||
spec:
|
||||
rules:
|
||||
- name: disallow-automoutingapicred
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Deny automounting API credentials"
|
||||
pattern:
|
||||
spec:
|
||||
=(serviceAccountName): "*"
|
||||
automountServiceAccountToken: false
|
|
@ -1,26 +1,26 @@
|
|||
apiVersion: "kyverno.io/v1alpha1"
|
||||
kind: "ClusterPolicy"
|
||||
metadata:
|
||||
name: "deny-use-of-host-fs"
|
||||
name: "disallow-bind-mounts"
|
||||
annotations:
|
||||
policies.kyverno.io/category: Data Protection
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: The volume of type `hostPath` allows pods to use host bind
|
||||
mounts (i.e. directories and volumes mounted to a host path) in containers. Using host
|
||||
resources can be used to access shared data or escalate priviliges. Also, this couples pods
|
||||
resources can be used to access shared data or escalate privileges. Also, this couples pods
|
||||
to a specific host and data persisted in the `hostPath` volume is coupled to the life of the
|
||||
node leading to potential pod scheduling failures. It is highly recommeded that applications
|
||||
are designed to be decoupled from the underlying infrstructure (in this case, nodes).
|
||||
node leading to potential pod scheduling failures. It is highly recommended that applications
|
||||
are designed to be decoupled from the underlying infrastructure (in this case, nodes).
|
||||
|
||||
spec:
|
||||
rules:
|
||||
- name: "deny-use-of-host-fs"
|
||||
- name: "validate-hostPath"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- "Pod"
|
||||
validate:
|
||||
message: "Host path is not allowed"
|
||||
message: "Host path volumes are not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
volumes:
|
||||
- X(hostPath): null
|
||||
- X(hostPath): null
|
|
@ -1,24 +1,26 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-namespace
|
||||
annotations:
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: With many users spread across multiple teams, restricting
|
||||
use of the default namespace and subdividing the cluster by namesoace isolates workloads.
|
||||
name: disallow-default-namespace
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: Kubernetes namespaces are an optional feature
|
||||
that provide a way to segment and isolate cluster resources across multiple
|
||||
applications and users. As a best practice, workloads should be isolated with
|
||||
namespaces. Namespaces should be required and the default (empty) namespace
|
||||
should not be used.
|
||||
spec:
|
||||
rules:
|
||||
- name: check-default-namespace
|
||||
- name: validate-namespace
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Using 'default' namespace is restricted"
|
||||
message: "Using 'default' namespace is not allowed"
|
||||
pattern:
|
||||
metadata:
|
||||
namespace: "!default"
|
||||
- name: check-namespace-exist
|
||||
- name: require-namespace
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
@ -28,3 +30,4 @@ spec:
|
|||
pattern:
|
||||
metadata:
|
||||
namespace: "?*"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: host-network-port
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: Using 'hostPort' and 'hostNetwork' allows pods to share
|
||||
the host network stack, allowing potential snooping of network traffic from an application pod.
|
||||
spec:
|
|
@ -1,9 +1,9 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-host-pid-ipc
|
||||
name: disallow-host-pid-ipc
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: Sharing the host's PID namespace allows visibility of process
|
||||
on the host, potentially exposing process information. Sharing the host's IPC namespace allows
|
||||
the container process to communicate with processes on the host. To avoid pod container from
|
||||
|
@ -11,7 +11,7 @@ metadata:
|
|||
spec:
|
||||
validationFailureAction: audit
|
||||
rules:
|
||||
- name: validate-host-pid-ipc
|
||||
- name: validate-hostPID-hostIPC
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
|
@ -1,32 +1,32 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-image-tag
|
||||
name: disallow-latest-tag
|
||||
annotations:
|
||||
policies.kyverno.io/category: Image
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: The ':latest' tag is mutable and can lead to
|
||||
unexpected errors if the image changes. A best practice is to use an immutable
|
||||
tag that maps to a specific version of an application pod.
|
||||
spec:
|
||||
rules:
|
||||
- name: image-tag-notspecified
|
||||
- name: require-image-tag
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Image tag not specified"
|
||||
message: "An image tag is required"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- image: "*:*"
|
||||
- name: image-tag-not-latest
|
||||
- name: validate-image-tag
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Using 'latest' image tag is restricted. Set image tag to a specific version"
|
||||
message: "Using a mutable image tag e.g. 'latest' is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
|
@ -1,9 +1,9 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-new-capabilities
|
||||
name: disallow-new-capabilities
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: Linux allows defining fine-grained permissions using
|
||||
capabilities. With Kubernetes, it is possible to add capabilities that escalate the
|
||||
level of kernel access and allow other potentially dangerous behaviors. This policy
|
||||
|
@ -11,13 +11,13 @@ metadata:
|
|||
default capabilities.
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-new-capabilities
|
||||
- name: validate-add-capabilities
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Capabilities cannot be added"
|
||||
message: "New capabilities cannot be added"
|
||||
anyPattern:
|
||||
- spec:
|
||||
=(securityContext):
|
||||
|
@ -28,4 +28,4 @@ spec:
|
|||
- name: "*"
|
||||
=(securityContext):
|
||||
=(capabilities):
|
||||
X(add): null
|
||||
X(add): null
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-deny-privileged-priviligedescalation
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/description: Privileged containers are defined as any container
|
||||
where the container uid 0 is mapped to the host’s uid 0. A process within privileged
|
||||
containers can get unrestricted host access. With 'securityContext.allowPrivilegeEscalation'
|
||||
enabled a process can gain privileges from its parent. To disallow privileged containers
|
||||
and the escalation of privileges it is recommended to run pod containers with
|
||||
'securityContext.priveleged' as 'false' and 'allowPrivilegeEscalation' as 'false'.
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-privileged-priviligedescalation
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
- spec:
|
||||
containers:
|
||||
- name: "*"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
46
samples/best_practices/disallow_privileged.yaml
Normal file
46
samples/best_practices/disallow_privileged.yaml
Normal file
|
@ -0,0 +1,46 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-privileged
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: Privileged containers are defined as any
|
||||
container where the container uid 0 is mapped to the host’s uid 0.
|
||||
A process within a privileged container can get unrestricted host access.
|
||||
With `securityContext.allowPrivilegeEscalation` enabled, a process can
|
||||
gain privileges from its parent.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-privileged
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Privileged mode is not allowed. Set privileged to false"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
||||
privileged: false
|
||||
- spec:
|
||||
containers:
|
||||
- name: "*"
|
||||
securityContext:
|
||||
privileged: false
|
||||
- name: validate-allowPrivilegeEscalation
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Privileged mode is not allowed. Set allowPrivilegeEscalation to false"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
- spec:
|
||||
containers:
|
||||
- name: "*"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-deny-runasrootuser
|
||||
name: disallow-root-user
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: By default, processes in a container run as a
|
||||
root user (uid 0). To prevent potential compromise of container hosts, specify a
|
||||
least privileged user ID when building the container image and require that
|
||||
application containers run as non root users.
|
||||
spec:
|
||||
rules:
|
||||
- name: deny-runasrootuser
|
||||
- name: validate-runAsNonRoot
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Root user is not allowed. Set runAsNonRoot to true"
|
||||
message: "Running as root user is not allowed. Set runAsNonRoot to true"
|
||||
anyPattern:
|
||||
- spec:
|
||||
securityContext:
|
22
samples/best_practices/disallow_sysctls.yaml
Normal file
22
samples/best_practices/disallow_sysctls.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-sysctls
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: The Sysctl interface allows modifications to kernel parameters
|
||||
at runtime. In a Kubernetes pod these parameters can be specified under `securityContext.sysctls`.
|
||||
Kernel parameter modifications can be used for exploits and should be restricted.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-sysctls
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Changes to kernel paramaters are not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
X(sysctls): null
|
|
@ -1,20 +0,0 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: known-ingress
|
||||
annotations:
|
||||
policies.kyverno.io/category: Ingress
|
||||
policies.kyverno.io/description:
|
||||
spec:
|
||||
rules:
|
||||
- name: known-ingress
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Ingress
|
||||
validate:
|
||||
message: "Unknown ingress class"
|
||||
pattern:
|
||||
metadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "F5 | nginx"
|
|
@ -1,27 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: default-deny-ingress-networkpolicy
|
||||
annotations:
|
||||
policies.kyverno.io/category: NetworkPolicy
|
||||
policies.kyverno.io/description: By default, Kubernetes allows all ingress and egress traffic
|
||||
to and from pods within a cluster. A "default" NetworkPolicy resource for a namespace should
|
||||
be used to deny all ingress traffic to the pods in that namespace. Additional NetworkPolicy
|
||||
resources can then be configured to allow desired traffic to application pods.
|
||||
spec:
|
||||
rules:
|
||||
- name: "default-deny-ingress"
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
name: "*"
|
||||
generate:
|
||||
kind: NetworkPolicy
|
||||
name: default-deny-ingress
|
||||
data:
|
||||
spec:
|
||||
# select all pods in the namespace
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
|
@ -1,26 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-namespace-quota
|
||||
annotations:
|
||||
policies.kyverno.io/category: Resource Quota
|
||||
policies.kyverno.io/description: To limit the number of objects, as well as the
|
||||
total amount of compute that may be consumed by an application, it is important
|
||||
to create resource limits and quotas for each namespace.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-namespace-quota
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
generate:
|
||||
kind: ResourceQuota
|
||||
name: "defaultresourcequota"
|
||||
data:
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: 4
|
||||
requests.memory: 16Gi
|
||||
limits.cpu: 4
|
||||
limits.memory: 16Gi
|
|
@ -1,9 +1,9 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: check-resource
|
||||
name: require-pod-requests-limits
|
||||
annotations:
|
||||
policies.kyverno.io/category: Resource Quota
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: As application workloads share cluster resources, it is important
|
||||
to limit resources requested and consumed by each pod. It is recommended to require
|
||||
'resources.requests' and 'resources.limits' per pod. If a namespace level request or limit is
|
||||
|
@ -11,7 +11,7 @@ metadata:
|
|||
spec:
|
||||
validationFailureAction: "audit"
|
||||
rules:
|
||||
- name: check-resource-request-limit
|
||||
- name: validate-resources
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-probes
|
||||
name: require-pod-probes
|
||||
annotations:
|
||||
policies.kyverno.io/category: Health Check
|
||||
policies.kyverno.io/description: For each pod, a 'livenessProbe' is carried out by the kubelet to
|
||||
determine when to restart a container. A 'readinessProbe' is used by services and deployments to
|
||||
determine if the pod is ready to recieve network traffic. Both liveness and readiness probes
|
||||
need to be configured to manage the pod lifecycle during restarts and upgrades.
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: Liveness and readiness probes need to be configured to
|
||||
correctly manage a pods lifecycle during deployments, restarts, and upgrades. For each
|
||||
pod, a periodic `livenessProbe` is performed by the kubelet to determine if the pod's
|
||||
containers are running or need to be restarted. A `readinessProbe` is used by services
|
||||
and deployments to determine if the pod is ready to receive network traffic.
|
||||
spec:
|
||||
rules:
|
||||
- name: check-probes
|
||||
- name: validate-livenessProbe-readinessProbe
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-readonly-rootfilesystem
|
||||
name: require-ro-rootfs
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: A read-only root file system helps to enforce an immutable
|
||||
infrastructure strategy; the container only needs to write on the mounted volume that p
|
||||
ersists the state. An immutable root filesystem can also prevent malicious binaries from
|
||||
writing to the host system.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-readonly-rootfilesystem
|
||||
- name: validate-readOnlyRootFilesystem
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Container require read-only rootfilesystem"
|
||||
message: "Root filesystem must be read-only"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
|
@ -1,24 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-container-capablities
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/description: Linux divides the privileges traditionally associated with
|
||||
superuser into distinct units, known as capabilities, which can be independently enabled
|
||||
or disabled by listing them in 'securityContext.capabilites'.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-container-capablities
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Allow certain linux capability"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"]
|
|
@ -1,26 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-allow-portrange-with-sysctl
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/description: The Sysctl interface allows to modify kernel parameters at
|
||||
runtime and in the pod can be specified under 'securityContext.sysctls'. If kernel parameters
|
||||
in the pod are to be modified, should be handled cautiously, and policy with rules restricting
|
||||
these options will be helpful. We can control minimum and maximum port that a network connection
|
||||
can use as its source(local) port by checking 'net.ipv4.ip_local_port_range'.
|
||||
spec:
|
||||
rules:
|
||||
- name: allow-portrange-with-sysctl
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Allowed port range is from 1024 to 65535"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
sysctls:
|
||||
- name: net.ipv4.ip_local_port_range
|
||||
value: "1024 65535"
|
|
@ -1,48 +0,0 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: validate-userid-groupid-fsgroup
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security Context
|
||||
policies.kyverno.io/description: All processes inside the pod can be made to run with specific user
|
||||
and groupID by setting 'runAsUser' and 'runAsGroup' respectively. 'fsGroup' can be specified
|
||||
to make sure any file created in the volume with have the specified groupID. These options can be
|
||||
used to validate the IDs used for user and group.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-userid
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "User ID should be 1000"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
- name: validate-groupid
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Group ID should be 3000"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsGroup: 3000
|
||||
- name: validate-fsgroup
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "fsgroup should be 2000"
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 2000
|
||||
# Alls processes inside the pod can be made to run with specific user and groupID by setting runAsUser and runAsGroup respectively.
|
||||
# fsGroup can be specified to make sure any file created in the volume with have the specified groupID.
|
||||
# The above parameters can also be used in a validate policy to restrict user & group IDs.
|
22
samples/more/restrict_automount_sa_token.yaml
Normal file
22
samples/more/restrict_automount_sa_token.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: restrict-automount-sa-token
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/description: Kubernetes automatically mounts service account
|
||||
credentials in each pod. The service account may be assigned roles allowing pods
|
||||
to access API resources. To restrict access, opt out of auto-mounting tokens by
|
||||
setting automountServiceAccountToken to false.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-automountServiceAccountToken
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Auto-mounting of Service Account tokens is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
|
@ -1,21 +1,20 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: trusted-registries
|
||||
name: restrict-image-registries
|
||||
annotations:
|
||||
policies.kyverno.io/category: Image
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: Images from unknown registries may not be scanned and secured.
|
||||
Requiring use of known registries helps reduce threat exposure. You can customize this policy
|
||||
to allow image registries that you trust.
|
||||
Requiring use of known registries helps reduce threat exposure.
|
||||
spec:
|
||||
rules:
|
||||
- name: trusted-registries
|
||||
- name: validate-registries
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Deny untrusted registries"
|
||||
message: "Unknown image registry"
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
22
samples/more/restrict_ingress_classes.yaml
Normal file
22
samples/more/restrict_ingress_classes.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: restrict-ingress-classes
|
||||
annotations:
|
||||
policies.kyverno.io/category: Workload Management
|
||||
policies.kyverno.io/description: It can be useful to restrict Ingress resources to a set of
|
||||
known ingress classes that are allowed in the cluster. You can customize this policy to
|
||||
allow ingress classes that are configured in the cluster.
|
||||
spec:
|
||||
rules:
|
||||
- name: validate-ingress
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Ingress
|
||||
validate:
|
||||
message: "Unknown ingress class"
|
||||
pattern:
|
||||
metadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "F5 | nginx"
|
|
@ -1,22 +1,22 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-node-port
|
||||
name: restrict-nodeport
|
||||
annotations:
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/category: Workload Isolation
|
||||
policies.kyverno.io/description: A Kubernetes service of type NodePort uses a
|
||||
host port to receive traffic from any source. A 'NetworkPolicy' resource cannot be used
|
||||
to control traffic to host ports. Although 'NodePort' services can be useful, their use
|
||||
must be limited to services with additional upstream security checks.
|
||||
spec:
|
||||
rules:
|
||||
- name: disallow-node-port
|
||||
- name: validate-nodeport
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Service
|
||||
validate:
|
||||
message: "Disallow service of type NodePort"
|
||||
message: "Services of type NodePort are not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
type: "!NodePort"
|
|
@ -8,4 +8,4 @@ spec:
|
|||
image: nginxinc/nginx-unprivileged
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: false
|
||||
privileged: true
|
|
@ -1,6 +1,6 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_default_network_policy.yaml
|
||||
policy: samples/best_practices/add_network_policy.yaml
|
||||
resource: test/resources/require_default_network_policy.yaml
|
||||
expected:
|
||||
generation:
|
||||
|
@ -9,7 +9,7 @@ expected:
|
|||
kind: NetworkPolicy
|
||||
namespace: devtest
|
||||
policyresponse:
|
||||
policy: default-deny-ingress-networkpolicy
|
||||
policy: add-networkpolicy
|
||||
resource:
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
|
@ -1,22 +1,21 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_namespace_quota.yaml
|
||||
policy: samples/best_practices/add_ns_quota.yaml
|
||||
resource: test/resources/require_namespace_quota.yaml
|
||||
expected:
|
||||
generation:
|
||||
generatedResources:
|
||||
- name: defaultresourcequota
|
||||
- name: default-resourcequota
|
||||
kind: ResourceQuota
|
||||
namespace: test-namespace-quota
|
||||
policyresponse:
|
||||
policy: generate-namespace-quota
|
||||
policy: add-ns-quota
|
||||
resource:
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: test-namespace-quota
|
||||
rules:
|
||||
- name: generate-namespace-quota
|
||||
- name: generate-resourcequota
|
||||
type: Generation
|
||||
success: true
|
||||
message: created resource ResourceQuota/test-namespace-quota/defaultresourcequota
|
|
@ -1,19 +1,19 @@
|
|||
# file path is relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/add_safe-to-evict_annotation.yaml
|
||||
policy: samples/best_practices/add_safe_to_evict.yaml
|
||||
resource: test/resources/pod-with-emptydir.yaml
|
||||
expected:
|
||||
mutation:
|
||||
patchedresource: test/output/pod-with-emptydir.yaml
|
||||
policyresponse:
|
||||
policy: annotate-emptydir-hostpath
|
||||
policy: add-safe-to-evict
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: pod-with-emptydir
|
||||
rules:
|
||||
- name: empty-dir-add-safe-to-evict
|
||||
- name: annotate-empty-dir
|
||||
type: Mutation
|
||||
success: true
|
||||
message: "successfully processed overlay"
|
|
@ -1,19 +1,19 @@
|
|||
# file path is relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/add_safe-to-evict_annotation.yaml
|
||||
policy: samples/best_practices/add_safe_to_evict.yaml
|
||||
resource: test/resources/pod-with-hostpath.yaml
|
||||
expected:
|
||||
mutation:
|
||||
patchedresource: test/output/pod-with-hostpath.yaml
|
||||
policyresponse:
|
||||
policy: annotate-emptydir-hostpath
|
||||
policy: add-safe-to-evict
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: pod-with-hostpath
|
||||
rules:
|
||||
- name: empty-dir-add-safe-to-evict
|
||||
- name: annotate-host-path
|
||||
type: Mutation
|
||||
success: true
|
||||
message: "successfully processed overlay"
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_host_filesystem.yaml
|
||||
policy: samples/best_practices/disallow_bind_mounts.yaml
|
||||
resource: test/resources/disallow_host_filesystem.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: deny-use-of-host-fs
|
||||
policy: disallow-bind-mounts
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: image-with-hostpath
|
||||
rules:
|
||||
- name: deny-use-of-host-fs
|
||||
- name: validate-hostPath
|
||||
type: Validation
|
||||
message: "Validation error: Host path is not allowed\nValidation rule 'deny-use-of-host-fs' failed at path '/spec/volumes/0/hostPath/'."
|
||||
success: false
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_host_filesystem.yaml
|
||||
policy: samples/best_practices/disallow_bind_mounts.yaml
|
||||
resource: test/resources/disallow_host_filesystem_pass.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: deny-use-of-host-fs
|
||||
policy: disallow-bind-mounts
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: image-with-hostpath
|
||||
rules:
|
||||
- name: deny-use-of-host-fs
|
||||
- name: validate-hostPath
|
||||
type: Validation
|
||||
message: Validation rule 'deny-use-of-host-fs' succeeded.
|
||||
success: true
|
|
@ -5,7 +5,7 @@ input:
|
|||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-namespace
|
||||
policy: disallow-default-namespace
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
|
@ -14,12 +14,10 @@ expected:
|
|||
namespace: 'default'
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: check-default-namespace
|
||||
- name: validate-namespace
|
||||
type: Validation
|
||||
message: "Validation error: Using 'default' namespace is restricted\nValidation rule 'check-default-namespace' failed at path '/metadata/namespace/'."
|
||||
success: false
|
||||
- name: check-namespace-exist
|
||||
- name: require-namespace
|
||||
type: Validation
|
||||
message: "Validation rule 'check-namespace-exist' succeeded."
|
||||
success: true
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_host_network_hostport.yaml
|
||||
policy: samples/best_practices/disallow_host_network_port.yaml
|
||||
resource: test/resources/disallow_host_network_hostport.yaml
|
||||
expected:
|
||||
validation:
|
||||
|
@ -17,4 +17,4 @@ expected:
|
|||
success: true
|
||||
- name: validate-host-port
|
||||
type: Validation
|
||||
success: false
|
||||
success: false
|
|
@ -1,17 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_hostpid_hostipc.yaml
|
||||
policy: samples/best_practices/disallow_host_pid_ipc.yaml
|
||||
resource: test/resources/disallow_hostpid_hostipc.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-host-pid-ipc
|
||||
policy: disallow-host-pid-ipc
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: "nginx-with-hostpid"
|
||||
rules:
|
||||
- name: validate-host-pid-ipc
|
||||
- name: validate-hostPID-hostIPC
|
||||
type: Validation
|
||||
success: false
|
||||
success: false
|
|
@ -0,0 +1,20 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_latest_tag.yaml
|
||||
resource: test/resources/pod_with_latest_tag.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: disallow-latest-tag
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: require-image-tag
|
||||
type: Validation
|
||||
success: true
|
||||
- name: validate-image-tag
|
||||
type: Validation
|
||||
success: false
|
|
@ -0,0 +1,20 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_latest_tag.yaml
|
||||
resource: test/resources/pod_with_version_tag.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: disallow-latest-tag
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: require-image-tag
|
||||
type: Validation
|
||||
success: true
|
||||
- name: validate-image-tag
|
||||
type: Validation
|
||||
success: true
|
|
@ -5,14 +5,13 @@ input:
|
|||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-new-capabilities
|
||||
policy: disallow-new-capabilities
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: "add-new-capabilities"
|
||||
rules:
|
||||
- name: deny-new-capabilities
|
||||
- name: validate-add-capabilities
|
||||
type: Validation
|
||||
message: "Validation error: Capabilities cannot be added\nValidation rule deny-new-capabilities anyPattern[0] failed at path /spec/.\nValidation rule deny-new-capabilities anyPattern[1] failed at path /spec/containers/0/securityContext/capabilities/add/."
|
||||
success: false
|
|
@ -0,0 +1,20 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_privileged.yaml
|
||||
resource: test/resources/disallow_privileged.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: disallow-privileged
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: check-privileged-cfg
|
||||
rules:
|
||||
- name: validate-privileged
|
||||
type: Validation
|
||||
success: false
|
||||
- name: validate-allowPrivilegeEscalation
|
||||
type: Validation
|
||||
success: false
|
|
@ -1,19 +1,18 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/deny_runasrootuser.yaml
|
||||
policy: samples/best_practices/disallow_root_user.yaml
|
||||
resource: test/resources/deny_runasrootuser.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-deny-runasrootuser
|
||||
policy: disallow-root-user
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: check-root-user
|
||||
rules:
|
||||
- name: deny-runasrootuser
|
||||
- name: validate-runAsNonRoot
|
||||
type: Validation
|
||||
message: "Validation rule 'deny-runasrootuser' anyPattern[1] succeeded."
|
||||
success: true
|
||||
|
18
test/scenarios/samples/best_practices/disallow_sysctls.yaml
Normal file
18
test/scenarios/samples/best_practices/disallow_sysctls.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_sysctls.yaml
|
||||
resource: test/resources/resource_validate_sysctl_configs.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: disallow-sysctls
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: nginx
|
||||
rules:
|
||||
- name: validate-sysctls
|
||||
type: Validation
|
||||
success: false
|
|
@ -5,14 +5,13 @@ input:
|
|||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: check-resource
|
||||
policy: require-pod-requests-limits
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: check-resource-request-limit
|
||||
- name: validate-resources
|
||||
type: Validation
|
||||
message: "Validation error: CPU and memory resource requests and limits are required\nValidation rule 'check-resource-request-limit' failed at path '/spec/containers/0/resources/limits/cpu/'."
|
||||
success: false
|
|
@ -5,14 +5,13 @@ input:
|
|||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-probes
|
||||
policy: require-pod-probes
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: check-probes
|
||||
- name: validate-livenessProbe-readinessProbe
|
||||
type: Validation
|
||||
message: "Validation error: Liveness and readiness probes are required\nValidation rule 'check-probes' failed at path '/spec/containers/0/livenessProbe/'."
|
||||
success: false
|
17
test/scenarios/samples/best_practices/require_ro_rootfs.yaml
Normal file
17
test/scenarios/samples/best_practices/require_ro_rootfs.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_ro_rootfs.yaml
|
||||
resource: test/resources/require_readonly_rootfilesystem.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: require-ro-rootfs
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: "ghost-with-readonly-rootfilesystem"
|
||||
rules:
|
||||
- name: validate-readOnlyRootFilesystem
|
||||
type: Validation
|
||||
success: false
|
|
@ -1,22 +0,0 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_image_tag_not_latest.yaml
|
||||
resource: test/resources/require_image_tag_not_latest_deny.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-image-tag
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: image-tag-notspecified
|
||||
type: Validation
|
||||
message: "Validation rule 'image-tag-notspecified' succeeded."
|
||||
success: true
|
||||
- name: image-tag-not-latest
|
||||
type: Validation
|
||||
message: "Validation error: Using 'latest' image tag is restricted. Set image tag to a specific version\nValidation rule 'image-tag-not-latest' failed at path '/spec/containers/0/image/'."
|
||||
success: false
|
|
@ -1,22 +0,0 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_image_tag_not_latest.yaml
|
||||
resource: test/resources/resource_validate_image_tag_latest_pass.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-image-tag
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: image-tag-notspecified
|
||||
type: Validation
|
||||
message: "Validation rule 'image-tag-notspecified' succeeded."
|
||||
success: true
|
||||
- name: image-tag-not-latest
|
||||
type: Validation
|
||||
message: "Validation rule 'image-tag-not-latest' succeeded."
|
||||
success: true
|
|
@ -1,19 +0,0 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_priviledged_priviligedescalation.yaml
|
||||
resource: test/resources/disallow_priviledged_priviligedescalation.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-deny-privileged-priviligedescalation
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: check-privileged-cfg
|
||||
rules:
|
||||
- name: deny-privileged-priviligedescalation
|
||||
type: Validation
|
||||
message: "Validation error: Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false\nValidation rule deny-privileged-priviligedescalation anyPattern[0] failed at path /spec/securityContext/.\nValidation rule deny-privileged-priviligedescalation anyPattern[1] failed at path /spec/containers/0/securityContext/allowPrivilegeEscalation/."
|
||||
success: false
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/require_readonly_rootfilesystem.yaml
|
||||
resource: test/resources/require_readonly_rootfilesystem.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-readonly-rootfilesystem
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: "ghost-with-readonly-rootfilesystem"
|
||||
rules:
|
||||
- name: validate-readonly-rootfilesystem
|
||||
type: Validation
|
||||
message: "Validation error: Container require read-only rootfilesystem\nValidation rule 'validate-readonly-rootfilesystem' failed at path '/spec/containers/0/securityContext/readOnlyRootFilesystem/'."
|
||||
success: false
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/disallow_automountingapicred.yaml
|
||||
policy: samples/more/restrict_automount_sa_token.yaml
|
||||
resource: test/resources/disallow_automountingapicred.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-disallow-automoutingapicred
|
||||
policy: restrict-automount-sa-token
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: myapp-pod
|
||||
rules:
|
||||
- name: disallow-automoutingapicred
|
||||
- name: validate-automountServiceAccountToken
|
||||
type: Validation
|
||||
message: Validation rule 'disallow-automoutingapicred' succeeded.
|
||||
success: true
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/trusted_image_registries.yaml
|
||||
policy: samples/more/restrict_image_registries.yaml
|
||||
resource: test/resources//trusted_image_registries.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: trusted-registries
|
||||
policy: restrict-image-registries
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: k8s-nginx
|
||||
rules:
|
||||
- name: trusted-registries
|
||||
- name: validate-registries
|
||||
type: Validation
|
||||
message: Validation rule 'trusted-registries' succeeded.
|
||||
success: true
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/known_ingress.yaml
|
||||
policy: samples/more/restrict_ingress_classes.yaml
|
||||
resource: test/resources/ingress-nginx.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: known-ingress
|
||||
policy: restrict-ingress-classes
|
||||
resource:
|
||||
kind: Ingress
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: test-ingress
|
||||
rules:
|
||||
- name: known-ingress
|
||||
- name: validate-ingress
|
||||
type: Validation
|
||||
message: Validation rule 'known-ingress' succeeded.
|
||||
success: true
|
|
@ -1,17 +1,16 @@
|
|||
input:
|
||||
policy: samples/best_practices/disallow_node_port.yaml
|
||||
policy: samples/more/restrict_node_port.yaml
|
||||
resource: test/resources/disallow_node_port.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: disallow-node-port
|
||||
policy: restrict-nodeport
|
||||
resource:
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: "my-service"
|
||||
rules:
|
||||
- name: disallow-node-port
|
||||
- name: validate-nodeport
|
||||
type: Validation
|
||||
message: "Validation error: Disallow service of type NodePort\nValidation rule 'disallow-node-port' failed at path '/spec/type/'."
|
||||
success: false
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/more/policy_validate_container_capabilities.yaml
|
||||
resource: test/resources/resource_validate_container_capabilities.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-container-capablities
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: add-capabilities
|
||||
rules:
|
||||
- name: validate-container-capablities
|
||||
type: Validation
|
||||
message: "Validation error: Allow certain linux capability\nValidation rule 'validate-container-capablities' failed at path '/spec/containers/0/securityContext/capabilities/add/0/'."
|
||||
success: false
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/more/policy_validate_user_group_fsgroup_id.yaml
|
||||
resource: test/resources/resource_validate_fsgroup.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-userid-groupid-fsgroup
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: fsgroup-demo
|
||||
rules:
|
||||
- name: validate-userid
|
||||
type: Validation
|
||||
message: Validation rule 'validate-userid' succeeded.
|
||||
success: true
|
||||
- name: validate-groupid
|
||||
type: Validation
|
||||
message: Validation rule 'validate-groupid' succeeded.
|
||||
success: true
|
||||
- name: validate-fsgroup
|
||||
type: Validation
|
||||
message: Validation rule 'validate-fsgroup' succeeded.
|
||||
success: true
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/more/policy_validate_sysctl_configs.yaml
|
||||
resource: test/resources/resource_validate_sysctl_configs.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: validate-allow-portrange-with-sysctl
|
||||
resource:
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: nginx
|
||||
rules:
|
||||
- name: allow-portrange-with-sysctl
|
||||
type: Validation
|
||||
message: "Validation error: Allowed port range is from 1024 to 65535\nValidation rule 'allow-portrange-with-sysctl' failed at path '/spec/securityContext/sysctls/0/value/'."
|
||||
success: false
|
|
@ -1,18 +1,17 @@
|
|||
# file path relative to project root
|
||||
input:
|
||||
policy: samples/best_practices/known_ingress.yaml
|
||||
policy: samples/more/restrict_ingress_classes.yaml
|
||||
resource: test/resources/ingress-haproxy.yaml
|
||||
expected:
|
||||
validation:
|
||||
policyresponse:
|
||||
policy: known-ingress
|
||||
policy: restrict-ingress-classes
|
||||
resource:
|
||||
kind: Ingress
|
||||
apiVersion: v1
|
||||
namespace: ''
|
||||
name: test-ingress
|
||||
rules:
|
||||
- name: known-ingress
|
||||
- name: validate-ingress
|
||||
type: Validation
|
||||
message: "Validation error: Unknown ingress class\nValidation rule 'known-ingress' failed at path '/metadata/annotations/kubernetes.io/ingress.class/'."
|
||||
success: false
|
Loading…
Reference in a new issue