Skip to content

Commit e4ec0f5

Browse files
authored
Port gitsign-attest to cobra subcommand. (#195)
Signed-off-by: Billy Lynch <billy@chainguard.dev> Signed-off-by: Billy Lynch <billy@chainguard.dev>
1 parent ce5a1ad commit e4ec0f5

File tree

14 files changed

+144
-90
lines changed

14 files changed

+144
-90
lines changed

cmd/gitsign-attest/main.go

Lines changed: 0 additions & 85 deletions
This file was deleted.

docs/cli/gitsign.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ gitsign [flags]
2222

2323
### SEE ALSO
2424

25+
* [gitsign attest](gitsign_attest.md) - add attestations to Git objects
2526
* [gitsign show](gitsign_show.md) - Show source predicate information
2627
* [gitsign version](gitsign_version.md) - print Gitsign version
2728

28-
###### Auto generated by spf13/cobra on 21-Nov-2022
29+
###### Auto generated by spf13/cobra on 26-Nov-2022

docs/cli/gitsign_attest.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## gitsign attest
2+
3+
add attestations to Git objects
4+
5+
```
6+
gitsign attest [flags]
7+
```
8+
9+
### Options
10+
11+
```
12+
-f, --filepath string attestation filepath
13+
-h, --help help for attest
14+
--objtype string [commit | tree] - Git object type to attest (default "commit")
15+
--type string specify a predicate type (slsaprovenance|link|spdx|spdxjson|cyclonedx|vuln|custom) or an URI (default "custom")
16+
```
17+
18+
### SEE ALSO
19+
20+
* [gitsign](gitsign.md) - Keyless Git signing with Sigstore!
21+
22+
###### Auto generated by spf13/cobra on 26-Nov-2022

docs/cli/gitsign_show.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ gitsign show [revision] [flags]
2626

2727
* [gitsign](gitsign.md) - Keyless Git signing with Sigstore!
2828

29-
###### Auto generated by spf13/cobra on 21-Nov-2022
29+
###### Auto generated by spf13/cobra on 26-Nov-2022

docs/cli/gitsign_version.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ gitsign version [flags]
1616

1717
* [gitsign](gitsign.md) - Keyless Git signing with Sigstore!
1818

19-
###### Auto generated by spf13/cobra on 21-Nov-2022
19+
###### Auto generated by spf13/cobra on 26-Nov-2022

cmd/gitsign-attest/README.md renamed to internal/commands/attest/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ f44de7a (HEAD -> main) commit
3030
2b0ff1e commit 1
3131
760568f initial commit
3232
$ gitsign-attest -f test.json
33-
$ gitsign-attest -f spdx.sbom -type spdx
33+
$ gitsign-attest -f spdx.sbom --type spdx
3434
$ git checkout refs/attestations/commits
3535
$ tree
3636
.
@@ -51,7 +51,7 @@ preserve attestations for squash commits, or between sub-directories.
5151
```sh
5252
$ git log --oneline --format="Commit: %h Tree: %t" -1
5353
Commit: edd19d9 Tree: 853a6ca
54-
$ gitsign-attest -f test.json -t
54+
$ gitsign-attest -f test.json --objtype tree
5555
$ git checkout refs/attestations/trees
5656
$ tree .
5757
.

internal/commands/attest/attest.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2022 The Sigstore Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package attest
16+
17+
import (
18+
"context"
19+
"fmt"
20+
21+
"github.com/go-git/go-git/v5"
22+
cosignopts "github.com/sigstore/cosign/cmd/cosign/cli/options"
23+
"github.com/sigstore/cosign/cmd/cosign/cli/sign"
24+
"github.com/sigstore/cosign/pkg/cosign"
25+
"github.com/sigstore/gitsign/internal/attest"
26+
"github.com/sigstore/gitsign/internal/config"
27+
"github.com/spf13/cobra"
28+
)
29+
30+
const (
31+
attCommitRef = "refs/attestations/commits"
32+
attTreeRef = "refs/attestations/trees"
33+
34+
FlagObjectTypeCommit = "commit"
35+
FlagObjectTypeTree = "tree"
36+
)
37+
38+
type options struct {
39+
Config *config.Config
40+
41+
FlagObjectType string
42+
FlagPath string
43+
FlagAttestationType string
44+
}
45+
46+
func (o *options) AddFlags(cmd *cobra.Command) {
47+
cmd.Flags().StringVar(&o.FlagObjectType, "objtype", FlagObjectTypeCommit, "[commit | tree] - Git object type to attest")
48+
cmd.Flags().StringVarP(&o.FlagPath, "filepath", "f", "", "attestation filepath")
49+
cmd.Flags().StringVar(&o.FlagAttestationType, "type", "", `specify a predicate type (slsaprovenance|link|spdx|spdxjson|cyclonedx|vuln|custom) or an URI (default "custom")`)
50+
}
51+
52+
func (o *options) Run(ctx context.Context) error {
53+
repo, err := git.PlainOpen(".")
54+
if err != nil {
55+
return fmt.Errorf("error opening repo: %w", err)
56+
}
57+
58+
head, err := repo.Head()
59+
if err != nil {
60+
return fmt.Errorf("error getting repository head: %w", err)
61+
}
62+
63+
// If we're attaching the attestation to a tree, resolve the tree SHA.
64+
sha := head.Hash()
65+
refName := attCommitRef
66+
if o.FlagObjectType == FlagObjectTypeTree {
67+
commit, err := repo.CommitObject(head.Hash())
68+
if err != nil {
69+
return fmt.Errorf("error getting tree: %w", err)
70+
}
71+
sha = commit.TreeHash
72+
73+
refName = attTreeRef
74+
}
75+
76+
sv, err := sign.SignerFromKeyOpts(ctx, "", "", cosignopts.KeyOpts{
77+
FulcioURL: o.Config.Fulcio,
78+
RekorURL: o.Config.Rekor,
79+
OIDCIssuer: o.Config.Issuer,
80+
OIDCClientID: o.Config.ClientID,
81+
})
82+
if err != nil {
83+
return fmt.Errorf("getting signer: %w", err)
84+
}
85+
defer sv.Close()
86+
87+
attestor := attest.NewAttestor(repo, sv, cosign.TLogUploadInTotoAttestation)
88+
89+
out, err := attestor.WriteFile(ctx, refName, sha, o.FlagPath, o.FlagAttestationType)
90+
if err != nil {
91+
return err
92+
}
93+
fmt.Println(out)
94+
95+
return nil
96+
}
97+
98+
func New(cfg *config.Config) *cobra.Command {
99+
o := &options{
100+
Config: cfg,
101+
}
102+
cmd := &cobra.Command{
103+
Use: "attest",
104+
Short: "add attestations to Git objects",
105+
Args: cobra.ArbitraryArgs,
106+
RunE: func(cmd *cobra.Command, args []string) error {
107+
ctx := context.Background()
108+
return o.Run(ctx)
109+
},
110+
}
111+
o.AddFlags(cmd)
112+
113+
return cmd
114+
}

internal/commands/root/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package root
1818
import (
1919
"github.com/spf13/cobra"
2020

21+
"github.com/sigstore/gitsign/internal/commands/attest"
2122
"github.com/sigstore/gitsign/internal/commands/show"
2223
"github.com/sigstore/gitsign/internal/commands/version"
2324
"github.com/sigstore/gitsign/internal/config"
@@ -82,6 +83,7 @@ func New(cfg *config.Config) *cobra.Command {
8283

8384
rootCmd.AddCommand(version.New(cfg))
8485
rootCmd.AddCommand(show.New(cfg))
86+
rootCmd.AddCommand(attest.New(cfg))
8587
o.AddFlags(rootCmd)
8688

8789
return rootCmd

0 commit comments

Comments
 (0)