updated to latest k8s version
This commit is contained in:
parent
974555da9e
commit
bbbd20b5f2
12 changed files with 668 additions and 525 deletions
|
|
@ -9,13 +9,12 @@ import (
|
|||
pve "git.giftfish.de/ston1th/pve-go"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
certificatesv1 "k8s.io/api/certificates/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
typedcertificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
typedcertificatesv1 "k8s.io/client-go/kubernetes/typed/certificates/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
|
|
@ -28,20 +27,19 @@ type CSRReconciler struct {
|
|||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
PVEClient *pve.Client
|
||||
CSRClient *typedcertificatesv1beta1.CertificatesV1beta1Client
|
||||
CSRClient *typedcertificatesv1.CertificatesV1Client
|
||||
}
|
||||
|
||||
func (r *CSRReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
WithOptions(options).
|
||||
For(&certificatesv1beta1.CertificateSigningRequest{}).
|
||||
For(&certificatesv1.CertificateSigningRequest{}).
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
func (r *CSRReconciler) Reconcile(req ctrl.Request) (res ctrl.Result, err error) {
|
||||
ctx := context.Background()
|
||||
func (r *CSRReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
|
||||
log := r.Log
|
||||
csr := &certificatesv1beta1.CertificateSigningRequest{}
|
||||
csr := &certificatesv1.CertificateSigningRequest{}
|
||||
if err = r.Get(ctx, req.NamespacedName, csr); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
err = nil
|
||||
|
|
@ -56,13 +54,13 @@ func (r *CSRReconciler) Reconcile(req ctrl.Request) (res ctrl.Result, err error)
|
|||
return
|
||||
}
|
||||
|
||||
var conditionv1beta1 = certificatesv1beta1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1beta1.CertificateApproved,
|
||||
var conditionv1 = certificatesv1.CertificateSigningRequestCondition{
|
||||
Type: certificatesv1.CertificateApproved,
|
||||
Reason: "AutoApproved",
|
||||
Message: "Auto approving kubelet client certificate in PVE Cluster",
|
||||
}
|
||||
|
||||
func (r *CSRReconciler) approve(ctx context.Context, log logr.Logger, request *certificatesv1beta1.CertificateSigningRequest) error {
|
||||
func (r *CSRReconciler) approve(ctx context.Context, log logr.Logger, request *certificatesv1.CertificateSigningRequest) error {
|
||||
if len(request.Status.Conditions) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -79,9 +77,9 @@ func (r *CSRReconciler) approve(ctx context.Context, log logr.Logger, request *c
|
|||
if len(request.Status.Conditions) > 0 {
|
||||
return nil
|
||||
}
|
||||
request.Status.Conditions = append(request.Status.Conditions, conditionv1beta1)
|
||||
request.Status.Conditions = append(request.Status.Conditions, conditionv1)
|
||||
// Submit the updated CSR.
|
||||
if _, err := client.UpdateApproval(ctx, request, metav1.UpdateOptions{}); err != nil {
|
||||
if _, err := client.UpdateApproval(ctx, request.Name, request, metav1.UpdateOptions{}); err != nil {
|
||||
if strings.Contains(err.Error(), "the object has been modified") {
|
||||
// The CSR might have been updated by a third-party, retry until we
|
||||
// succeed.
|
||||
|
|
@ -98,8 +96,8 @@ func (r *CSRReconciler) approve(ctx context.Context, log logr.Logger, request *c
|
|||
}
|
||||
}
|
||||
|
||||
func checkCSR(ctx context.Context, pveClient *pve.Client, request *certificatesv1beta1.CertificateSigningRequest) error {
|
||||
req, err := certificates.ParseCSR(request.Spec.Request)
|
||||
func checkCSR(ctx context.Context, pveClient *pve.Client, request *certificatesv1.CertificateSigningRequest) error {
|
||||
req, err := ParseCSR(request.Spec.Request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -107,7 +105,7 @@ func checkCSR(ctx context.Context, pveClient *pve.Client, request *certificatesv
|
|||
for i, v := range request.Spec.Usages {
|
||||
usages[i] = string(v)
|
||||
}
|
||||
if !certificates.IsKubeletServingCSR(req, sets.NewString(usages...)) {
|
||||
if !IsKubeletServingCSR(req, sets.NewString(usages...)) {
|
||||
return ErrNoKubeletServingCSR
|
||||
}
|
||||
hostname := strings.TrimPrefix(req.Subject.CommonName, "system:node:")
|
||||
|
|
|
|||
81
pkg/approver/helper.go
Normal file
81
pkg/approver/helper.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copied from https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/certificates/helpers.go
|
||||
// to avoid importing k8s.io/kubernetes
|
||||
|
||||
package approver
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// ParseCSR extracts the CSR from the bytes and decodes it.
|
||||
func ParseCSR(pemBytes []byte) (*x509.CertificateRequest, error) {
|
||||
block, _ := pem.Decode(pemBytes)
|
||||
if block == nil || block.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, errors.New("PEM block type must be CERTIFICATE REQUEST")
|
||||
}
|
||||
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return csr, nil
|
||||
}
|
||||
|
||||
var (
|
||||
organizationNotSystemNodesErr = fmt.Errorf("subject organization is not system:nodes")
|
||||
commonNameNotSystemNode = fmt.Errorf("subject common name does not begin with system:node:")
|
||||
dnsOrIPSANRequiredErr = fmt.Errorf("DNS or IP subjectAltName is required")
|
||||
emailSANNotAllowedErr = fmt.Errorf("Email subjectAltNames are not allowed")
|
||||
uriSANNotAllowedErr = fmt.Errorf("URI subjectAltNames are not allowed")
|
||||
)
|
||||
|
||||
type KeyUsage string
|
||||
|
||||
const (
|
||||
UsageDigitalSignature KeyUsage = "digital signature"
|
||||
UsageKeyEncipherment KeyUsage = "key encipherment"
|
||||
UsageServerAuth KeyUsage = "server auth"
|
||||
)
|
||||
|
||||
var kubeletServingRequiredUsages = sets.NewString(
|
||||
string(UsageDigitalSignature),
|
||||
string(UsageKeyEncipherment),
|
||||
string(UsageServerAuth),
|
||||
)
|
||||
|
||||
func IsKubeletServingCSR(req *x509.CertificateRequest, usages sets.String) bool {
|
||||
return ValidateKubeletServingCSR(req, usages) == nil
|
||||
}
|
||||
func ValidateKubeletServingCSR(req *x509.CertificateRequest, usages sets.String) error {
|
||||
if !reflect.DeepEqual([]string{"system:nodes"}, req.Subject.Organization) {
|
||||
return organizationNotSystemNodesErr
|
||||
}
|
||||
|
||||
// at least one of dnsNames or ipAddresses must be specified
|
||||
if len(req.DNSNames) == 0 && len(req.IPAddresses) == 0 {
|
||||
return dnsOrIPSANRequiredErr
|
||||
}
|
||||
|
||||
if len(req.EmailAddresses) > 0 {
|
||||
return emailSANNotAllowedErr
|
||||
}
|
||||
if len(req.URIs) > 0 {
|
||||
return uriSANNotAllowedErr
|
||||
}
|
||||
|
||||
if !kubeletServingRequiredUsages.Equal(usages) {
|
||||
return fmt.Errorf("usages did not match %v", kubeletServingRequiredUsages.List())
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(req.Subject.CommonName, "system:node:") {
|
||||
return commonNameNotSystemNode
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue