From 1cd6f5da659034e570b59a73fe1a390681ca30a0 Mon Sep 17 00:00:00 2001 From: Jan Bouska Date: Mon, 8 Jan 2024 16:25:53 +0100 Subject: [PATCH] Remove scaffolding jobs --- .github/workflows/main.yml | 62 ++-- README.md | 21 +- api/v1alpha1/trillian_types.go | 5 +- .../crd/bases/rhtas.redhat.com_trillians.yaml | 4 + config/rbac/role.yaml | 12 + config/samples/rhtas_v1alpha1_securesign.yaml | 5 +- ...rhtas_v1alpha1_securesign_cert_create.yaml | 2 +- controllers/common/base_action.go | 6 + controllers/common/utils/kubernetes/secret.go | 15 +- controllers/constants/images.go | 5 + controllers/ctlog/create.go | 43 ++- controllers/ctlog/ctlog_controller.go | 4 + controllers/ctlog/pending.go | 73 +++++ controllers/ctlog/utils/ctlog_config.go | 300 ++++++++++++++++++ controllers/ctlog/utils/ctlog_create_job.go | 76 ----- controllers/ctlog/utils/ctlog_deployment.go | 7 +- controllers/ctlog/wait.go | 2 +- controllers/fulcio/create.go | 7 +- controllers/fulcio/utils/fulcio_deployment.go | 2 +- controllers/fulcio/utils/fulcio_secrets.go | 36 +-- controllers/fulcio/wait.go | 2 +- controllers/rekor/action.go | 15 +- controllers/rekor/create.go | 22 +- controllers/rekor/init.go | 75 +++++ controllers/rekor/rekor_controller.go | 3 + controllers/rekor/utils/rekor_deployment.go | 19 +- controllers/rekor/utils/rekor_secrets.go | 4 +- controllers/rekor/wait.go | 44 --- controllers/securesign_controller.go | 6 + controllers/trillian/create.go | 13 +- controllers/trillian/init.go | 11 +- .../trillian/utils/trillian-deployment.go | 7 +- .../{wait.go => wait_for_creation.go} | 0 controllers/tuf/create.go | 10 +- controllers/tuf/pending.go | 2 - controllers/tuf/utils/tuf_copy_job.go | 46 --- controllers/tuf/wait.go | 3 +- go.mod | 14 +- go.sum | 70 +++- 39 files changed, 699 insertions(+), 354 deletions(-) create mode 100644 controllers/ctlog/pending.go create mode 100644 controllers/ctlog/utils/ctlog_config.go delete mode 100644 controllers/ctlog/utils/ctlog_create_job.go create mode 100644 controllers/rekor/init.go delete mode 100644 controllers/rekor/wait.go rename controllers/trillian/{wait.go => wait_for_creation.go} (100%) delete mode 100644 controllers/tuf/utils/tuf_copy_job.go diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bf2c996cc..51514b09e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,79 +83,65 @@ jobs: kubectl create ns create-cert kubectl apply -f config/samples/rhtas_v1alpha1_securesign_cert_create.yaml -n create-cert - - name: Until shell script to wait for fulcio deployment to be created + #Deployment is done in iterations TUF should be the last one + - name: Until shell script to wait for tuf deployment to be created run: | - until [ ! -z "$(kubectl get deployment fulcio-server -n test 2>/dev/null)" ] + until [ ! -z "$(kubectl get deployment tuf -n test 2>/dev/null)" ] do - echo "Waiting for fulcio deployment to be created. Pods in test namespace:" + echo "Waiting for tuf deployment to be created. Pods in test namespace:" kubectl get pods -n test + kubectl get rekor,fulcio,tuf,ctlog,trillian -n test sleep 3 done shell: bash - name: Check the deployment of fulcio - run: kubectl wait --for=condition=available deployment/fulcio-server --timeout=80s -n test + run: kubectl wait --for=condition=available deployment/fulcio-server --timeout=200s -n test - name: Check the deployment of rekor - run: kubectl wait --for=condition=available deployment/rekor-server --timeout=80s -n test + run: kubectl wait --for=condition=available deployment/rekor-server --timeout=200s -n test - name: Check for the deployment of redis - run: kubectl wait --for=condition=available deployment/rekor-redis --timeout=80s -n test + run: kubectl wait --for=condition=available deployment/rekor-redis --timeout=200s -n test - name: Check for the deployment of trillian logsigner - run: kubectl wait --for=condition=available deployment/trillian-logsigner --timeout=80s -n test + run: kubectl wait --for=condition=available deployment/trillian-logsigner --timeout=200s -n test - name: Check for the deployment of trillian logserver - run: kubectl wait --for=condition=available deployment/trillian-logserver --timeout=80s -n test - - - name: wait for the createtree job to finish - run: kubectl wait --for=condition=complete job/create-tree --timeout=120s -n test - - - name: wait for the create-tree-rekor job to finish - run: kubectl wait --for=condition=complete job/create-tree-rekor --timeout=120s -n test - - - name: wait for create-config job to finish - run: kubectl wait --for=condition=complete job/create-config --timeout=120s -n test + run: kubectl wait --for=condition=available deployment/trillian-logserver --timeout=200s -n test - name: Check for the deployment of tuf - run: kubectl wait --for=condition=available deployment/tuf --timeout=120s -n test + run: kubectl wait --for=condition=available deployment/tuf --timeout=200s -n test - name: Check for the deployment of ctlog - run: kubectl wait --for=condition=available deployment/ctlog --timeout=120s -n test + run: kubectl wait --for=condition=available deployment/ctlog --timeout=200s -n test - - name: Until shell script to wait for fulcio deployment to be created + #Deployment is done in iterations TUF should be the last one + - name: Until shell script to wait for tuf deployment to be created run: | - until [ ! -z "$(kubectl get deployment fulcio-server -n create-cert 2>/dev/null)" ] + until [ ! -z "$(kubectl get deployment tuf -n create-cert 2>/dev/null)" ] do - echo "Waiting for fulcio deployment to be created. Pods in create-cert namespace:" + echo "Waiting for tuf deployment to be created. Pods in create-cert namespace:" kubectl get pods -n create-cert + kubectl get rekor,fulcio,tuf,ctlog,trillian -n create-cert sleep 3 done shell: bash - name: Check the deployment of fulcio - run: kubectl wait --for=condition=available deployment/fulcio-server --timeout=80s -n create-cert + run: kubectl wait --for=condition=available deployment/fulcio-server --timeout=200s -n create-cert - name: Check the deployment of rekor - run: kubectl wait --for=condition=available deployment/rekor-server --timeout=80s -n create-cert + run: kubectl wait --for=condition=available deployment/rekor-server --timeout=200s -n create-cert - name: Check for the deployment of redis - run: kubectl wait --for=condition=available deployment/rekor-redis --timeout=80s -n create-cert + run: kubectl wait --for=condition=available deployment/rekor-redis --timeout=200s -n create-cert - name: Check for the deployment of trillian logsigner - run: kubectl wait --for=condition=available deployment/trillian-logsigner --timeout=80s -n create-cert + run: kubectl wait --for=condition=available deployment/trillian-logsigner --timeout=200s -n create-cert - name: Check for the deployment of trillian logserver - run: kubectl wait --for=condition=available deployment/trillian-logserver --timeout=80s -n create-cert - - - name: wait for the createtree job to finish - run: kubectl wait --for=condition=complete job/create-tree --timeout=120s -n create-cert - - - name: wait for the create-tree-rekor job to finish - run: kubectl wait --for=condition=complete job/create-tree-rekor --timeout=120s -n create-cert - - - name: wait for create-config job to finish - run: kubectl wait --for=condition=complete job/create-config --timeout=120s -n create-cert + run: kubectl wait --for=condition=available deployment/trillian-logserver --timeout=200s -n create-cert - name: Check for the deployment of tuf run: kubectl wait --for=condition=available deployment/tuf --timeout=120s -n create-cert @@ -169,5 +155,7 @@ jobs: if: always() - name: dump all deployments - run: kubectl get deployments -A + run: | + kubectl get deployments -A + kubectl get rekor,fulcio,tuf,ctlog,trillian -A if: always() diff --git a/README.md b/README.md index 850737dc6..b09519e6b 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,15 @@ UnDeploy the controller from the cluster: make undeploy ``` +### Local Development +The controller connects to services running inside the cluster to configure them. The Trillian server is configured using RPC protocol. +The RPC protocol rely on the HTTP/2 that is hard to route outside the cluster (see #issueLink). +Until the issue is fixed, the locally running operator will fail with +``` +Admin server unavailable: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup trillian-logserver.test.svc: no such host" +CreateTree... +``` + ## Contributing // TODO(user): Add detailed information on how you would like others to contribute to this project @@ -51,9 +60,6 @@ It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controlle which provide a reconcile function responsible for synchronizing resources until the desired state is reached on the cluster. ### Test It Out -The controller connects to services running inside the cluster. If you want to run the operator locally, -you would need to expose them OR use `kubectl port-forward` function. - 1. Install the CRDs into the cluster: ```sh @@ -67,15 +73,6 @@ make run **NOTE:** You can also run this in one step by running: `make install run` -### FAQ -#### Q: I am getting following error from the locally running operator -``` -Admin server unavailable: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup trillian-logserver.test.svc: no such host" -CreateTree... -``` -**A:** The controller try to connect to the local service (trillian in this case). -You need to export it OR use port-forward and set the correct URL to the CR configuration. - ### Modifying the API definitions If you are editing the API definitions, generate the manifests such as CRs or CRDs using: diff --git a/api/v1alpha1/trillian_types.go b/api/v1alpha1/trillian_types.go index 95611e927..c98158dae 100644 --- a/api/v1alpha1/trillian_types.go +++ b/api/v1alpha1/trillian_types.go @@ -33,8 +33,9 @@ type TrillianSpec struct { // TrillianStatus defines the observed state of Trillian type TrillianStatus struct { - Url string `json:"url"` - Phase Phase `json:"phase"` + Url string `json:"url"` + TreeID int64 `json:"treeID"` + Phase Phase `json:"phase"` // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file } diff --git a/config/crd/bases/rhtas.redhat.com_trillians.yaml b/config/crd/bases/rhtas.redhat.com_trillians.yaml index 0b0361ced..242b25e91 100644 --- a/config/crd/bases/rhtas.redhat.com_trillians.yaml +++ b/config/crd/bases/rhtas.redhat.com_trillians.yaml @@ -56,10 +56,14 @@ spec: properties: phase: type: string + treeID: + format: int64 + type: integer url: type: string required: - phase + - treeID - url type: object type: object diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 364e0af9f..4fa4a1a50 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -329,3 +329,15 @@ rules: - get - patch - update +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index 76f36830f..3c6a16551 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -20,13 +20,12 @@ spec: oidcIssuers: "http://keycloak-internal.keycloak-system.svc/auth/realms/sigstore": ClientID: "sigstore" - IssuerURL: "https://keycloak-keycloak-system.apps.rosa.hhdxf-cd9dh-3dt.1b9r.p3.openshiftapps.com/auth/realms/sigstore" + IssuerURL: "http://keycloak-internal.keycloak-system.svc/auth/realms/sigstore" Type: "email" fulcioCert: create: false trillian: - external: true tuf: external: true - ctlog: + ctlog: \ No newline at end of file diff --git a/config/samples/rhtas_v1alpha1_securesign_cert_create.yaml b/config/samples/rhtas_v1alpha1_securesign_cert_create.yaml index 092c0d00d..0e32221ba 100644 --- a/config/samples/rhtas_v1alpha1_securesign_cert_create.yaml +++ b/config/samples/rhtas_v1alpha1_securesign_cert_create.yaml @@ -31,4 +31,4 @@ spec: trillian: tuf: external: true - ctlog: + ctlog: \ No newline at end of file diff --git a/controllers/common/base_action.go b/controllers/common/base_action.go index 19ad3fc28..76057b31b 100644 --- a/controllers/common/base_action.go +++ b/controllers/common/base_action.go @@ -1,6 +1,7 @@ package common import ( + "github.com/go-logr/logr" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -8,6 +9,7 @@ import ( type BaseAction struct { Client client.Client Recorder record.EventRecorder + Logger logr.Logger } func (action *BaseAction) InjectClient(client client.Client) { @@ -17,3 +19,7 @@ func (action *BaseAction) InjectClient(client client.Client) { func (action *BaseAction) InjectRecorder(recorder record.EventRecorder) { action.Recorder = recorder } + +func (action *BaseAction) InjectLogger(logger logr.Logger) { + action.Logger = logger +} diff --git a/controllers/common/utils/kubernetes/secret.go b/controllers/common/utils/kubernetes/secret.go index 783e30b3d..4a57ae7aa 100644 --- a/controllers/common/utils/kubernetes/secret.go +++ b/controllers/common/utils/kubernetes/secret.go @@ -5,22 +5,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func CreateSecret(namespace, name, component, app string, secrets map[string]string) *corev1.Secret { - secretData := make(map[string][]byte) - for k, v := range secrets { - secretData[k] = []byte(v) - } - +func CreateSecret(name string, namespace string, data map[string][]byte, labels map[string]string) *corev1.Secret { return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, - Labels: map[string]string{ - "app.kubernetes.io/component": component, - "app.kubernetes.io/name": app, - "app.kubernetes.io/instance": "trusted-artifact-signer", - }, + Labels: labels, }, - Data: secretData, + Data: data, } } diff --git a/controllers/constants/images.go b/controllers/constants/images.go index aa2ddda81..0f122cddf 100644 --- a/controllers/constants/images.go +++ b/controllers/constants/images.go @@ -5,10 +5,15 @@ const ( TrillianServerImage = "registry.redhat.io/rhtas-tech-preview/trillian-logserver-rhel9@sha256:43bfc6b7b8ed902592f19b830103d9030b59862f959c97c376cededba2ac3a03" TrillianDbImage = "registry.redhat.io/rhtas-tech-preview/trillian-database-rhel9@sha256:fe4758ff57a9a6943a4655b21af63fb579384dc51838af85d0089c04290b4957" + // TODO: remove and check the DB pod status + TrillianNetcatImage = "registry.redhat.io/rhtas-tech-preview/trillian-netcat-rhel9@sha256:b9fa895af8967cceb7a05ed7c9f2b80df047682ed11c87249ca2edba86492f6e" + FulcioServerImage = "registry.redhat.io/rhtas-tech-preview/fulcio-rhel9@sha256:0421d44d2da8dd87f05118293787d95686e72c65c0f56dfb9461a61e259b8edc" RekorRedisImage = "docker.io/redis@sha256:6c42cce2871e8dc5fb3e843ed5c4e7939d312faf5e53ff0ff4ca955a7e0b2b39" RekorServerImage = "registry.redhat.io/rhtas-tech-preview/rekor-server-rhel9@sha256:8ee7d5dd2fa1c955d64ab83d716d482a3feda8e029b861241b5b5dfc6f1b258e" TufImage = "registry.redhat.io/rhtas-tech-preview/tuf-server-rhel9@sha256:413e361de99f09e617084438b2fc3c9c477f4a8e2cd65bd5f48271e66d57a9d9" + + CTLogImage = "registry.redhat.io/rhtas-tech-preview/ct-server-rhel9@sha256:6124a531097c91bf8c872393a6f313c035ca03eca316becd3c350930d978929f" ) diff --git a/controllers/ctlog/create.go b/controllers/ctlog/create.go index 05b6b9611..9891aeaba 100644 --- a/controllers/ctlog/create.go +++ b/controllers/ctlog/create.go @@ -31,7 +31,7 @@ func (i createAction) Name() string { } func (i createAction) CanHandle(ctlog *rhtasv1alpha1.CTlog) bool { - return ctlog.Status.Phase == rhtasv1alpha1.PhaseNone + return ctlog.Status.Phase == rhtasv1alpha1.PhaseCreating } func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) (*rhtasv1alpha1.CTlog, error) { @@ -41,28 +41,37 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) labels["app.kubernetes.io/component"] = ComponentName labels["app.kubernetes.io/name"] = deploymentName - server := ctlogUtils.CreateDeployment(instance.Namespace, deploymentName, labels) - controllerutil.SetControllerReference(instance, server, i.Client.Scheme()) - if err = i.Client.Create(ctx, server); err != nil { + trillians, err := findTrillians(ctx, i.Client, *instance) + if err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError - return instance, fmt.Errorf("could not create job: %w", err) + return instance, fmt.Errorf("could not find trillian: %w", err) } - cm := utils.InitConfigmap(instance.Namespace, "ctlog-config", labels, map[string]string{ - "__placeholder": "###################################################################\n" + - "# Just a placeholder so that reapplying this won't overwrite treeID\n" + - "# if it already exists. This caused grief, do not remove.\n" + - "###################################################################", - }) - controllerutil.SetControllerReference(instance, cm, i.Client.Scheme()) - if err = i.Client.Create(ctx, cm); err != nil { + fulcios, err := findFulcios(ctx, i.Client, *instance) + if err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError - return instance, fmt.Errorf("could not create job: %w", err) + return instance, fmt.Errorf("could not find fulcio: %w", err) } - // TODO: move code from job to operator - config := ctlogUtils.CreateCTJob(instance.Namespace, "create-config") + var config, pubKey *corev1.Secret + if config, pubKey, err = ctlogUtils.CreateCtlogConfig(ctx, i.Client, instance.Namespace, trillians.Items[0].Status.Url, trillians.Items[0].Status.TreeID, fulcios.Items[0].Status.Url, labels); err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, fmt.Errorf("could not create CTLog configuration: %w", err) + } + controllerutil.SetControllerReference(instance, config, i.Client.Scheme()) + controllerutil.SetControllerReference(instance, pubKey, i.Client.Scheme()) if err = i.Client.Create(ctx, config); err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, fmt.Errorf("could not create CTLog configuration secret: %w", err) + } + if err = i.Client.Create(ctx, pubKey); err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, fmt.Errorf("could not create CTLog public key secret: %w", err) + } + + server := ctlogUtils.CreateDeployment(instance.Namespace, deploymentName, config.Name, labels) + controllerutil.SetControllerReference(instance, server, i.Client.Scheme()) + if err = i.Client.Create(ctx, server); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError return instance, fmt.Errorf("could not create job: %w", err) } @@ -80,7 +89,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) return instance, fmt.Errorf("could not create service: %w", err) } - instance.Status.Phase = rhtasv1alpha1.PhaseCreating + instance.Status.Phase = rhtasv1alpha1.PhaseInitialize return instance, nil } diff --git a/controllers/ctlog/ctlog_controller.go b/controllers/ctlog/ctlog_controller.go index 066a0e758..534e0a535 100644 --- a/controllers/ctlog/ctlog_controller.go +++ b/controllers/ctlog/ctlog_controller.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -66,6 +67,7 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl } target := instance.DeepCopy() actions := []Action{ + NewPendingAction(), NewCreateAction(), NewWaitAction(), } @@ -98,5 +100,7 @@ func (r *CTlogReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&rhtasv1alpha1.CTlog{}). Owns(&v1.Deployment{}). + // TODO: we should not rely on ownership of securesign resource + Watches(&rhtasv1alpha1.Trillian{}, handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &rhtasv1alpha1.Securesign{})). Complete(r) } diff --git a/controllers/ctlog/pending.go b/controllers/ctlog/pending.go new file mode 100644 index 000000000..c250dd7b3 --- /dev/null +++ b/controllers/ctlog/pending.go @@ -0,0 +1,73 @@ +package ctlog + +import ( + "context" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/controllers/common" + "github.com/securesign/operator/controllers/common/utils/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func NewPendingAction() Action { + return &pendingAction{} +} + +type pendingAction struct { + common.BaseAction +} + +func (i pendingAction) Name() string { + return "pending" +} + +func (i pendingAction) CanHandle(tuf *rhtasv1alpha1.CTlog) bool { + return tuf.Status.Phase == rhtasv1alpha1.PhaseNone || tuf.Status.Phase == rhtasv1alpha1.PhasePending +} + +func (i pendingAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) (*rhtasv1alpha1.CTlog, error) { + if instance.Status.Phase == rhtasv1alpha1.PhaseNone { + instance.Status.Phase = rhtasv1alpha1.PhasePending + } + + trillians, err := findTrillians(ctx, i.Client, *instance) + if err != nil { + return instance, err + } + if len(trillians.Items) == 0 || trillians.Items[0].Status.Phase != rhtasv1alpha1.PhaseReady { + return instance, nil + } + + fulcios, err := findFulcios(ctx, i.Client, *instance) + if err != nil { + return instance, err + } + if len(fulcios.Items) == 0 || fulcios.Items[0].Status.Phase != rhtasv1alpha1.PhaseReady { + return instance, nil + } + + instance.Status.Phase = rhtasv1alpha1.PhaseCreating + return instance, err +} + +func findTrillians(ctx context.Context, cli client.Client, instance rhtasv1alpha1.CTlog) (*rhtasv1alpha1.TrillianList, error) { + searchLabels := kubernetes.FilterCommonLabels(instance.Labels) + + list := &rhtasv1alpha1.TrillianList{} + err := cli.List(ctx, list, client.InNamespace(instance.Namespace), client.MatchingLabels(searchLabels)) + if err != nil { + return nil, err + } + return list, nil +} + +func findFulcios(ctx context.Context, cli client.Client, instance rhtasv1alpha1.CTlog) (*rhtasv1alpha1.FulcioList, error) { + searchLabels := kubernetes.FilterCommonLabels(instance.Labels) + + list := &rhtasv1alpha1.FulcioList{} + err := cli.List(ctx, list, client.InNamespace(instance.Namespace), client.MatchingLabels(searchLabels)) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/controllers/ctlog/utils/ctlog_config.go b/controllers/ctlog/utils/ctlog_config.go new file mode 100644 index 000000000..b5bcfe5ea --- /dev/null +++ b/controllers/ctlog/utils/ctlog_config.go @@ -0,0 +1,300 @@ +package utils + +import ( + "bytes" + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "net/url" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/google/certificate-transparency-go/trillian/ctfe/configpb" + "github.com/google/trillian/crypto/keyspb" + "github.com/securesign/operator/controllers/common/utils/kubernetes" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "knative.dev/pkg/logging" + + fulcioclient "github.com/sigstore/fulcio/pkg/api" +) + +const ( + bitSize = 4096 + + curveType = "p256" + // ConfigKey is the key in the map holding the marshalled CTLog config. + ConfigKey = "config" + // PrivateKey is the key in the map holding the encrypted PEM private key + // for CTLog. + PrivateKey = "private" + // PublicKey is the key in the map holding the PEM public key for CTLog. + PublicKey = "public" + + // This is hardcoded since this is where we mount the certs in the + // container. + rootsPemFileDir = "/ctfe-keys/" + // This file contains the private key for the CTLog + privateKeyFile = "/ctfe-keys/private" +) + +var supportedCurves = map[string]elliptic.Curve{ + "p256": elliptic.P256(), + "p384": elliptic.P384(), + "p521": elliptic.P521(), +} + +// Config abstracts the proto munging to/from bytes suitable for working +// with secrets / configmaps. Note that we keep fulcioCerts here though +// technically they are not part of the config, however because we create a +// secret/CM that we then mount, they need to be synced. +type Config struct { + PrivKey crypto.PrivateKey + PrivKeyPassword string + PubKey crypto.PublicKey + LogID int64 + LogPrefix string + + // Address of the gRPC Trillian Admin Server (host:port) + TrillianServerAddr string + + // FulcioCerts contains one or more Root certificates for Fulcio. + // It may contain more than one if Fulcio key is rotated for example, so + // there will be a period of time when we allow both. It might also contain + // multiple Root Certificates, if we choose to support admitting certificates from fulcio instances run by others + FulcioCerts [][]byte +} + +func extractFulcioRoot(fulcioRoot []byte) ([]byte, error) { + // Fetch only root certificate from the chain + certs, err := cryptoutils.UnmarshalCertificatesFromPEM(fulcioRoot) + if err != nil { + return nil, fmt.Errorf("unable to unmarshal certficate chain: %w", err) + } + return cryptoutils.MarshalCertificateToPEM(certs[len(certs)-1]) +} + +// AddFulcioRoot will add the specified fulcioRoot to the list of trusted +// Fulcios. If it already exists, it's a nop. +// The fulcioRoot should come from the call to fetch a PublicFulcio root +// and is the ChainPEM from the fulcioclient RootResponse. +func (c *Config) AddFulcioRoot(ctx context.Context, fulcioRoot []byte) error { + root, err := extractFulcioRoot(fulcioRoot) + if err != nil { + return fmt.Errorf("extracting fulcioRoot: %w", err) + } + for _, fc := range c.FulcioCerts { + if bytes.Equal(fc, root) { + //TODO: improve logging + logging.FromContext(ctx).Info("Found existing fulcio root, not adding") + return nil + } + } + //TODO: improve logging + logging.FromContext(ctx).Info("Adding new FulcioRoot") + c.FulcioCerts = append(c.FulcioCerts, root) + return nil +} + +// MarshalConfig marshals the CTLogConfig into a format that can be handed +// to the CTLog in form of a secret or configmap. Returns a map with the +// following keys: +// config - CTLog configuration +// private - CTLog private key, PEM encoded and encrypted with the password +// public - CTLog public key, PEM encoded +// fulcio-%d - For each fulcioCerts, contains one entry so we can support +// multiple. +func (c *Config) MarshalConfig(ctx context.Context) (map[string][]byte, error) { + // Since we can have multiple Fulcio secrets, we need to construct a set + // of files containing them for the RootsPemFile. Names don't matter + // so we just call them fulcio-% + // What matters however is to ensure that the filenames match the keys + // in the configmap / secret that we construct so they get properly mounted. + rootPems := make([]string, 0, len(c.FulcioCerts)) + for i := range c.FulcioCerts { + rootPems = append(rootPems, fmt.Sprintf("%sfulcio-%d", rootsPemFileDir, i)) + } + + var pubkey crypto.Signer + var ok bool + // Note this goofy cast to crypto.Signer since the any interface has no + // methods so cast here so that we get the Public method which all core + // keys support. + if pubkey, ok = c.PrivKey.(crypto.Signer); !ok { + logging.FromContext(ctx).Fatalf("Failed to convert private key to crypto.Signer") + } + keyDER, err := x509.MarshalPKIXPublicKey(pubkey.Public()) + if err != nil { + logging.FromContext(ctx).Panicf("Failed to marshal the public key: %v", err) + } + proto := configpb.LogConfig{ + LogId: c.LogID, + Prefix: c.LogPrefix, + RootsPemFile: rootPems, + PrivateKey: mustMarshalAny(&keyspb.PEMKeyFile{ + Path: privateKeyFile, + Password: c.PrivKeyPassword}), + PublicKey: &keyspb.PublicKey{Der: keyDER}, + LogBackendName: "trillian", + ExtKeyUsages: []string{"CodeSigning"}, + } + + multiConfig := configpb.LogMultiConfig{ + LogConfigs: &configpb.LogConfigSet{ + Config: []*configpb.LogConfig{&proto}, + }, + Backends: &configpb.LogBackendSet{ + Backend: []*configpb.LogBackend{{ + Name: "trillian", + BackendSpec: c.TrillianServerAddr, + }}, + }, + } + marshalledConfig, err := prototext.Marshal(&multiConfig) + if err != nil { + return nil, err + } + secrets, err := c.marshalSecrets() + if err != nil { + return nil, err + } + secrets[ConfigKey] = marshalledConfig + return secrets, nil +} + +// MarshalSecrets returns a map suitable for creating a secret out of +// containing the following keys: +// private - CTLog private key, PEM encoded and encrypted with the password +// public - CTLog public key, PEM encoded +// fulcio-%d - For each fulcioCerts, contains one entry so we can support +// multiple. +func (c *Config) marshalSecrets() (map[string][]byte, error) { + // Encode private key to PKCS #8 ASN.1 PEM. + marshalledPrivKey, err := x509.MarshalPKCS8PrivateKey(c.PrivKey) + if err != nil { + return nil, fmt.Errorf("failed to marshal private key: %w", err) + } + block := &pem.Block{ + Type: "PRIVATE KEY", + Bytes: marshalledPrivKey, + } + // Encrypt the pem + encryptedBlock, err := x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, []byte(c.PrivKeyPassword), x509.PEMCipherAES256) // nolint + if err != nil { + return nil, fmt.Errorf("failed to encrypt private key: %w", err) + } + + privPEM := pem.EncodeToMemory(encryptedBlock) + if privPEM == nil { + return nil, fmt.Errorf("failed to encode encrypted private key") + } + // Encode public key to PKIX ASN.1 PEM. + var pubkey crypto.Signer + var ok bool + + // Note this goofy cast to crypto.Signer since the any interface has no + // methods so cast here so that we get the Public method which all core + // keys support. + if pubkey, ok = c.PrivKey.(crypto.Signer); !ok { + return nil, fmt.Errorf("failed to convert private key to crypto.Signer") + } + + marshalledPubKey, err := x509.MarshalPKIXPublicKey(pubkey.Public()) + if err != nil { + return nil, fmt.Errorf("failed to marshal public key: %w", err) + } + pubPEM := pem.EncodeToMemory( + &pem.Block{ + Type: "PUBLIC KEY", + Bytes: marshalledPubKey, + }, + ) + data := map[string][]byte{ + PrivateKey: privPEM, + PublicKey: pubPEM, + } + for i, cert := range c.FulcioCerts { + fulcioKey := fmt.Sprintf("fulcio-%d", i) + data[fulcioKey] = cert + } + return data, nil +} + +func mustMarshalAny(pb proto.Message) *anypb.Any { + ret, err := anypb.New(pb) + if err != nil { + panic(fmt.Sprintf("MarshalAny failed: %v", err)) + } + return ret +} + +func createConfigWithKeys(ctx context.Context, keytype string) (*Config, error) { + var privKey crypto.PrivateKey + var err error + if keytype == "rsa" { + privKey, err = rsa.GenerateKey(rand.Reader, bitSize) + if err != nil { + return nil, fmt.Errorf("failed to generate Private RSA Key: %w", err) + } + } else { + privKey, err = ecdsa.GenerateKey(supportedCurves[curveType], rand.Reader) + if err != nil { + return nil, fmt.Errorf("failed to generate Private ECDSA Key: %w", err) + } + } + + var ok bool + var signer crypto.Signer + if signer, ok = privKey.(crypto.Signer); !ok { + return nil, fmt.Errorf("failed to convert to Signer") + } + return &Config{ + PrivKey: privKey, + PubKey: signer.Public(), + }, nil +} + +func CreateCtlogConfig(ctx context.Context, cli client.Client, ns string, trillianUrl string, treeID int64, fulcioUrl string, labels map[string]string) (*corev1.Secret, *corev1.Secret, error) { + u, err := url.Parse(fulcioUrl) + if err != nil { + return nil, nil, fmt.Errorf("invalid fulcioURL %s : %v", fulcioUrl, err) + } + client := fulcioclient.NewClient(u) + root, err := client.RootCert() + if err != nil { + return nil, nil, fmt.Errorf("Failed to fetch fulcio Root cert: %w", err) + } + + ctlogConfig, err := createConfigWithKeys(ctx, "ecdsa") + if err != nil { + return nil, nil, err + } + ctlogConfig.PrivKeyPassword = "test" + ctlogConfig.LogID = treeID + ctlogConfig.LogPrefix = "trusted-artifact-signer" + ctlogConfig.TrillianServerAddr = trillianUrl + + if err = ctlogConfig.AddFulcioRoot(ctx, root.ChainPEM); err != nil { + return nil, nil, fmt.Errorf("Failed to add fulcio root: %v", err) + } + configMap, err := ctlogConfig.MarshalConfig(ctx) + if err != nil { + return nil, nil, fmt.Errorf("Failed to marshal ctlog config: %v", err) + } + + config := kubernetes.CreateSecret("ctlog-secret", ns, configMap, labels) + + pubData := map[string][]byte{PublicKey: configMap[PublicKey]} + pubKeySecret := kubernetes.CreateSecret("ctlog-public-key", ns, pubData, labels) + + return config, pubKeySecret, nil +} diff --git a/controllers/ctlog/utils/ctlog_create_job.go b/controllers/ctlog/utils/ctlog_create_job.go deleted file mode 100644 index a47efd3c1..000000000 --- a/controllers/ctlog/utils/ctlog_create_job.go +++ /dev/null @@ -1,76 +0,0 @@ -package utils - -import ( - batch "k8s.io/api/batch/v1" - core "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func CreateCTJob(namespace string, jobName string) *batch.Job { - - imageName := "registry.redhat.io/rhtas-tech-preview/createctconfig-rhel9@sha256:10155f8c2b73b12599124895b2db0c9e08b2c3953df7361574fd08467c42fd04" - - // Define a new Namespace object - return &batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: map[string]string{ - "app.kubernetes.io/component": "ctlog", - "app.kubernetes.io/instance": "trusted-artifact-signer", - }, - }, - Spec: batch.JobSpec{ - Template: core.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/component": "mysql", - "app.kubernetes.io/instance": "trusted-artifact-signer", - }, - }, - Spec: core.PodSpec{ - ServiceAccountName: "sigstore-sa", - AutomountServiceAccountToken: &[]bool{true}[0], - RestartPolicy: core.RestartPolicyNever, - InitContainers: []core.Container{ - { - Name: "wait-for-createtree-configmap", - Image: "registry.redhat.io/openshift4/ose-cli:latest", - Command: []string{ - "sh", - "-c", - "until curl --fail --header \"Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)\" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --max-time 10 https://kubernetes.default.svc/api/v1/namespaces/" + namespace + "/configmaps/trillian-tree | grep '\"treeID\"':; do echo waiting for Configmap ctlog-config; sleep 5; done;", - }, - Env: []core.EnvVar{ - { - Name: "NAMESPACE", - Value: namespace, - }, - }, - }, - }, - Containers: []core.Container{ - { - Name: "trusted-artifact-signer-ctlog-createctconfig", - Image: imageName, - Args: []string{ - "--configmap=trillian-tree", - "--secret=ctlog-secret", - "--pubkeysecret=ctlog-public-key", - "--fulcio-url=http://fulcio-server." + namespace + ".svc", - "--trillian-server=trillian-logserver." + namespace + ":8091", - "--log-prefix=sigstorescaffolding", - }, - Env: []core.EnvVar{ - { - Name: "NAMESPACE", - Value: namespace, - }, - }, - }, - }, - }, - }, - }, - } -} diff --git a/controllers/ctlog/utils/ctlog_deployment.go b/controllers/ctlog/utils/ctlog_deployment.go index 1871de8e1..971e986a6 100644 --- a/controllers/ctlog/utils/ctlog_deployment.go +++ b/controllers/ctlog/utils/ctlog_deployment.go @@ -1,13 +1,14 @@ package utils import ( + "github.com/securesign/operator/controllers/constants" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) -func CreateDeployment(namespace string, deploymentName string, labels map[string]string) *appsv1.Deployment { +func CreateDeployment(namespace string, deploymentName string, configName string, labels map[string]string) *appsv1.Deployment { replicas := int32(1) // Define a new Deployment object return &appsv1.Deployment{ @@ -30,7 +31,7 @@ func CreateDeployment(namespace string, deploymentName string, labels map[string Containers: []corev1.Container{ { Name: "ctlog", - Image: "registry.redhat.io/rhtas-tech-preview/ct-server-rhel9@sha256:6124a531097c91bf8c872393a6f313c035ca03eca316becd3c350930d978929f", + Image: constants.CTLogImage, Args: []string{ "--http_endpoint=0.0.0.0:6962", "--metrics_endpoint=0.0.0.0:6963", @@ -79,7 +80,7 @@ func CreateDeployment(namespace string, deploymentName string, labels map[string Name: "keys", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "ctlog-secret", + SecretName: configName, }, }, }, diff --git a/controllers/ctlog/wait.go b/controllers/ctlog/wait.go index 7cc75ac19..78598af44 100644 --- a/controllers/ctlog/wait.go +++ b/controllers/ctlog/wait.go @@ -21,7 +21,7 @@ func (i waitAction) Name() string { } func (i waitAction) CanHandle(ctlog *rhtasv1alpha1.CTlog) bool { - return ctlog.Status.Phase == rhtasv1alpha1.PhaseCreating + return ctlog.Status.Phase == rhtasv1alpha1.PhaseInitialize } func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) (*rhtasv1alpha1.CTlog, error) { diff --git a/controllers/fulcio/create.go b/controllers/fulcio/create.go index 4c3a6f80c..49ccbfb2f 100644 --- a/controllers/fulcio/create.go +++ b/controllers/fulcio/create.go @@ -59,12 +59,12 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio return instance, err } - secret := kubernetes.CreateSecret(instance.Namespace, instance.Spec.KeySecret, "fulcio-server", "fulcio", map[string]string{ + secret := kubernetes.CreateSecret(instance.Spec.KeySecret, instance.Namespace, map[string][]byte{ "private": certConfig.FulcioPrivateKey, "public": certConfig.FulcioPublicKey, "cert": certConfig.FulcioRootCert, "password": certConfig.CertPassword, - }) + }, labels) controllerutil.SetOwnerReference(instance, secret, i.Client.Scheme()) if err = i.Client.Create(ctx, secret); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError @@ -106,6 +106,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio if instance.Spec.External { // TODO: do we need to support ingress? route := kubernetes.CreateRoute(*svc, "80-tcp", labels) + controllerutil.SetControllerReference(instance, route, i.Client.Scheme()) if err = i.Client.Create(ctx, route); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError return instance, fmt.Errorf("could not create route: %w", err) @@ -115,7 +116,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio instance.Status.Url = fmt.Sprintf("http://%s.%s.svc", svc.Name, svc.Namespace) } - instance.Status.Phase = rhtasv1alpha1.PhaseCreating + instance.Status.Phase = rhtasv1alpha1.PhaseInitialize return instance, nil } diff --git a/controllers/fulcio/utils/fulcio_deployment.go b/controllers/fulcio/utils/fulcio_deployment.go index 817c6882f..e1cc7a0cd 100644 --- a/controllers/fulcio/utils/fulcio_deployment.go +++ b/controllers/fulcio/utils/fulcio_deployment.go @@ -46,7 +46,7 @@ func CreateDeployment(namespace string, deploymentName string, labels map[string "/var/run/fulcio-secrets/cert.pem", "--fileca-key-passwd", "$(PASSWORD)", - fmt.Sprintf("--ct-log-url=http://ctlog.%s.svc/sigstorescaffolding", namespace), + fmt.Sprintf("--ct-log-url=http://ctlog.%s.svc/trusted-artifact-signer", namespace), }, Env: []corev1.EnvVar{ { diff --git a/controllers/fulcio/utils/fulcio_secrets.go b/controllers/fulcio/utils/fulcio_secrets.go index dc79df8fb..0f43952c6 100644 --- a/controllers/fulcio/utils/fulcio_secrets.go +++ b/controllers/fulcio/utils/fulcio_secrets.go @@ -15,10 +15,10 @@ import ( ) type FulcioCertConfig struct { - FulcioPrivateKey string - FulcioPublicKey string - FulcioRootCert string - CertPassword string + FulcioPrivateKey []byte + FulcioPublicKey []byte + FulcioRootCert []byte + CertPassword []byte } func SetupCerts(instance *rhtasv1alpha1.Fulcio) (*FulcioCertConfig, error) { @@ -45,34 +45,34 @@ func SetupCerts(instance *rhtasv1alpha1.Fulcio) (*FulcioCertConfig, error) { return nil, err } fulcioConfig.FulcioRootCert = fulcioRootCert - fulcioConfig.CertPassword = instance.Spec.FulcioCert.CertPassword + fulcioConfig.CertPassword = []byte(instance.Spec.FulcioCert.CertPassword) return fulcioConfig, nil } -func createCAKey(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) (string, error) { +func createCAKey(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) ([]byte, error) { mKey, err := x509.MarshalECPrivateKey(key) if err != nil { - return "", err + return nil, err } block, err := x509.EncryptPEMBlock(rand.Reader, "EC PRIVATE KEY", mKey, []byte(instance.Spec.FulcioCert.CertPassword), x509.PEMCipherAES256) if err != nil { - return "", err + return nil, err } var pemData bytes.Buffer if err := pem.Encode(&pemData, block); err != nil { - return "", err + return nil, err } - return pemData.String(), nil + return pemData.Bytes(), nil } -func createCAPub(key *ecdsa.PrivateKey) (string, error) { +func createCAPub(key *ecdsa.PrivateKey) ([]byte, error) { mPubKey, err := x509.MarshalPKIXPublicKey(key.Public()) if err != nil { - return "", err + return nil, err } var pemPubKey bytes.Buffer @@ -81,13 +81,13 @@ func createCAPub(key *ecdsa.PrivateKey) (string, error) { Bytes: mPubKey, }) if err != nil { - return "", err + return nil, err } - return pemPubKey.String(), nil + return pemPubKey.Bytes(), nil } -func createFulcioCA(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) (string, error) { +func createFulcioCA(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) ([]byte, error) { notBefore := time.Now() notAfter := notBefore.Add(365 * 24 * 10 * time.Hour) @@ -111,7 +111,7 @@ func createFulcioCA(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) (stri fulcioRoot, err := x509.CreateCertificate(rand.Reader, &template, &template, key.Public(), key) if err != nil { - return "", err + return nil, err } var pemFulcioRoot bytes.Buffer @@ -120,8 +120,8 @@ func createFulcioCA(key *ecdsa.PrivateKey, instance *rhtasv1alpha1.Fulcio) (stri Bytes: fulcioRoot, }) if err != nil { - return "", err + return nil, err } - return pemFulcioRoot.String(), nil + return pemFulcioRoot.Bytes(), nil } diff --git a/controllers/fulcio/wait.go b/controllers/fulcio/wait.go index f72bcf31e..3bec2da56 100644 --- a/controllers/fulcio/wait.go +++ b/controllers/fulcio/wait.go @@ -21,7 +21,7 @@ func (i waitAction) Name() string { } func (i waitAction) CanHandle(Fulcio *rhtasv1alpha1.Fulcio) bool { - return Fulcio.Status.Phase == rhtasv1alpha1.PhaseCreating + return Fulcio.Status.Phase == rhtasv1alpha1.PhaseInitialize } func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio) (*rhtasv1alpha1.Fulcio, error) { diff --git a/controllers/rekor/action.go b/controllers/rekor/action.go index 778986dcc..fc20e4e41 100644 --- a/controllers/rekor/action.go +++ b/controllers/rekor/action.go @@ -3,6 +3,7 @@ package rekor import ( "context" + "github.com/go-logr/logr" "github.com/securesign/operator/api/v1alpha1" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" @@ -11,6 +12,7 @@ import ( type Action interface { InjectClient(client client.Client) InjectRecorder(recorder record.EventRecorder) + InjectLogger(logger logr.Logger) // a user friendly name for the action Name() string @@ -21,16 +23,3 @@ type Action interface { // executes the handling function Handle(context.Context, *v1alpha1.Rekor) (*v1alpha1.Rekor, error) } - -type BaseAction struct { - Client client.Client - Recorder record.EventRecorder -} - -func (action *BaseAction) InjectClient(client client.Client) { - action.Client = client -} - -func (action *BaseAction) InjectRecorder(recorder record.EventRecorder) { - action.Recorder = recorder -} diff --git a/controllers/rekor/create.go b/controllers/rekor/create.go index 582301b2d..d30e20381 100644 --- a/controllers/rekor/create.go +++ b/controllers/rekor/create.go @@ -36,13 +36,13 @@ func (i createAction) CanHandle(Rekor *rhtasv1alpha1.Rekor) bool { func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) (*rhtasv1alpha1.Rekor, error) { //log := ctrllog.FromContext(ctx) var err error - commonLabels := k8sutils.FilterCommonLabels(instance.Labels) - commonLabels["app.kubernetes.io/component"] = ComponentName - redisLabels := commonLabels + redisLabels := k8sutils.FilterCommonLabels(instance.Labels) + redisLabels["app.kubernetes.io/component"] = ComponentName redisLabels["app.kubernetes.io/name"] = rekorRedisDeploymentName - rekorServerLabels := commonLabels + rekorServerLabels := k8sutils.FilterCommonLabels(instance.Labels) + rekorServerLabels["app.kubernetes.io/component"] = ComponentName rekorServerLabels["app.kubernetes.io/name"] = rekorDeploymentName if instance.Spec.KeySecret == "" { @@ -56,7 +56,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) return instance, err } - secret := k8sutils.CreateSecret(instance.Namespace, instance.Spec.KeySecret, "rekor-server", "rekor", map[string]string{"private": certConfig.RekorKey}) + secret := k8sutils.CreateSecret(instance.Spec.KeySecret, instance.Namespace, map[string][]byte{"private": certConfig.RekorKey}, rekorServerLabels) controllerutil.SetOwnerReference(instance, secret, i.Client.Scheme()) if err = i.Client.Create(ctx, secret); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError @@ -65,6 +65,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) } sharding := k8sutils.InitConfigmap(instance.Namespace, "rekor-sharding-config", rekorServerLabels, map[string]string{"sharding-config.yaml": ""}) + controllerutil.SetControllerReference(instance, sharding, i.Client.Scheme()) if err = i.Client.Create(ctx, sharding); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError return instance, fmt.Errorf("could not create Rekor secret: %w", err) @@ -83,7 +84,13 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) rekorPvcName = instance.Spec.PvcName } - dp := utils.CreateRekorDeployment(instance.Namespace, rekorDeploymentName, rekorPvcName, rekorServerLabels) + trillians, err := findTrillians(ctx, i.Client, *instance) + if err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, fmt.Errorf("could not find trillian TreeID: %w", err) + } + + dp := utils.CreateRekorDeployment(instance.Namespace, rekorDeploymentName, trillians.Items[0].Status.TreeID, rekorPvcName, rekorServerLabels) controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()) if err = i.Client.Create(ctx, dp); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError @@ -113,6 +120,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) if instance.Spec.External { // TODO: do we need to support ingress? route := k8sutils.CreateRoute(*svc, "80-tcp", rekorServerLabels) + controllerutil.SetControllerReference(instance, route, i.Client.Scheme()) if err = i.Client.Create(ctx, route); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError return instance, fmt.Errorf("could not create route: %w", err) @@ -122,7 +130,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) instance.Status.Url = fmt.Sprintf("http://%s.%s.svc", svc.Name, svc.Namespace) } - instance.Status.Phase = rhtasv1alpha1.PhaseCreating + instance.Status.Phase = rhtasv1alpha1.PhaseInitialize return instance, nil } diff --git a/controllers/rekor/init.go b/controllers/rekor/init.go new file mode 100644 index 000000000..9e4e69e18 --- /dev/null +++ b/controllers/rekor/init.go @@ -0,0 +1,75 @@ +package rekor + +import ( + "context" + "fmt" + "io" + "net/http" + "time" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/controllers/common" + commonUtils "github.com/securesign/operator/controllers/common/utils/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +func NewWaitAction() Action { + return &waitAction{} +} + +type waitAction struct { + common.BaseAction +} + +func (i waitAction) Name() string { + return "wait" +} + +func (i waitAction) CanHandle(Rekor *rhtasv1alpha1.Rekor) bool { + return Rekor.Status.Phase == rhtasv1alpha1.PhaseInitialize +} + +func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) (*rhtasv1alpha1.Rekor, error) { + var ( + ok bool + err error + ) + labels := commonUtils.FilterCommonLabels(instance.Labels) + labels["app.kubernetes.io/component"] = ComponentName + ok, err = commonUtils.DeploymentIsRunning(ctx, i.Client, instance.Namespace, labels) + if err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, err + } + if !ok { + return instance, nil + } + + var pubKeyResponse *http.Response + for retry := 1; retry < 5; retry++ { + time.Sleep(time.Duration(retry) * time.Second) + pubKeyResponse, err = http.Get(instance.Status.Url + "/api/v1/log/publicKey") + if err == nil && pubKeyResponse.StatusCode == http.StatusOK { + continue + } + i.Logger.Info("retrying to get rekor public key") + } + + if err != nil || pubKeyResponse.StatusCode != http.StatusOK { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, err + } + body, err := io.ReadAll(pubKeyResponse.Body) + if err != nil || pubKeyResponse.StatusCode != http.StatusOK { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, err + } + secret := commonUtils.CreateSecret("rekor-public-key", instance.Namespace, map[string][]byte{"key": body}, labels) + controllerutil.SetControllerReference(instance, secret, i.Client.Scheme()) + if err = i.Client.Create(ctx, secret); err != nil { + instance.Status.Phase = rhtasv1alpha1.PhaseError + return instance, fmt.Errorf("could not create rekor-public-key secret: %w", err) + } + instance.Status.Phase = rhtasv1alpha1.PhaseReady + return instance, nil +} diff --git a/controllers/rekor/rekor_controller.go b/controllers/rekor/rekor_controller.go index b9cb4b155..e85b38a17 100644 --- a/controllers/rekor/rekor_controller.go +++ b/controllers/rekor/rekor_controller.go @@ -25,6 +25,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" + ctrllog "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" @@ -52,6 +53,7 @@ type RekorReconciler struct { // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.1/pkg/reconcile func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var instance rhtasv1alpha1.Rekor + log := ctrllog.FromContext(ctx) if err := r.Client.Get(ctx, req.NamespacedName, &instance); err != nil { if errors.IsNotFound(err) { @@ -72,6 +74,7 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl for _, a := range actions { a.InjectClient(r.Client) + a.InjectLogger(log) if a.CanHandle(target) { newTarget, err := a.Handle(ctx, target) diff --git a/controllers/rekor/utils/rekor_deployment.go b/controllers/rekor/utils/rekor_deployment.go index 332808fde..a9a1bde1c 100644 --- a/controllers/rekor/utils/rekor_deployment.go +++ b/controllers/rekor/utils/rekor_deployment.go @@ -1,13 +1,15 @@ package utils import ( + "fmt" + "github.com/securesign/operator/controllers/constants" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func CreateRekorDeployment(namespace string, dpName string, pvc string, labels map[string]string) *apps.Deployment { +func CreateRekorDeployment(namespace string, dpName string, treeID int64, pvc string, labels map[string]string) *apps.Deployment { replicas := int32(1) return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -72,19 +74,6 @@ func CreateRekorDeployment(namespace string, dpName string, pvc string, labels m // SuccessThreshold: 1, // FailureThreshold: 3, //}, - Env: []core.EnvVar{ - { - Name: "TREE_ID", - ValueFrom: &core.EnvVarSource{ - ConfigMapKeyRef: &core.ConfigMapKeySelector{ - LocalObjectReference: core.LocalObjectReference{ - Name: "trillian-tree", - }, - Key: "treeID", - }, - }, - }, - }, Image: constants.RekorServerImage, Ports: []core.ContainerPort{ { @@ -106,7 +95,7 @@ func CreateRekorDeployment(namespace string, dpName string, pvc string, labels m "--rekor_server.address=0.0.0.0", "--rekor_server.signer=/key/private", "--enable_retrieve_api=true", - "--trillian_log_server.tlog_id=$(TREE_ID)", + fmt.Sprintf("--trillian_log_server.tlog_id=%d", treeID), "--enable_attestation_storage", "--attestation_storage_bucket=file:///var/run/attestations", }, diff --git a/controllers/rekor/utils/rekor_secrets.go b/controllers/rekor/utils/rekor_secrets.go index 25ef2ac90..1a3725b45 100644 --- a/controllers/rekor/utils/rekor_secrets.go +++ b/controllers/rekor/utils/rekor_secrets.go @@ -10,7 +10,7 @@ import ( ) type RekorCertConfig struct { - RekorKey string + RekorKey []byte } func CreateRekorKey() (*RekorCertConfig, error) { @@ -34,7 +34,7 @@ func CreateRekorKey() (*RekorCertConfig, error) { return nil, err } - rekorCertConfig.RekorKey = pemRekorKey.String() + rekorCertConfig.RekorKey = pemRekorKey.Bytes() return rekorCertConfig, nil } diff --git a/controllers/rekor/wait.go b/controllers/rekor/wait.go deleted file mode 100644 index c3802a37e..000000000 --- a/controllers/rekor/wait.go +++ /dev/null @@ -1,44 +0,0 @@ -package rekor - -import ( - "context" - - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/controllers/common" - commonUtils "github.com/securesign/operator/controllers/common/utils/kubernetes" -) - -func NewWaitAction() Action { - return &waitAction{} -} - -type waitAction struct { - common.BaseAction -} - -func (i waitAction) Name() string { - return "wait" -} - -func (i waitAction) CanHandle(Rekor *rhtasv1alpha1.Rekor) bool { - return Rekor.Status.Phase == rhtasv1alpha1.PhaseCreating -} - -func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) (*rhtasv1alpha1.Rekor, error) { - var ( - ok bool - err error - ) - labels := commonUtils.FilterCommonLabels(instance.Labels) - labels["app.kubernetes.io/component"] = ComponentName - ok, err = commonUtils.DeploymentIsRunning(ctx, i.Client, instance.Namespace, labels) - if err != nil { - instance.Status.Phase = rhtasv1alpha1.PhaseError - return instance, err - } - if !ok { - return instance, nil - } - instance.Status.Phase = rhtasv1alpha1.PhaseReady - return instance, nil -} diff --git a/controllers/securesign_controller.go b/controllers/securesign_controller.go index f71b26e5b..d99f012bf 100644 --- a/controllers/securesign_controller.go +++ b/controllers/securesign_controller.go @@ -51,6 +51,7 @@ type SecuresignReconciler struct { //+kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=networking,resources=ingresses,verbs=get;list;watch;create;update;patch;delete @@ -358,6 +359,11 @@ func (r *SecuresignReconciler) ensureRole( Resources: []string{"secrets"}, Verbs: []string{"create", "get", "update"}, }, + { + APIGroups: []string{"route.openshift.io"}, + Resources: []string{"routes"}, + Verbs: []string{"create", "get", "update"}, + }, }, } diff --git a/controllers/trillian/create.go b/controllers/trillian/create.go index e937c4c12..2ed52cf1d 100644 --- a/controllers/trillian/create.go +++ b/controllers/trillian/create.go @@ -41,19 +41,20 @@ func (i createAction) CanHandle(trillian *rhtasv1alpha1.Trillian) bool { func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trillian) (*rhtasv1alpha1.Trillian, error) { //log := ctrllog.FromContext(ctx) var err error - labels := kubernetes.FilterCommonLabels(instance.Labels) - labels["app.kubernetes.io/component"] = ComponentName - dbLabels := labels + dbLabels := kubernetes.FilterCommonLabels(instance.Labels) + dbLabels["app.kubernetes.io/component"] = ComponentName dbLabels["app.kubernetes.io/name"] = dbDeploymentName - logSignerLabels := labels + logSignerLabels := kubernetes.FilterCommonLabels(instance.Labels) + logSignerLabels["app.kubernetes.io/component"] = ComponentName logSignerLabels["app.kubernetes.io/name"] = logsignerDeploymentName - logServerLabels := labels + logServerLabels := kubernetes.FilterCommonLabels(instance.Labels) + logServerLabels["app.kubernetes.io/component"] = ComponentName logServerLabels["app.kubernetes.io/name"] = logserverDeploymentName - dbSecret := i.createDbSecret(instance.Namespace, labels) + dbSecret := i.createDbSecret(instance.Namespace, dbLabels) controllerutil.SetControllerReference(instance, dbSecret, i.Client.Scheme()) if err = i.Client.Create(ctx, dbSecret); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError diff --git a/controllers/trillian/init.go b/controllers/trillian/init.go index f3c6f8082..6098b0322 100644 --- a/controllers/trillian/init.go +++ b/controllers/trillian/init.go @@ -6,7 +6,6 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/controllers/common" - "github.com/securesign/operator/controllers/common/utils/kubernetes" "github.com/securesign/operator/controllers/trillian/utils" ) @@ -34,15 +33,7 @@ func (i initializeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tr return instance, fmt.Errorf("could not create Trillian tree: %w", err) } - labels := kubernetes.FilterCommonLabels(instance.Labels) - labels["app.kubernetes.io/component"] = ComponentName - labels["app.kubernetes.io/name"] = logserverDeploymentName - - config := kubernetes.InitConfigmap(instance.Namespace, "trillian-tree", labels, map[string]string{"treeID": fmt.Sprint(tree.TreeId)}) - if err = i.Client.Create(ctx, config); err != nil { - instance.Status.Phase = rhtasv1alpha1.PhaseError - return instance, fmt.Errorf("could not create Trillian tree: %w", err) - } + instance.Status.TreeID = tree.TreeId instance.Status.Phase = rhtasv1alpha1.PhaseReady return instance, nil } diff --git a/controllers/trillian/utils/trillian-deployment.go b/controllers/trillian/utils/trillian-deployment.go index 7aafe3bf8..fda4d7e96 100644 --- a/controllers/trillian/utils/trillian-deployment.go +++ b/controllers/trillian/utils/trillian-deployment.go @@ -1,15 +1,12 @@ package utils import ( + "github.com/securesign/operator/controllers/constants" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const ( - netcat = "registry.redhat.io/rhtas-tech-preview/trillian-netcat-rhel9@sha256:b9fa895af8967cceb7a05ed7c9f2b80df047682ed11c87249ca2edba86492f6e" -) - func CreateTrillDeployment(namespace string, image string, dpName string, dbsecret string, labels map[string]string) *apps.Deployment { replicas := int32(1) return &apps.Deployment{ @@ -32,7 +29,7 @@ func CreateTrillDeployment(namespace string, image string, dpName string, dbsecr InitContainers: []core.Container{ { Name: "wait-for-trillian-db", - Image: netcat, + Image: constants.TrillianNetcatImage, Command: []string{ "sh", "-c", diff --git a/controllers/trillian/wait.go b/controllers/trillian/wait_for_creation.go similarity index 100% rename from controllers/trillian/wait.go rename to controllers/trillian/wait_for_creation.go diff --git a/controllers/tuf/create.go b/controllers/tuf/create.go index 49b609b38..0aded76c2 100644 --- a/controllers/tuf/create.go +++ b/controllers/tuf/create.go @@ -40,13 +40,6 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) ( labels["app.kubernetes.io/component"] = ComponentName labels["app.kubernetes.io/name"] = tufDeploymentName - // TODO: migrate code to the operator - copyJob := tufutils.InitTufCopyJob(instance.Namespace, "tuf-secret-copy-job") - if err = i.Client.Create(ctx, copyJob); err != nil { - instance.Status.Phase = rhtasv1alpha1.PhaseError - return instance, fmt.Errorf("could not create copy job: %w", err) - } - db := tufutils.CreateTufDeployment(instance.Namespace, tufDeploymentName, labels) controllerutil.SetControllerReference(instance, db, i.Client.Scheme()) if err = i.Client.Create(ctx, db); err != nil { @@ -66,6 +59,7 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) ( if instance.Spec.External { // TODO: do we need to support ingress? route := kubernetes.CreateRoute(*svc, "tuf", labels) + controllerutil.SetControllerReference(instance, route, i.Client.Scheme()) if err = i.Client.Create(ctx, route); err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError return instance, fmt.Errorf("could not create route: %w", err) @@ -75,6 +69,6 @@ func (i createAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) ( instance.Status.Url = fmt.Sprintf("http://%s.%s.svc", svc.Name, svc.Namespace) } - instance.Status.Phase = rhtasv1alpha1.PhaseCreating + instance.Status.Phase = rhtasv1alpha1.PhaseInitialize return instance, nil } diff --git a/controllers/tuf/pending.go b/controllers/tuf/pending.go index 159bcea01..1cd3fff85 100644 --- a/controllers/tuf/pending.go +++ b/controllers/tuf/pending.go @@ -6,7 +6,6 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/controllers/common" "github.com/securesign/operator/controllers/common/utils/kubernetes" - "github.com/securesign/operator/controllers/rekor" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -32,7 +31,6 @@ func (i pendingAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) } searchLabels := kubernetes.FilterCommonLabels(instance.Labels) - searchLabels["app.kubernetes.io/component"] = rekor.ComponentName rekorList := &rhtasv1alpha1.RekorList{} err := i.Client.List(ctx, rekorList, client.InNamespace(instance.Namespace), client.MatchingLabels(searchLabels)) diff --git a/controllers/tuf/utils/tuf_copy_job.go b/controllers/tuf/utils/tuf_copy_job.go deleted file mode 100644 index 03f32903e..000000000 --- a/controllers/tuf/utils/tuf_copy_job.go +++ /dev/null @@ -1,46 +0,0 @@ -package utils - -import ( - batch "k8s.io/api/batch/v1" - core "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func InitTufCopyJob(namespace string, jobName string) *batch.Job { - - imageName := "registry.redhat.io/openshift4/ose-cli:latest" - return &batch.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: map[string]string{ - "app.kubernetes.io/component": jobName, - "app.kubernetes.io/instance": "trusted-artifact-signer", - "app.kubernetes.io/name": "tuf-secret-copy", - }, - }, - Spec: batch.JobSpec{ - Template: core.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/component": jobName, - "app.kubernetes.io/instance": "trusted-artifact-signer", - "app.kubernetes.io/name": "tuf-secret-copy", - }, - }, - Spec: core.PodSpec{ - ServiceAccountName: "sigstore-sa", - RestartPolicy: core.RestartPolicyOnFailure, - Containers: []core.Container{ - { - Name: "copy-rekor-secret", - Image: imageName, - Command: []string{"/bin/sh"}, - Args: []string{ - "-c", - "curl rekor-server." + namespace + ".svc.cluster.local/api/v1/log/publicKey -o /tmp/key -v && kubectl create secret generic rekor-public-key --from-file=key=/tmp/key", - }, - }, - }}}}, - } -} diff --git a/controllers/tuf/wait.go b/controllers/tuf/wait.go index 450f85c0f..cbd9aec82 100644 --- a/controllers/tuf/wait.go +++ b/controllers/tuf/wait.go @@ -21,7 +21,7 @@ func (i waitAction) Name() string { } func (i waitAction) CanHandle(tuf *rhtasv1alpha1.Tuf) bool { - return tuf.Status.Phase == rhtasv1alpha1.PhaseCreating + return tuf.Status.Phase == rhtasv1alpha1.PhaseInitialize } func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) (*rhtasv1alpha1.Tuf, error) { @@ -30,7 +30,6 @@ func (i waitAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) (*r err error ) labels := commonUtils.FilterCommonLabels(instance.Labels) - labels["app.kubernetes.io/component"] = ComponentName ok, err = commonUtils.DeploymentIsRunning(ctx, i.Client, instance.Namespace, labels) if err != nil { instance.Status.Phase = rhtasv1alpha1.PhaseError diff --git a/go.mod b/go.mod index 8ae66f133..1af9cf401 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,23 @@ module github.com/securesign/operator go 1.21 require ( + github.com/google/certificate-transparency-go v1.1.6 github.com/google/trillian v1.5.3 github.com/openshift/api v0.0.0-20231118005202-0f638a8a4705 + github.com/sigstore/fulcio v1.4.3 + github.com/sigstore/sigstore v1.7.3 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 k8s.io/api v0.27.2 k8s.io/apimachinery v0.27.2 k8s.io/client-go v0.27.2 + knative.dev/pkg v0.0.0-20230612155445-74c4be5e935e sigs.k8s.io/controller-runtime v0.15.2 ) require ( github.com/beorn7/perks v1.0.1 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect @@ -30,11 +35,12 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.4.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -47,9 +53,12 @@ require ( github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/theupdateframework/go-tuf v0.5.2 // indirect + github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sys v0.13.0 // indirect @@ -60,13 +69,14 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.27.2 // indirect k8s.io/component-base v0.27.2 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect - k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect + k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 44863af61..b2f6ac37a 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -17,8 +19,15 @@ github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg= +github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01/go.mod h1:ypD5nozFk9vcGw1ATYefw6jHe/jZP++Z15/+VTMcWhc= +github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8= +github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52/go.mod h1:yIquW87NGRw1FU5p5lEkpnt/QxoH5uPAOUlOVkAUuMg= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -33,7 +42,9 @@ github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -41,6 +52,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -53,6 +65,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/certificate-transparency-go v1.1.6 h1:SW5K3sr7ptST/pIvNkSVWMiJqemRmkjJPPT0jzXdOOY= +github.com/google/certificate-transparency-go v1.1.6/go.mod h1:0OJjOsOk+wj6aYQgP7FU0ioQ0AJUmnWPFMqTjQeazPQ= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -64,31 +78,44 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= +github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/trillian v1.5.3 h1:3ioA5p09qz+U9/t2riklZtaQdZclaStp0/eQNfewNRg= github.com/google/trillian v1.5.3/go.mod h1:p4tcg7eBr7aT6DxrAoILpc3uXNfcuAvZSnQKonVg+Eo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/honeycombio/beeline-go v1.10.0 h1:cUDe555oqvw8oD76BQJ8alk7FP0JZ/M/zXpNvOEDLDc= +github.com/honeycombio/beeline-go v1.10.0/go.mod h1:Zz5WMeQCJzFt2Mvf8t6HC1X8RLskLVR/e8rvcmXB1G8= +github.com/honeycombio/libhoney-go v1.16.0 h1:kPpqoz6vbOzgp7jC6SR7SkNj7rua7rgxvznI6M3KdHc= +github.com/honeycombio/libhoney-go v1.16.0/go.mod h1:izP4fbREuZ3vqC4HlCAmPrcPT9gxyxejRjGtCYpmBn0= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4= +github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.7 h1:7cgTQxJCU/vy+oP/E3B9RGbQTgbiVzIJWIKOLoAsPok= +github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf h1:ndns1qx/5dL43g16EQkPV/i8+b3l5bYQwLeoSBe7tS8= +github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf/go.mod h1:aGkAgvWY/IUcVFfuly53REpfv5edu25oij+qHRFaraA= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= @@ -103,6 +130,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/openshift/api v0.0.0-20231118005202-0f638a8a4705 h1:GwpCt0VhL9GjVGJhdF+96RoUkGTf/d+7ICL/3jKWRkA= github.com/openshift/api v0.0.0-20231118005202-0f638a8a4705/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -120,6 +148,11 @@ github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGy github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/sigstore/fulcio v1.4.3 h1:9JcUCZjjVhRF9fmhVuz6i1RyhCc/EGCD7MOl+iqCJLQ= +github.com/sigstore/fulcio v1.4.3/go.mod h1:BQPWo7cfxmJwgaHlphUHUpFkp5+YxeJes82oo39m5og= +github.com/sigstore/sigstore v1.7.3 h1:HVVTfrMezJeLyl2xhJ8edzkrEGBa4KxjQZB4FlQ4JLU= +github.com/sigstore/sigstore v1.7.3/go.mod h1:cl0c7Dtg3MM3c13L8pqqrfrmBa0eM3POcdtBepjylmw= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -131,20 +164,33 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/theupdateframework/go-tuf v0.5.2 h1:habfDzTmpbzBLIFGWa2ZpVhYvFBoK0C1onC3a4zuPRA= +github.com/theupdateframework/go-tuf v0.5.2/go.mod h1:SyMV5kg5n4uEclsyxXJZI2UxPFJNDc4Y+r7wv+MlvTA= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= @@ -152,6 +198,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -161,6 +209,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -185,6 +235,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -221,6 +272,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -236,7 +288,9 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= +google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -256,6 +310,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc= +gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -263,6 +319,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -287,8 +345,10 @@ k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= -k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= +k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +knative.dev/pkg v0.0.0-20230612155445-74c4be5e935e h1:koM+NopG2Yw738NlJhQF3ZwpyS+HHznuLm294VYlUKg= +knative.dev/pkg v0.0.0-20230612155445-74c4be5e935e/go.mod h1:dqC6IrvyBE7E+oZocs5PkVhq1G59pDTA7r8U17EAKMk= sigs.k8s.io/controller-runtime v0.15.2 h1:9V7b7SDQSJ08IIsJ6CY1CE85Okhp87dyTMNDG0FS7f4= sigs.k8s.io/controller-runtime v0.15.2/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=