Skip to content

Commit

Permalink
refactor: refactor csi driver (#186)
Browse files Browse the repository at this point in the history
* refactor: rename volumeSelector to volumeContext

* refactor: refactor backend and add qualified node for volume topology

* refactor: refactor podInfo impl node scope check

* refactor: add cache to podInfo and impl qualified ndoe

* fix: fix topology value err and pref code with lint

* fix: pvc delete rbac missing
  • Loading branch information
whg517 authored Dec 30, 2024
1 parent 6ceb65b commit 9dea930
Show file tree
Hide file tree
Showing 11 changed files with 557 additions and 453 deletions.
13 changes: 12 additions & 1 deletion config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ rules:
- ""
resources:
- events
- persistentvolumes
- pods
- secrets
verbs:
Expand All @@ -27,6 +26,18 @@ rules:
- get
- list
- watch
- apiGroups:
- ""
resources:
- persistentvolumes
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- secrets.kubedoop.dev
resources:
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/secretclass_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type SecretClassReconciler struct {
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=core,resources=persistentvolumeclaims,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch;create;update;patch;delete

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
40 changes: 20 additions & 20 deletions internal/csi/backend/autotls.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,20 @@ const (
DefaultCertBuffer time.Duration = 8 * time.Hour
)

var _ IBackend = &AutoTlsBackend{}

type AutoTlsBackend struct {
client client.Client
podInfo *pod_info.PodInfo
volumeSelector *volume.SecretVolumeSelector
volumeContext *volume.SecretVolumeContext
maxCertificateLifeTime time.Duration

ca *secretsv1alpha1.CASpec
certManager *ca.CertificateManager
}

func NewAutoTlsBackend(
client client.Client,
podInfo *pod_info.PodInfo,
volumeSelector *volume.SecretVolumeSelector,
autotls *secretsv1alpha1.AutoTlsSpec,
) (*AutoTlsBackend, error) {
func NewAutoTlsBackend(config *BackendConfig) (IBackend, error) {
autotls := config.SecretClass.Spec.Backend.AutoTls
maxCertificateLifeTime, err := time.ParseDuration(autotls.MaxCertificateLifeTime)
if err != nil {
return nil, err
Expand All @@ -58,14 +56,14 @@ func NewAutoTlsBackend(
}

return &AutoTlsBackend{
client: client,
podInfo: podInfo,
volumeSelector: volumeSelector,
client: config.Client,
podInfo: config.PodInfo,
volumeContext: config.VolumeContext,
maxCertificateLifeTime: maxCertificateLifeTime,
ca: autotls.CA,

certManager: ca.NewCertificateManager(
client,
config.Client,
caCertificateLifeTime,
autotls.CA.AutoGenerated,
autotls.CA.Secret.Name,
Expand All @@ -78,12 +76,12 @@ func NewAutoTlsBackend(
func (a *AutoTlsBackend) getCertLife() (time.Duration, error) {
now := time.Now()

certLife := a.volumeSelector.AutoTlsCertLifetime
certLife := a.volumeContext.AutoTlsCertLifetime
if certLife == 0 {
logger.Info("Certificate lifetime is not set, using default certificate lifetime", "defaultCertLifeTime", DefaultCertLifeTime)
certLife = DefaultCertLifeTime
}
restarterBuffer := a.volumeSelector.AutoTlsCertRestartBuffer
restarterBuffer := a.volumeContext.AutoTlsCertRestartBuffer
if restarterBuffer == 0 {
logger.Info("Certificate restart buffer is not set, using default certificate restart buffer", "defaultCertBuffer", DefaultCertBuffer)
restarterBuffer = DefaultCertBuffer
Expand All @@ -97,7 +95,7 @@ func (a *AutoTlsBackend) getCertLife() (time.Duration, error) {
certLife = a.maxCertificateLifeTime
}

jitterFactor := a.volumeSelector.AutoTlsCertJitterFactor
jitterFactor := a.volumeContext.AutoTlsCertJitterFactor

jitterFactorAllowedRange := 0.0 < jitterFactor && jitterFactor < 1.0
if !jitterFactorAllowedRange {
Expand Down Expand Up @@ -129,7 +127,7 @@ func (a *AutoTlsBackend) getCertLife() (time.Duration, error) {
}

func (a *AutoTlsBackend) certificateFormat() volume.SecretFormat {
return a.volumeSelector.Format
return a.volumeContext.Format
}

// Convert the certificate to the format required by the volume
Expand All @@ -142,7 +140,7 @@ func (a *AutoTlsBackend) certificateConvert(cert *ca.Certificate) (map[string]st

if format == volume.SecretFormatTLSP12 {
logger.Info("Converting certificate to PKCS12 format")
password := a.volumeSelector.TlsPKCS12Password
password := a.volumeContext.TlsPKCS12Password

caCerts := make([]*x509.Certificate, 0, len(trustAnchors))
for _, caCert := range trustAnchors {
Expand Down Expand Up @@ -177,6 +175,11 @@ func (a *AutoTlsBackend) certificateConvert(cert *ca.Certificate) (map[string]st
}, nil
}

func (k *AutoTlsBackend) GetQualifiedNodeNames(ctx context.Context) ([]string, error) {
// Default implementation, return nil
return nil, nil
}

func (a *AutoTlsBackend) GetSecretData(ctx context.Context) (*util.SecretContent, error) {
certificateAuthority, err := a.getCertificateAuthority(ctx)
if err != nil {
Expand All @@ -195,10 +198,7 @@ func (a *AutoTlsBackend) GetSecretData(ctx context.Context) (*util.SecretContent

notAfter := time.Now().Add(certLife)

cert, err := certificateAuthority.SignServerCertificate(
addresses,
notAfter,
)
cert, err := certificateAuthority.SignServerCertificate(addresses, notAfter)

if err != nil {
return nil, err
Expand Down
117 changes: 73 additions & 44 deletions internal/csi/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package backend

import (
"context"
"fmt"
"sync"

secretsv1alpha1 "github.com/zncdatadev/secret-operator/api/v1alpha1"
"github.com/zncdatadev/secret-operator/pkg/pod_info"
Expand All @@ -15,70 +17,97 @@ var (
logger = ctrl.Log.WithName("csi-backend")
)

type BackendType string

const (
KerberosKeytabType BackendType = "KerberosKeytab"
AutoTlsType BackendType = "AutoTls"
K8sSearchType BackendType = "K8sSearch"
)

type BackendConfig struct {
Client client.Client
PodInfo *pod_info.PodInfo
VolumeContext *volume.SecretVolumeContext
SecretClass *secretsv1alpha1.SecretClass
}

type IBackend interface {
GetSecretData(ctx context.Context) (*util.SecretContent, error)
GetQualifiedNodeNames(ctx context.Context) ([]string, error)
}

type Backend struct {
client client.Client
podInfo *pod_info.PodInfo
volumeSelector *volume.SecretVolumeSelector
secretClass *secretsv1alpha1.SecretClass
impl IBackend
}

func NewBackend(
Client client.Client,
PodInfo *pod_info.PodInfo,
VolumeSelector *volume.SecretVolumeSelector,
secretClass *secretsv1alpha1.SecretClass,
) *Backend {
return &Backend{
client: Client,
podInfo: PodInfo,
volumeSelector: VolumeSelector,
secretClass: secretClass,
func NewBackend(ctx context.Context, c client.Client, podInfo *pod_info.PodInfo, volumeCtx *volume.SecretVolumeContext) (*Backend, error) {
secretClass := &secretsv1alpha1.SecretClass{}
if err := c.Get(ctx, client.ObjectKey{Name: volumeCtx.Class}, secretClass); err != nil {
return nil, err
}
}

func (b *Backend) backendImpl() (IBackend, error) {
config := &BackendConfig{Client: c, PodInfo: podInfo, VolumeContext: volumeCtx, SecretClass: secretClass}

backend := b.secretClass.Spec.Backend
backendType := determineBackendType(config.SecretClass)
impl, err := CreateBackend(backendType, config)
if err != nil {
return nil, fmt.Errorf("failed to create backend: %w", err)
}
return &Backend{impl: impl}, nil
}

func determineBackendType(secretClass *secretsv1alpha1.SecretClass) BackendType {
backend := secretClass.Spec.Backend

if backend.KerberosKeytab != nil {
return NewKerberosBackend(
b.client,
b.podInfo,
b.volumeSelector,
backend.KerberosKeytab,
), nil
return KerberosKeytabType
}

if backend.AutoTls != nil {
return NewAutoTlsBackend(
b.client,
b.podInfo,
b.volumeSelector,
backend.AutoTls,
)
return AutoTlsType
}

if backend.K8sSearch != nil {
return NewK8sSearchBackend(
b.client,
b.podInfo,
b.volumeSelector,
backend.K8sSearch,
)
return K8sSearchType
}

panic("can not find backend")
return ""
}

func (b *Backend) GetSecretData(ctx context.Context) (*util.SecretContent, error) {
impl, err := b.backendImpl()
if err != nil {
return nil, err
return b.impl.GetSecretData(ctx)
}

func (b *Backend) GetQualifiedNodeNames(ctx context.Context) ([]string, error) {
return b.impl.GetQualifiedNodeNames(ctx)
}

type BackendFactory func(config *BackendConfig) (IBackend, error)

type BackendRegistry struct {
mu sync.RWMutex
factories map[BackendType]BackendFactory
}

var registry = &BackendRegistry{factories: make(map[BackendType]BackendFactory)}

func RegisterBackend(backendType BackendType, factory BackendFactory) {
registry.mu.Lock()
defer registry.mu.Unlock()
registry.factories[backendType] = factory
}

func CreateBackend(backendType BackendType, config *BackendConfig) (IBackend, error) {
registry.mu.RLock()
factory, exists := registry.factories[backendType]
registry.mu.RUnlock()

if !exists {
return nil, fmt.Errorf("backend type %s not registered", backendType)
}
return factory(config)
}

return impl.GetSecretData(ctx)
func init() {
RegisterBackend(KerberosKeytabType, NewKerberosBackend)
RegisterBackend(AutoTlsType, NewAutoTlsBackend)
RegisterBackend(K8sSearchType, NewK8sSearchBackend)
}
Loading

0 comments on commit 9dea930

Please sign in to comment.