Skip to content

Commit

Permalink
Merge pull request #144 from vinzent/persistent-jks-creationdate-prop…
Browse files Browse the repository at this point in the history
…erty

Use ConfigMaps CreationDate for JKS CreateDate property
  • Loading branch information
raffaelespazzoli committed Apr 26, 2023
2 parents eec8294 + cdcb7a3 commit 3b0bfc9
Show file tree
Hide file tree
Showing 6 changed files with 3,622 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.16 as builder
FROM golang:1.20 as builder

WORKDIR /workspace
# Copy the Go Modules manifests
Expand Down
28 changes: 16 additions & 12 deletions controllers/configmaptokeystore/configmap_to_keystore_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import (
"errors"
"reflect"
"strconv"
"time"

"github.com/go-logr/logr"
keystore "github.com/pavel-v-chernykh/keystore-go"
"github.com/pavlo-v-chernykh/keystore-go/v4"
"github.com/redhat-cop/cert-utils-operator/controllers/util"
outils "github.com/redhat-cop/operator-utils/pkg/util"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -127,26 +126,31 @@ func (r *ConfigMapToKeystoreReconciler) Reconcile(context context.Context, req c
}

func (r *ConfigMapToKeystoreReconciler) getTrustStoreFromConfigMap(configMap *corev1.ConfigMap, sourceKey string) ([]byte, error) {
keyStore := keystore.KeyStore{}
keyStore := keystore.New(
keystore.WithOrderedAliases(),
)
ca, ok := configMap.Data[sourceKey]
if !ok {
return nil, errors.New("ca bundle key not found: " + sourceKey)
}
i := 0

for p, rest := pem.Decode([]byte(ca)); p != nil; p, rest = pem.Decode(rest) {
keyStore["alias"+strconv.Itoa(i)] = &keystore.TrustedCertificateEntry{
Entry: keystore.Entry{
CreationDate: time.Now(),
},
Certificate: keystore.Certificate{
Type: "X.509",
Content: p.Bytes,
keyStore.SetTrustedCertificateEntry(
"alias"+strconv.Itoa(i),
keystore.TrustedCertificateEntry{
CreationTime: configMap.GetCreationTimestamp().Time,
Certificate: keystore.Certificate{
Type: "X.509",
Content: p.Bytes,
},
},
}
)
i++
}

buffer := bytes.Buffer{}
err := keystore.Encode(&buffer, keyStore, []byte(getPassword(configMap)))
err := keyStore.Store(&buffer, []byte(getPassword(configMap)))
if err != nil {
r.Log.Error(err, "unable to encode keystore", "keystore", keyStore)
return nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"bytes"
"context"
"encoding/pem"
"io/ioutil"
"testing"

"github.com/pavel-v-chernykh/keystore-go"
"github.com/pavlo-v-chernykh/keystore-go/v4"
"github.com/redhat-cop/operator-utils/pkg/util"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -112,16 +113,21 @@ pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
cl.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, outConfigMap)

// validate truststore.jks was set with a valid keystore
keyStore, err := keystore.Decode(bytes.NewBuffer(outConfigMap.BinaryData["truststore.jks"]), []byte("changeme"))
ks := keystore.New()
err = ks.Load(
bytes.NewBuffer(outConfigMap.BinaryData["truststore.jks"]),
[]byte("changeme"),
)
assert.Nil(t, err, "error reading generated truststore")

// make sure expected cert was set
assert.Equal(t, 1, len(keyStore))
assert.Equal(t, 1, len(ks.Aliases()))

// make sure cert data match
tce, err := ks.GetTrustedCertificateEntry("alias0")
decodePem := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: keyStore["alias0"].(*keystore.TrustedCertificateEntry).Certificate.Content,
Bytes: tce.Certificate.Content,
})
if err != nil {
t.Error(err)
Expand Down Expand Up @@ -223,20 +229,92 @@ pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
cl.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, outConfigMap)

// validate truststore.jks was set with a valid keystore
keyStore, err := keystore.Decode(bytes.NewBuffer(outConfigMap.BinaryData["truststore.jks"]), []byte("changeme"))
ks := keystore.New()
err = ks.Load(bytes.NewBuffer(outConfigMap.BinaryData["truststore.jks"]), []byte("changeme"))
assert.Nil(t, err, "error reading generated truststore")

// make sure expected cert was set
assert.Equal(t, 1, len(keyStore))
assert.Equal(t, 1, len(ks.Aliases()))

// make sure cert data match
tce, err := ks.GetTrustedCertificateEntry("alias0")
decodePem := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: keyStore["alias0"].(*keystore.TrustedCertificateEntry).Certificate.Content,
Bytes: tce.Certificate.Content,
})
if err != nil {
t.Error(err)
}

assert.Equal(t, []byte(configMap.Data["my-custom-key"]), decodePem)
}

func TestConfigmapControllerCreateFromConfigMapBinaryEquals(t *testing.T) {
var (
name = "cert-utils-operator"
namespace = "cert-utils-operator"
)

caBundle, err := ioutil.ReadFile("testdata/ca-bundle.crt")
if err != nil {
t.Fatal(err)
}

// A configmap injection annotation
configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
"cert-utils-operator.redhat-cop.io/generate-java-truststore": "true",
},
},
Data: map[string]string{
"ca-bundle.crt": string(caBundle),
},
}

objs := []runtime.Object{configMap}

cl := fake.NewFakeClient(objs...)

fakeRecorder := record.NewFakeRecorder(3)

reconcileBase := util.NewReconcilerBase(cl, scheme.Scheme, nil, fakeRecorder, nil)
r := &ConfigMapToKeystoreReconciler{
ReconcilerBase: reconcileBase,
Log: ctrl.Log.WithName("controllers").WithName("configmap_to_keystore_controller"),
}

// First reconcile
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: name,
Namespace: namespace,
},
}
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}

outConfigMap := &corev1.ConfigMap{}
cl.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, outConfigMap)

// Reconcile a second time
req = reconcile.Request{
NamespacedName: types.NamespacedName{
Name: name,
Namespace: namespace,
},
}
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}

outConfigMap2 := &corev1.ConfigMap{}
cl.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, outConfigMap2)

assert.Equal(t, outConfigMap.BinaryData["truststore.jks"], outConfigMap2.BinaryData["truststore.jks"])
}
Loading

0 comments on commit 3b0bfc9

Please sign in to comment.