From 25a70d6b1ee7627b89e8ab38e8b1b8059267a3cd Mon Sep 17 00:00:00 2001 From: Marco Iorio Date: Sat, 2 Apr 2022 18:38:30 +0200 Subject: [PATCH 1/2] Remove the OPA policies folder --- .github/workflows/test.yml | 18 - deploy/crownlabs/Chart.lock | 7 +- deploy/crownlabs/Chart.yaml | 5 - infrastructure/policy-enforcement/README.md | 26 - .../examples/config-sync.yaml | 14 - .../examples/constraint.yaml | 11 - .../examples/constraintTemplate.yaml | 28 - policies/.gitignore | 2 - policies/.helmignore | 27 - policies/Chart.yaml | 20 - policies/README.md | 155 ----- .../policies/instance-template-reference.rego | 28 - .../instance-template-reference_test.rego | 156 ----- policies/policies/tenant-patch.rego | 126 ---- policies/policies/tenant-patch_test.rego | 647 ------------------ policies/templates/_helpers.tpl | 60 -- policies/templates/config-sync.yaml | 23 - policies/templates/constraint-template.yaml | 18 - .../templates/hook-create-constraint.yaml | 138 ---- policies/values.yaml | 67 -- 20 files changed, 2 insertions(+), 1574 deletions(-) delete mode 100644 infrastructure/policy-enforcement/README.md delete mode 100644 infrastructure/policy-enforcement/examples/config-sync.yaml delete mode 100644 infrastructure/policy-enforcement/examples/constraint.yaml delete mode 100644 infrastructure/policy-enforcement/examples/constraintTemplate.yaml delete mode 100644 policies/.gitignore delete mode 100644 policies/.helmignore delete mode 100644 policies/Chart.yaml delete mode 100644 policies/README.md delete mode 100644 policies/policies/instance-template-reference.rego delete mode 100644 policies/policies/instance-template-reference_test.rego delete mode 100644 policies/policies/tenant-patch.rego delete mode 100644 policies/policies/tenant-patch_test.rego delete mode 100644 policies/templates/_helpers.tpl delete mode 100644 policies/templates/config-sync.yaml delete mode 100644 policies/templates/constraint-template.yaml delete mode 100644 policies/templates/hook-create-constraint.yaml delete mode 100644 policies/values.yaml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 649ab6441..d710ac3dc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -213,21 +213,3 @@ jobs: docker run -v ${{ github.workspace }}:/CrownLabs zegl/kube-score:v1.11.0 score \ --ignore-test=pod-networkpolicy,container-security-context,container-image-pull-policy \ /CrownLabs/deploy/crownlabs/rendered.yaml - - opa: - name: Policies - runs-on: ubuntu-latest - needs: configure - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: "${{ needs.configure.outputs.ref }}" - repository: "${{ needs.configure.outputs.repo-name }}" - persist-credentials: false - - name: Perform the tests - uses: petroprotsakh/opa-test-action@v2.1 - with: - tests: ./policies/policies - options: | - --verbose --threshold 100 diff --git a/deploy/crownlabs/Chart.lock b/deploy/crownlabs/Chart.lock index 7a28e4799..3d8a044b3 100644 --- a/deploy/crownlabs/Chart.lock +++ b/deploy/crownlabs/Chart.lock @@ -26,8 +26,5 @@ dependencies: - name: exam-agent repository: file://../../operators/deploy/exam-agent version: 0.1.0 -- name: policies - repository: file://../../policies/ - version: 0.1.0 -digest: sha256:86459acf438793fc1f9ec34dfd8d32263c6996f02e8b7712eee73c12be6f4d4b -generated: "2022-03-23T10:17:15.785619631+01:00" +digest: sha256:5e61e140806766e46aa2014b018ba66c40653756b213e3ff042782b0d662a6a8 +generated: "2022-04-02T18:37:42.140831116+02:00" diff --git a/deploy/crownlabs/Chart.yaml b/deploy/crownlabs/Chart.yaml index 70cc48f33..97cf23cde 100644 --- a/deploy/crownlabs/Chart.yaml +++ b/deploy/crownlabs/Chart.yaml @@ -64,8 +64,3 @@ dependencies: version: "0.1.0" repository: file://../../operators/deploy/exam-agent condition: exam-agent.enabled - -- name: policies - version: "0.1.0" - repository: file://../../policies/ - condition: policies.enabled diff --git a/infrastructure/policy-enforcement/README.md b/infrastructure/policy-enforcement/README.md deleted file mode 100644 index 64140a1ec..000000000 --- a/infrastructure/policy-enforcement/README.md +++ /dev/null @@ -1,26 +0,0 @@ - -CUSTOM POLICY ENFORCEMENT -===================================== -## GOALS -Kubernetes allows you to write policies on your cluster objects by means of admission controller webhooks which are executed everytime a cluster component is created or modified. -[OPA](https://www.openpolicyagent.org/) (Open Policy Agent) is an open source, general-purpose policy engine to write unifed policies across different applications. It exploits [REGO](https://www.openpolicyagent.org/docs/latest/policy-language/) language to write policies. -[Gatekeeper](https://github.com/open-policy-agent/gatekeeper) allows you to integrate easily OPA on kubernetes by adding: - - native kubernetes CRDs for instantiating the policy library (Constraint) - - native kubernetes CRDs for extending the policy library (ConstraintTemplate) - - -## HOW TO INSTALL -### Prerequisites - -- minimun kubernetes version: 1.14 -- make sure you have cluster admin permissions -#### Deploying a Release using Prebuilt Image -Run the following command: - - kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.3/deploy/gatekeeper.yaml -For more information visit the [gatekeeper official repository](https://github.com/open-policy-agent/gatekeeper). - -## HOW TO USE GATEKEEPER - -The following pages contain some more [information](../../policies/README.md) and [examples](./examples) about how to use gatekeeper and OPA policy. -The examples are taken from the original [repository](https://open-policy-agent.github.io/gatekeeper/website/docs/howto/) \ No newline at end of file diff --git a/infrastructure/policy-enforcement/examples/config-sync.yaml b/infrastructure/policy-enforcement/examples/config-sync.yaml deleted file mode 100644 index aebe0aa6d..000000000 --- a/infrastructure/policy-enforcement/examples/config-sync.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: config.gatekeeper.sh/v1alpha1 -kind: Config -metadata: - name: config - namespace: "gatekeeper-system" -spec: - sync: - syncOnly: - - group: "" - version: "v1" - kind: "Namespace" - - group: "" - version: "v1" - kind: "Pod" \ No newline at end of file diff --git a/infrastructure/policy-enforcement/examples/constraint.yaml b/infrastructure/policy-enforcement/examples/constraint.yaml deleted file mode 100644 index e86dfca3d..000000000 --- a/infrastructure/policy-enforcement/examples/constraint.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: constraints.gatekeeper.sh/v1beta1 -kind: K8sRequiredLabels -metadata: - name: ns-must-have-gk -spec: - match: - kinds: - - apiGroups: [""] - kinds: ["Namespace"] - parameters: - labels: ["gatekeeper"] \ No newline at end of file diff --git a/infrastructure/policy-enforcement/examples/constraintTemplate.yaml b/infrastructure/policy-enforcement/examples/constraintTemplate.yaml deleted file mode 100644 index b7dbe4e85..000000000 --- a/infrastructure/policy-enforcement/examples/constraintTemplate.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: templates.gatekeeper.sh/v1beta1 -kind: ConstraintTemplate -metadata: - name: k8srequiredlabels -spec: - crd: - spec: - names: - kind: K8sRequiredLabels - validation: - # Schema for the `parameters` field - openAPIV3Schema: - properties: - labels: - type: array - items: string - targets: - - target: admission.k8s.gatekeeper.sh - rego: | - package k8srequiredlabels - - violation[{"msg": msg, "details": {"missing_labels": missing}}] { - provided := {label | input.review.object.metadata.labels[label]} - required := {label | label := input.parameters.labels[_]} - missing := required - provided - count(missing) > 0 - msg := sprintf("you must provide labels: %v", [missing]) - } \ No newline at end of file diff --git a/policies/.gitignore b/policies/.gitignore deleted file mode 100644 index b80bc0bde..000000000 --- a/policies/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -charts/ -*.tgz diff --git a/policies/.helmignore b/policies/.helmignore deleted file mode 100644 index b68c1acbf..000000000 --- a/policies/.helmignore +++ /dev/null @@ -1,27 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ -# Readme files -*.md -# Rego tests -policies/*_test.rego diff --git a/policies/Chart.yaml b/policies/Chart.yaml deleted file mode 100644 index c22698864..000000000 --- a/policies/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: v2 -name: policies -description: The CrownLabs Gatekeeper policies - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -icon: https://crownlabs.polito.it/images/logo.svg diff --git a/policies/README.md b/policies/README.md deleted file mode 100644 index 29f2b24c3..000000000 --- a/policies/README.md +++ /dev/null @@ -1,155 +0,0 @@ -# OPA Policies - -## Available policies - -This section details and documents the different policies available in CrownLabs: -* **Verify Tenant Patch**: verifies that a tenant creation or patch is allowed -* **Verify Instance-Template Reference**: this policy verifies that an instance refers to an existing template in the correct namespace when it is created or updated. - -### Verify Tenant Patch - -This policy verifies that a tenant creation or patch is allowed. In particular : - -- for creation - - is allowed only if the creator is manager in all workspaces for which he creates the new tenant resource. - - is never allowed for a user. - - the creator must already have his own tenant in the cluster. - - is not allowed to create a tenant that already exists - -- for update - - a user can modify any tenant workspaces for which he is manager - - a user can always update the publicKeys on his own tenant - - is not allowed to modify any other field - -- for a cluster-admin or an operator all operations are allowed - -## How to deploy - -The creation of the Gatekeeper resources and their deployment is automated through an Helm Chart. - -This allows the creators of the policies to focus on writing the appropriate constraints in the `rego` language (together with the corresponding tests), without dealing with the Gatekeeper manifests. -Additionally, it also prevents the duplication of the policies themselves in two files (i.e. the `rego` policy, which is used to run the tests, and the Gatekeeper ConstraintTemplate), avoiding possible inconsistencies between the two. - -In order to add a new policy to the Helm chart, it is sufficient to an add an entry to the `policies` array of the [values.yaml](values.yaml) file. Specifically, each entry contains the following fields: - -* **name**: the name assigned to the policy resources (in camel-case); -* **file**: the path of the `rego` file implementing the policy; -* **dryRun**: whether the policy is enforced or violations are only logged; -* **resources**: the list of resources the policy applies to; -* **sync**: the list of resources that need to be accessed from the policy (optional). - -## OPA POLICIES - -Policies are rules that can be applied when any of your cluster object is _created_, _updated_, _patched_ and _deleted_. - -Policies are always executed _before_ the action takes place and their goal is to allow or prevent the requested actions. - -The language used to express OPA policies is [REGO](https://www.openpolicyagent.org/docs/latest/policy-language/). - -### HOW TO USE GATEKEEPER - -To use OPA gatekeeper you need to: - -- Install Gatekeeper in your cluster, deploying the CRDs and the associated operators/components. See [this README](../infrastructure/policy-enforcement/README.md) for further information about the installation process. - -- Create your own constraint and constraintTemplate files and, if needed, the config-sync file. See [the examples folder](../infrastructure/policy-enforcement/examples) for an example of the three resources. - -Now you can test your policies on your cluster objects. - - - -### ConstraintTemplate - -In the ConstraintTemplate you should define your own constraint CRD schema and associate it to your rego policies, such as in this example: [**ConstraintTemplate.yaml**](../infrastructure/policy-enforcement/examples/constraintTemplate.yaml). - -Under the _crd_ tag you have to define your constraint CRD schema: -- _kind_: must be the same as the constraintTemplate name in camelcase (mandatory) -- _properties_: must declare your fixed parameters (optional) - -Under the _targets_ tag you have to define your rego policy. -The example REGO policy executes the following operations: -- the `provided` variable retrieves all the label keys of the input object -- the `required` variable retrieves all the label values of the constraint parameters -- the `missing` variable calculates the result of subtraction between required and provided, therefore it will contain all the labels required but not provided -- if `missing` is empty then `count(missing)>0` will be false, the execution will be ended and so there will be no violation -- if `missing` is not empty then the condition will be true, the execution will continue and so there will be a violation -- the `msg` variable, containg the `sprintf` value, will be the returned value of the violation together with the `details` object - -As you could see, you can retrieve your input object using `input` variable. -In OPA, input is a reserved, global variable whose value is the Kubernetes AdmissionReview object that the API server hands to any admission control webhook. - - -### Constraint - -In Constraint you should declare the resources on which your ConstraintTemplate operates and define possible optional parameters (e.g., reject a modification if a value is greater than a given threshold), for example: [**constraint.yaml**](../infrastructure/policy-enforcement/examples/constraint.yaml). - -The _kind_ tag must be the one specified in the _kind_ tag of the related constraintTemplate. - -The _match_ tag must list the cluster resources on which you want to enforce the policy. - -The _paramters_ tag must list your fixed parameters, if any. - - -### Config-Sync - -Some constraints cannot be written without having access to more cluster resources than just the object under test. For example, it is impossible to know if an instance is valid unless a rule has access to all the templates. To make such rules possible, we enable syncing of data into OPA. [1] - -The OPA rules do not require cluster resources by default, however if you need them you must first cache your objects before using them in your contraint violations. -To do so Gatekeeper provides a Config CRD where you can define which resources need to be cached. - -**Note:** The Config resource has to be named `config` for it to be reconciled by Gatekeeper. Gatekeeper will ignore the resource if you do not name it `config`. - -Kubernetes data can be replicated into OPA via the sync config resource. Currently resources defined in `syncOnly` will be synced into OPA. Updating syncOnly should dynamically update what objects are synced. -Once data is synced into OPA, rules can access the cached data under the `data.inventory` document, for example: [**config-sync.yaml**](../infrastructure/policy-enforcement/examples/config-sync.yaml). - -Under _syncOnly_ tag yuo should list the resources to be cached, for each object define its _group_, _version_ and _kind_. - - -### Retrieve cached resources - - To retrieve the cached resources in the rego rules you can do as follow [1]: - -- For cluster-scoped objects: `data.inventory.cluster[][][]` - -- Example referencing the Gatekeeper namespace: `data.inventory.cluster["v1"].Namespace["gatekeeper"]` - -- For namespace-scoped objects: `data.inventory.namespace[][groupVersion][][]` - -- Example referencing the Gatekeeper pod: `data.inventory.namespace["gatekeeper"]["v1"]["Pod"]["gatekeeper-controller-manager-d4c98b788-j7d92"]` - -### Retrieve input object - -The `input` document contains the following fields [2]: - -- `input.review.kind` specifies the type of the object (e.g., `Pod`, `Service`, etc.) -- `input.review.operation` specifies the type of the operation, i.e., `CREATE`, `UPDATE`, `DELETE`, `CONNECT`. -- `input.review.userInfo` specifies the identity of the caller. -- `input.review.object` contains the entire Kubernetes object. -- `input.review.oldObject` specifies the previous version of the Kubernetes object on `UPDATE` and `DELETE`. - -### How to write rego policies in gatekeeper -You should use `violation` functions to write your rules. - - violation[{"msg":msg,"details":{}}]{ - } - - `msg` and `details`are the values returned if a violation occurs, otherwise nothing is returned. -The rule must have at least one boolean condition to take a decision whether the violation occurs or not. -If you need to specify more boolean conditions, proceed as follows: - - - For `and` conditions (all your conditions must be true in order for the violation to take place): - write all of them in one violation function - - - For `or` conditions (at least one condition must be true in order for the violation to take place): - write one violation function for each condition - -In general OPA policies in gatekeeper work as black list mode: so you specify what can't be done. - - You can learn [REGO](https://www.openpolicyagent.org/docs/latest/#rego) language. - - You can exploit [PLAYGROUND](https://play.openpolicyagent.org/) to try your rules. - -### Note -[1] This information is taken from the official [documentation](https://open-policy-agent.github.io/gatekeeper/website/docs/sync). - -[2] This information is taken from the official [documentation](https://www.openpolicyagent.org/docs/latest/kubernetes-introduction/#how-does-it-work-with-plain-opa-and-kube-mgmt). diff --git a/policies/policies/instance-template-reference.rego b/policies/policies/instance-template-reference.rego deleted file mode 100644 index b9f94f309..000000000 --- a/policies/policies/instance-template-reference.rego +++ /dev/null @@ -1,28 +0,0 @@ -package crownlabs_instance_template_reference - -tmpl_api_version := "crownlabs.polito.it/v1alpha2" - -tmpl_ref_field := "template.crownlabs.polito.it/TemplateRef" - -# Return the referenced template namespace, in case the field is defined, otherwise "default" -get_tmpl_namespace(review) = namespace { - review.object.spec[tmpl_ref_field].namespace - namespace := review.object.spec[tmpl_ref_field].namespace -} else = "default" { - true -} - -# Return the referenced template name -get_tmpl_name(review) = name { - name := review.object.spec[tmpl_ref_field].name -} - -# This violation is triggered if the referenced template does not exist -violation[{"msg": msg, "details": details}] { - tmpl_namespace := get_tmpl_namespace(input.review) - tmpl_name := get_tmpl_name(input.review) - - not data.inventory.namespace[tmpl_namespace][tmpl_api_version].Template[tmpl_name] - msg := sprintf("Template %v not found in namespace %v", [tmpl_name, tmpl_namespace]) - details := {"template_name": tmpl_name, "template_namespace": tmpl_namespace} -} diff --git a/policies/policies/instance-template-reference_test.rego b/policies/policies/instance-template-reference_test.rego deleted file mode 100644 index 792df0252..000000000 --- a/policies/policies/instance-template-reference_test.rego +++ /dev/null @@ -1,156 +0,0 @@ -package crownlabs_instance_template_reference - -test_generic_namespace_not_exists { - input := {"review": input_review_with_namespace("workspace-not-existing", "whatever")} - results := violation with input as input with data.inventory as data_inventory - count(results) > 0 -} - -test_generic_namespace_empty { - input1 := {"review": input_review_with_namespace("workspace-empty-1", "whatever")} - input2 := {"review": input_review_with_namespace("workspace-empty-2", "whatever")} - input3 := {"review": input_review_with_namespace("workspace-empty-3", "whatever")} - input4 := {"review": input_review_with_namespace("workspace-empty-4", "whatever")} - - results1 := violation with input as input1 with data.inventory as data_inventory - results2 := violation with input as input2 with data.inventory as data_inventory - results3 := violation with input as input3 with data.inventory as data_inventory - results4 := violation with input as input4 with data.inventory as data_inventory - - count(results1) > 0 - count(results2) > 0 - count(results3) > 0 - count(results4) > 0 -} - -test_generic_namespace_template_not_exists { - # This template exists but in a different namespace - input := {"review": input_review_with_namespace("workspace-coffee", "green-tea")} - results := violation with input as input with data.inventory as data_inventory - count(results) > 0 -} - -test_generic_namespace_template_exists_single { - input := {"review": input_review_with_namespace("workspace-coffee", "dark-coffee")} - results := violation with input as input with data.inventory as data_inventory - count(results) == 0 -} - -test_generic_namespace_template_exists_multiple { - input1 := {"review": input_review_with_namespace("workspace-tea", "green-tea")} - input2 := {"review": input_review_with_namespace("workspace-tea", "white-tea")} - - results1 := violation with input as input1 with data.inventory as data_inventory - results2 := violation with input as input2 with data.inventory as data_inventory - - count(results1) == 0 - count(results2) == 0 -} - -test_default_namespace_empty { - input := {"review": input_review_without_namespace("whatever")} - results := violation with input as input with data.inventory as data_inventory_empty_default_namespace - count(results) > 0 -} - -test_default_namespace_template_not_exists { - input := {"review": input_review_without_namespace("not-existing")} - results := violation with input as input with data.inventory as data_inventory - count(results) > 0 -} - -test_default_namespace_template_exists { - input1 := {"review": input_review_without_namespace("chilly-pepper")} - input2 := {"review": input_review_without_namespace("just-pepper")} - - results1 := violation with input as input1 with data.inventory as data_inventory - results2 := violation with input as input2 with data.inventory as data_inventory - - count(results1) == 0 - count(results2) == 0 -} - -input_review_with_namespace(template_namespace, template_name) = output { - output = {"object": { - "metadata": { - "name": "instance-name", - "namespace": "instance-namespace", - }, - "spec": { - "template.crownlabs.polito.it/TemplateRef": { - "name": template_name, - "namespace": template_namespace, - }, - "tenant.crownlabs.polito.it/TenantRef": {"name": "tenant-name"}, - }, - }} -} - -input_review_without_namespace(template_name) = output { - output = {"object": { - "metadata": { - "name": "instance-name", - "namespace": "instance-namespace", - }, - "spec": { - "template.crownlabs.polito.it/TemplateRef": {"name": template_name}, - "tenant.crownlabs.polito.it/TenantRef": {"name": "tenant-name"}, - }, - }} -} - -data_inventory = {"namespace": { - "workspace-tea": {"crownlabs.polito.it/v1alpha2": {"Template": { - "green-tea": { - "apiVersion": "crownlabs.polito.it/v1alpha2", - "kind": "Template", - "metadata": { - "name": "green-tea", - "namespace": "workspace-tea", - }, - }, - "white-tea": { - "apiVersion": "crownlabs.polito.it/v1alpha2", - "kind": "Template", - "metadata": { - "name": "white-tea", - "namespace": "workspace-tea", - }, - }, - }}}, - "workspace-coffee": { - "crownlabs.polito.it/v1alpha2": {"Template": {"dark-coffee": { - "apiVersion": "crownlabs.polito.it/v1alpha2", - "kind": "Template", - "metadata": { - "name": "dark-coffee", - "namespace": "workspace-coffee", - }, - }}}, - "foo.bar.com/v1alpha1": {"Baz": {}}, - }, - "workspace-empty-1": {}, - "workspace-empty-2": {"foo.bar.com/v1alpha1": {"Baz": {}}}, - "workspace-empty-3": {"crownlabs.polito.it/v1alpha2": {"Baz": {}}}, - "workspace-empty-4": {"crownlabs.polito.it/v1alpha2": {"Template": {}}}, - "default": {"crownlabs.polito.it/v1alpha2": {"Template": { - "chilly-pepper": { - "apiVersion": "crownlabs.polito.it/v1alpha2", - "kind": "Template", - "metadata": { - "name": "chilly-pepper", - "namespace": "default", - }, - }, - "just-pepper": { - "apiVersion": "crownlabs.polito.it/v1alpha2", - "kind": "Template", - "metadata": { - "name": "just-pepper", - "namespace": "default", - }, - }, - }}}, -}} - -data_inventory_empty_default_namespace = {"namespace": {"default": {"crownlabs.polito.it/v1alpha2": {"Template": {}}}}} diff --git a/policies/policies/tenant-patch.rego b/policies/policies/tenant-patch.rego deleted file mode 100644 index 8f4d58bea..000000000 --- a/policies/policies/tenant-patch.rego +++ /dev/null @@ -1,126 +0,0 @@ -package crownlabs_tenant_patch - -priviledged_users := ["kubernetes:admin", "system:serviceaccounts"] - -#verify if creator is admin or an operator. returns true if not. -admin_operator_check{ - requiredPr := {ws | ws := priviledged_users[_]} - providedPr := {ws | ws := input.review.userInfo.groups[_]} - missingPr := requiredPr - providedPr - count(missingPr) > 1 -} - - -#check if creator has a tenant -violation[{"msg": msg, "details": {}}] { - admin_operator_check - user := input.review.userInfo.username - not data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user] - msg := sprintf("Denied request. There is no tenant resource for user %v in the cluster", [user]) -} - -#check if creator already has a tenant -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "CREATE" - user := input.review.userInfo.username - tenantName := input.review.object.metadata.name - user == tenantName - msg := sprintf("Denied creation request. %v already has a tenant", [user]) -} - -#check creation of new user can be done only in workspaces where the creator is enrolled -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "CREATE" - user := input.review.userInfo.username - requiredWs := {ws | ws := input.review.object.spec.workspaces[_].workspaceRef.name} - providedWs := {ws | ws := data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user].spec.workspaces[_].workspaceRef.name} - missing := requiredWs - providedWs - count(missing) > 0 - msg := sprintf("Denied creation request. You do not have the priviledges to create users in this workspace: %v", [missing]) -} - -#check creation of new user can be done only in workspaces where the creator is manager -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "CREATE" - user := input.review.userInfo.username - some p - some q - ws := input.review.object.spec.workspaces[p].workspaceRef.name - wsData := data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user].spec.workspaces[q] - wsData.workspaceRef.name == ws - wsData.role != "manager" - msg := sprintf("Denied creation request. You do not have the priviledges to create users in this workspace: %v", [ws]) -} - -#update cannot be done on anything but publicKeys and workspaces -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "UPDATE" - user := input.review.userInfo.username - some key - input.review.oldObject.spec[key] != input.review.object.spec[key] - key != "publicKeys" - key != "workspaces" - msg := sprintf("Denied patch request. You cannot modify: %v field of tenant resource", [key]) -} - -#update cannot be done on a workspace the creator is not part of -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "UPDATE" - user := input.review.userInfo.username - some key - input.review.oldObject.spec[key] != input.review.object.spec[key] - key == "workspaces" - some i - input.review.oldObject.spec.workspaces[i] != input.review.object.spec.workspaces[i] - requiredWs := {ws | ws := input.review.object.spec.workspaces[i].workspaceRef.name} - providedWs := {ws | ws := data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user].spec.workspaces[_].workspaceRef.name} - missing := requiredWs - providedWs - count(missing) > 0 - msg := sprintf("Denied patch request. You cannot modify the workspace %v, because you are not enrolled in it", [missing]) -} - -#update cannot be done on a workspace you are not manager for -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "UPDATE" - user := input.review.userInfo.username - some key - input.review.oldObject.spec[key] != input.review.object.spec[key] - key == "workspaces" - some i - input.review.oldObject.spec.workspaces[i] != input.review.object.spec.workspaces[i] - wsChangedName := input.review.object.spec.workspaces[i].workspaceRef.name - some j - wsRole = data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user].spec.workspaces[j].role - wsName = data.inventory.cluster["crownlabs.polito.it/v1alpha1"].Tenant[user].spec.workspaces[j].workspaceRef.name - wsName == wsChangedName - wsRole != "manager" - msg := sprintf("Denied patch request. You have not the priviledges to modify %v workspace", [wsName]) -} - -#update on publicKeys can be done only on your own tenant -violation[{"msg": msg, "details": {}}] { - admin_operator_check - operation := input.review.operation - operation == "UPDATE" - user := input.review.userInfo.username - tenantName := input.review.oldObject.metadata.name - oldObj := input.review.oldObject - newObj := input.review.object - some key - oldObj.spec[key] != newObj.spec[key] - key == "publicKeys" - user != tenantName - msg := sprintf("Denied patch request. You do not have the priviledges to modify: %v field", [key]) -} diff --git a/policies/policies/tenant-patch_test.rego b/policies/policies/tenant-patch_test.rego deleted file mode 100644 index 47f3e2284..000000000 --- a/policies/policies/tenant-patch_test.rego +++ /dev/null @@ -1,647 +0,0 @@ -package crownlabs_tenant_patch - -#creator does not have any tenant -test_no_tenant_present { - input := {"review": input_review_invalid_creation_creator_has_not_tenant} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#creator cannot create a tenant for himself -test_creator_already_has_a_tenant { - input := {"review": input_review_invalid_creation_creator_has_a_tenant} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#creator cannot create a tenant in workspace he is not enrolled in -test_creator_not_enrolled { - input := {"review": input_review_invalid_creation_creator_not_enrolled} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#creator cannot create a tenant where he is not manager -test_creator_not_manager { - input := {"review": input_review_invalid_creation_creator_not_manager} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#correct creation of new tenant -test_correct_creation_of_tenant { - input := {"review": input_review_valid_creation_tenant} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) == 0 -} - -#try to change the email -test_invalid_patch_on_wrong_fields { - input := {"review": input_review_invalid_patch_field} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#update a workspace in which the creator is not enrolled -test_invalid_patch_for_notenrolled_workspace { - input := {"review": input_review_invalid_patch_creator_not_enrolled} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#update a workspace in which the creator is not manager -test_invalid_patch_for_not_manager_creator { - input := {"review": input_review_invalid_patch_creator_not_manager} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#update a workspace in which the creator is the manager -test_valid_patch_for_manager_creator { - input := {"review": input_review_valid_patch_creator_is_manager} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) == 0 -} - -#update public key not on your own tenant -test_invalid_patch_publicKey { - input := {"review": input_review_invalid_patch_publicKey} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) > 0 -} - -#update public key on your own tenant -test_valid_patch_publicKey { - input := {"review": input_review_valid_patch_publicKey} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) == 0 -} - -#create tenant with cluster-admin priviledges -test_valid_creation_cluster_admin { - input := {"review": input_review_valid_creation_cluster_admin} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) == 0 -} - -#update tenant with serviceaccounts priviledges -test_valid_creation_serviceaccounts { - input := {"review": input_review_valid_patch_serviceaccounts} - my_data := data_review1 - result := violation with input as input with data.inventory as my_data - count(result) == 0 -} - - -data_review1 = output { - output = {"cluster": {"crownlabs.polito.it/v1alpha1": {"Tenant": { - "mariocalza": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "name": "mariocalza", - "resourceVersion": "2580284", - "selfLink": "/apis/crownlabs.polito.it/v1alpha1/tenants/mariocalza", - "uid": "f9fe46e2-e8bc-4442-acff-30f6bb812bf2", - "creationTimestamp": "2020-12-25T15:22:44Z", - "generation": 1, - }, - "spec": { - "workspaces": [ - {"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, - {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}, - ], - "email": "mario.calza@email.com", - "firstName": "mario", - "lastName": "calza", - "publicKeys": ["key1", "key2", "key3"], - }, - }, - "mariorossi": { - "metadata": { - "creationTimestamp": "2020-12-25T14:57:30Z", - "generation": 1, - "name": "mariorossi", - "resourceVersion": "2576050", - "selfLink": "/apis/crownlabs.polito.it/v1alpha1/tenants/mariorossi", - "uid": "ecc18c03-c3e9-4a95-9339-fdd7bec3df4d", - }, - "spec": { - "email": "mario.rossi@email.com", - "firstName": "mario", - "lastName": "rossi", - "publicKeys": ["key1", "key2", "key3"], - "workspaces": [ - {"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, - {"groupNumber": 11, "role": "user", "workspaceRef": {"name": "landa"}}, - ], - }, - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - }, - }}}} -} - -input_review_invalid_patch_field = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario11.calza@email.it", - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_invalid_patch_creator_not_enrolled = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "newName"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_invalid_patch_creator_not_manager = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "manager", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_valid_patch_creator_is_manager = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_invalid_patch_publicKey = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - "name": "mario", - "publicKeys": ["test-key4 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_valid_patch_publicKey = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariorossi", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "rossi", - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.rossi@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariorossi", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.rossi@email.it", - "name": "mario", - "publicKeys": ["test-key4 test-key2"], - "surname": "rossi", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} - -input_review_invalid_creation_creator_has_not_tenant = output { - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "test-any-name", - "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "test-any-name", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "test.any-name@email.com", "firstName": "test-name", "lastName": "test-last", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - }, - }, - "oldObject": null, - "userInfo": {"username": "test-name-no-tenant", "groups": ["system:masters", "system:authenticated"]}, - } -} - -input_review_invalid_creation_creator_has_a_tenant = output { - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "mariocalza", "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "mariocalza", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "mario.calza@email.com", "firstName": "mario", "lastName": "calza", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - }, - }, - "oldObject": null, - "userInfo": {"username": "mariocalza", "groups": ["system:masters", "system:authenticated"]}, - } -} - -input_review_invalid_creation_creator_not_enrolled = output { - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "test-name", "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "test-name", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "test.name@email.com", "firstName": "test-name", "lastName": "test-last", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "test-land"}}], - }, - }, - "oldObject": null, - "userInfo": {"username": "mariocalza", "groups": ["system:masters", "system:authenticated"]}, - } -} - -input_review_invalid_creation_creator_not_manager = output { - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "test-name", "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "test-name", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "test.name@email.com", "firstName": "test-name", "lastName": "test-last", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "manager", "workspaceRef": {"name": "landc"}}], - }, - }, - "oldObject": null, - "userInfo": {"username": "mariocalza", "groups": ["system:masters", "system:authenticated"]}, - } -} - -input_review_valid_creation_tenant = output { - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "test-name", "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "test-name", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "test.name@email.com", "firstName": "test-name", "lastName": "test-last", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}], - }, - }, - "oldObject": null, - "userInfo": {"username": "mariorossi", "groups": ["system:masters", "system:authenticated"]}, - } -} - - -input_review_valid_creation_cluster_admin=output{ - output = { - "requestKind": {"group": "crownlabs.polito.it", "version": "v1alpha1", "kind": "Tenant"}, "name": "test-name", "operation": "CREATE", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", "kind": "Tenant", - "metadata": {"creationTimestamp": "2020-12-25T16:16:14Z", "generation": 1, "name": "test-name", "uid": "c3b3a51a-1a43-47f2-a7f4-c84914b026ba"}, - "spec": { - "email": "test.name@email.com", "firstName": "test-name", "lastName": "test-last", "publicKeys": ["key1", "key2", "key3"], - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landa"}}], - }, - }, - "oldObject": null, - "userInfo": {"username": "giovannibianchi", "groups": ["system:masters", "system:authenticated","kubernetes:admin"]}, - } -} - - - -input_review_valid_patch_serviceaccounts = output { - output = { - "requestKind": {"kind": "Tenant", "group": "crownlabs.polito.it", "version": "v1alpha1"}, - "operation": "UPDATE", - "userInfo": {"username": "giovannibianchi", "groups": ["system:masters", "system:authenticated","system:serviceaccounts"]}, - "oldObject": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario.calza@email.it", - }, - }, - "options": {"kind": "UpdateOptions", "apiVersion": "meta.k8s.io/v1", "fieldManager": "kubectl-patch"}, - "uid": "3771271d-9194-4924-b3b6-edccf84d8f76", - "requestResource": {"group": "crownlabs.polito.it", "version": "v1alpha1", "resource": "tenants"}, - "name": "example.com", - "object": { - "apiVersion": "crownlabs.polito.it/v1alpha1", - "kind": "Tenant", - "metadata": { - "uid": "664a606d-0f45-4ca3-9ae5-629bc86495eb", - "creationTimestamp": "2020-12-20T11:14:59Z", - "generation": 1, - "name": "mariocalza", - "resourceVersion": "231625", - }, - "spec": { - "workspaces": [{"groupNumber": 12, "role": "user", "workspaceRef": {"name": "landc"}}, {"role": "user", "workspaceRef": {"name": "landa"}, "groupNumber": 11}], - "createSandbox": false, - "email": "mario11.calza@email.it", - "name": "mario", - "publicKeys": ["test-key1 test-key2"], - "surname": "calza", - }, - }, - "dryRun": false, - "kind": { - "group": "crownlabs.polito.it", - "version": "v1alpha1", - "kind": "Tenant", - }, - } -} diff --git a/policies/templates/_helpers.tpl b/policies/templates/_helpers.tpl deleted file mode 100644 index a200bf52d..000000000 --- a/policies/templates/_helpers.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "policies.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "policies.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -The version of the application to be deployed -*/}} -{{- define "policies.version" -}} -{{- if .Values.global }} -{{- .Values.global.version | default .Chart.AppVersion }} -{{- else }} -{{- .Chart.AppVersion }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "policies.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "policies.labels" -}} -helm.sh/chart: {{ include "policies.chart" . }} -{{ include "policies.selectorLabels" . }} -app.kubernetes.io/version: {{ include "policies.version" . | quote }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "policies.selectorLabels" -}} -app.kubernetes.io/name: {{ include "policies.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} diff --git a/policies/templates/config-sync.yaml b/policies/templates/config-sync.yaml deleted file mode 100644 index 0d26efbef..000000000 --- a/policies/templates/config-sync.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- define "policies.sync" -}} -{{- $sync := list }} -{{- range .Values.policies }} -{{- if .sync }} -{{- $sync = concat $sync .sync }} -{{- end -}} -{{- end -}} -{{ toYaml ( $sync | uniq ) }} -{{- end -}} - -apiVersion: config.gatekeeper.sh/v1alpha1 -kind: Config -metadata: - # The name must be config, otherwise it is not reconciled by gatekeeper - # https://github.com/open-policy-agent/gatekeeper#replicating-data - name: config - namespace: {{ .Values.gatekeeperNamespace }} - labels: - {{- include "policies.labels" . | nindent 4 }} -spec: - sync: - syncOnly: - {{- ( include "policies.sync" . ) | nindent 6 }} diff --git a/policies/templates/constraint-template.yaml b/policies/templates/constraint-template.yaml deleted file mode 100644 index 4fc656991..000000000 --- a/policies/templates/constraint-template.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- range .Values.policies }} ---- -apiVersion: templates.gatekeeper.sh/v1beta1 -kind: ConstraintTemplate -metadata: - name: {{ lower .name }} - labels: - {{- include "policies.labels" $ | nindent 4 }} -spec: - crd: - spec: - names: - kind: {{ .name }} - targets: - - target: admission.k8s.gatekeeper.sh - rego: |- - {{- $.Files.Get .file | nindent 6 }} -{{- end }} diff --git a/policies/templates/hook-create-constraint.yaml b/policies/templates/hook-create-constraint.yaml deleted file mode 100644 index 3d218fba4..000000000 --- a/policies/templates/hook-create-constraint.yaml +++ /dev/null @@ -1,138 +0,0 @@ -# The creation of the gatekeeper Constraints is implemented through an hook since they require -# that the corresponding ConstraintTemplate has already been deployed. Then, the gatekeeper operator -# generates the appropriate CRDs, and it is finally possible to apply the Constraints. Trying to deploy -# the Constraints earlier leads to a failure as the CRD is not yet available: thus, the corresponding -# type is unknown. -{{ $fullname := printf "%s-create-constraints-hook" ( include "policies.fullname" $ ) -}} - ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -rules: -- apiGroups: - - "constraints.gatekeeper.sh" - resources: - {{- range .Values.policies }} - - {{ lower .name | quote }} - {{- end }} - verbs: - - get - - create - - patch - - update - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ $fullname }} -subjects: - - kind: ServiceAccount - name: {{ $fullname }} - namespace: {{ .Release.Namespace }} - ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" $ | nindent 4 }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -data: - {{- range .Values.policies }} - {{- if not .resources }} - {{ $errormsg := printf "You need to specify the resources the '%s' policy applies to" .name }} - {{- fail $errormsg }} - {{- else }} - {{- $filename := printf "%s.yaml" (kebabcase .name) }} - {{ $filename }}: | - apiVersion: constraints.gatekeeper.sh/v1beta1 - kind: {{ .name }} - metadata: - name: {{ lower .name }} - labels: - {{- include "policies.labels" $ | nindent 8 }} - spec: - match: - kinds: - {{- toYaml .resources | nindent 10 }} - {{- if .dryRun }} - enforcementAction: dryrun - {{- end}} - {{- end}} - {{- end}} - ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -spec: - template: - metadata: - name: {{ $fullname }} - labels: - {{- include "policies.labels" . | nindent 8 }} - spec: - restartPolicy: OnFailure - serviceAccountName: {{ $fullname }} - containers: - - name: kubectl - image: {{ .Values.hook.kubectlImage }} - command: - - kubectl - args: - - apply - - -f - - /tmp/policies/ - securityContext: - {{- toYaml .Values.hook.securityContext | nindent 12 }} - resources: - {{- toYaml .Values.hook.resources | nindent 12 }} - volumeMounts: - - name: policies - mountPath: /tmp/policies/ - volumes: - - name: policies - configMap: - name: {{ $fullname }} diff --git a/policies/values.yaml b/policies/values.yaml deleted file mode 100644 index b29eb2835..000000000 --- a/policies/values.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# Default values for policies. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Include here the policies that need to be deployed with the helm chart -### Name is the name of the policy -### File is the path of the rego rule implementing the policy -### DryRun decides whether the policy is enforced or not -### Resources is the list of kinds the policy applies to -### Sync is the list of resources that need to be accessed from the policy -policies: - - # This policy verifies that an instance refers to an existing template - # in the correct namespace when it is created or updated. - - name: CrownLabsInstanceTemplateReference - file: policies/instance-template-reference.rego - dryRun: true - resources: - - apiGroups: - - crownlabs.polito.it - kinds: - - Instance - sync: - - group: "crownlabs.polito.it" - version: "v1alpha2" - kind: "Template" - - # This policy verifies that a tenant creation or patch is allowed. - - name: CrownLabsTenantPatch - file: policies/tenant-patch.rego - dryRun: true - resources: - - apiGroups: - - crownlabs.polito.it - kinds: - - Tenant - sync: - - group: "crownlabs.polito.it" - version: "v1alpha1" - kind: "Tenant" - -# The namespace where gatekeeper is installed -gatekeeperNamespace: gatekeeper-system - -# Hook configurations -hook: - kubectlImage: bitnami/kubectl:1.21 - pullPolicy: IfNotPresent - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 - privileged: false - resources: - limits: - memory: 250Mi - cpu: 1000m - requests: - memory: 250Mi - cpu: 10m - -nameOverride: "" -fullNameOverride: "" From 595b389a517d698d900ce07d9b64d26756567e33 Mon Sep 17 00:00:00 2001 From: Marco Iorio Date: Sat, 2 Apr 2022 16:16:26 +0200 Subject: [PATCH 2/2] GitHub actions: bump golangci-lint-action --- .github/workflows/lint.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 081868e5a..560ec9cd6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,8 +19,13 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} persist-credentials: false + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: 1.16 + - name: Check linting - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: version: v1.43.0 working-directory: operators