mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-18 11:00:25 +00:00
api: add CSIProvisionerRBAC functions for the NFS-provisioner
Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
parent
35da67be45
commit
6b13352c9b
48
api/deploy/kubernetes/nfs/csi-provisioner-rbac-cr.yaml
Normal file
48
api/deploy/kubernetes/nfs/csi-provisioner-rbac-cr.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: nfs-external-provisioner-runner
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["nodes"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get", "list"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["list", "watch", "create", "update", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumes"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "update", "delete", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["get", "list", "watch", "update"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["storageclasses"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["volumeattachments"]
|
||||||
|
verbs: ["get", "list", "watch", "update", "patch"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["volumeattachments/status"]
|
||||||
|
verbs: ["patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims/status"]
|
||||||
|
verbs: ["update", "patch"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["csinodes"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshotclasses"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshotcontents"]
|
||||||
|
verbs: ["get", "list", "watch", "update", "patch"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshotcontents/status"]
|
||||||
|
verbs: ["update", "patch"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshots"]
|
||||||
|
verbs: ["get", "list"]
|
13
api/deploy/kubernetes/nfs/csi-provisioner-rbac-crb.yaml
Normal file
13
api/deploy/kubernetes/nfs/csi-provisioner-rbac-crb.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "{{ .ServiceAccount }}-role"
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "{{ .ServiceAccount }}"
|
||||||
|
namespace: "{{ .Namespace }}"
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: nfs-external-provisioner-runner
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
14
api/deploy/kubernetes/nfs/csi-provisioner-rbac-r.yaml
Normal file
14
api/deploy/kubernetes/nfs/csi-provisioner-rbac-r.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
namespace: "{{ .Namespace }}"
|
||||||
|
name: nfs-external-provisioner-cfg
|
||||||
|
rules:
|
||||||
|
# remove this once we stop supporting v1.0.0
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps"]
|
||||||
|
verbs: ["get", "list", "create", "delete"]
|
||||||
|
- apiGroups: ["coordination.k8s.io"]
|
||||||
|
resources: ["leases"]
|
||||||
|
verbs: ["get", "watch", "list", "delete", "update", "create"]
|
14
api/deploy/kubernetes/nfs/csi-provisioner-rbac-rb.yaml
Normal file
14
api/deploy/kubernetes/nfs/csi-provisioner-rbac-rb.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "{{ .ServiceAccount }}-role-cfg"
|
||||||
|
namespace: "{{ .Namespace }}"
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "{{ .ServiceAccount }}"
|
||||||
|
namespace: "{{ .Namespace }}"
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: nfs-external-provisioner-cfg
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
220
api/deploy/kubernetes/nfs/csi-provisioner-rbac.go
Normal file
220
api/deploy/kubernetes/nfs/csi-provisioner-rbac.go
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Ceph-CSI Authors.
|
||||||
|
|
||||||
|
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 nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"text/template"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ghodss/yaml"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/api/deploy/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed csi-provisioner-rbac-cr.yaml
|
||||||
|
var csiProvisionerClusterRole string
|
||||||
|
|
||||||
|
//go:embed csi-provisioner-rbac-crb.yaml
|
||||||
|
var csiProvisionerClusterRoleBinding string
|
||||||
|
|
||||||
|
//go:embed csi-provisioner-rbac-r.yaml
|
||||||
|
var csiProvisionerRole string
|
||||||
|
|
||||||
|
//go:embed csi-provisioner-rbac-rb.yaml
|
||||||
|
var csiProvisionerRoleBinding string
|
||||||
|
|
||||||
|
var CSIProvisionerRBACDefaults = kubernetes.CSIProvisionerRBACValues{
|
||||||
|
Namespace: "default",
|
||||||
|
ServiceAccount: "nfs-csi-provisioner",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCSIProvisionerRBAC takes a driver name from the CSIProvisionerRBACValues
|
||||||
|
// struct and replaces the value in the template. A CSIProvisionerRBAC object
|
||||||
|
// is returned which can be used to create permissions for the provisioner in
|
||||||
|
// the Kubernetes cluster.
|
||||||
|
func NewCSIProvisionerRBAC(values kubernetes.CSIProvisionerRBACValues) (kubernetes.CSIProvisionerRBAC, error) {
|
||||||
|
sa := &corev1.ServiceAccount{}
|
||||||
|
sa.Namespace = values.Namespace
|
||||||
|
sa.Name = values.ServiceAccount
|
||||||
|
|
||||||
|
cr, err := newClusterRole(values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
crb, err := newClusterRoleBinding(values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := newRole(values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rb, err := newRoleBinding(values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &csiProvisionerRBAC{
|
||||||
|
serviceAccount: sa,
|
||||||
|
clusterRole: cr,
|
||||||
|
clusterRoleBinding: crb,
|
||||||
|
role: r,
|
||||||
|
roleBinding: rb,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCSIProvisionerRBACYAML(values kubernetes.CSIProvisionerRBACValues) (string, error) {
|
||||||
|
docs := []string{}
|
||||||
|
|
||||||
|
data, err := newYAML("csiProvisionerClusterRole", csiProvisionerClusterRole, values)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
docs = append(docs, data)
|
||||||
|
|
||||||
|
data, err = newYAML("csiProvisionerClusterRoleBinding", csiProvisionerClusterRoleBinding, values)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
docs = append(docs, data)
|
||||||
|
|
||||||
|
data, err = newYAML("csiProvisionerRole", csiProvisionerRole, values)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
docs = append(docs, data)
|
||||||
|
|
||||||
|
data, err = newYAML("csiProvisionerRoleBinding", csiProvisionerRoleBinding, values)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
docs = append(docs, data)
|
||||||
|
|
||||||
|
return strings.Join(docs, "\n"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func newYAML(name, data string, values kubernetes.CSIProvisionerRBACValues) (string, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
tmpl, err := template.New(name).Parse(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to parse template: %w", err)
|
||||||
|
}
|
||||||
|
err = tmpl.Execute(&buf, values)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to replace values in template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClusterRole(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.ClusterRole, error) {
|
||||||
|
data, err := newYAML("csiProvisionerClusterRole", csiProvisionerClusterRole, values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cr := &rbacv1.ClusterRole{}
|
||||||
|
err = yaml.Unmarshal([]byte(data), cr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed convert YAML to %T: %w", cr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClusterRoleBinding(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.ClusterRoleBinding, error) {
|
||||||
|
data, err := newYAML("csiProvisionerClusterRoleBinding", csiProvisionerClusterRoleBinding, values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
crb := &rbacv1.ClusterRoleBinding{}
|
||||||
|
err = yaml.Unmarshal([]byte(data), crb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed convert YAML to %T: %w", crb, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return crb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRole(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.Role, error) {
|
||||||
|
data, err := newYAML("csiProvisionerRole", csiProvisionerRole, values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &rbacv1.Role{}
|
||||||
|
err = yaml.Unmarshal([]byte(data), r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed convert YAML to %T: %w", r, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoleBinding(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.RoleBinding, error) {
|
||||||
|
data, err := newYAML("csiProvisionerRoleBinding", csiProvisionerRoleBinding, values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rb := &rbacv1.RoleBinding{}
|
||||||
|
err = yaml.Unmarshal([]byte(data), rb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed convert YAML to %T: %w", rb, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type csiProvisionerRBAC struct {
|
||||||
|
serviceAccount *corev1.ServiceAccount
|
||||||
|
clusterRole *rbacv1.ClusterRole
|
||||||
|
clusterRoleBinding *rbacv1.ClusterRoleBinding
|
||||||
|
role *rbacv1.Role
|
||||||
|
roleBinding *rbacv1.RoleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rbac *csiProvisionerRBAC) GetServiceAccount() *corev1.ServiceAccount {
|
||||||
|
return rbac.serviceAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rbac *csiProvisionerRBAC) GetClusterRole() *rbacv1.ClusterRole {
|
||||||
|
return rbac.clusterRole
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rbac *csiProvisionerRBAC) GetClusterRoleBinding() *rbacv1.ClusterRoleBinding {
|
||||||
|
return rbac.clusterRoleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rbac *csiProvisionerRBAC) GetRole() *rbacv1.Role {
|
||||||
|
return rbac.role
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rbac *csiProvisionerRBAC) GetRoleBinding() *rbacv1.RoleBinding {
|
||||||
|
return rbac.roleBinding
|
||||||
|
}
|
67
api/deploy/kubernetes/nfs/csi-provisioner-rbac_test.go
Normal file
67
api/deploy/kubernetes/nfs/csi-provisioner-rbac_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Ceph-CSI Authors.
|
||||||
|
|
||||||
|
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 nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewCSIProvisionerRBAC(t *testing.T) {
|
||||||
|
rbac, err := NewCSIProvisionerRBAC(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, rbac)
|
||||||
|
require.Equal(t, rbac.GetServiceAccount().Namespace, CSIProvisionerRBACDefaults.Namespace)
|
||||||
|
require.Equal(t, rbac.GetServiceAccount().Name, CSIProvisionerRBACDefaults.ServiceAccount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewCSIProvisionerRBACYAML(t *testing.T) {
|
||||||
|
yaml, err := NewCSIProvisionerRBACYAML(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEqual(t, "", yaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewClusterRole(t *testing.T) {
|
||||||
|
cr, err := newClusterRole(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, cr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewClusterRoleBinding(t *testing.T) {
|
||||||
|
crb, err := newClusterRoleBinding(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, crb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewRole(t *testing.T) {
|
||||||
|
r, err := newRole(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewRoleBinding(t *testing.T) {
|
||||||
|
rb, err := newRoleBinding(CSIProvisionerRBACDefaults)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, rb)
|
||||||
|
}
|
39
api/deploy/kubernetes/provisioner.go
Normal file
39
api/deploy/kubernetes/provisioner.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Ceph-CSI Authors.
|
||||||
|
|
||||||
|
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 kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CSIProvisionerRBAC describes the interface that is provided by different
|
||||||
|
// provisioner backends to get details about the required RBAC.
|
||||||
|
type CSIProvisionerRBAC interface {
|
||||||
|
GetServiceAccount() *corev1.ServiceAccount
|
||||||
|
GetClusterRole() *rbacv1.ClusterRole
|
||||||
|
GetClusterRoleBinding() *rbacv1.ClusterRoleBinding
|
||||||
|
GetRole() *rbacv1.Role
|
||||||
|
GetRoleBinding() *rbacv1.RoleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSIProvisionerRBACValues contains values that can be passed to
|
||||||
|
// NewCSIProvisionerRBAC() functions for different provisioner backends.
|
||||||
|
type CSIProvisionerRBACValues struct {
|
||||||
|
Namespace string
|
||||||
|
ServiceAccount string
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user