Skip to content

Commit

Permalink
SECURESIGN-568: Extend Rekor API to support sharding configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
osmman committed Jul 26, 2024
1 parent ad9da1d commit d4a7c3e
Show file tree
Hide file tree
Showing 16 changed files with 882 additions and 85 deletions.
24 changes: 24 additions & 0 deletions api/v1alpha1/rekor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ type RekorSpec struct {
// BackFillRedis CronJob Configuration
//+kubebuilder:default:={enabled: true, schedule: "0 0 * * *"}
BackFillRedis BackFillRedis `json:"backFillRedis,omitempty"`
// Inactive shards
// +listType=map
// +listMapKey=treeID
// +patchStrategy=merge
// +patchMergeKey=treeID
// +kubebuilder:default:={}
Sharding []RekorLogRange `json:"sharding"`
}

type RekorSigner struct {
Expand Down Expand Up @@ -67,6 +74,23 @@ type BackFillRedis struct {
Schedule string `json:"schedule,omitempty"`
}

// RekorLogRange defines the range and details of a log shard
// +structType=atomic
type RekorLogRange struct {
// ID of Merkle tree in Trillian backend
// +kubebuilder:validation:Required
// +kubebuilder:validation:Minimum=1
TreeID int64 `json:"treeID"`
// +kubebuilder:validation:Optional
// +kubebuilder:validation:Minimum=0
// Length of the tree
TreeLength int64 `json:"treeLength"`
// The public key for the log shard, encoded in Base64 format
// +kubebuilder:validation:Optional
// +kubebuilder:validation:Pattern=`^[A-Za-z0-9+/\n]+={0,2}\n*$`
EncodedPublicKey string `json:"encodedPublicKey,omitempty"`
}

// RekorStatus defines the observed state of Rekor
type RekorStatus struct {
// Reference to secret with Rekor's signer public key.
Expand Down
51 changes: 51 additions & 0 deletions api/v1alpha1/rekor_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,50 @@ var _ = Describe("Rekor", func() {
})
})

Context("sharding", func() {
It("require treeId", func() {
invalidObject := generateRekorObject("sharding-treeid")
invalidObject.Spec.Sharding = []RekorLogRange{
{},
}

Expect(apierrors.IsInvalid(k8sClient.Create(context.Background(), invalidObject))).To(BeTrue())
Expect(k8sClient.Create(context.Background(), invalidObject)).
To(MatchError(ContainSubstring("treeID in body should be greater than or equal to 1")))
})

It("base64 encoded public key", func() {
invalidObject := generateRekorObject("sharding-bas64")
invalidObject.Spec.Sharding = []RekorLogRange{
{
TreeID: 1,
EncodedPublicKey: "-----BEGIN PUBLIC KEY-----\nABCD\n-----END PUBLIC KEY-----",
},
}

Expect(apierrors.IsInvalid(k8sClient.Create(context.Background(), invalidObject))).To(BeTrue())
Expect(k8sClient.Create(context.Background(), invalidObject)).
To(MatchError(ContainSubstring("body should match '^[A-Za-z0-9+/]+={0,2}$'")))
})

It("duplicate trees", func() {
invalidObject := generateRekorObject("sharding-duplicate")
invalidObject.Spec.Sharding = []RekorLogRange{
{
TreeID: 123,
},
{
TreeID: 123,
TreeLength: 1,
},
}

Expect(apierrors.IsInvalid(k8sClient.Create(context.Background(), invalidObject))).To(BeTrue())
Expect(k8sClient.Create(context.Background(), invalidObject)).
To(MatchError(ContainSubstring("Duplicate value")))
})
})

Context("Default settings", func() {
var (
rekorInstance Rekor
Expand Down Expand Up @@ -246,6 +290,13 @@ var _ = Describe("Rekor", func() {
Address: "trillian-system.default.svc",
Port: &port,
},
Sharding: []RekorLogRange{
{
TreeID: 123456789,
TreeLength: 1,
EncodedPublicKey: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFWkZ0Nk5FcU14YWVVNzZsbmxZekZVTmpGUUdIcQpORjQ2QlBDVGxQL0ZnZk1aak42MDhjRFhmM0xNNWhUYnZOeUNFYWJFKzRNYk9jRU1YaERRVWxZRnZBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==",
},
},
},
}

Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bundle/manifests/rhtas-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ metadata:
]
capabilities: Seamless Upgrades
containerImage: registry.redhat.io/rhtas/rhtas-rhel9-operator@sha256:a21f7128694a64989bf0d84a7a7da4c1ffc89edf62d594dc8bea7bcfe9ac08d3
createdAt: "2024-07-10T17:23:58Z"
createdAt: "2024-07-26T09:59:15Z"
features.operators.openshift.io/cnf: "false"
features.operators.openshift.io/cni: "false"
features.operators.openshift.io/csi: "false"
Expand Down
32 changes: 32 additions & 0 deletions bundle/manifests/rhtas.redhat.com_rekors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,36 @@ spec:
required:
- enabled
type: object
sharding:
default: []
description: Inactive shards
items:
description: RekorLogRange defines the range and details of a log
shard
properties:
encodedPublicKey:
description: The public key for the log shard, encoded in Base64
format
pattern: ^[A-Za-z0-9+/\n]+={0,2}\n*$
type: string
treeID:
description: ID of Merkle tree in Trillian backend
format: int64
minimum: 1
type: integer
treeLength:
description: Length of the tree
format: int64
minimum: 0
type: integer
required:
- treeID
type: object
x-kubernetes-map-type: atomic
type: array
x-kubernetes-list-map-keys:
- treeID
x-kubernetes-list-type: map
signer:
description: Signer configuration
properties:
Expand Down Expand Up @@ -223,6 +253,8 @@ spec:
minimum: 1
type: integer
type: object
required:
- sharding
type: object
status:
description: RekorStatus defines the observed state of Rekor
Expand Down
32 changes: 32 additions & 0 deletions bundle/manifests/rhtas.redhat.com_securesigns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,36 @@ spec:
required:
- enabled
type: object
sharding:
default: []
description: Inactive shards
items:
description: RekorLogRange defines the range and details of
a log shard
properties:
encodedPublicKey:
description: The public key for the log shard, encoded in
Base64 format
pattern: ^[A-Za-z0-9+/\n]+={0,2}\n*$
type: string
treeID:
description: ID of Merkle tree in Trillian backend
format: int64
minimum: 1
type: integer
treeLength:
description: Length of the tree
format: int64
minimum: 0
type: integer
required:
- treeID
type: object
x-kubernetes-map-type: atomic
type: array
x-kubernetes-list-map-keys:
- treeID
x-kubernetes-list-type: map
signer:
description: Signer configuration
properties:
Expand Down Expand Up @@ -586,6 +616,8 @@ spec:
minimum: 1
type: integer
type: object
required:
- sharding
type: object
trillian:
description: TrillianSpec defines the desired state of Trillian
Expand Down
32 changes: 32 additions & 0 deletions config/crd/bases/rhtas.redhat.com_rekors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,36 @@ spec:
required:
- enabled
type: object
sharding:
default: []
description: Inactive shards
items:
description: RekorLogRange defines the range and details of a log
shard
properties:
encodedPublicKey:
description: The public key for the log shard, encoded in Base64
format
pattern: ^[A-Za-z0-9+/\n]+={0,2}\n*$
type: string
treeID:
description: ID of Merkle tree in Trillian backend
format: int64
minimum: 1
type: integer
treeLength:
description: Length of the tree
format: int64
minimum: 0
type: integer
required:
- treeID
type: object
x-kubernetes-map-type: atomic
type: array
x-kubernetes-list-map-keys:
- treeID
x-kubernetes-list-type: map
signer:
description: Signer configuration
properties:
Expand Down Expand Up @@ -223,6 +253,8 @@ spec:
minimum: 1
type: integer
type: object
required:
- sharding
type: object
status:
description: RekorStatus defines the observed state of Rekor
Expand Down
32 changes: 32 additions & 0 deletions config/crd/bases/rhtas.redhat.com_securesigns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,36 @@ spec:
required:
- enabled
type: object
sharding:
default: []
description: Inactive shards
items:
description: RekorLogRange defines the range and details of
a log shard
properties:
encodedPublicKey:
description: The public key for the log shard, encoded in
Base64 format
pattern: ^[A-Za-z0-9+/\n]+={0,2}\n*$
type: string
treeID:
description: ID of Merkle tree in Trillian backend
format: int64
minimum: 1
type: integer
treeLength:
description: Length of the tree
format: int64
minimum: 0
type: integer
required:
- treeID
type: object
x-kubernetes-map-type: atomic
type: array
x-kubernetes-list-map-keys:
- treeID
x-kubernetes-list-type: map
signer:
description: Signer configuration
properties:
Expand Down Expand Up @@ -586,6 +616,8 @@ spec:
minimum: 1
type: integer
type: object
required:
- sharding
type: object
trillian:
description: TrillianSpec defines the desired state of Trillian
Expand Down
6 changes: 3 additions & 3 deletions docs/rekor-key-rotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ These variables are necessary for the subsequent steps to successfully rotate th
{
"op": "replace",
"path": "/spec/rekor/treeID",
"value": "$NEW_TREE_ID"
"value": $NEW_TREE_ID
},
{
"op": "add",
"path": "/spec/rekor/sharding",
"value": {
"treeID": "$CURRENT_TREE_ID",
"treeLength": "$CURRENT_SHARD_LENGTH",
"treeID": $CURRENT_TREE_ID,
"treeLength": $CURRENT_SHARD_LENGTH,
"encodedPublicKey": "$CURRENT_SHARD_PUBLIC_KEY"
}
},
Expand Down
Loading

0 comments on commit d4a7c3e

Please sign in to comment.