mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-18 02:50:30 +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