# Policy

The policy is defined as K8s `Custom Resource Definition` (CRD). it's API version is still `v1alpha1` since this is a first release
that is yet to be tested and mature into a v1beta1.

The policy implements the `ObjectMeta` attibutes, which means is must have a name, and can have `labels` and `annotations`.

#### remediationAction

`remediationAction: "enforce"`  describes what type of action the policy-controller should take when a policy is created.
The two actions supported are `enforce` or `inform`. With `infrom` only the policy status is updated showing weather the cluster
it is deployed at is compliant or not (and if not, the reasons why not). 
On the other hand, `enforce` will trigger the policy-contoller to take actions remediate the cluster state to a compliant state. 
This may entail creating/deleting objects (such as RBAC roles), or modifying existing ones. 

#### namespaces
A policy can apply to one or many namepsaces. We support the use of the asterisk `*` wild card to specify of set of namespaces.

```
  namespaces:
    include: ["*"]
    exclude: ["kube*"]
```
the `*` wild card can be used alone to denote `all-namespaces`, e.g. `include: ["*"]` or it can be used with a prefix or suffix
such as `exclude: ["kube*"]` which would mean exclude all namespaces that start with `kube`.
We can also use the double `*` to express containment. For instance `exclude: ["*kube*"]` will exclude all the namespaces
that inlude `kube`in their names. There are only 3 uses supported for the `*` : *suffix, prefix* and *containment*.

#### templates
A template is a description of how which object are allowed to exist and in which format they can exist.

In the example below we see a template with a RBAC role template. In this `roleTemplate` we can specify which K8s RBAC roles are involved using:
```
metadata:
  namespace: "" # will be inferred
  name: operator
selector:
  matchLabels:
    dev: "true"

```
this will select the Role named `operator` that has a label `dev: "true"`. Note that instead of a unique name we could have specfied a set of RBAC roles using the `*` wildcard. for instance `name: "*"` would have meant select all RBAC roles with label `dev: "true"`.

The namespaces will be infered from the policy namespaces described above. Since RBAC roles are namespaced, the policy will apply for all the RBAC role that are in the namepsaces specified by the policy. 

#### RoleTemplate ComplianceType

Within a template we can have a `complianceType` at various levels. at the higher level, the `complianceType: "musthave"` signifies that the role must exist. However the policy-controller can only create the role if the role template has a fully qualified name, i.e. without `*`. Since the policy-controller needs a full name to be specified when creating an RBAC role. If the name resolves to a set of RBAC roles, or if the RBAC role already exists, then the controller will perfrom a `deep-compare` to check if the existing RBAC roles that are selected based on their names and labels satisfy the rule conditions.

If at the higher level we have a  `complianceType: "mustnothave"` then all the RBAC that match the set of names and labels will be deleted by the policy-controller.

If at the higher level we have a  `complianceType: "mustonlyhave"` then all the RBAC that match the set of names and labels will be kept, if they are missing and the name is fully qualified then the role is created. if they exist  then the controller will perfrom a `deep-compare` to check if the existing RBAC roles that are selected based on their names and labels satisfy the rule conditions.


At the lower level (i.e. rule level), the `complianceType: "musthave"` signifies that the rule must have the specified verbs for the specified resource(s) within the specified API group(s). for example this rule:
```
  - complianceType: "musthave" # at this level, it means if the role exists the rule is a musthave
    policyRule:
      apiGroups: ["extensions", "apps"]
      resources: ["deployments"]
      verbs: ["get", "list", "watch", "create", "delete","patch"]
```

Translates to:

`deployments.extensions  musthave              [get list watch create delete]`

`deployments.apps        musthave              [get list watch create delete]`

the same logic applies for the `mustnothave`.

The `mustonlyhave` is slightly different. It signifies only the verbs specified under that rule are allowed for a given resource.APIgroup.




```
apiVersion: policy.mcm.io/v1alpha1
kind: Policy
metadata:
  name: policy03
  description: Instance descriptor for policy resource
spec:
  remediationAction: "enforce" # enforce or inform 
  namespaces:
    include: ["*"]
    exclude: ["kube*"]
  templates:
    - kind: RoleTemplate
      apiVersion: roletemplate.mcm.io/v1alpha1
      complianceType: "musthave" # at this level, it means the role must exist with the rules that it musthave below
      metadata:
        namespace: "" # will be inferred
        name: operator
      selector:
        matchLabels:
          dev: "true"
      rules:
        - complianceType: "musthave" # at this level, it means if the role exists the rule is a musthave
          policyRule:
            apiGroups: ["extensions", "apps"]
            resources: ["deployments"]
            verbs: ["get", "list", "watch", "create", "delete","patch"]
        - complianceType: "mustnothave" # at this level, it means if the role exists the rule is a mustnothave  
          policyRule:
            apiGroups: ["core"]
            resources: ["secrets"]
            verbs: ["get", "watch", "list", "create", "delete", "update", "patch"]  

    
  
#PolicyRule:
#Resources               Non-Resource URLs  Resource Names  Verbs
#---------               -----------------  --------------  -----
```
