Skip to content

Commit fc61ae2

Browse files
committed
cli: use workload owner key during set command
1 parent 95eaecc commit fc61ae2

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

cli/set.go

+68-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ package main
22

33
import (
44
"context"
5+
"crypto/ecdsa"
6+
"crypto/sha256"
7+
"crypto/x509"
58
"encoding/hex"
69
"encoding/json"
10+
"encoding/pem"
711
"fmt"
812
"io"
13+
"log/slog"
914
"net"
1015
"os"
1116
"time"
@@ -45,6 +50,7 @@ func newSetCmd() *cobra.Command {
4550
cmd.Flags().StringP("coordinator", "c", "", "endpoint the coordinator can be reached at")
4651
must(cobra.MarkFlagRequired(cmd.Flags(), "coordinator"))
4752
cmd.Flags().String("coordinator-policy-hash", DefaultCoordinatorPolicyHash, "expected policy hash of the coordinator, will not be checked if empty")
53+
cmd.Flags().String("workload-owner-key", workloadOwnerPEM, "path to workload owner key (.pem) file")
4854

4955
return cmd
5056
}
@@ -69,6 +75,11 @@ func runSet(cmd *cobra.Command, args []string) error {
6975
return fmt.Errorf("failed to unmarshal manifest: %w", err)
7076
}
7177

78+
workloadOwnerKey, err := loadWorkloadOwnerKey(flags.workloadOwnerKeyPath, m, log)
79+
if err != nil {
80+
return fmt.Errorf("loading workload owner key: %w", err)
81+
}
82+
7283
paths, err := findGenerateTargets(args, log)
7384
if err != nil {
7485
return fmt.Errorf("finding yaml files: %w", err)
@@ -92,7 +103,7 @@ func runSet(cmd *cobra.Command, args []string) error {
92103
kdsCache := fsstore.New(kdsDir, log.WithGroup("kds-cache"))
93104
kdsGetter := snp.NewCachedHTTPSGetter(kdsCache, snp.NeverGCTicker, log.WithGroup("kds-getter"))
94105
validator := snp.NewValidator(validateOptsGen, kdsGetter, log.WithGroup("snp-validator"))
95-
dialer := dialer.New(atls.NoIssuer, validator, &net.Dialer{})
106+
dialer := dialer.NewWithKey(atls.NoIssuer, validator, &net.Dialer{}, workloadOwnerKey)
96107

97108
conn, err := dialer.Dial(cmd.Context(), flags.coordinator)
98109
if err != nil {
@@ -124,9 +135,10 @@ func runSet(cmd *cobra.Command, args []string) error {
124135
}
125136

126137
type setFlags struct {
127-
manifestPath string
128-
coordinator string
129-
policy []byte
138+
manifestPath string
139+
coordinator string
140+
policy []byte
141+
workloadOwnerKeyPath string
130142
}
131143

132144
func parseSetFlags(cmd *cobra.Command) (*setFlags, error) {
@@ -149,6 +161,10 @@ func parseSetFlags(cmd *cobra.Command) (*setFlags, error) {
149161
if err != nil {
150162
return nil, fmt.Errorf("hex-decoding coordinator-policy-hash flag: %w", err)
151163
}
164+
flags.workloadOwnerKeyPath, err = cmd.Flags().GetString("workload-owner-key")
165+
if err != nil {
166+
return nil, fmt.Errorf("getting workload-owner-key flag: %w", err)
167+
}
152168

153169
return flags, nil
154170
}
@@ -161,6 +177,54 @@ func policyMapToBytesList(m map[string]deployment) [][]byte {
161177
return policies
162178
}
163179

180+
func loadWorkloadOwnerKey(path string, manifst manifest.Manifest, log *slog.Logger) (*ecdsa.PrivateKey, error) {
181+
key, err := os.ReadFile(path)
182+
if os.IsNotExist(err) {
183+
if len(manifst.WorkloadOwnerKeys) == 0 {
184+
log.Warn("No workload owner keys in manifest nor private key found. Further manifest updates will be rejected by the coordinator.")
185+
} else {
186+
log.Warn("No workload owner private key found. Setting the manifest may fail.")
187+
}
188+
return nil, nil
189+
}
190+
if err != nil {
191+
return nil, fmt.Errorf("reading workload owner key: %w", err)
192+
}
193+
pemBlock, _ := pem.Decode(key)
194+
if pemBlock == nil {
195+
return nil, fmt.Errorf("decoding workload owner key: %w", err)
196+
}
197+
if pemBlock.Type != "EC PRIVATE KEY" {
198+
return nil, fmt.Errorf("workload owner key is not an EC private key")
199+
}
200+
workloadOwnerKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
201+
if err != nil {
202+
return nil, fmt.Errorf("parsing workload owner key: %w", err)
203+
}
204+
pubKey, err := x509.MarshalPKIXPublicKey(&workloadOwnerKey.PublicKey)
205+
if err != nil {
206+
return nil, fmt.Errorf("marshaling public key: %w", err)
207+
}
208+
ownerKeyHash := sha256.Sum256(pubKey)
209+
ownerKeyHex := manifest.NewHexString(ownerKeyHash[:])
210+
if len(manifst.WorkloadOwnerKeys) == 0 {
211+
log.Warn("No workload owner keys in manifest. Further manifest updates will be rejected by the coordinator")
212+
return workloadOwnerKey, nil
213+
}
214+
log.Debug("Workload owner keys in manifest", "keys", manifst.WorkloadOwnerKeys)
215+
var found bool
216+
for _, k := range manifst.WorkloadOwnerKeys {
217+
if k == ownerKeyHex {
218+
found = true
219+
break
220+
}
221+
}
222+
if !found {
223+
log.Warn("Workload owner key not found in manifest. This may lock you out from further updates")
224+
}
225+
return workloadOwnerKey, nil
226+
}
227+
164228
func setLoop(
165229
ctx context.Context, client coordapi.CoordAPIClient, out io.Writer, req *coordapi.SetManifestRequest,
166230
) (resp *coordapi.SetManifestResponse, retErr error) {

0 commit comments

Comments
 (0)