1 package cmd
2
3 import (
4 "fmt"
5 "os"
6
7 intoto "github.com/in-toto/in-toto-golang/in_toto"
8 "github.com/spf13/cobra"
9 )
10
11 var (
12 pubKeyPaths []string
13 linkDir string
14 intermediatePaths []string
15 )
16
17 var verifyCmd = &cobra.Command{
18 Use: "verify",
19 Short: "Verify that the software supply chain of the delivered product",
20 Long: `in-toto-verify is the main verification tool of the suite, and
21 it is used to verify that the software supply chain of the delivered
22 product was carried out as defined in the passed in-toto supply chain
23 layout. Evidence for supply chain steps must be available in the form
24 of link metadata files named ‘<step name>.<functionary keyid prefix>.link’.`,
25 RunE: verify,
26 }
27
28 func init() {
29 rootCmd.AddCommand(verifyCmd)
30
31 verifyCmd.Flags().StringVarP(
32 &layoutPath,
33 "layout",
34 "l",
35 "",
36 `Path to root layout specifying the software supply chain to be verified`,
37 )
38
39 verifyCmd.Flags().StringSliceVarP(
40 &pubKeyPaths,
41 "layout-keys",
42 "k",
43 []string{},
44 `Path(s) to PEM formatted public key(s), used to verify the passed
45 root layout's signature(s). Passing at least one key using
46 '--layout-keys' is required. For each passed key the layout
47 must carry a valid signature.`,
48 )
49
50 verifyCmd.Flags().StringVarP(
51 &linkDir,
52 "link-dir",
53 "d",
54 "",
55 `Path to directory where link metadata files for steps defined in
56 the root layout should be loaded from. If not passed links are
57 loaded from the current working directory.`,
58 )
59
60 verifyCmd.Flags().StringSliceVarP(
61 &intermediatePaths,
62 "intermediate-certs",
63 "i",
64 []string{},
65 `Path(s) to PEM formatted certificates, used as intermediaries to verify
66 the chain of trust to the layout's trusted root. These will be used in
67 addition to any intermediates in the layout.`,
68 )
69
70 verifyCmd.MarkFlagRequired("layout")
71 verifyCmd.MarkFlagRequired("layout-keys")
72
73 verifyCmd.Flags().BoolVar(
74 &lineNormalization,
75 "normalize-line-endings",
76 false,
77 `Enable line normalization in order to support different
78 operating systems. It is done by replacing all line separators
79 with a new line character.`,
80 )
81 }
82
83 func verify(cmd *cobra.Command, args []string) error {
84 layoutMb, err := intoto.LoadMetadata(layoutPath)
85 if err != nil {
86 return fmt.Errorf("failed to load layout at %s: %w", layoutPath, err)
87 }
88
89 layoutKeys := make(map[string]intoto.Key, len(pubKeyPaths))
90
91 for _, pubKeyPath := range pubKeyPaths {
92 var pubKey intoto.Key
93
94 if err := pubKey.LoadKeyDefaults(pubKeyPath); err != nil {
95 return fmt.Errorf("invalid key at %s: %w", pubKeyPath, err)
96 }
97
98 layoutKeys[pubKey.KeyID] = pubKey
99 }
100
101 intermediatePems := make([][]byte, 0, len(intermediatePaths))
102 for _, intermediate := range intermediatePaths {
103 pemBytes, err := os.ReadFile(intermediate)
104 if err != nil {
105 return fmt.Errorf("failed to read intermediate %s: %w", intermediate, err)
106 }
107
108 intermediatePems = append(intermediatePems, pemBytes)
109 }
110
111 _, err = intoto.InTotoVerify(layoutMb, layoutKeys, linkDir, "", make(map[string]string), intermediatePems, lineNormalization)
112 if err != nil {
113 return fmt.Errorf("inspection failed: %w", err)
114 }
115
116 return nil
117 }
118
View as plain text