/
tuf_updates_rotate_online_key.go
92 lines (78 loc) · 3.79 KB
/
tuf_updates_rotate_online_key.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package keys
import (
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/exp/slices"
"github.com/foundriesio/fioctl/subcommands"
)
func init() {
rotate := &cobra.Command{
Use: "rotate-online-key --role targets|snapshot|timestamp [--txid=<txid>]",
Short: "Stage rotation of the online TUF signing key for the Factory",
Long: `Stage rotation of the online TUF signing key for the Factory.
The new online signing key will be used in both CI and production TUF root.
When you rotate the TUF online signing key:
- if there are CI or production targets in your factory, they are re-signed using the new key.
- if there is an active wave in your factory, the TUF online key rotation is not allowed.
- the new wave cannot be created until you apply the online keys rotation.
When you apply the online key rotation, these features are temporarily disabled until it succeeds:
- new CI targets upload (including the targets upload during CI builds).
- automatic re-signing of expired TUF roles using online keys (both CI and production targets).`,
Example: `
- Rotate online TUF targets key and re-sign the new TUF root:
fioctl keys tuf updates rotate-online-key \
--txid=abc --role=targets --keys=tuf-root-keys.tgz --sign
- Rotate all online TUF keys explicitly specifying new key type (and signing algorithm):
fioctl keys tuf updates rotate-online-key \
--txid=abc --role=targets,snapshot,timestamp --key-type=ed25519`,
Run: doTufUpdatesRotateOnlineKey,
}
rotate.Flags().StringSliceP("role", "r", nil, "TUF role name, supported: Targets, Snapshot, Timestamp.")
_ = rotate.MarkFlagRequired("role")
rotate.Flags().StringP("txid", "x", "", "TUF root updates transaction ID.")
rotate.Flags().StringP("keys", "k", "", "Path to <tuf-root-keys.tgz> used to sign TUF root.")
_ = rotate.MarkFlagFilename("keys")
rotate.Flags().StringP("key-type", "y", tufKeyTypeNameEd25519, "Key type, supported: Ed25519, RSA.")
rotate.Flags().BoolP("sign", "s", false, "Sign the new TUF root using the offline root keys.")
rotate.MarkFlagsRequiredTogether("sign", "keys")
tufUpdatesCmd.AddCommand(rotate)
}
func doTufUpdatesRotateOnlineKey(cmd *cobra.Command, args []string) {
factory := viper.GetString("factory")
txid, _ := cmd.Flags().GetString("txid")
roleNames, _ := cmd.Flags().GetStringSlice("role")
for idx, roleName := range roleNames {
roleNames[idx] = strings.ToLower(ParseTufRoleNameOnline(roleName))
}
keyTypeStr, _ := cmd.Flags().GetString("key-type")
keyType := ParseTufKeyType(keyTypeStr)
keysFile, _ := cmd.Flags().GetString("keys")
shouldSign, _ := cmd.Flags().GetBool("sign")
// Preliminary check to give a more verbose error message before requesting to generate new keys
updates, err := api.TufRootUpdatesGet(factory)
subcommands.DieNotNil(err)
_, _, _ = checkTufRootUpdatesStatus(updates, true)
fmt.Println("= Generating new online TUF keys")
subcommands.DieNotNil(api.TufRootUpdatesGenerateOnlineKeys(
factory, txid, keyType.Name(), roleNames,
))
updates, err = api.TufRootUpdatesGet(factory)
subcommands.DieNotNil(err, "Failed to fetch new online TUF keys")
for _, roleName := range []string{tufRoleNameTargets, tufRoleNameSnapshot, tufRoleNameTimestamp} {
roleName = strings.ToLower(roleName)
if slices.Contains(roleNames, roleName) {
fmt.Printf("= New online %s keyid: %s\n", roleName, updates.Updated.OnlineKeys[roleName])
}
}
if shouldSign {
creds, err := GetOfflineCreds(keysFile)
subcommands.DieNotNil(err)
curCiRoot, newCiRoot, newProdRoot := checkTufRootUpdatesStatus(updates, true)
newCiRoot, newProdRoot = finalizeTufRootChanges(newCiRoot, newProdRoot)
signNewTufRoot(curCiRoot, newCiRoot, newProdRoot, creds)
fmt.Println("= Uploading new TUF root")
subcommands.DieNotNil(api.TufRootUpdatesPut(factory, txid, newCiRoot, newProdRoot, nil))
}
}