Skip to content

Commit

Permalink
Wire up timestamp authorities option to config. (#162)
Browse files Browse the repository at this point in the history
Adds GITSIGN_TIMESTAMP_AUTHORITY config option for specifying a TSA URL in the gitsign config.
Also adds an e2e test since this is a pain to test without a real TSA.

Note: certain TSA (notably freetsa.org) do not work due to a bug. github/smimesign#118. Trying to fix upstream.
Signed-off-by: Billy Lynch <billy@chainguard.dev>

Signed-off-by: Billy Lynch <billy@chainguard.dev>
  • Loading branch information
wlynch authored Oct 17, 2022
1 parent 5c853c2 commit 175234a
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 30 deletions.
20 changes: 19 additions & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
go-version: 1.19
check-latest: true

- name: Test Sign and Verify commit
- name: Install Gitsign
run: |
set -e
Expand All @@ -72,13 +72,31 @@ jobs:
# Verify tool is on our path
gitsign -h
- name: Test Sign and Verify commit
run: |
set -e
# Sign commit
git commit --allow-empty -S --message="Signed commit"
# Verify commit
git verify-commit HEAD
# Extra debug info
git cat-file commit HEAD | sed -n '/BEGIN/, /END/p' | sed 's/^ //g' | sed 's/gpgsig //g' | sed 's/SIGNED MESSAGE/PKCS7/g' | openssl pkcs7 -print -print_certs -text
- name: Test Timestamped Commit
env:
# See https://knowledge.digicert.com/generalinformation/INFO4231.html
GITSIGN_TIMESTAMP_AUTHORITY: "http://timestamp.digicert.com"
run: |
set -e
# Sign commit
git commit --allow-empty -S --message="Signed timestamp commit"
# Verify commit
git verify-commit HEAD
# Extra debug info
git cat-file commit HEAD | sed -n '/BEGIN/, /END/p' | sed 's/^ //g' | sed 's/gpgsig //g' | sed 's/SIGNED MESSAGE/PKCS7/g' | openssl pkcs7 -print -print_certs -text
- name: Debug log
Expand Down
40 changes: 21 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,30 @@ $ git config --local gitsign.fulcio https://fulcio.example.com

The following config options are supported:

| Option | Default | Description |
| ----------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| fulcio | https://fulcio.sigstore.dev | Address of Fulcio server |
| logPath | | Path to log status output. Helpful for debugging when no TTY is available in the environment. |
| clientID | sigstore | OIDC client ID for application |
| issuer | https://oauth2.sigstore.dev/auth | OIDC provider to be used to issue ID token |
| redirectURL | | OIDC Redirect URL |
| rekor | https://rekor.sigstore.dev | Address of Rekor server |
| connectorID | | Optional Connector ID to auto-select to pre-select auth flow to use. For the public sigstore instance, valid values are:<br>- `https://github.com/login/oauth`<br>- `https://accounts.google.com`<br>- `https://login.microsoftonline.com` |
| Option | Default | Description |
| ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| fulcio | https://fulcio.sigstore.dev | Address of Fulcio server |
| logPath | | Path to log status output. Helpful for debugging when no TTY is available in the environment. |
| clientID | sigstore | OIDC client ID for application |
| issuer | https://oauth2.sigstore.dev/auth | OIDC provider to be used to issue ID token |
| redirectURL | | OIDC Redirect URL |
| rekor | https://rekor.sigstore.dev | Address of Rekor server |
| connectorID | | Optional Connector ID to auto-select to pre-select auth flow to use. For the public sigstore instance, valid values are:<br>- `https://github.com/login/oauth`<br>- `https://accounts.google.com`<br>- `https://login.microsoftonline.com` |
| timestampAuthority | | Optional address of timestamping authority. If set, a trusted timestamp will be included in the signature. |

### Environment Variables

| Environment Variable | Sigstore<br>Prefix | Default | Description |
| ------------------------- | ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| GITSIGN_CREDENTIAL_CACHE || | Optional path to [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) socket. |
| GITSIGN_CONNECTOR_ID || | Optional Connector ID to auto-select to pre-select auth flow to use. For the public sigstore instance, valid values are:<br>- `https://github.com/login/oauth`<br>- `https://accounts.google.com`<br>- `https://login.microsoftonline.com` |
| GITSIGN_FULCIO_URL || https://fulcio.sigstore.dev | Address of Fulcio server |
| GITSIGN_LOG || | Path to log status output. Helpful for debugging when no TTY is available in the environment. |
| GITSIGN_OIDC_CLIENT_ID || sigstore | OIDC client ID for application |
| GITSIGN_OIDC_ISSUER || https://oauth2.sigstore.dev/auth | OIDC provider to be used to issue ID token |
| GITSIGN_OIDC_REDIRECT_URL || | OIDC Redirect URL |
| GITSIGN_REKOR_URL || https://rekor.sigstore.dev | Address of Rekor server |
| Environment Variable | Sigstore<br>Prefix | Default | Description |
| --------------------------- | ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| GITSIGN_CREDENTIAL_CACHE || | Optional path to [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) socket. |
| GITSIGN_CONNECTOR_ID || | Optional Connector ID to auto-select to pre-select auth flow to use. For the public sigstore instance, valid values are:<br>- `https://github.com/login/oauth`<br>- `https://accounts.google.com`<br>- `https://login.microsoftonline.com` |
| GITSIGN_FULCIO_URL || https://fulcio.sigstore.dev | Address of Fulcio server |
| GITSIGN_LOG || | Path to log status output. Helpful for debugging when no TTY is available in the environment. |
| GITSIGN_OIDC_CLIENT_ID || sigstore | OIDC client ID for application |
| GITSIGN_OIDC_ISSUER || https://oauth2.sigstore.dev/auth | OIDC provider to be used to issue ID token |
| GITSIGN_OIDC_REDIRECT_URL || | OIDC Redirect URL |
| GITSIGN_REKOR_URL || https://rekor.sigstore.dev | Address of Rekor server |
| GITSIGN_TIMESTAMP_AUTHORITY || | Optional address of timestamping authority. If set, a trusted timestamp will be included in the signature. |

For environment variables that support `Sigstore Prefix`, the values may be
provided with either a `GITSIGN_` or `SIGSTORE_` prefix - e.g.
Expand Down
2 changes: 1 addition & 1 deletion command_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func commandSign(cfg *config.Config) error {

sig, cert, err := git.Sign(ctx, rekor, userIdent, dataBuf.Bytes(), signature.SignOptions{
Detached: *detachSignFlag,
TimestampAuthority: *tsaOpt,
TimestampAuthority: cfg.TimestampAuthority,
Armor: *armorFlag,
IncludeCerts: *includeCertsOpt,
})
Expand Down
4 changes: 4 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type Config struct {
// for more details.
ConnectorID string

// Timestamp Authority address to use to get a trusted timestamp
TimestampAuthority string

// Path to log status output. Helpful for debugging when no TTY is available in the environment.
LogPath string
}
Expand Down Expand Up @@ -83,6 +86,7 @@ func Get() (*Config, error) {
out.RedirectURL = envOrValue(fmt.Sprintf("%s_OIDC_REDIRECT_URL", prefix), out.RedirectURL)
out.Issuer = envOrValue(fmt.Sprintf("%s_OIDC_ISSUER", prefix), out.Issuer)
out.ConnectorID = envOrValue(fmt.Sprintf("%s_CONNECTOR_ID", prefix), out.ConnectorID)
out.TimestampAuthority = envOrValue(fmt.Sprintf("%s_TIMESTAMP_AUTHORITY", prefix), out.TimestampAuthority)
}

out.LogPath = envOrValue("GITSIGN_LOG", out.LogPath)
Expand Down
4 changes: 2 additions & 2 deletions internal/signature/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ func Sign(ident Identity, body []byte, opts SignOptions) ([]byte, *x509.Certific

chain, err := ident.CertificateChain()
if err != nil {
return nil, nil, fmt.Errorf("failed to get idenity certificate chain: %w", err)
return nil, nil, fmt.Errorf("failed to get identity certificate chain: %w", err)
}
// TODO: look into adding back support for opts.IncludeCerts here.
// This was removed due to unstable ordering in the cert chain when
// intermediates were included.
if chain, err = certsForSignature(chain, 1); err != nil {
return nil, nil, err
return nil, nil, fmt.Errorf("failed to extract certificates from chain: %w", err)
}
if err := sd.SetCertificates(chain); err != nil {
return nil, nil, fmt.Errorf("failed to set certificates: %w", err)
Expand Down
9 changes: 2 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"io"
"os"
"runtime/debug"

"github.com/mattn/go-tty"
"github.com/pborman/getopt/v2"
Expand All @@ -29,11 +30,6 @@ import (
"github.com/sigstore/gitsign/internal/config"
)

const (
// TODO: Use fulcio as timestamp authority.
defaultTSA = ""
)

var (
// Action flags
helpFlag = getopt.BoolLong("help", 'h', "print this help message")
Expand All @@ -46,7 +42,6 @@ var (
detachSignFlag = getopt.BoolLong("detach-sign", 'b', "make a detached signature")
armorFlag = getopt.BoolLong("armor", 'a', "create ascii armored output")
statusFdOpt = getopt.IntLong("status-fd", 0, -1, "write special status strings to the file descriptor n.", "n")
tsaOpt = getopt.StringLong("timestamp-authority", 't', defaultTSA, "URL of RFC3161 timestamp authority to use for timestamping", "url")
includeCertsOpt = getopt.IntLong("include-certs", 0, -2, "-3 is the same as -2, but ommits issuer when cert has Authority Information Access extension. -2 includes all certs except root. -1 includes all certs. 0 includes no certs. 1 includes leaf cert. >1 includes n from the leaf. Default -2.", "n")

// Remaining arguments
Expand Down Expand Up @@ -104,7 +99,7 @@ func wrapIO(cfg *config.Config, fn func(*config.Config) error) error {
// Log any panics to ttyout, since otherwise they will be lost to os.Stderr.
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(ttyout, r)
fmt.Fprintln(ttyout, string(debug.Stack()), r)
}
}()

Expand Down

0 comments on commit 175234a

Please sign in to comment.