diff --git a/internal/controller/common/action/transitions/create_tree_job.go b/internal/controller/common/action/transitions/create_tree_job.go new file mode 100644 index 000000000..466bab675 --- /dev/null +++ b/internal/controller/common/action/transitions/create_tree_job.go @@ -0,0 +1,210 @@ +package transitions + +import ( + "context" + "fmt" + + "github.com/securesign/operator/internal/apis" + "github.com/securesign/operator/internal/controller/common/action" + cutils "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes/job" + "github.com/securesign/operator/internal/controller/constants" + "github.com/securesign/operator/internal/controller/ctlog/utils" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +type TreeJobSupplier[T apis.ConditionsAwareObject] func( + instance T, +) ( + trillianAddress string, + instanceName string, + treeJobConfigMapName string, + treeJobName string, + treeDisplayName string, + trillianDeploymentName string, + namespace string, + trillianPort *int32, + caPath string, + rbac string, + labels map[string]string, + annotations map[string]string, + treeID *int64, + err error, +) + +func NewCreateTreeJobAction[T apis.ConditionsAwareObject](supplier TreeJobSupplier[T]) action.Action[T] { + return &createTreeJobAction[T]{supplier: supplier} +} + +type createTreeJobAction[T apis.ConditionsAwareObject] struct { + action.BaseAction + supplier TreeJobSupplier[T] +} + +func (i createTreeJobAction[T]) Name() string { + return "create tree job" +} + +func (i createTreeJobAction[T]) CanHandle(ctx context.Context, instance T) bool { + _, _, treeJobConfigMapName, _, _, _, _, _, _, _, _, _, treeID, err := i.supplier(instance) + if err != nil { + return false + } + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.GetNamespace(), treeJobConfigMapName) + c := meta.FindStatusCondition(instance.GetConditions(), constants.Ready) + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && treeID == nil +} + +func (i createTreeJobAction[T]) Handle(ctx context.Context, instance T) *action.Result { + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName, namespace, trillianPort, caPath, rbac, labels, annotations, _, err := i.supplier(instance) + + if err != nil { + return i.Failed(fmt.Errorf("failed to get job details: %w", err)) + } + + var trillUrl string + + switch { + case trillianPort == nil: + err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) + case trillianAddress == "": + trillUrl = fmt.Sprintf("%s.%s.svc:%d", trillianDeploymentName, namespace, *trillianPort) + default: + trillUrl = fmt.Sprintf("%s:%d", trillianAddress, *trillianPort) + } + if err != nil { + return i.Failed(err) + } + + i.Logger.V(1).Info("trillian logserver", "address", trillUrl) + + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "Creating tree Job", + }) + + // Needed for configMap clean-up + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: treeJobConfigMapName, + Namespace: instance.GetNamespace(), + Labels: labels, + }, + Data: map[string]string{}, + } + + if err := controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + + updated, err := i.Ensure(ctx, configMap) + if err != nil { + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + return i.Failed(err) + } + if updated { + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "ConfigMap created", + }) + i.Recorder.Event(instance, corev1.EventTypeNormal, "TreeConfigCreated", "ConfigMap for TreeID created") + } + + parallelism := int32(1) + completions := int32(1) + activeDeadlineSeconds := int64(600) + backoffLimit := int32(5) + + trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(annotations) + + cmd := "" + switch { + case trustedCAAnnotation != nil: + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, treeDisplayName, caPath) + case kubernetes.IsOpenShift(): + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, treeDisplayName) + default: + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, treeDisplayName) + } + command := []string{ + "/bin/sh", + "-c", + fmt.Sprintf(` + TREE_ID=$(%s) + if [ $? -eq 0 ]; then + echo "TREE_ID=$TREE_ID" + TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) + API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} + curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/merge-patch+json" \ + -d '{ + "data": { + "tree_id": "'$TREE_ID'" + } + }' + if [ $? -ne 0 ]; then + echo "Failed to update ConfigMap" >&2 + exit 1 + fi + else + echo "Failed to create tree" >&2 + exit 1 + fi + `, cmd, treeJobConfigMapName), + } + env := []corev1.EnvVar{} + + job := job.CreateJob(namespace, treeJobName, labels, constants.CreateTreeImage, rbac, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + if err := ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for job: %w", err)) + } + + if err := cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation); err != nil { + return i.Failed(err) + } + + if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { + job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: instanceName + "-trillian-server-tls", + }, + }, + }) + job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/var/run/secrets/tas", + ReadOnly: true, + }) + } + + if _, err := i.Ensure(ctx, job); err != nil { + return i.Failed(fmt.Errorf("failed to ensure the job: %w", err)) + } + + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionTrue, + Reason: constants.Creating, + Message: "Tree Job created", + }) + + return i.Continue() +} diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go deleted file mode 100644 index df977d95a..000000000 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ /dev/null @@ -1,199 +0,0 @@ -package actions - -import ( - "context" - "fmt" - - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common/action" - cutils "github.com/securesign/operator/internal/controller/common/utils" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes/job" - "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" - corev1 "k8s.io/api/core/v1" - apiErrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.CTlog] { - return &createTreeJobAction{} -} - -type createTreeJobAction struct { - action.BaseAction -} - -func (i createTreeJobAction) Name() string { - return "create tree job" -} - -func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, CtlogTreeJobConfigMapName) - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil -} - -func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { - var ( - err error - updated bool - ) - - var trillUrl string - - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) - } - if err != nil { - return i.Failed(err) - } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - - if c := meta.FindStatusCondition(instance.Status.Conditions, CtlogTreeJobName); c == nil { - instance.SetCondition(metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Creating, - Message: "Creating tree Job", - }) - } - - labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) - - // Needed for configMap clean-up - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: CtlogTreeJobConfigMapName, - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - } - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") - } - - parallelism := int32(1) - completions := int32(1) - activeDeadlineSeconds := int64(600) - backoffLimit := int32(5) - - trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) - caPath, err := utils.CAPath(ctx, i.Client, instance) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - i.StatusUpdate(ctx, instance) - if apiErrors.IsNotFound(err) { - return i.Requeue() - } - return i.Failed(err) - } - cmd := "" - switch { - case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, CtlogTreeName, caPath) - case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, CtlogTreeName) - default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, CtlogTreeName) - } - command := []string{ - "/bin/sh", - "-c", - fmt.Sprintf(` - TREE_ID=$(%s) - if [ $? -eq 0 ]; then - echo "TREE_ID=$TREE_ID" - TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} - curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/merge-patch+json" \ - -d '{ - "data": { - "tree_id": "'$TREE_ID'" - } - }' - if [ $? -ne 0 ]; then - echo "Failed to update ConfigMap" >&2 - exit 1 - fi - else - echo "Failed to create tree" >&2 - exit 1 - fi - `, cmd, CtlogTreeJobConfigMapName), - } - env := []corev1.EnvVar{} - - job := job.CreateJob(instance.Namespace, CtlogTreeJobName, labels, constants.CreateTreeImage, RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) - if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) - } - - err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) - if err != nil { - return i.Failed(err) - } - - if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { - job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-server-tls", - }, - }, - }) - job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - } - - _, err = i.Ensure(ctx, job) - if err != nil { - return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) - } - - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionTrue, - Reason: constants.Creating, - Message: "tree Job Created", - }) - - return i.Continue() -} diff --git a/internal/controller/ctlog/ctlog_controller.go b/internal/controller/ctlog/ctlog_controller.go index a32a6c6ce..ca1c6e3dc 100644 --- a/internal/controller/ctlog/ctlog_controller.go +++ b/internal/controller/ctlog/ctlog_controller.go @@ -22,9 +22,11 @@ import ( olpredicate "github.com/operator-framework/operator-lib/predicate" "github.com/securesign/operator/internal/controller/annotations" "github.com/securesign/operator/internal/controller/common/action/transitions" + "github.com/securesign/operator/internal/controller/constants" "k8s.io/apimachinery/pkg/runtime/schema" "github.com/securesign/operator/internal/controller/ctlog/actions" + "github.com/securesign/operator/internal/controller/ctlog/utils" fulcioActions "github.com/securesign/operator/internal/controller/fulcio/actions" v12 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + actions2 "github.com/securesign/operator/internal/controller/trillian/actions" ) // CTlogReconciler reconciles a CTlog object @@ -96,7 +99,28 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions.NewRBACAction(), actions.NewHandleFulcioCertAction(), actions.NewHandleKeysAction(), - actions.NewCreateTreeJobAction(), + transitions.NewCreateTreeJobAction[*rhtasv1alpha1.CTlog](func(instance *rhtasv1alpha1.CTlog) ( + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName string, + namespace string, trillianPort *int32, caPath string, rbac string, labels map[string]string, annotations map[string]string, + treeID *int64, err error, + ) { + caPath, err = utils.CAPath(ctx, r.Client, instance) + labels = constants.LabelsFor(actions.ComponentName, actions.ComponentName, instance.Name) + return instance.Spec.Trillian.Address, + instance.Name, + actions.CtlogTreeJobConfigMapName, + actions.CtlogTreeJobName, + actions.CtlogTreeName, + actions2.LogserverDeploymentName, + instance.Namespace, + instance.Spec.Trillian.Port, + caPath, + actions.RBACName, + labels, + instance.Annotations, + instance.Status.TreeID, + err + }), actions.NewResolveTreeAction(), actions.NewServerConfigAction(), diff --git a/internal/controller/ctlog/utils/ctlog_deployment.go b/internal/controller/ctlog/utils/ctlog_deployment.go index 082caa306..a8075b12d 100644 --- a/internal/controller/ctlog/utils/ctlog_deployment.go +++ b/internal/controller/ctlog/utils/ctlog_deployment.go @@ -8,7 +8,6 @@ import ( "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -125,7 +124,8 @@ func CreateDeployment(ctx context.Context, client client.Client, instance *v1alp }, } - if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + useTLS := UseTLS(instance) + if useTLS { caPath, err := CAPath(ctx, client, instance) if err != nil { return nil, errors.New("failed to get CA path: " + err.Error()) diff --git a/internal/controller/ctlog/utils/tls.go b/internal/controller/ctlog/utils/tls.go index b4c456955..bfeb1ae1f 100644 --- a/internal/controller/ctlog/utils/tls.go +++ b/internal/controller/ctlog/utils/tls.go @@ -9,6 +9,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +func UseTLS(instance *rhtasv1alpha1.CTlog) bool { + + if instance == nil { + return false + } + // TLS enabled on Trillian logserver + if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + return true + } + + return false +} + func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.CTlog) (string, error) { if instance.Spec.TrustedCA != nil { cfgTrust, err := kubernetes.GetConfigMap(ctx, cli, instance.Namespace, instance.Spec.TrustedCA.Name) diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go deleted file mode 100644 index 87211481b..000000000 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ /dev/null @@ -1,200 +0,0 @@ -package server - -import ( - "context" - "fmt" - - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common/action" - cutils "github.com/securesign/operator/internal/controller/common/utils" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes/job" - "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/rekor/actions" - "github.com/securesign/operator/internal/controller/rekor/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" - corev1 "k8s.io/api/core/v1" - apiErrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.Rekor] { - return &createTreeJobAction{} -} - -type createTreeJobAction struct { - action.BaseAction -} - -func (i createTreeJobAction) Name() string { - return "create tree job" -} - -func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, actions.RekorTreeJobConfigMapName) - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil -} - -func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { - var ( - err error - updated bool - ) - - var trillUrl string - - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) - } - if err != nil { - return i.Failed(err) - } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - - if c := meta.FindStatusCondition(instance.Status.Conditions, actions.RekorTreeJobName); c == nil { - instance.SetCondition(metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Creating, - Message: "Creating tree Job", - }) - } - - labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) - - // Needed for configMap clean-up - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: actions.RekorTreeJobConfigMapName, - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - } - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") - } - - parallelism := int32(1) - completions := int32(1) - activeDeadlineSeconds := int64(600) - backoffLimit := int32(5) - - trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) - caPath, err := utils.CAPath(ctx, i.Client, instance) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - i.StatusUpdate(ctx, instance) - if apiErrors.IsNotFound(err) { - return i.Requeue() - } - return i.Failed(err) - } - cmd := "" - switch { - case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, actions.RekorTreeName, caPath) - case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, actions.RekorTreeName) - default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, actions.RekorTreeName) - } - command := []string{ - "/bin/sh", - "-c", - fmt.Sprintf(` - TREE_ID=$(%s) - if [ $? -eq 0 ]; then - echo "TREE_ID=$TREE_ID" - TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} - curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/merge-patch+json" \ - -d '{ - "data": { - "tree_id": "'$TREE_ID'" - } - }' - if [ $? -ne 0 ]; then - echo "Failed to update ConfigMap" >&2 - exit 1 - fi - else - echo "Failed to create tree" >&2 - exit 1 - fi - `, cmd, actions.RekorTreeJobConfigMapName), - } - env := []corev1.EnvVar{} - - job := job.CreateJob(instance.Namespace, actions.RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) - if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) - } - - err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) - if err != nil { - return i.Failed(err) - } - - if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { - job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-server-tls", - }, - }, - }) - job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - } - - _, err = i.Ensure(ctx, job) - if err != nil { - return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) - } - - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionTrue, - Reason: constants.Creating, - Message: "tree Job Created", - }) - - return i.Continue() -} diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index db0cd03d8..380afadb1 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -24,12 +24,14 @@ import ( olpredicate "github.com/operator-framework/operator-lib/predicate" "github.com/securesign/operator/internal/controller/annotations" "github.com/securesign/operator/internal/controller/common/action/transitions" + "github.com/securesign/operator/internal/controller/constants" actions2 "github.com/securesign/operator/internal/controller/rekor/actions" backfillredis "github.com/securesign/operator/internal/controller/rekor/actions/backfillRedis" "github.com/securesign/operator/internal/controller/rekor/actions/redis" "github.com/securesign/operator/internal/controller/rekor/actions/server" "github.com/securesign/operator/internal/controller/rekor/actions/ui" + "github.com/securesign/operator/internal/controller/rekor/utils" v13 "k8s.io/api/core/v1" v1 "k8s.io/api/networking/v1" "k8s.io/client-go/tools/record" @@ -43,6 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + actions3 "github.com/securesign/operator/internal/controller/trillian/actions" batchv1 "k8s.io/api/batch/v1" ) @@ -109,7 +112,28 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions2.NewRBACAction(), server.NewShardingConfigAction(), - server.NewCreateTreeJobAction(), + transitions.NewCreateTreeJobAction[*rhtasv1alpha1.Rekor](func(instance *rhtasv1alpha1.Rekor) ( + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName string, + namespace string, trillianPort *int32, caPath string, rbac string, labels map[string]string, annotations map[string]string, + treeID *int64, err error, + ) { + caPath, err = utils.CAPath(ctx, r.Client, instance) + labels = constants.LabelsFor(actions2.ServerComponentName, actions2.ServerDeploymentName, instance.Name) + return instance.Spec.Trillian.Address, + instance.Name, + actions2.RekorTreeJobConfigMapName, + actions2.RekorTreeJobName, + actions2.RekorTreeName, + actions3.LogserverDeploymentName, + instance.Namespace, + instance.Spec.Trillian.Port, + caPath, + actions2.RBACName, + labels, + instance.Annotations, + instance.Status.TreeID, + err + }), server.NewResolveTreeAction(), server.NewCreatePvcAction(), server.NewDeployAction(),