diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index 3bb8edbd7..a8d3940db 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -21,6 +21,19 @@ type MonitoringConfig struct { Enabled bool `json:"enabled"` } +// TrillianService configuration to connect Trillian server +type TrillianService struct { + // Address to Trillian Log Server End point + //+optional + Address string `json:"address,omitempty"` + // Port of Trillian Log Server End point + //+kubebuilder:validation:Minimum:=1 + //+kubebuilder:validation:Maximum:=65535 + //+kubebuilder:default:=8091 + //+optional + Port *int32 `json:"port,omitempty"` +} + // LocalObjectReference contains enough information to let you locate the // referenced object inside the same namespace. // +structType=atomic diff --git a/api/v1alpha1/rekor_types.go b/api/v1alpha1/rekor_types.go index 7c36c3250..c56636842 100644 --- a/api/v1alpha1/rekor_types.go +++ b/api/v1alpha1/rekor_types.go @@ -13,6 +13,8 @@ type RekorSpec struct { // If it is unset, the operator will create new Merkle tree in the Trillian backend //+optional TreeID *int64 `json:"treeID,omitempty"` + // Trillian service configuration + Trillian TrillianService `json:"trillian,omitempty"` // Define whether you want to export service or not ExternalAccess ExternalAccess `json:"externalAccess,omitempty"` //Enable Service monitors for rekor diff --git a/api/v1alpha1/rekor_types_test.go b/api/v1alpha1/rekor_types_test.go index e9660ad8f..263e759ae 100644 --- a/api/v1alpha1/rekor_types_test.go +++ b/api/v1alpha1/rekor_types_test.go @@ -198,6 +198,7 @@ var _ = Describe("Rekor", func() { It("outputs the CR", func() { storage := k8sresource.MustParse("987Gi") tree := int64(1269875) + port := int32(8091) rekorInstance = Rekor{ ObjectMeta: metav1.ObjectMeta{ @@ -241,6 +242,10 @@ var _ = Describe("Rekor", func() { Key: "key", }, }, + Trillian: TrillianService{ + Address: "trillian-system.default.svc", + Port: &port, + }, }, } @@ -254,7 +259,6 @@ var _ = Describe("Rekor", func() { When("CR is partially set", func() { It("sets spec.pvc.storage if spec.pvc is partially set", func() { - rekorInstance = Rekor{ ObjectMeta: metav1.ObjectMeta{ Name: "rekor-storage", @@ -300,6 +304,10 @@ func generateRekorObject(name string) *Rekor { Retain: utils.Pointer(true), Size: &storage, }, + Trillian: TrillianService{ + Port: utils.Pointer(int32(8091)), + }, + }, } } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 90e5fbe28..a241f7012 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -564,6 +564,7 @@ func (in *RekorSpec) DeepCopyInto(out *RekorSpec) { *out = new(int64) **out = **in } + in.Trillian.DeepCopyInto(&out.Trillian) out.ExternalAccess = in.ExternalAccess out.Monitoring = in.Monitoring in.RekorSearchUI.DeepCopyInto(&out.RekorSearchUI) @@ -865,6 +866,26 @@ func (in *TrillianList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrillianService) DeepCopyInto(out *TrillianService) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrillianService. +func (in *TrillianService) DeepCopy() *TrillianService { + if in == nil { + return nil + } + out := new(TrillianService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrillianSpec) DeepCopyInto(out *TrillianSpec) { *out = *in diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index 1da8d6cfd..998f7dc99 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -192,7 +192,7 @@ metadata: ] capabilities: Seamless Upgrades containerImage: registry.redhat.io/rhtas/rhtas-rhel9-operator@sha256:a21f7128694a64989bf0d84a7a7da4c1ffc89edf62d594dc8bea7bcfe9ac08d3 - createdAt: "2024-05-28T11:15:21Z" + createdAt: "2024-06-03T14:37:13Z" features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" features.operators.openshift.io/csi: "false" @@ -204,7 +204,7 @@ metadata: features.operators.openshift.io/token-auth-azure: "false" features.operators.openshift.io/token-auth-gcp: "false" operators.openshift.io/valid-subscription: '["Red Hat Trusted Artifact Signer"]' - operators.operatorframework.io/builder: operator-sdk-v1.34.1 + operators.operatorframework.io/builder: operator-sdk-v1.34.2 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 repository: https://github.com/securesign/secure-sign-operator support: Red Hat diff --git a/bundle/manifests/rhtas.redhat.com_rekors.yaml b/bundle/manifests/rhtas.redhat.com_rekors.yaml index 7dfc7fad7..69840e28f 100644 --- a/bundle/manifests/rhtas.redhat.com_rekors.yaml +++ b/bundle/manifests/rhtas.redhat.com_rekors.yaml @@ -204,6 +204,20 @@ spec: If it is unset, the operator will create new Merkle tree in the Trillian backend format: int64 type: integer + trillian: + description: Trillian service configuration + properties: + address: + description: Address to Trillian Log Server End point + type: string + port: + default: 8091 + description: Port of Trillian Log Server End point + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object type: object status: description: RekorStatus defines the observed state of Rekor diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index 51225a2b8..0081cdad5 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -551,6 +551,20 @@ spec: If it is unset, the operator will create new Merkle tree in the Trillian backend format: int64 type: integer + trillian: + description: Trillian service configuration + properties: + address: + description: Address to Trillian Log Server End point + type: string + port: + default: 8091 + description: Port of Trillian Log Server End point + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object type: object trillian: description: TrillianSpec defines the desired state of Trillian diff --git a/config/crd/bases/rhtas.redhat.com_rekors.yaml b/config/crd/bases/rhtas.redhat.com_rekors.yaml index 5d89022fa..c6023a488 100644 --- a/config/crd/bases/rhtas.redhat.com_rekors.yaml +++ b/config/crd/bases/rhtas.redhat.com_rekors.yaml @@ -204,6 +204,20 @@ spec: If it is unset, the operator will create new Merkle tree in the Trillian backend format: int64 type: integer + trillian: + description: Trillian service configuration + properties: + address: + description: Address to Trillian Log Server End point + type: string + port: + default: 8091 + description: Port of Trillian Log Server End point + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object type: object status: description: RekorStatus defines the observed state of Rekor diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index d8b1df23e..44acb39c3 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -551,6 +551,20 @@ spec: If it is unset, the operator will create new Merkle tree in the Trillian backend format: int64 type: integer + trillian: + description: Trillian service configuration + properties: + address: + description: Address to Trillian Log Server End point + type: string + port: + default: 8091 + description: Port of Trillian Log Server End point + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object type: object trillian: description: TrillianSpec defines the desired state of Trillian diff --git a/controllers/rekor/actions/server/createTree.go b/controllers/rekor/actions/server/createTree.go index e352f205a..fbd137cfa 100644 --- a/controllers/rekor/actions/server/createTree.go +++ b/controllers/rekor/actions/server/createTree.go @@ -3,14 +3,14 @@ package server import ( "context" "fmt" - + "github.com/google/trillian" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/controllers/common" "github.com/securesign/operator/controllers/common/action" - k8sutils "github.com/securesign/operator/controllers/common/utils/kubernetes" "github.com/securesign/operator/controllers/constants" "github.com/securesign/operator/controllers/rekor/actions" - trillian "github.com/securesign/operator/controllers/trillian/actions" + "github.com/securesign/operator/controllers/rekor/utils" + actions2 "github.com/securesign/operator/controllers/trillian/actions" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -39,12 +39,20 @@ func (i createTrillianTreeAction) Handle(ctx context.Context, instance *rhtasv1a return i.StatusUpdate(ctx, instance) } var err error + var tree *trillian.Tree + var trillUrl string - trillUrl, err := k8sutils.GetInternalUrl(ctx, i.Client, instance.Namespace, trillian.LogserverDeploymentName) - if err != nil { - return i.Failed(err) + switch { + case instance.Spec.Trillian.Port == nil: + err = fmt.Errorf("%s: %w", i.Name(), utils.TrillianPortNotSpecified) + case instance.Spec.Trillian.Address == "": + trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName ,instance.Namespace, instance.Spec.Trillian.Port) + i.Logger.V(1).Info("trillian logserver", "address", trillUrl) + default: + trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, instance.Spec.Trillian.Port) } - tree, err := common.CreateTrillianTree(ctx, "rekor-tree", trillUrl+":8091") + + tree, err = common.CreateTrillianTree(ctx, "rekor-tree", trillUrl) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, diff --git a/controllers/rekor/actions/server/deployment.go b/controllers/rekor/actions/server/deployment.go index b73f1370a..3faffa24c 100644 --- a/controllers/rekor/actions/server/deployment.go +++ b/controllers/rekor/actions/server/deployment.go @@ -3,6 +3,7 @@ package server import ( "context" "fmt" + actions2 "github.com/securesign/operator/controllers/trillian/actions" "github.com/securesign/operator/controllers/common/action" "github.com/securesign/operator/controllers/constants" @@ -38,7 +39,14 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) updated bool ) labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) - dp, err := utils.CreateRekorDeployment(instance, actions.ServerDeploymentName, actions.RBACName, labels) + + insCopy := instance.DeepCopy() + if insCopy.Spec.Trillian.Address == "" { + insCopy.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", actions2.LogserverDeploymentName, instance.Namespace) + } + i.Logger.V(1).Info("trillian logserver", "address", insCopy.Spec.Trillian.Address) + dp, err := utils.CreateRekorDeployment(insCopy, actions.ServerDeploymentName, actions.RBACName, labels) + if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, diff --git a/controllers/rekor/utils/errors.go b/controllers/rekor/utils/errors.go new file mode 100644 index 000000000..e7d475b0c --- /dev/null +++ b/controllers/rekor/utils/errors.go @@ -0,0 +1,11 @@ +package utils + +import "errors" + +var ( + ServerConfigNotSpecified = errors.New("server config name not specified") + TreeNotSpecified = errors.New("tree not specified") + TrillianAddressNotSpecified = errors.New("trillian address not specified") + TrillianPortNotSpecified = errors.New("trillian port not specified") + SignerKeyNotSpecified = errors.New("signer key reference not specified") +) diff --git a/controllers/rekor/utils/rekor_deployment.go b/controllers/rekor/utils/rekor_deployment.go index 63ca3fa0d..d1b8e5665 100644 --- a/controllers/rekor/utils/rekor_deployment.go +++ b/controllers/rekor/utils/rekor_deployment.go @@ -1,7 +1,6 @@ package utils import ( - "errors" "fmt" "github.com/securesign/operator/api/v1alpha1" @@ -12,17 +11,23 @@ import ( ) func CreateRekorDeployment(instance *v1alpha1.Rekor, dpName string, sa string, labels map[string]string) (*apps.Deployment, error) { - if instance.Status.ServerConfigRef == nil { - return nil, errors.New("server config name not specified") - } - if instance.Status.TreeID == nil { - return nil, errors.New("reference to trillian TreeID not set") + switch { + case instance.Status.ServerConfigRef == nil: + return nil, fmt.Errorf("CreateRekorDeployment: %w", ServerConfigNotSpecified) + case instance.Status.TreeID == nil: + return nil, fmt.Errorf("CreateRekorDeployment: %w", TreeNotSpecified) + case instance.Spec.Trillian.Address == "": + return nil, fmt.Errorf("CreateRekorDeployment: %w", TrillianAddressNotSpecified) + case instance.Spec.Trillian.Port == nil: + return nil, fmt.Errorf("CreateRekorDeployment: %w", TrillianPortNotSpecified) } + env := make([]core.EnvVar, 0) + appArgs := []string{ "serve", - "--trillian_log_server.address=trillian-logserver." + instance.Namespace + ".svc", - "--trillian_log_server.port=8091", + "--trillian_log_server.address=" + instance.Spec.Trillian.Address, + fmt.Sprintf("--trillian_log_server.port=%d", *instance.Spec.Trillian.Port), "--trillian_log_server.sharding_config=/sharding/sharding-config.yaml", "--redis_server.address=rekor-redis", "--redis_server.port=6379", @@ -71,7 +76,7 @@ func CreateRekorDeployment(instance *v1alpha1.Rekor, dpName string, sa string, l // KMS secret if instance.Spec.Signer.KMS == "secret" || instance.Spec.Signer.KMS == "" { if instance.Status.Signer.KeyRef == nil { - return nil, errors.New("signer key ref not specified") + return nil, SignerKeyNotSpecified } svsPrivate := &core.SecretVolumeSource{ SecretName: instance.Status.Signer.KeyRef.Name,