mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 04:26:45 +00:00
Avoiding TLS/CA race condition on Capsule installation (#7)
* Avoiding race condition on Capsule installation The TLS Secret controller needs to wait for the CA one in order to retrieve the updated one, otherwise it could use a non-stored CA. * Linting Minor linting fixes * Makefile for Docker Image Providing `make docker-image` to speed-up generation of Docker image
This commit is contained in:
@@ -5,3 +5,7 @@ k8s:
|
||||
.PHONY: crds
|
||||
crds:
|
||||
operator-sdk generate crds
|
||||
|
||||
.PHONY: docker-image
|
||||
docker-image:
|
||||
operator-sdk build quay.io/clastix/capsule:latest
|
||||
|
||||
@@ -71,7 +71,6 @@ func main() {
|
||||
// controller-runtime)
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
|
||||
var v bool
|
||||
pflag.BoolVarP(&v, "version", "v", false, "Print the Capsule version and exit")
|
||||
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ func (c CapsuleCa) ExpiresIn(now time.Time) (time.Duration, error) {
|
||||
if !c.isAlreadyValid(now) {
|
||||
return time.Nanosecond, CaNotYetValidError{}
|
||||
}
|
||||
return time.Duration(c.ca.NotAfter.Unix() - now.Unix()) * time.Second, nil
|
||||
return time.Duration(c.ca.NotAfter.Unix()-now.Unix()) * time.Second, nil
|
||||
}
|
||||
|
||||
func (c CapsuleCa) CaCertificatePem() (b *bytes.Buffer, err error) {
|
||||
@@ -108,7 +108,7 @@ func NewCertificateAuthorityFromBytes(certBytes, keyBytes []byte) (s *CapsuleCa,
|
||||
}
|
||||
|
||||
s = &CapsuleCa{
|
||||
ca: cert,
|
||||
ca: cert,
|
||||
privateKey: key,
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ func TestNewCertificateAuthorityFromBytes(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
|
||||
var crt *bytes.Buffer
|
||||
crt, err =ca.CaCertificatePem()
|
||||
crt, err = ca.CaCertificatePem()
|
||||
assert.Nil(t, err)
|
||||
|
||||
var key *bytes.Buffer
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
package cert
|
||||
|
||||
type CaNotYetValidError struct {}
|
||||
type CaNotYetValidError struct{}
|
||||
|
||||
func (CaNotYetValidError) Error() string {
|
||||
return "The current CA is not yet valid"
|
||||
}
|
||||
|
||||
type CaExpiredError struct {}
|
||||
type CaExpiredError struct{}
|
||||
|
||||
func (CaExpiredError) Error() string {
|
||||
return "The current CA is expired"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package secret
|
||||
|
||||
type MissingCaError struct {
|
||||
}
|
||||
|
||||
func (MissingCaError) Error() string {
|
||||
return "CA has not been created yet, please generate a new"
|
||||
}
|
||||
@@ -63,17 +63,7 @@ func (r *ReconcileSecret) GetCertificateAuthority() (ca cert.Ca, err error) {
|
||||
}
|
||||
|
||||
if instance.Data == nil {
|
||||
ca, err = cert.GenerateCertificateAuthority()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
instance.Data = map[string][]byte{}
|
||||
|
||||
crt, _ := ca.CaCertificatePem()
|
||||
instance.Data[Cert] = crt.Bytes()
|
||||
key, _ := ca.CaPrivateKeyPem()
|
||||
instance.Data[PrivateKey] = key.Bytes()
|
||||
return nil, MissingCaError{}
|
||||
}
|
||||
|
||||
ca, err = cert.NewCertificateAuthorityFromBytes(instance.Data[Cert], instance.Data[PrivateKey])
|
||||
@@ -86,4 +76,4 @@ func (r *ReconcileSecret) GetCertificateAuthority() (ca cert.Ca, err error) {
|
||||
|
||||
func filterByName(objName, desired string) bool {
|
||||
return objName == desired
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package secret
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
@@ -89,7 +90,12 @@ func caReconcile(r *ReconcileSecret, request reconcile.Request) (reconcile.Resul
|
||||
var ca cert.Ca
|
||||
var rq time.Duration
|
||||
ca, err = r.GetCertificateAuthority()
|
||||
if err != nil {
|
||||
if err != nil && errors.Is(err, MissingCaError{}) {
|
||||
ca, err = cert.GenerateCertificateAuthority()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
} else if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
@@ -150,7 +156,7 @@ func caReconcile(r *ReconcileSecret, request reconcile.Request) (reconcile.Resul
|
||||
r.logger.Info("Capsule CA has been updated, we need to trigger TLS update too")
|
||||
tls := &corev1.Secret{}
|
||||
err = r.client.Get(context.TODO(), types.NamespacedName{
|
||||
Namespace: "capsuel-system",
|
||||
Namespace: "capsule-system",
|
||||
Name: TlsSecretName,
|
||||
}, tls)
|
||||
if err != nil {
|
||||
|
||||
@@ -130,7 +130,7 @@ func tlsReconcile(r *ReconcileSecret, request reconcile.Request) (reconcile.Resu
|
||||
}
|
||||
|
||||
var res controllerutil.OperationResult
|
||||
t := &corev1.Secret{ObjectMeta: instance.ObjectMeta,}
|
||||
t := &corev1.Secret{ObjectMeta: instance.ObjectMeta}
|
||||
res, err = controllerutil.CreateOrUpdate(context.TODO(), r.client, t, func() error {
|
||||
t.Data = instance.Data
|
||||
return nil
|
||||
|
||||
@@ -62,7 +62,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
||||
}
|
||||
|
||||
// Watch for changes to primary resource Tenant
|
||||
err = c.Watch(&source.Kind{Type: &capsulev1alpha1.Tenant{}}, &handler.EnqueueRequestForObject{}, )
|
||||
err = c.Watch(&source.Kind{Type: &capsulev1alpha1.Tenant{}}, &handler.EnqueueRequestForObject{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ func (r *ownerRef) Handle(ctx context.Context, req admission.Request) admission.
|
||||
return admission.Errored(http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
|
||||
g := utils.UserGroupList(req.UserInfo.Groups)
|
||||
if !g.IsInCapsuleGroup() {
|
||||
// user requested NS creation is not a Capsule user, so skipping the validation checks
|
||||
|
||||
Reference in New Issue
Block a user