mirror of
https://github.com/clastix/kamaji.git
synced 2026-08-26 00:47:20 +00:00
refactor(crypto): eliminating bloated certs functions
This commit is contained in:
+159
-101
@@ -5,103 +5,31 @@ package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
mathrand "math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
certBitSize = 2048
|
||||
)
|
||||
|
||||
func GetCertificateAndKeyPair(template *x509.Certificate, caCert []byte, caPrivKey []byte) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
caCertBytes, err := GetCertificate(caCert)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
// CheckPublicAndPrivateKeyValidity checks if the given bytes for the private and public keys are valid.
|
||||
func CheckPublicAndPrivateKeyValidity(publicKey []byte, privateKey []byte) (bool, error) {
|
||||
if len(publicKey) == 0 || len(privateKey) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
caPrivKeyBytes, err := GetPrivateKey(caPrivKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return GenerateCertificateKeyPairBytes(template, certBitSize, caCertBytes, caPrivKeyBytes)
|
||||
}
|
||||
|
||||
func GetCertificate(cert []byte) (*x509.Certificate, error) {
|
||||
pemContent, _ := pem.Decode(cert)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
return x509.ParseCertificate(pemContent.Bytes)
|
||||
}
|
||||
|
||||
func GetPrivateKey(privKey []byte) (*rsa.PrivateKey, error) {
|
||||
pemContent, _ := pem.Decode(privKey)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
return x509.ParsePKCS1PrivateKey(pemContent.Bytes)
|
||||
}
|
||||
|
||||
func GetPublickKey(pubKey []byte) (*rsa.PublicKey, error) {
|
||||
pemContent, _ := pem.Decode(pubKey)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
pub, err := x509.ParsePKIXPublicKey(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pub.(*rsa.PublicKey), nil //nolint:forcetypeassert
|
||||
}
|
||||
|
||||
func GenerateCertificateKeyPairBytes(template *x509.Certificate, bitSize int, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
certPrivKey, err := rsa.GenerateKey(rand.Reader, bitSize)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
certBytes, err := x509.CreateCertificate(rand.Reader, template, caCert, &certPrivKey.PublicKey, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
certPEM := &bytes.Buffer{}
|
||||
if err := pem.Encode(certPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Headers: nil,
|
||||
Bytes: certBytes,
|
||||
}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
certPrivKeyPEM := &bytes.Buffer{}
|
||||
if err := pem.Encode(certPrivKeyPEM, &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Headers: nil,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
|
||||
}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return certPEM, certPrivKeyPEM, nil
|
||||
}
|
||||
|
||||
func IsValidKeyPairBytes(pubKeyBytes []byte, privKeyBytes []byte) (bool, error) {
|
||||
privKey, err := GetPrivateKey(privKeyBytes)
|
||||
pubKey, err := ParsePublicKeyBytes(publicKey)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
pubKey, err := GetPublickKey(pubKeyBytes)
|
||||
privKey, err := ParsePrivateKeyBytes(privateKey)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -109,22 +37,134 @@ func IsValidKeyPairBytes(pubKeyBytes []byte, privKeyBytes []byte) (bool, error)
|
||||
return checkPublicKeys(privKey.PublicKey, *pubKey), nil
|
||||
}
|
||||
|
||||
func IsValidCertificateKeyPairBytes(certBytes []byte, privKeyBytes []byte) (bool, error) {
|
||||
cert, err := GetCertificate(certBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
// CheckCertificateAndPrivateKeyPairValidity checks if the certificate and private key pair are valid.
|
||||
func CheckCertificateAndPrivateKeyPairValidity(certificate []byte, privateKey []byte) (bool, error) {
|
||||
switch {
|
||||
case len(certificate) == 0, len(privateKey) == 0:
|
||||
return false, nil
|
||||
default:
|
||||
return IsValidCertificateKeyPairBytes(certificate, privateKey)
|
||||
}
|
||||
|
||||
privKey, err := GetPrivateKey(privKeyBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return isValidCertificateKeyPairBytes(*cert, *privKey), nil
|
||||
}
|
||||
|
||||
func isValidCertificateKeyPairBytes(cert x509.Certificate, privKey rsa.PrivateKey) bool {
|
||||
return checkCertificateValidity(cert) && checkCertificateKeyPair(cert, privKey)
|
||||
// GenerateCertificatePrivateKeyPair starts from the Certificate Authority bytes a certificate using the provided
|
||||
// template, returning the bytes both for the certificate and its key.
|
||||
func GenerateCertificatePrivateKeyPair(template *x509.Certificate, caCertificate []byte, caPrivateKey []byte) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
caCertBytes, err := ParseCertificateBytes(caCertificate)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
caPrivKeyBytes, err := ParsePrivateKeyBytes(caPrivateKey)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "provided CA private key for certificate generation cannot be parsed")
|
||||
}
|
||||
|
||||
return generateCertificateKeyPairBytes(template, caCertBytes, caPrivKeyBytes)
|
||||
}
|
||||
|
||||
// ParseCertificateBytes takes the certificate bytes returning a x509 certificate by parsing it.
|
||||
func ParseCertificateBytes(content []byte) (*x509.Certificate, error) {
|
||||
pemContent, _ := pem.Decode(content)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
crt, err := x509.ParseCertificate(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse x509 Certificate")
|
||||
}
|
||||
|
||||
return crt, nil
|
||||
}
|
||||
|
||||
// ParsePrivateKeyBytes takes the private key bytes returning an RSA private key by parsing it.
|
||||
func ParsePrivateKeyBytes(content []byte) (*rsa.PrivateKey, error) {
|
||||
pemContent, _ := pem.Decode(content)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
privateKey, err := x509.ParsePKCS1PrivateKey(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse PKCS1 Private Key")
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// ParsePublicKeyBytes takes the public key bytes returning an RSA public key by parsing it.
|
||||
func ParsePublicKeyBytes(content []byte) (*rsa.PublicKey, error) {
|
||||
pemContent, _ := pem.Decode(content)
|
||||
if pemContent == nil {
|
||||
return nil, fmt.Errorf("no right PEM block")
|
||||
}
|
||||
|
||||
publicKey, err := x509.ParsePKIXPublicKey(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rsaPublicKey, ok := publicKey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected *rsa.PublicKey, got %T", rsaPublicKey)
|
||||
}
|
||||
|
||||
return rsaPublicKey, nil
|
||||
}
|
||||
|
||||
// IsValidCertificateKeyPairBytes checks if the certificate matches the private key bounded to it.
|
||||
func IsValidCertificateKeyPairBytes(certificateBytes []byte, privateKeyBytes []byte) (bool, error) {
|
||||
crt, err := ParseCertificateBytes(certificateBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
key, err := ParsePrivateKeyBytes(privateKeyBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case !checkCertificateValidity(*crt):
|
||||
return false, nil
|
||||
case !checkPublicKeys(*crt.PublicKey.(*rsa.PublicKey), key.PublicKey): //nolint:forcetypeassert
|
||||
return false, nil
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
func generateCertificateKeyPairBytes(template *x509.Certificate, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
certPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot generate an RSA key")
|
||||
}
|
||||
|
||||
certBytes, err := x509.CreateCertificate(cryptorand.Reader, template, caCert, &certPrivKey.PublicKey, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot create the certificate")
|
||||
}
|
||||
|
||||
certPEM := &bytes.Buffer{}
|
||||
if err = pem.Encode(certPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Headers: nil,
|
||||
Bytes: certBytes,
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot encode the generate certificate bytes")
|
||||
}
|
||||
|
||||
certPrivKeyPEM := &bytes.Buffer{}
|
||||
if err = pem.Encode(certPrivKeyPEM, &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Headers: nil,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot encode private key")
|
||||
}
|
||||
|
||||
return certPEM, certPrivKeyPEM, nil
|
||||
}
|
||||
|
||||
func checkCertificateValidity(cert x509.Certificate) bool {
|
||||
@@ -133,13 +173,31 @@ func checkCertificateValidity(cert x509.Certificate) bool {
|
||||
return now.Before(cert.NotAfter) && now.After(cert.NotBefore)
|
||||
}
|
||||
|
||||
func checkCertificateKeyPair(cert x509.Certificate, privKey rsa.PrivateKey) bool {
|
||||
return checkPublicKeys(*cert.PublicKey.(*rsa.PublicKey), privKey.PublicKey) //nolint:forcetypeassert
|
||||
}
|
||||
|
||||
func checkPublicKeys(a rsa.PublicKey, b rsa.PublicKey) bool {
|
||||
isN := a.N.Cmp(b.N) == 0
|
||||
isE := a.E == b.E
|
||||
|
||||
return isN && isE
|
||||
}
|
||||
|
||||
// NewCertificateTemplate returns the template that must be used to generate a certificate,
|
||||
// used to perform the authentication against the DataStore.
|
||||
func NewCertificateTemplate(commonName string) *x509.Certificate {
|
||||
return &x509.Certificate{
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
SerialNumber: big.NewInt(mathrand.Int63()),
|
||||
Subject: pkix.Name{
|
||||
CommonName: commonName,
|
||||
Organization: []string{"system:masters"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(10, 0, 0),
|
||||
SubjectKeyId: []byte{1, 2, 3, 4, 6},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||
x509.ExtKeyUsageClientAuth,
|
||||
x509.ExtKeyUsageServerAuth,
|
||||
x509.ExtKeyUsageCodeSigning,
|
||||
},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package kubeadm
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
@@ -44,8 +44,8 @@ func GenerateCACertificatePrivateKeyPair(baseName string, config *Configuration)
|
||||
func GenerateCertificatePrivateKeyPair(baseName string, config *Configuration, ca CertificatePrivateKeyPair) (*CertificatePrivateKeyPair, error) {
|
||||
defer deleteCertificateDirectory(config.InitConfiguration.CertificatesDir)
|
||||
|
||||
certificate, _ := cryptoKamaji.GetCertificate(ca.Certificate)
|
||||
signer, _ := cryptoKamaji.GetPrivateKey(ca.PrivateKey)
|
||||
certificate, _ := cryptoKamaji.ParseCertificateBytes(ca.Certificate)
|
||||
signer, _ := cryptoKamaji.ParsePrivateKeyBytes(ca.PrivateKey)
|
||||
|
||||
kubeadmCert, err := getKubeadmCert(baseName)
|
||||
if err != nil {
|
||||
@@ -106,28 +106,6 @@ func GeneratePublicKeyPrivateKeyPair(baseName string, config *Configuration) (*P
|
||||
return publicKeyPrivateKeyPair, err
|
||||
}
|
||||
|
||||
func IsCertificatePrivateKeyPairValid(certificate []byte, privKey []byte) (bool, error) {
|
||||
if len(certificate) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if len(privKey) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return cryptoKamaji.IsValidCertificateKeyPairBytes(certificate, privKey)
|
||||
}
|
||||
|
||||
func IsPublicKeyPrivateKeyPairValid(pubKey []byte, privKey []byte) (bool, error) {
|
||||
if len(pubKey) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if len(privKey) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return cryptoKamaji.IsValidKeyPairBytes(pubKey, privKey)
|
||||
}
|
||||
|
||||
func initPhaseCertsSA(config *Configuration) error {
|
||||
return certs.CreateServiceAccountKeyAndPublicKeyFiles(config.InitConfiguration.CertificatesDir, config.InitConfiguration.PublicKeyAlgorithm())
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func (r *APIServerCertificate) mutate(ctx context.Context, tenantControlPlane *k
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.APIServer.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsCertificatePrivateKeyPairValid(
|
||||
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
|
||||
r.resource.Data[kubeadmconstants.APIServerCertName],
|
||||
r.resource.Data[kubeadmconstants.APIServerKeyName],
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func (r *APIServerKubeletClientCertificate) mutate(ctx context.Context, tenantCo
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.APIServerKubeletClient.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsCertificatePrivateKeyPairValid(
|
||||
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
|
||||
r.resource.Data[kubeadmconstants.APIServerKubeletClientCertName],
|
||||
r.resource.Data[kubeadmconstants.APIServerKubeletClientKeyName],
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func (r *CACertificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.CA.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsCertificatePrivateKeyPairValid(
|
||||
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
|
||||
r.resource.Data[kubeadmconstants.CACertName],
|
||||
r.resource.Data[kubeadmconstants.CAKeyName],
|
||||
)
|
||||
|
||||
@@ -6,12 +6,7 @@ package datastore
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -114,7 +109,7 @@ func (r *Certificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1al
|
||||
return err
|
||||
}
|
||||
|
||||
crt, key, err = crypto.GetCertificateAndKeyPair(r.getCertificateTemplate(tenantControlPlane), ca, privateKey)
|
||||
crt, key, err = crypto.GenerateCertificatePrivateKeyPair(crypto.NewCertificateTemplate(tenantControlPlane.GetName()), ca, privateKey)
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to generate certificate and private key")
|
||||
|
||||
@@ -164,25 +159,3 @@ func (r *Certificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1al
|
||||
return ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
}
|
||||
}
|
||||
|
||||
// getCertificateTemplate returns the template that must be used to generate a certificate,
|
||||
// used to perform the authentication against the DataStore.
|
||||
func (r *Certificate) getCertificateTemplate(tenant *kamajiv1alpha1.TenantControlPlane) *x509.Certificate {
|
||||
return &x509.Certificate{
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
SerialNumber: big.NewInt(rand.Int63()),
|
||||
Subject: pkix.Name{
|
||||
CommonName: tenant.GetName(),
|
||||
Organization: []string{"system:masters"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(10, 0, 0),
|
||||
SubjectKeyId: []byte{1, 2, 3, 4, 6},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||
x509.ExtKeyUsageClientAuth,
|
||||
x509.ExtKeyUsageServerAuth,
|
||||
x509.ExtKeyUsageCodeSigning,
|
||||
},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func (r *FrontProxyClientCertificate) mutate(ctx context.Context, tenantControlP
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.FrontProxyClient.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsCertificatePrivateKeyPairValid(
|
||||
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
|
||||
r.resource.Data[kubeadmconstants.FrontProxyClientCertName],
|
||||
r.resource.Data[kubeadmconstants.FrontProxyClientKeyName],
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -82,7 +83,7 @@ func (r *FrontProxyCACertificate) mutate(ctx context.Context, tenantControlPlane
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.FrontProxyCA.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsCertificatePrivateKeyPairValid(
|
||||
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
|
||||
r.resource.Data[kubeadmconstants.FrontProxyCACertName],
|
||||
r.resource.Data[kubeadmconstants.FrontProxyCAKeyName],
|
||||
)
|
||||
|
||||
@@ -4,14 +4,8 @@
|
||||
package konnectivity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -102,11 +96,8 @@ func (r *CertificateResource) mutate(ctx context.Context, tenantControlPlane *ka
|
||||
return func() error {
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.CA.Checksum; len(checksum) > 0 && checksum == utilities.CalculateConfigMapChecksum(r.resource.StringData) {
|
||||
isValid, err := isCertificateAndKeyPairValid(
|
||||
r.resource.Data[corev1.TLSCertKey],
|
||||
r.resource.Data[corev1.TLSPrivateKeyKey],
|
||||
)
|
||||
if checksum := tenantControlPlane.Status.Addons.Konnectivity.Certificate.Checksum; len(checksum) > 0 && checksum == utilities.CalculateConfigMapChecksum(r.resource.StringData) {
|
||||
isValid, err := crypto.IsValidCertificateKeyPairBytes(r.resource.Data[corev1.TLSCertKey], r.resource.Data[corev1.TLSPrivateKeyKey])
|
||||
if err != nil {
|
||||
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", konnectivityCertAndKeyBaseName, err.Error()))
|
||||
}
|
||||
@@ -128,9 +119,10 @@ func (r *CertificateResource) mutate(ctx context.Context, tenantControlPlane *ka
|
||||
Certificate: secretCA.Data[kubeadmconstants.CACertName],
|
||||
PrivateKey: secretCA.Data[kubeadmconstants.CAKeyName],
|
||||
}
|
||||
cert, privKey, err := getCertificateAndKeyPair(ca.Certificate, ca.PrivateKey)
|
||||
|
||||
cert, privKey, err := crypto.GenerateCertificatePrivateKeyPair(crypto.NewCertificateTemplate(CertCommonName), ca.Certificate, ca.PrivateKey)
|
||||
if err != nil {
|
||||
logger.Error(err, "cannot generate certificate and key pair")
|
||||
logger.Error(err, "unable to generate certificate and private key")
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -159,35 +151,3 @@ func (r *CertificateResource) mutate(ctx context.Context, tenantControlPlane *ka
|
||||
return ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
}
|
||||
}
|
||||
|
||||
func getCertificateAndKeyPair(caCert []byte, caPrivKey []byte) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
template := getCertTemplate()
|
||||
|
||||
return crypto.GetCertificateAndKeyPair(template, caCert, caPrivKey)
|
||||
}
|
||||
|
||||
func isCertificateAndKeyPairValid(cert []byte, privKey []byte) (bool, error) {
|
||||
return crypto.IsValidCertificateKeyPairBytes(cert, privKey)
|
||||
}
|
||||
|
||||
func getCertTemplate() *x509.Certificate {
|
||||
serialNumber := big.NewInt(rand.Int63())
|
||||
|
||||
return &x509.Certificate{
|
||||
PublicKeyAlgorithm: x509.RSA,
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
CommonName: CertCommonName,
|
||||
Organization: []string{certOrganization},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(certExpirationDelayYears, 0, 0),
|
||||
SubjectKeyId: []byte{1, 2, 3, 4, 6},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||
x509.ExtKeyUsageClientAuth,
|
||||
x509.ExtKeyUsageServerAuth,
|
||||
x509.ExtKeyUsageCodeSigning,
|
||||
},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ const (
|
||||
|
||||
agentTokenName = "konnectivity-agent-token"
|
||||
apiServerAPIVersion = "apiserver.k8s.io/v1beta1"
|
||||
certExpirationDelayYears = 10
|
||||
certOrganization = "system:master"
|
||||
defaultClusterName = "kubernetes"
|
||||
defaultUDSName = "/run/konnectivity/konnectivity-server.socket"
|
||||
egressSelectorConfigurationKind = "EgressSelectorConfiguration"
|
||||
|
||||
@@ -43,7 +43,7 @@ func (r *KubernetesDeploymentResource) ShouldStatusBeUpdated(context.Context, *k
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil && tenantControlPlane.Status.Addons.Konnectivity.Enabled == true
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) CleanUp(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/crypto"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -84,10 +85,7 @@ func (r *SACertificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if checksum := tenantControlPlane.Status.Certificates.SA.Checksum; len(checksum) > 0 && checksum == r.resource.GetAnnotations()["checksum"] {
|
||||
isValid, err := kubeadm.IsPublicKeyPrivateKeyPairValid(
|
||||
r.resource.Data[kubeadmconstants.ServiceAccountPublicKeyName],
|
||||
r.resource.Data[kubeadmconstants.ServiceAccountPrivateKeyName],
|
||||
)
|
||||
isValid, err := crypto.CheckPublicAndPrivateKeyValidity(r.resource.Data[kubeadmconstants.ServiceAccountPublicKeyName], r.resource.Data[kubeadmconstants.ServiceAccountPrivateKeyName])
|
||||
if err != nil {
|
||||
logger.Info(fmt.Sprintf("%s public_key-private_key pair is not valid: %s", kubeadmconstants.ServiceAccountKeyBaseName, err.Error()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user