Skip to content

Commit

Permalink
Load custom CA cert
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Nathan Abellard <[email protected]>
  • Loading branch information
jabellard committed Nov 19, 2024
1 parent 6795dba commit 7596959
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 73 deletions.
20 changes: 20 additions & 0 deletions operator/pkg/apis/operator/v1alpha1/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ type KarmadaSpec struct {
// By default, the operator will only attempt to download the tarball if it's not yet present in the local cache.
// +optional
CRDTarball *CRDTarball `json:"crdTarball,omitempty"`

// CustomCertificate specifies the configuration to customize the certificates
// for Karmada components or control the certificate generation process, such as
// the algorithm, validity period, etc.
// Currently, it only supports customizing the CA certificate for limited components.
// +optional
CustomCertificate *CustomCertificate `json:"customCertificate,omitempty"`
}

// CustomCertificate holds the configuration for generating the certificate.
type CustomCertificate struct {
// APIServerCACert references a Kubernetes secret containing the CA certificate
// for component karmada-apiserver.
// The secret must contain the following data keys:
// - tls.crt: The TLS certificate.
// - tls.key: The TLS private key.
// If specified, this CA will be used to issue client certificates for
// all components that access the APIServer as clients.
// +optional
APIServerCACert *LocalSecretReference `json:"apiServerCACert,omitempty"`
}

// ImageRegistry represents an image registry as well as the
Expand Down
32 changes: 16 additions & 16 deletions operator/pkg/certs/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,25 +212,25 @@ func KarmadaCertEtcdClient() *CertConfig {
// KarmadaCert is karmada certificate, it includes certificate basic message.
// we can directly get the byte array of certificate key and cert from the object.
type KarmadaCert struct {
pairName string
caName string
cert []byte
key []byte
PairName string
CAName string
Cert []byte
Key []byte
}

// CertData returns certificate cert data.
func (cert *KarmadaCert) CertData() []byte {
return cert.cert
return cert.Cert
}

// KeyData returns certificate key data.
func (cert *KarmadaCert) KeyData() []byte {
return cert.key
return cert.Key
}

// CertName returns cert file name. its default suffix is ".crt".
func (cert *KarmadaCert) CertName() string {
pair := cert.pairName
pair := cert.PairName
if len(pair) == 0 {
pair = "cert"
}
Expand All @@ -239,7 +239,7 @@ func (cert *KarmadaCert) CertName() string {

// KeyName returns cert key file name. its default suffix is ".key".
func (cert *KarmadaCert) KeyName() string {
pair := cert.pairName
pair := cert.PairName
if len(pair) == 0 {
pair = "cert"
}
Expand Down Expand Up @@ -282,10 +282,10 @@ func NewCertificateAuthority(cc *CertConfig) (*KarmadaCert, error) {
}

return &KarmadaCert{
pairName: cc.Name,
caName: cc.CAName,
cert: EncodeCertPEM(cert),
key: encoded,
PairName: cc.Name,
CAName: cc.CAName,
Cert: EncodeCertPEM(cert),
Key: encoded,
}, nil
}

Expand Down Expand Up @@ -329,10 +329,10 @@ func CreateCertAndKeyFilesWithCA(cc *CertConfig, caCertData, caKeyData []byte) (
}

return &KarmadaCert{
pairName: cc.Name,
caName: cc.CAName,
cert: EncodeCertPEM(cert),
key: encoded,
PairName: cc.Name,
CAName: cc.CAName,
Cert: EncodeCertPEM(cert),
Key: encoded,
}, nil
}

Expand Down
28 changes: 14 additions & 14 deletions operator/pkg/certs/certs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,23 +428,23 @@ func TestNewCertificateAuthority(t *testing.T) {
t.Fatal("NewCertificateAuthority() returned nil cert")
}

if cert.pairName != cc.Name {
t.Errorf("expected pairName to be %s, got %s", cc.Name, cert.pairName)
if cert.PairName != cc.Name {
t.Errorf("expected pairName to be %s, got %s", cc.Name, cert.PairName)
}

if cert.caName != cc.CAName {
t.Errorf("expected caName to be %s, got %s", cc.CAName, cert.caName)
if cert.CAName != cc.CAName {
t.Errorf("expected caName to be %s, got %s", cc.CAName, cert.CAName)
}

if cert.cert == nil {
if cert.Cert == nil {
t.Error("expected cert to be non-nil")
}

if cert.key == nil {
if cert.Key == nil {
t.Error("expected key to be non-nil")
}

block, _ := pem.Decode(cert.cert)
block, _ := pem.Decode(cert.Cert)
if block == nil || block.Type != CertificateBlockType {
t.Errorf("expected PEM block type to be %s, got %v", CertificateBlockType, block)
}
Expand Down Expand Up @@ -524,19 +524,19 @@ func TestCreateCertAndKeyFilesWithCA(t *testing.T) {
t.Fatal("CreateCertAndKeyFilesWithCA() returned nil cert")
}

if cert.cert == nil || cert.key == nil {
if cert.Cert == nil || cert.Key == nil {
t.Error("Expected cert and key to be non-nil")
}

if cert.pairName != certConfig.Name {
t.Errorf("expected pairName to be %s, got %s", certConfig.Name, cert.pairName)
if cert.PairName != certConfig.Name {
t.Errorf("expected pairName to be %s, got %s", certConfig.Name, cert.PairName)
}

if cert.caName != certConfig.CAName {
t.Errorf("expected caName to be %s, got %s", certConfig.CAName, cert.caName)
if cert.CAName != certConfig.CAName {
t.Errorf("expected caName to be %s, got %s", certConfig.CAName, cert.CAName)
}

block, _ := pem.Decode(cert.cert)
block, _ := pem.Decode(cert.Cert)
if block == nil || block.Type != CertificateBlockType {
t.Errorf("expected PEM block type to be %s, got %v", CertificateBlockType, block)
}
Expand Down Expand Up @@ -566,7 +566,7 @@ func TestNewSignedCert_Success(t *testing.T) {
}
caCert := caCerts[0]

caKey, err := ParsePrivateKeyPEM(caKarmadaCert.key)
caKey, err := ParsePrivateKeyPEM(caKarmadaCert.Key)
if err != nil {
t.Error(err)
}
Expand Down
14 changes: 7 additions & 7 deletions operator/pkg/certs/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ func NewCertStore() CertStore {
}
}

// AddCert adds a cert to cert store, the cache key is cert pairName by default.
// AddCert adds a cert to cert store, the cache key is cert PairName by default.
func (store *KarmadaCertStore) AddCert(cert *KarmadaCert) {
store.certs[cert.pairName] = cert
store.certs[cert.PairName] = cert
}

// GetCert get cert from store by cert pairName.
// GetCert get cert from store by cert PairName.
func (store *KarmadaCertStore) GetCert(name string) *KarmadaCert {
for _, c := range store.certs {
if c.pairName == name {
if c.PairName == name {
return c
}
}
Expand Down Expand Up @@ -105,15 +105,15 @@ func (store *KarmadaCertStore) LoadCertFromSecret(secret *corev1.Secret) error {
kc := store.GetCert(pairName)
if kc == nil {
kc = &KarmadaCert{
pairName: pairName,
PairName: pairName,
}
}

if strings.Contains(name, certExtension) {
kc.cert = data
kc.Cert = data
}
if strings.Contains(name, keyExtension) {
kc.key = data
kc.Key = data
}

store.AddCert(kc)
Expand Down
32 changes: 16 additions & 16 deletions operator/pkg/certs/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (
corev1 "k8s.io/api/core/v1"
)

// Helper function to create a new KarmadaCert with given pairName.
// Helper function to create a new KarmadaCert with given PairName.
func newKarmadaCert(pairName string, certData, keyData []byte) *KarmadaCert {
return &KarmadaCert{
pairName: pairName,
cert: certData,
key: keyData,
PairName: pairName,
Cert: certData,
Key: keyData,
}
}

Expand All @@ -51,11 +51,11 @@ func TestAddAndGetCert(t *testing.T) {
if retrievedCert == nil {
t.Fatalf("expected to retrieve cert but got nil")
}
if string(retrievedCert.cert) != "certData" {
t.Errorf("expected certData but got %s", string(retrievedCert.cert))
if string(retrievedCert.Cert) != "certData" {
t.Errorf("expected certData but got %s", string(retrievedCert.Cert))
}
if string(retrievedCert.key) != "keyData" {
t.Errorf("expected keyData but got %s", string(retrievedCert.key))
if string(retrievedCert.Key) != "keyData" {
t.Errorf("expected keyData but got %s", string(retrievedCert.Key))
}
}

Expand Down Expand Up @@ -98,13 +98,13 @@ func TestLoadCertFromSecret(t *testing.T) {
}

cert1 := store.GetCert("cert1")
if cert1 == nil || string(cert1.cert) != "cert1CertData" || string(cert1.key) != "cert1KeyData" {
t.Errorf("cert1 content is incorrect expected cert %s key %s, got cert %s key %s", "cert1CertData", "cert1KeyData", string(cert1.cert), string(cert1.key))
if cert1 == nil || string(cert1.Cert) != "cert1CertData" || string(cert1.Key) != "cert1KeyData" {
t.Errorf("cert1 content is incorrect expected cert %s key %s, got cert %s key %s", "cert1CertData", "cert1KeyData", string(cert1.Cert), string(cert1.Key))
}

cert2 := store.GetCert("cert2")
if cert2 == nil || string(cert2.cert) != "cert2CertData" || string(cert2.key) != "cert2KeyData" {
t.Errorf("cert2 content is incorrect expected cert %s key %s, got cert %s key %s", "cert2CertData", "cert2KeyData", string(cert2.cert), string(cert2.key))
if cert2 == nil || string(cert2.Cert) != "cert2CertData" || string(cert2.Key) != "cert2KeyData" {
t.Errorf("cert2 content is incorrect expected cert %s key %s, got cert %s key %s", "cert2CertData", "cert2KeyData", string(cert2.Cert), string(cert2.Key))
}
}

Expand Down Expand Up @@ -144,10 +144,10 @@ func TestLoadCertFromSecret_InvalidFormat(t *testing.T) {
}

karmadaCert := store.GetCert(pairName)
if len(karmadaCert.key) != 0 {
t.Errorf("expected the cert data content to be empty but got %v", karmadaCert.cert)
if len(karmadaCert.Key) != 0 {
t.Errorf("expected the cert data content to be empty but got %v", karmadaCert.Cert)
}
if len(karmadaCert.key) != 0 {
t.Errorf("expected the key data content to be empty but got %v", karmadaCert.key)
if len(karmadaCert.Key) != 0 {
t.Errorf("expected the key data content to be empty but got %v", karmadaCert.Key)
}
}
46 changes: 26 additions & 20 deletions operator/pkg/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ var (

// InitOptions defines all the init workflow options.
type InitOptions struct {
Name string
Namespace string
Kubeconfig *rest.Config
KarmadaVersion string
CRDTarball operatorv1alpha1.CRDTarball
KarmadaDataDir string
Karmada *operatorv1alpha1.Karmada
Name string
Namespace string
Kubeconfig *rest.Config
KarmadaVersion string
CRDTarball operatorv1alpha1.CRDTarball
CustomCertificateConfig operatorv1alpha1.CustomCertificate
KarmadaDataDir string
Karmada *operatorv1alpha1.Karmada
}

// Validate is used to validate the initOptions before creating initJob.
Expand All @@ -75,19 +76,20 @@ var _ tasks.InitData = &initData{}
type initData struct {
sync.Once
certs.CertStore
name string
namespace string
karmadaVersion *utilversion.Version
controlplaneConfig *rest.Config
controlplaneAddress string
remoteClient clientset.Interface
karmadaClient clientset.Interface
dnsDomain string
CRDTarball operatorv1alpha1.CRDTarball
karmadaDataDir string
privateRegistry string
featureGates map[string]bool
components *operatorv1alpha1.KarmadaComponents
name string
namespace string
karmadaVersion *utilversion.Version
controlplaneConfig *rest.Config
controlplaneAddress string
remoteClient clientset.Interface
karmadaClient clientset.Interface
dnsDomain string
CRDTarball operatorv1alpha1.CRDTarball
CustomCertificateConfig operatorv1alpha1.CustomCertificate
karmadaDataDir string
privateRegistry string
featureGates map[string]bool
components *operatorv1alpha1.KarmadaComponents
}

// NewInitJob initializes a job with list of init sub-task. and build
Expand Down Expand Up @@ -226,6 +228,10 @@ func (data *initData) CrdTarball() operatorv1alpha1.CRDTarball {
return data.CRDTarball
}

func (data *initData) CustomCertificate() operatorv1alpha1.CustomCertificate {
return data.CustomCertificateConfig
}

func (data *initData) KarmadaVersion() string {
return data.karmadaVersion.String()
}
Expand Down
Loading

0 comments on commit 7596959

Please sign in to comment.