From a2cd348a8187a00129bf67745c8b83ff437f938e Mon Sep 17 00:00:00 2001 From: Forrest Xia Date: Thu, 7 Jul 2022 09:04:06 +0800 Subject: [PATCH 1/2] Add more code owners --- .github/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 29ecac31..cd0e5145 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -17,6 +17,12 @@ # Shayna Finocchiaro (shaynafinocchiaro) # Logan Jones (lj-software) # Sharmila Ramamoorthy (sharmilarama) +# Tao He (taohe1012) +# Peter Cao (P-Cao) +# Yiming Bao (baoy1) +# Yian Zong (YianZong) +# Forrest Xia (forrestxia) # for all files: * @medegw01 @gallacher @tdawe @alikdell @atye @hoppea2 @coulof @shaynafinocchiaro @lj-software @sharmilarama +* @taohe1012 @P-Cao @baoy1 @YianZong @forrestxia From 8e7fa945ede4904cde39687ca579feb1bcd49ced Mon Sep 17 00:00:00 2001 From: sharmilarama <72404078+sharmilarama@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:45:43 -0400 Subject: [PATCH 2/2] chart/csm-authorization: Release v1.3.0 updates (#128) * [charts/csm-authorization] feature-261: Authorization helm chart (#109) * use 1.3.0 (#125) Co-authored-by: Aaron Tye Co-authored-by: EvgenyUglov <63835199+EvgenyUglov@users.noreply.github.com> --- .github/CODEOWNERS | 10 +- .github/workflows/helm-validations.yml | 1 + charts/csm-authorization/.gitignore | 2 + charts/csm-authorization/.helmignore | 24 ++ charts/csm-authorization/Chart.yaml | 15 ++ charts/csm-authorization/README.md | 19 ++ .../charts/redis/.helmignore | 23 ++ .../csm-authorization/charts/redis/Chart.yaml | 6 + .../charts/redis/templates/redis.yaml | 128 +++++++++++ .../charts/redis/values.yaml | 0 charts/csm-authorization/policies/common.rego | 4 + .../policies/powermax-url.rego | 47 ++++ .../policies/powerscale-url.rego | 42 ++++ .../csm-authorization/policies/url-test.rego | 63 ++++++ charts/csm-authorization/policies/url.rego | 39 ++++ .../policies/volumes-create-test.rego | 117 ++++++++++ .../policies/volumes-create.rego | 74 +++++++ .../policies/volumes-delete.rego | 48 ++++ .../policies/volumes-map.rego | 42 ++++ .../policies/volumes-powermax-create.rego | 74 +++++++ .../policies/volumes-powerscale-create.rego | 60 +++++ .../policies/volumes-unmap.rego | 42 ++++ charts/csm-authorization/templates/NOTES.txt | 23 ++ .../templates/certificate.yaml | 82 +++++++ .../templates/csm-config-params.yaml | 12 + .../csm-authorization/templates/ingress.yaml | 207 ++++++++++++++++++ .../templates/karavi-storage-secret.yaml | 8 + .../csm-authorization/templates/policies.yaml | 79 +++++++ .../templates/proxy-server.yaml | 115 ++++++++++ .../templates/role-service.yaml | 79 +++++++ .../templates/storage-service.yaml | 81 +++++++ .../templates/tenant-service.yaml | 51 +++++ charts/csm-authorization/values.yaml | 89 ++++++++ samples/csm-authorization/config.yaml | 2 + 34 files changed, 1705 insertions(+), 3 deletions(-) create mode 100644 charts/csm-authorization/.gitignore create mode 100644 charts/csm-authorization/.helmignore create mode 100644 charts/csm-authorization/Chart.yaml create mode 100644 charts/csm-authorization/README.md create mode 100644 charts/csm-authorization/charts/redis/.helmignore create mode 100644 charts/csm-authorization/charts/redis/Chart.yaml create mode 100644 charts/csm-authorization/charts/redis/templates/redis.yaml create mode 100644 charts/csm-authorization/charts/redis/values.yaml create mode 100644 charts/csm-authorization/policies/common.rego create mode 100644 charts/csm-authorization/policies/powermax-url.rego create mode 100644 charts/csm-authorization/policies/powerscale-url.rego create mode 100644 charts/csm-authorization/policies/url-test.rego create mode 100644 charts/csm-authorization/policies/url.rego create mode 100644 charts/csm-authorization/policies/volumes-create-test.rego create mode 100644 charts/csm-authorization/policies/volumes-create.rego create mode 100644 charts/csm-authorization/policies/volumes-delete.rego create mode 100644 charts/csm-authorization/policies/volumes-map.rego create mode 100644 charts/csm-authorization/policies/volumes-powermax-create.rego create mode 100644 charts/csm-authorization/policies/volumes-powerscale-create.rego create mode 100644 charts/csm-authorization/policies/volumes-unmap.rego create mode 100644 charts/csm-authorization/templates/NOTES.txt create mode 100644 charts/csm-authorization/templates/certificate.yaml create mode 100644 charts/csm-authorization/templates/csm-config-params.yaml create mode 100644 charts/csm-authorization/templates/ingress.yaml create mode 100644 charts/csm-authorization/templates/karavi-storage-secret.yaml create mode 100644 charts/csm-authorization/templates/policies.yaml create mode 100644 charts/csm-authorization/templates/proxy-server.yaml create mode 100644 charts/csm-authorization/templates/role-service.yaml create mode 100644 charts/csm-authorization/templates/storage-service.yaml create mode 100644 charts/csm-authorization/templates/tenant-service.yaml create mode 100644 charts/csm-authorization/values.yaml create mode 100644 samples/csm-authorization/config.yaml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 29ecac31..1421ef37 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,7 +7,6 @@ # be requested for review when someone opens a pull request. # order is alphabetical for easier maintenance. # -# Michael Edegware (medegw01) # Sean Gallacher (gallacher) # Trevor Dawe (tdawe) # Alexander Hoppe (hoppea2) @@ -15,8 +14,13 @@ # Aaron Tye (atye) # Florian Coulombel (coulof) # Shayna Finocchiaro (shaynafinocchiaro) -# Logan Jones (lj-software) # Sharmila Ramamoorthy (sharmilarama) +# Tao He (taohe1012) +# Peter Cao (P-Cao) +# Yiming Bao (baoy1) +# Yian Zong (YianZong) +# Forrest Xia (forrestxia) # for all files: -* @medegw01 @gallacher @tdawe @alikdell @atye @hoppea2 @coulof @shaynafinocchiaro @lj-software @sharmilarama +* @gallacher @tdawe @alikdell @atye @hoppea2 @coulof @shaynafinocchiaro @sharmilarama +* @taohe1012 @P-Cao @baoy1 @YianZong @forrestxia diff --git a/.github/workflows/helm-validations.yml b/.github/workflows/helm-validations.yml index 444af715..bd318268 100644 --- a/.github/workflows/helm-validations.yml +++ b/.github/workflows/helm-validations.yml @@ -7,6 +7,7 @@ on: branches: - main - karavi-observability-release + - csm-authorization-release jobs: # This job will check to see if any .yaml file is modified diff --git a/charts/csm-authorization/.gitignore b/charts/csm-authorization/.gitignore new file mode 100644 index 00000000..a4d58c62 --- /dev/null +++ b/charts/csm-authorization/.gitignore @@ -0,0 +1,2 @@ +Chart.lock +charts/*tgz diff --git a/charts/csm-authorization/.helmignore b/charts/csm-authorization/.helmignore new file mode 100644 index 00000000..9d56613f --- /dev/null +++ b/charts/csm-authorization/.helmignore @@ -0,0 +1,24 @@ +# 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/ +installer/ diff --git a/charts/csm-authorization/Chart.yaml b/charts/csm-authorization/Chart.yaml new file mode 100644 index 00000000..31ce6501 --- /dev/null +++ b/charts/csm-authorization/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: csm-authorization +version: 1.3.0 +appVersion: 1.3.0 +type: application +description: CSM for Authorization is part of the [Container Storage Modules](https://github.com/dell/csm) open source suite of Kubernetes storage enablers for Dell EMC storage products. CSM for Authorization provides storage and Kubernetes administrators the ability to apply RBAC for Dell CSI Drivers. +dependencies: +- name: cert-manager + version: 1.6.1 + repository: https://charts.jetstack.io + condition: cert-manager.enabled +- name: ingress-nginx + version: 4.0.19 + repository: https://kubernetes.github.io/ingress-nginx + condition: ingress-nginx.enabled diff --git a/charts/csm-authorization/README.md b/charts/csm-authorization/README.md new file mode 100644 index 00000000..1b5eed59 --- /dev/null +++ b/charts/csm-authorization/README.md @@ -0,0 +1,19 @@ + + +# Container Storage Modules (CSM) for Authorization Dell Community Helm Chart + +CSM for Authorization can be deployed using Helm. + +For complete deployment instructions, refer to the [Container Storage Modules documentation](https://dell.github.io/csm-docs/docs/authorization/deployment/helm). + +## Helm Chart Versioning + +For an explanation and examples on versioning/releasing the CSM for Authorization Helm chart, please see the [contributing guide](../../docs/CONTRIBUTING.md#helm-chart-release-strategy). diff --git a/charts/csm-authorization/charts/redis/.helmignore b/charts/csm-authorization/charts/redis/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/csm-authorization/charts/redis/.helmignore @@ -0,0 +1,23 @@ +# 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/ diff --git a/charts/csm-authorization/charts/redis/Chart.yaml b/charts/csm-authorization/charts/redis/Chart.yaml new file mode 100644 index 00000000..30b032ee --- /dev/null +++ b/charts/csm-authorization/charts/redis/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: redis +description: A Helm chart for Redis +type: application +version: 0.1.0 +appVersion: 0.1.0 diff --git a/charts/csm-authorization/charts/redis/templates/redis.yaml b/charts/csm-authorization/charts/redis/templates/redis.yaml new file mode 100644 index 00000000..fdc9dc70 --- /dev/null +++ b/charts/csm-authorization/charts/redis/templates/redis.yaml @@ -0,0 +1,128 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-primary + namespace: {{ .Release.Namespace }} + labels: + app: redis +spec: + selector: + matchLabels: + app: redis + role: primary + tier: backend + replicas: 1 + template: + metadata: + labels: + app: redis + role: primary + tier: backend + spec: + containers: + - name: primary + image: {{ .Values.images.redis }} + imagePullPolicy: IfNotPresent + args: ["--appendonly", "yes", "--appendfsync", "always"] + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 + volumeMounts: + - name: redis-primary-volume + mountPath: /data + volumes: + - name: redis-primary-volume + persistentVolumeClaim: + claimName: redis-primary-pv-claim +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-primary-pv-claim + namespace: {{ .Release.Namespace }} + labels: + app: redis-primary +spec: + accessModes: + - ReadWriteOnce + {{- if (.Values.storageClass) }} + storageClassName: {{.Values.storageClass }} + {{- end}} + resources: + requests: + storage: 8Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-commander + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: redis-commander + template: + metadata: + labels: + app: redis-commander + tier: backend + spec: + containers: + - name: redis-commander + image: {{ .Values.images.commander }} + imagePullPolicy: IfNotPresent + env: + - name: REDIS_HOSTS + value: "rbac:redis.{{ .Release.Namespace }}.svc.cluster.local:6379" + - name: K8S_SIGTERM + value: "1" + ports: + - name: redis-commander + containerPort: 8081 + livenessProbe: + httpGet: + path: /favicon.png + port: 8081 + initialDelaySeconds: 10 + timeoutSeconds: 5 + resources: + limits: + cpu: "500m" + memory: "512M" + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL +--- +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: {{ .Release.Namespace }} +spec: + selector: + app: redis + ports: + - protocol: TCP + port: 6379 + targetPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-commander + namespace: {{ .Release.Namespace }} +spec: + selector: + app: redis-commander + ports: + - protocol: TCP + port: 8081 + targetPort: 8081 diff --git a/charts/csm-authorization/charts/redis/values.yaml b/charts/csm-authorization/charts/redis/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/charts/csm-authorization/policies/common.rego b/charts/csm-authorization/policies/common.rego new file mode 100644 index 00000000..99709c9a --- /dev/null +++ b/charts/csm-authorization/policies/common.rego @@ -0,0 +1,4 @@ +package karavi.common +default roles = {} +roles = {} + diff --git a/charts/csm-authorization/policies/powermax-url.rego b/charts/csm-authorization/policies/powermax-url.rego new file mode 100644 index 00000000..25cd3f6e --- /dev/null +++ b/charts/csm-authorization/policies/powermax-url.rego @@ -0,0 +1,47 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.authz.powermax.url + +allowlist = [ + "GET /univmax/restapi/version", + "GET /univmax/restapi/(90|91)/system/symmetrix/[a-f0-9A-F]+", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/srp", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/storagegroup", + "POST /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/storagegroup", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/storagegroup/(.+)", + "PUT /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/storagegroup/(.+)", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/volume", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/volume/[a-f0-9A-F]+", + "PUT /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/volume/[a-f0-9A-F]+", + "DELETE /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/volume/[a-f0-9A-F]+", + "DELETE /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/storagegroup/[a-f0-9A-F]+", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/volume/[a-f0-9A-F]+/snapshot", + "GET /univmax/restapi/91/sloprovisioning/symmetrix/[a-f0-9A-F]+/portgroup/(.+)", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/initiator", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/host/(.+)", + "GET /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/maskingview/(.+)", + "GET /univmax/restapi/(90|91)/system/symmetrix", + "GET /univmax/restapi/private/(90|91)/replication/symmetrix/[a-f0-9A-F]+/volume/[a-f0-9A-F]+/snapshot", + "GET /univmax/restapi/private/(90|91)/replication/symmetrix/[a-f0-9A-F]+/volume/", + "DELETE /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/maskingview/(.+)", + "GET /univmax/restapi/(90|91)/replication/capabilities/symmetrix/", + "POST /univmax/restapi/(90|91)/sloprovisioning/symmetrix/[a-f0-9A-F]+/maskingview", +] + +default allow = true + +allow { + regex.match(allowlist[_], sprintf("%s %s", [input.method, input.url])) +} diff --git a/charts/csm-authorization/policies/powerscale-url.rego b/charts/csm-authorization/policies/powerscale-url.rego new file mode 100644 index 00000000..4a3032bd --- /dev/null +++ b/charts/csm-authorization/policies/powerscale-url.rego @@ -0,0 +1,42 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.authz.powerscale.url + +allowlist = [ + "GET /platform/latest/", + "GET /platform/[0-9]/cluster/config/", + "GET /namespace/(.+)", + "GET /platform/[0-9]/protocols/nfs/exports/?(.+)", + "PUT /namespace/(.+)", + "GET /platform/[0-9]/quota/license/", + "POST /platform/[0-9]/quota/quotas/", + "POST /platform/[0-9]/protocols/nfs/exports/?(.+)", + "GET /platform/[0-9]/protocols/nfs/exports/[0-9]+?(.+)", + "PUT /platform/[0-9]/protocols/nfs/exports/[0-9]+?(.+)", + "DELETE /platform/[0-9]/quota/quotas/[a-z0-9A-Z]+/", + "DELETE /platform/[0-9]/protocols/nfs/exports/[0-9]+?(.+)", + "DELETE /namespace/(.+)", + "GET /platform/[0-9]/snapshot/snapshots/(.+)", + "POST /platform/[0-9]/snapshot/snapshots", + "DELETE /platform/[0-9]/snapshot/snapshots/(.+)", + "POST /session/[0-9]/session/", + "GET /session/[0-9]/session/", + "POST /proxy/refresh-token/" +] + +default allow = true +allow { + regex.match(allowlist[_], sprintf("%s %s", [input.method, input.url])) +} diff --git a/charts/csm-authorization/policies/url-test.rego b/charts/csm-authorization/policies/url-test.rego new file mode 100644 index 00000000..ed849eb4 --- /dev/null +++ b/charts/csm-authorization/policies/url-test.rego @@ -0,0 +1,63 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.authz.url + +test_get_api_login_allowed { + allow with input as {"method": "GET", "url": "/api/login/"} +} + +test_post_proxy_refresh_token_allowed { + allow with input as {"method": "POST", "url": "/proxy/refresh-token/"} +} + +test_get_api_version_allowed { + allow with input as {"method": "GET", "url": "/api/version/"} +} + +test_get_system_instances_allowed { + allow with input as {"method": "GET", "url": "/api/types/System/instances/"} +} + +test_get_storagpool_instances_allowed { + allow with input as {"method": "GET", "url": "/api/types/StoragePool/instances/"} +} + +test_post_volume_instances_allowed { + allow with input as {"method": "POST", "url": "/api/types/Volume/instances/"} +} + +test_get_volume_instance_allowed { + allow with input as {"method": "GET", "url": "/api/instances/Volume::2a3814c600000003/"} +} + +test_post_volume_instances_queryIdByKey_allowed { + allow with input as {"method": "POST", "url": "/api/types/Volume/instances/action/queryIdByKey/"} +} + +test_get_system_sdc_allowed { + allow with input as {"method": "GET", "url": "/api/instances/System::7045c4cc20dffc0f/relationships/Sdc/"} +} + +test_post_volume_add_sdc_allowed { + allow with input as {"method": "POST", "url": "/api/instances/Volume::2a3814c600000003/action/addMappedSdc/"} +} + +test_post_volume_remove_sdc_allowed { + allow with input as {"method": "POST", "url": "/api/instances/Volume::2a3814c600000003/action/removeMappedSdc/"} +} + +test_post_volume_remove_allowed { + allow with input as {"method": "POST", "url": "/api/instances/Volume::2a3814c600000003/action/removeVolume/"} +} diff --git a/charts/csm-authorization/policies/url.rego b/charts/csm-authorization/policies/url.rego new file mode 100644 index 00000000..fe0e04b1 --- /dev/null +++ b/charts/csm-authorization/policies/url.rego @@ -0,0 +1,39 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.authz.url + +allowlist = [ + "GET /api/login/", + "POST /proxy/refresh-token/", + "GET /api/version/", + "GET /api/types/System/instances/", + "GET /api/types/StoragePool/instances/", + "POST /api/types/Volume/instances/", + "GET /api/instances/Volume::[a-f0-9]+/$", + "POST /api/types/Volume/instances/action/queryIdByKey/", + "GET /api/instances/System::[a-f0-9]+/relationships/Sdc/", + "GET /api/instances/Sdc::[a-f0-9]+/relationships/Statistics/", + "GET /api/instances/Sdc::[a-f0-9]+/relationships/Volume/", + "GET /api/instances/Volume::[a-f0-9]+/relationships/Statistics/", + "GET /api/instances/StoragePool::[a-f0-9]+/relationships/Statistics/", + "POST /api/instances/Volume::[a-f0-9]+/action/addMappedSdc/", + "POST /api/instances/Volume::[a-f0-9]+/action/removeMappedSdc/", + "POST /api/instances/Volume::[a-f0-9]+/action/removeVolume/" +] + +default allow = false +allow { + regex.match(allowlist[_], sprintf("%s %s", [input.method, input.url])) +} diff --git a/charts/csm-authorization/policies/volumes-create-test.rego b/charts/csm-authorization/policies/volumes-create-test.rego new file mode 100644 index 00000000..619e5a8d --- /dev/null +++ b/charts/csm-authorization/policies/volumes-create-test.rego @@ -0,0 +1,117 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.create + +roles = { + "us-east-1": { + "system_types": { + "powerflex": { + "system_ids": { + "2222": { + "pool_quotas": { + "bronze": "44000000" + } + } + } + } + } + }, + "us-west-1": { + "system_types": { + "powerflex": { + "system_ids": { + "1111": { + "pool_quotas": { + "bronze": 83886080 + } + } + } + } + } + }, + "us-west-2-small": { + "system_types": { + "powerflex": { + "system_ids": { + "2222": { + "pool_quotas": { + "bronze": 83886080 + } + } + } + } + } + }, + "us-west-2-large": { + "system_types": { + "powerflex": { + "system_ids": { + "2222": { + "pool_quotas": { + "bronze": 838860800, + "silver": 93886080000 + } + } + } + } + } + } + } + +test_small_request_allowed { + allow with input as { + "claims": { + "aud": "karavi", + "exp": 1615426023, + "group": "DevOpsGroup1", + "iss":"com.dell.karavi", + "roles":"us-east-1", + "sub":"karavi-tenant" + }, + "request": { + "name":"k8s-0fc0695995", + "protectionDomainId":"6b2ffe6c00000000", + "storagePoolId":"ae376b0300000000", + "volumeSizeInKb":"8388608", + "volumeType":"ThinProvisioned" + }, + "storagepool":"bronze", + "storagesystemid":"2222", + "systemtype": "powerflex" + } with data.karavi.common.roles as roles +} + +test_large_request_not_allowed { + not allow with input as { + "claims": { + "aud": "karavi", + "exp": 1615426023, + "group": "DevOpsGroup1", + "iss":"com.dell.karavi", + "roles":"us-west-2-small,us-west-2-large", + "sub":"karavi-tenant" + }, + "request": { + "name":"k8s-0fc0695995", + "protectionDomainId":"6b2ffe6c00000000", + "storagePoolId":"ae376b0300000000", + "volumeSizeInKb":"9999999999", + "volumeType":"ThinProvisioned" + }, + "storagepool":"bronze", + "storagesystemid":"2222", + "storagetype": "powerflex" + } with data.karavi.common.roles as roles +} diff --git a/charts/csm-authorization/policies/volumes-create.rego b/charts/csm-authorization/policies/volumes-create.rego new file mode 100644 index 00000000..ee506874 --- /dev/null +++ b/charts/csm-authorization/policies/volumes-create.rego @@ -0,0 +1,74 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.create + +import data.karavi.common + +# Deny requests by default. +default allow = false + +# +# Allows the request if one of the claimed roles matches +# a role configured to allow the storage request. +# +allow { + count(permitted_roles) != 0 + count(deny) == 0 +} + +# +# Deny if there are no roles found. +# +deny[msg] { + common.roles == {} + msg := sprintf("no configured roles", []) +} + +# +# Deny if claimed roles has no match for the request. +# +deny[msg] { + count(permitted_roles) == 0 + msg := sprintf("no roles in [%s] allow the %s Kb request on %s/%s/%s", + [input.claims.roles, + input.request.volumeSizeInKb, + input.systemtype, + input.storagesystemid, + input.storagepool]) +} + +# +# These are permitted roles that are configured +# with the requested storage system, mapped to +# the allowable quota for the request storage +# pool. +# +# Example: { "role-1": 800000 } +# +permitted_roles[v] = y { + # Split the claimed roles by comma into an array. + claimed_roles := split(input.claims.roles, ",") + + # This block filters 'a' to contain only roles + # that are found in 'common.roles'. + some i + a := claimed_roles[i] + common.roles[a] + + # v will contain permitted roles that match the storage request. + v := claimed_roles[i] + common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool] >= to_number(input.request.volumeSizeInKb) + y := to_number(common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool]) +} diff --git a/charts/csm-authorization/policies/volumes-delete.rego b/charts/csm-authorization/policies/volumes-delete.rego new file mode 100644 index 00000000..2ee0938c --- /dev/null +++ b/charts/csm-authorization/policies/volumes-delete.rego @@ -0,0 +1,48 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.delete + +import data.karavi.common + +default response = { + "allowed": true +} +response = { + "allowed": false, + "status": { + "reason": reason, + }, +} { + reason = concat(", ", deny) + reason != "" +} + +# +# Ensure there are roles configured. +# +deny[msg] { + common.roles == {} + msg := sprintf("no role data found", []) +} + +# +# Validate input: claims. +# +default claims = {} +claims = input.claims +deny[msg] { + claims == {} + msg := sprintf("missing claims", []) +} diff --git a/charts/csm-authorization/policies/volumes-map.rego b/charts/csm-authorization/policies/volumes-map.rego new file mode 100644 index 00000000..15fb172e --- /dev/null +++ b/charts/csm-authorization/policies/volumes-map.rego @@ -0,0 +1,42 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.map + +import data.karavi.common + +default response = { + "allowed": true +} +response = { + "allowed": false, + "status": { + "reason": reason, + }, +} { + reason = concat(", ", deny) + reason != "" +} + +deny[msg] { + common.roles == {} + msg := sprintf("no role data found", []) +} + +default claims = {} +claims = input.claims +deny[msg] { + claims == {} + msg := sprintf("missing claims", []) +} diff --git a/charts/csm-authorization/policies/volumes-powermax-create.rego b/charts/csm-authorization/policies/volumes-powermax-create.rego new file mode 100644 index 00000000..96eb8894 --- /dev/null +++ b/charts/csm-authorization/policies/volumes-powermax-create.rego @@ -0,0 +1,74 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.powermax.create + +import data.karavi.common + +# Deny requests by default. +default allow = false + +# +# Allows the request if one of the claimed roles matches +# a role configured to allow the storage request. +# +allow { + count(permitted_roles) != 0 + count(deny) == 0 +} + +# +# Deny if there are no roles found. +# +deny[msg] { + common.roles == {} + msg := sprintf("no configured roles", []) +} + +# +# Deny if claimed roles has no match for the request. +# +deny[msg] { + count(permitted_roles) == 0 + msg := sprintf("no roles in [%s] allow the %v Kb request on %s/%s/%s", + [input.claims.roles, + input.request.volumeSizeInKb, + input.systemtype, + input.storagesystemid, + input.storagepool]) +} + +# +# These are permitted roles that are configured +# with the requested storage system, mapped to +# the allowable quota for the request storage +# pool. +# +# Example: { "role-1": 800000 } +# +permitted_roles[v] = y { + # Split the claimed roles by comma into an array. + claimed_roles := split(input.claims.roles, ",") + + # This block filters 'a' to contain only roles + # that are found in 'common.roles'. + some i + a := claimed_roles[i] + common.roles[a] + + # v will contain permitted roles that match the storage request. + v := claimed_roles[i] + common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool] >= to_number(input.request.volumeSizeInKb) + y := to_number(common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool]) +} diff --git a/charts/csm-authorization/policies/volumes-powerscale-create.rego b/charts/csm-authorization/policies/volumes-powerscale-create.rego new file mode 100644 index 00000000..47a6fe12 --- /dev/null +++ b/charts/csm-authorization/policies/volumes-powerscale-create.rego @@ -0,0 +1,60 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.powerscale.create + +import data.karavi.common + +# Deny requests by default. +default allow = false + +# +# Allows the request if one of the claimed roles matches +# a role configured to allow the storage request. +# +allow { + count(deny) == 0 +} + +# +# Deny if there are no roles found. +# +deny[msg] { + common.roles == {} + msg := sprintf("no configured roles", []) +} + +# +# These are permitted roles that are configured +# with the requested storage system, mapped to +# the allowable quota for the request storage +# pool. +# +# Example: { "role-1": 800000 } +# +permitted_roles[v] = y { + # Split the claimed roles by comma into an array. + claimed_roles := split(input.claims.roles, ",") + + # This block filters 'a' to contain only roles + # that are found in 'common.roles'. + some i + a := claimed_roles[i] + common.roles[a] + + # v will contain permitted roles that match the storage request. + v := claimed_roles[i] + common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool] >= to_number(input.request.volumeSizeInKb) + y := to_number(common.roles[v].system_types[input.systemtype].system_ids[input.storagesystemid].pool_quotas[input.storagepool]) +} diff --git a/charts/csm-authorization/policies/volumes-unmap.rego b/charts/csm-authorization/policies/volumes-unmap.rego new file mode 100644 index 00000000..f4a85f1f --- /dev/null +++ b/charts/csm-authorization/policies/volumes-unmap.rego @@ -0,0 +1,42 @@ +# Copyright © 2022 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package karavi.volumes.unmap + +import data.karavi.common + +default response = { + "allowed": true +} +response = { + "allowed": false, + "status": { + "reason": reason, + }, +} { + reason = concat(", ", deny) + reason != "" +} + +deny[msg] { + common.roles == {} + msg := sprintf("no role data found", []) +} + +default claims = {} +claims = input.claims +deny[msg] { + claims == {} + msg := sprintf("missing claims", []) +} diff --git a/charts/csm-authorization/templates/NOTES.txt b/charts/csm-authorization/templates/NOTES.txt new file mode 100644 index 00000000..531c1aae --- /dev/null +++ b/charts/csm-authorization/templates/NOTES.txt @@ -0,0 +1,23 @@ +The CSM Authorization deployment has been successfully installed. + +Execute the following commands in your shell to print the URL of the CSM Authorization NodePort LoadBalancer: + +export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[1].nodePort}" service {{ .Release.Namespace }}-ingress-nginx-controller) +export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") +echo https://$NODE_IP:$NODE_PORT + +LoadBalancer host rules for proxy-server: +- {{ .Values.authorization.hostname }} +- {{ .Release.Name }}-ingress-nginx-controller.{{ .Release.Namespace }}.svc.cluster.local + +LoadBalancer host rules for tenant-service: +- tenant.{{ .Values.authorization.hostname }} + +LoadBalancer host rules for role-service: +- role.{{ .Values.authorization.hostname }} + +LoadBalancer host rules for storage-service: +- storage.{{ .Values.authorization.hostname }} + +authorization.proxyHost value for a CSI Driver examples: +- {{ .Release.Name }}-ingress-nginx-controller.{{ .Release.Namespace }}.svc.cluster.local:443 (CSI Driver in the same cluster as CSM Authorization) diff --git a/charts/csm-authorization/templates/certificate.yaml b/charts/csm-authorization/templates/certificate.yaml new file mode 100644 index 00000000..956ca260 --- /dev/null +++ b/charts/csm-authorization/templates/certificate.yaml @@ -0,0 +1,82 @@ +# If the cert and key are provided, use them to create a tls secret +{{- if and (.Values.authorization.certificate) (.Values.authorization.privateKey) }} +{{- $certificateFileContents := .Values.authorization.certificate }} +{{- $privateKeyFileContents := .Values.authorization.privateKey }} +apiVersion: v1 +data: + tls.crt: {{ $certificateFileContents | b64enc }} + tls.key: {{ $privateKeyFileContents | b64enc }} +kind: Secret +type: kubernetes.io/tls +metadata: + name: user-provided-tls + namespace: {{ .Release.Namespace }} + +--- +{{- end }} + + +# If the cert and key are not provided, user cert-manager to create a self-signed tls secret +{{- if or (not .Values.authorization.certificate) (not .Values.authorization.privateKey) }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} + +--- + +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: karavi-auth + namespace: {{ .Release.Namespace }} +spec: + secretName: karavi-selfsigned-tls + duration: 2160h # 90d + renewBefore: 360h # 15d + subject: + organizations: + - dellemc + isCA: false + privateKey: + algorithm: RSA + encoding: PKCS1 + size: 2048 + usages: + - server auth + - client auth + dnsNames: + - karavi-auth + - karavi-auth.{{ .Release.Namespace }}.svc.kubernetes.local + - {{ .Values.authorization.hostname }} + - tenant.{{ .Values.authorization.hostname }} + - role.{{ .Values.authorization.hostname }} + - storage.{{ .Values.authorization.hostname }} + {{- if .Values.authorization.proxyServerIngress.hosts }} + {{- range .Values.authorization.proxyServerIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if .Values.authorization.tenantServiceIngress.hosts }} + {{- range .Values.authorization.tenantServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if .Values.authorization.roleServiceIngress.hosts }} + {{- range .Values.authorization.roleServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if .Values.authorization.storageServiceIngress.hosts }} + {{- range .Values.authorization.storageServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + issuerRef: + name: selfsigned + kind: Issuer + group: cert-manager.io +{{- end }} diff --git a/charts/csm-authorization/templates/csm-config-params.yaml b/charts/csm-authorization/templates/csm-config-params.yaml new file mode 100644 index 00000000..7ea7f66f --- /dev/null +++ b/charts/csm-authorization/templates/csm-config-params.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: csm-config-params + namespace: {{ .Release.Namespace }} +data: + csm-config-params.yaml: | + LOG_LEVEL: {{ .Values.authorization.logLevel }} + {{- if (.Values.authorization.zipkin.collectoruri) }} + zipkin.collectoruri: {{ .Values.authorization.zipkin.collectoruri }} + zipkin.probability: {{ .Values.authorization.zipkin.probability }} + {{- end }} diff --git a/charts/csm-authorization/templates/ingress.yaml b/charts/csm-authorization/templates/ingress.yaml new file mode 100644 index 00000000..b36fa5f4 --- /dev/null +++ b/charts/csm-authorization/templates/ingress.yaml @@ -0,0 +1,207 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: proxy-server + namespace: {{ .Release.Namespace }} + {{- if .Values.authorization.proxyServerIngress.annotations }} + annotations: + {{- range $key, $value := .Values.authorization.proxyServerIngress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + ingressClassName: {{ .Values.authorization.proxyServerIngress.ingressClassName }} + tls: + - hosts: + - {{ .Values.authorization.hostname }} + {{- if .Values.authorization.proxyServerIngress.hosts }} + {{- range .Values.authorization.proxyServerIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if and (.Values.authorization.certificate) (.Values.authorization.privateKey) }} + secretName: user-provided-tls + {{- else }} + secretName: karavi-selfsigned-tls + {{- end}} + rules: + - host: {{ .Values.authorization.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: proxy-server + port: + number: 8080 + {{- if .Values.authorization.proxyServerIngress.hosts }} + {{- range .Values.authorization.proxyServerIngress.hosts }} + - host: {{ tpl . $}} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: proxy-server + port: + number: 8080 + {{- end }} + {{- end}} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: tenant-service + namespace: {{ .Release.Namespace }} + annotations: + {{- if .Values.authorization.tenantServiceIngress.annotations }} + {{- range $key, $value := .Values.authorization.tenantServiceIngress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + ingressClassName: {{ .Values.authorization.tenantServiceIngress.ingressClassName }} + tls: + - hosts: + - tenant.{{ .Values.authorization.hostname }} + {{- if .Values.authorization.tenantServiceIngress.hosts }} + {{- range .Values.authorization.tenantServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if and (.Values.authorization.certificate) (.Values.authorization.privateKey) }} + secretName: user-provided-tls + {{- else }} + secretName: karavi-selfsigned-tls + {{- end}} + rules: + - host: tenant.{{ .Values.authorization.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: tenant-service + port: + number: 50051 + {{- if .Values.authorization.tenantServiceIngress.hosts }} + {{- range .Values.authorization.tenantServiceIngress.hosts }} + - host: {{ tpl . $}} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: tenant-service + port: + number: 50051 + {{- end }} + {{- end}} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: role-service + namespace: {{ .Release.Namespace }} + annotations: + {{- if .Values.authorization.roleServiceIngress.annotations }} + {{- range $key, $value := .Values.authorization.roleServiceIngress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + ingressClassName: {{ .Values.authorization.roleServiceIngress.ingressClassName }} + tls: + - hosts: + - role.{{ .Values.authorization.hostname }} + {{- if .Values.authorization.roleServiceIngress.hosts }} + {{- range .Values.authorization.roleServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if and (.Values.authorization.certificate) (.Values.authorization.privateKey) }} + secretName: user-provided-tls + {{- else }} + secretName: karavi-selfsigned-tls + {{- end}} + rules: + - host: role.{{ .Values.authorization.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: role-service + port: + number: 50051 + {{- if .Values.authorization.roleServiceIngress.hosts }} + {{- range .Values.authorization.roleServiceIngress.hosts }} + - host: {{ tpl . $}} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: role-service + port: + number: 50051 + {{- end}} + {{- end}} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: storage-service + namespace: {{ .Release.Namespace }} + annotations: + {{- if .Values.authorization.storageServiceIngress.annotations }} + {{- range $key, $value := .Values.authorization.storageServiceIngress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + ingressClassName: {{ .Values.authorization.storageServiceIngress.ingressClassName }} + tls: + - hosts: + - storage.{{ .Values.authorization.hostname }} + {{- if .Values.authorization.storageServiceIngress.hosts }} + {{- range .Values.authorization.storageServiceIngress.hosts }} + - {{ tpl . $}} + {{- end }} + {{- end}} + {{- if and (.Values.authorization.certificate) (.Values.authorization.privateKey) }} + secretName: user-provided-tls + {{- else }} + secretName: karavi-selfsigned-tls + {{- end}} + rules: + - host: storage.{{ .Values.authorization.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: storage-service + port: + number: 50051 + {{- if .Values.authorization.storageServiceIngress.hosts }} + {{- range .Values.authorization.storageServiceIngress.hosts }} + - host: {{ tpl . $}} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: storage-service + port: + number: 50051 + {{- end}} + {{- end}} diff --git a/charts/csm-authorization/templates/karavi-storage-secret.yaml b/charts/csm-authorization/templates/karavi-storage-secret.yaml new file mode 100644 index 00000000..4aa41669 --- /dev/null +++ b/charts/csm-authorization/templates/karavi-storage-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: karavi-storage-secret + namespace: {{ .Release.Namespace }} +data: + storage-systems.yaml: c3RvcmFnZToK diff --git a/charts/csm-authorization/templates/policies.yaml b/charts/csm-authorization/templates/policies.yaml new file mode 100644 index 00000000..8627b54a --- /dev/null +++ b/charts/csm-authorization/templates/policies.yaml @@ -0,0 +1,79 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: common + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/common.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: powermax-urls + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/powermax-url.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: powerscale-urls + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/powerscale-url.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: powerflex-urls + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/url.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: volumes-create + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-create.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: volumes-delete + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-delete.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: volumes-map + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-map.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: powermax-volumes-create + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-powermax-create.rego").AsConfig | nindent 2 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: powerscale-volumes-create + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-powerscale-create.rego").AsConfig | nindent 2 }}3 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: volumes-unmap + namespace: {{ .Release.Namespace }} +data: + {{- (.Files.Glob "policies/volumes-unmap.rego").AsConfig | nindent 2 }} \ No newline at end of file diff --git a/charts/csm-authorization/templates/proxy-server.yaml b/charts/csm-authorization/templates/proxy-server.yaml new file mode 100644 index 00000000..957858b3 --- /dev/null +++ b/charts/csm-authorization/templates/proxy-server.yaml @@ -0,0 +1,115 @@ +# Grant OPA/kube-mgmt read-only access to resources. This lets kube-mgmt +# list configmaps to be loaded into OPA as policies. +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: opa-viewer +roleRef: + kind: ClusterRole + name: view + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: Group + name: system:serviceaccounts:{{ .Release.Namespace }} + apiGroup: rbac.authorization.k8s.io +--- +# Define role for OPA/kube-mgmt to update configmaps with policy status. +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + namespace: {{ .Release.Namespace }} + name: configmap-modifier +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["update", "patch"] +--- +# Grant OPA/kube-mgmt role defined above. +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + namespace: {{ .Release.Namespace }} + name: opa-configmap-modifier +roleRef: + kind: Role + name: configmap-modifier + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: Group + name: system:serviceaccounts:karavi + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: proxy-server + namespace: {{ .Release.Namespace }} + labels: + app: proxy-server +spec: + replicas: 1 + selector: + matchLabels: + app: proxy-server + template: + metadata: + labels: + app: proxy-server + spec: + containers: + - name: proxy-server + image: {{ required "Must provide the proxy-server image." .Values.authorization.images.proxyService }} + imagePullPolicy: Always + args: + - "--redis-host=redis.{{ .Release.Namespace }}.svc.cluster.local:6379" + - "--tenant-service=tenant-service.{{ .Release.Namespace }}.svc.cluster.local:50051" + ports: + - containerPort: 8080 + volumeMounts: + - name: config-volume + mountPath: /etc/karavi-authorization/config + - name: storage-volume + mountPath: /etc/karavi-authorization/storage + - name: csm-config-params + mountPath: /etc/karavi-authorization/csm-config-params + - name: opa + image: {{ required "Must provide the openpolicyagent image." .Values.authorization.images.opa }} + imagePullPolicy: IfNotPresent + args: + - "run" + - "--ignore=." + - "--server" + - "--log-level=debug" + ports: + - name: http + containerPort: 8181 + - name: kube-mgmt + image: {{ required "Must provide the opaKubeMgmt image." .Values.authorization.images.opaKubeMgmt }} + imagePullPolicy: IfNotPresent + args: + - "--policies={{ .Release.Namespace }}" + - "--enable-data" + volumes: + - name: config-volume + secret: + secretName: karavi-config-secret + - name: storage-volume + secret: + secretName: karavi-storage-secret + - name: csm-config-params + configMap: + name: csm-config-params +--- +apiVersion: v1 +kind: Service +metadata: + name: proxy-server + namespace: {{ .Release.Namespace }} +spec: + selector: + app: proxy-server + ports: + - name: http + protocol: TCP + port: 8080 + targetPort: 8080 diff --git a/charts/csm-authorization/templates/role-service.yaml b/charts/csm-authorization/templates/role-service.yaml new file mode 100644 index 00000000..180586b9 --- /dev/null +++ b/charts/csm-authorization/templates/role-service.yaml @@ -0,0 +1,79 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: role-service + namespace: {{ .Release.Namespace }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: role-service +rules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "patch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: role-service +subjects: + - kind: ServiceAccount + name: role-service + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: role-service + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: role-service + namespace: {{ .Release.Namespace }} + labels: + app: role-service +spec: + replicas: 1 + selector: + matchLabels: + app: role-service + template: + metadata: + labels: + app: role-service + spec: + serviceAccountName: role-service + containers: + - name: role-service + image: {{ required "Must provide the role-service image." .Values.authorization.images.roleService }} + imagePullPolicy: Always + ports: + - containerPort: 50051 + name: grpc + env: + - name: NAMESPACE + value: {{ .Release.Namespace }} + volumeMounts: + - name: csm-config-params + mountPath: /etc/karavi-authorization/csm-config-params + volumes: + - name: csm-config-params + configMap: + name: csm-config-params +--- +apiVersion: v1 +kind: Service +metadata: + name: role-service + namespace: {{ .Release.Namespace }} +spec: + selector: + app: role-service + ports: + - port: 50051 + targetPort: 50051 + name: grpc diff --git a/charts/csm-authorization/templates/storage-service.yaml b/charts/csm-authorization/templates/storage-service.yaml new file mode 100644 index 00000000..3df96faa --- /dev/null +++ b/charts/csm-authorization/templates/storage-service.yaml @@ -0,0 +1,81 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: storage-service + namespace: {{ .Release.Namespace }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: storage-service +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "patch"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: storage-service +subjects: + - kind: ServiceAccount + name: storage-service + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: storage-service + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: storage-service + namespace: {{ .Release.Namespace }} + labels: + app: storage-service +spec: + replicas: 1 + selector: + matchLabels: + app: storage-service + template: + metadata: + labels: + app: storage-service + spec: + serviceAccountName: storage-service + containers: + - name: storage-service + image: {{ required "Must provide the storage-service image." .Values.authorization.images.storageService }} + imagePullPolicy: Always + ports: + - containerPort: 50051 + name: grpc + env: + - name: NAMESPACE + value: {{ .Release.Namespace }} + volumeMounts: + - name: storage-volume + mountPath: /etc/karavi-authorization/storage + - name: csm-config-params + mountPath: /etc/karavi-authorization/csm-config-params + volumes: + - name: storage-volume + secret: + secretName: karavi-storage-secret + - name: csm-config-params + configMap: + name: csm-config-params +--- +apiVersion: v1 +kind: Service +metadata: + name: storage-service + namespace: {{ .Release.Namespace }} +spec: + selector: + app: storage-service + ports: + - port: 50051 + targetPort: 50051 + name: grpc diff --git a/charts/csm-authorization/templates/tenant-service.yaml b/charts/csm-authorization/templates/tenant-service.yaml new file mode 100644 index 00000000..a526a763 --- /dev/null +++ b/charts/csm-authorization/templates/tenant-service.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tenant-service + namespace: {{ .Release.Namespace }} + labels: + app: tenant-service +spec: + replicas: 1 + selector: + matchLabels: + app: tenant-service + template: + metadata: + labels: + app: tenant-service + spec: + containers: + - name: tenant-service + image: {{ required "Must provide the tenant-service image." .Values.authorization.images.tenantService }} + imagePullPolicy: Always + args: + - "--redis-host=redis.{{ .Release.Namespace }}.svc.cluster.local:6379" + ports: + - containerPort: 50051 + name: grpc + volumeMounts: + - name: config-volume + mountPath: /etc/karavi-authorization/config + - name: csm-config-params + mountPath: /etc/karavi-authorization/csm-config-params + volumes: + - name: config-volume + secret: + secretName: karavi-config-secret + - name: csm-config-params + configMap: + name: csm-config-params +--- +apiVersion: v1 +kind: Service +metadata: + name: tenant-service + namespace: {{ .Release.Namespace }} +spec: + selector: + app: tenant-service + ports: + - port: 50051 + targetPort: 50051 + name: grpc diff --git a/charts/csm-authorization/values.yaml b/charts/csm-authorization/values.yaml new file mode 100644 index 00000000..69af919c --- /dev/null +++ b/charts/csm-authorization/values.yaml @@ -0,0 +1,89 @@ +# if enabled, nginx ingress controller will be deployed +# if you have your own ingress controller, keep this false and set the appropriate annotations for the ingresses in the authorization section +ingress-nginx: + enabled: true + +# if enabled, cert-manager will be deployed +# if cert-manager is already deployed, keep this false +cert-manager: + enabled: true + +authorization: + # images to use in installation + images: + proxyService: dellemc/csm-authorization-proxy:v1.3.0 + tenantService: dellemc/csm-authorization-tenant:v1.3.0 + roleService: dellemc/csm-authorization-role:v1.3.0 + storageService: dellemc/csm-authorization-storage:v1.3.0 + opa: openpolicyagent/opa + opaKubeMgmt: openpolicyagent/kube-mgmt:0.11 + + # base hostname for the ingress rules that expose the services + # the proxy-server ingress will use this hostname + # the tenant-service ingress will use tenant.hostname + # the role-service ingress will use role.hostname + hostname: csm-authorization.com + + # log level for csm-authorization + logLevel: debug + + # tracing configuration + # this can be updated on the fly via the csm-config-params configMap + zipkin: {} + # collectoruri: http://DNS-hostname:9411/api/v2/spans + # probability: 1 + + # proxy-server ingress configuration + proxyServerIngress: + ingressClassName: # nginx + + # additional host rules for the proxy-server ingress + hosts: [] + # - namespace-ingress-nginx-controller.namespace.svc.cluster.local + + # additional annotations for the proxy-server ingress + annotations: {} + + # tenant-service ingress configuration + tenantServiceIngress: + ingressClassName: # nginx + + # additional host rules for the tenant-service ingress + hosts: [] + + # additional annotations for the tenant-service ingress + # if applicable, an annotation supporting grpc for your ingress controller must be supplied + annotations: {} + # nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + + # role-service ingress configuration + roleServiceIngress: + ingressClassName: nginx + + # additional host rules for the role-service ingress + hosts: [] + + # additional annotations for the role-service ingress + # an annotation supporting grpc for your ingress controller must be supplied, if applicable + annotations: {} + # nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + + # storage-service ingress configuration + storageServiceIngress: + ingressClassName: nginx + + # additional host rules for the storage-service ingress + hosts: [] + + # additional annotations for the storage-service ingress + # an annotation supporting grpc for your ingress controller must be supplied, if applicable + annotations: {} + # nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + +redis: + images: + redis: redis:6.0.8-alpine + commander: rediscommander/redis-commander:latest + + # set the storageClass for redis to use. otherwise, the default storage class is used + # storageClass: local-storage diff --git a/samples/csm-authorization/config.yaml b/samples/csm-authorization/config.yaml new file mode 100644 index 00000000..b19b2e6a --- /dev/null +++ b/samples/csm-authorization/config.yaml @@ -0,0 +1,2 @@ +web: + jwtsigningsecret: secret