Skip to content

Commit

Permalink
Allow parsing of certificates from Fulcio if ctlog is disabled (#288)
Browse files Browse the repository at this point in the history
* Allow parsing of certificates from Fulcio if ctlog is disabled

Signed-off-by: Cody Soyland <[email protected]>

* Change if/else to switch

Signed-off-by: Cody Soyland <[email protected]>

* Add test for detached sct

Signed-off-by: Cody Soyland <[email protected]>

---------

Signed-off-by: Cody Soyland <[email protected]>
  • Loading branch information
codysoyland authored Oct 16, 2024
1 parent 7f63a20 commit 8a157ab
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
18 changes: 14 additions & 4 deletions pkg/sign/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,18 @@ type publicKey struct {
}

type fulcioResponse struct {
SctCertWithChain signedCertificateEmbeddedSct `json:"signedCertificateEmbeddedSct"`
SignedCertificateEmbeddedSct signedCertificateEmbeddedSct `json:"signedCertificateEmbeddedSct"`
SignedCertificateDetachedSct signedCertificateDetachedSct `json:"signedCertificateDetachedSct"`
}

type signedCertificateEmbeddedSct struct {
Chain chain `json:"chain"`
}

type signedCertificateDetachedSct struct {
Chain chain `json:"chain"`
}

type chain struct {
Certificates []string `json:"certificates"`
}
Expand Down Expand Up @@ -204,12 +209,17 @@ func (f *Fulcio) GetCertificate(ctx context.Context, keypair Keypair, opts *Cert
return nil, err
}

certs := fulcioResp.SctCertWithChain.Chain.Certificates
if len(certs) == 0 {
var cert []byte
switch {
case len(fulcioResp.SignedCertificateEmbeddedSct.Chain.Certificates) > 0:
cert = []byte(fulcioResp.SignedCertificateEmbeddedSct.Chain.Certificates[0])
case len(fulcioResp.SignedCertificateDetachedSct.Chain.Certificates) > 0:
cert = []byte(fulcioResp.SignedCertificateDetachedSct.Chain.Certificates[0])
default:
return nil, errors.New("Fulcio returned no certificates")
}

certBlock, _ := pem.Decode([]byte(certs[0]))
certBlock, _ := pem.Decode(cert)
if certBlock == nil {
return nil, errors.New("unable to parse Fulcio certificate")
}
Expand Down
43 changes: 32 additions & 11 deletions pkg/sign/certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func setupVirtualSigstore() {
}
}

func getFulcioResponse() (*http.Response, error) {
func getFulcioResponse(detachedSct bool) (*http.Response, error) {
virtualSigstoreOnce.Do(setupVirtualSigstore)
if virtualSigstoreErr != nil {
return nil, virtualSigstoreErr
Expand All @@ -55,14 +55,24 @@ func getFulcioResponse() (*http.Response, error) {
Bytes: leafCert.Raw,
}))

responseStruct := fulcioResponse{
SctCertWithChain: signedCertificateEmbeddedSct{
Chain: chain{
Certificates: []string{certPEM},
var responseStruct fulcioResponse
if detachedSct {
responseStruct = fulcioResponse{
SignedCertificateDetachedSct: signedCertificateDetachedSct{
Chain: chain{
Certificates: []string{certPEM},
},
},
},
}
} else {
responseStruct = fulcioResponse{
SignedCertificateEmbeddedSct: signedCertificateEmbeddedSct{
Chain: chain{
Certificates: []string{certPEM},
},
},
}
}

fulcioJSON, err := json.Marshal(responseStruct)
if err != nil {
return nil, err
Expand All @@ -76,14 +86,17 @@ func getFulcioResponse() (*http.Response, error) {
return response, nil
}

type mockFulcio struct{}
type mockFulcio struct {
detachedSct bool
}

func (m *mockFulcio) RoundTrip(_ *http.Request) (*http.Response, error) {
return getFulcioResponse()
return getFulcioResponse(m.detachedSct)
}

type failFirstFulcio struct {
Count int
Count int
detachedSct bool
}

func (f *failFirstFulcio) RoundTrip(_ *http.Request) (*http.Response, error) {
Expand All @@ -96,7 +109,7 @@ func (f *failFirstFulcio) RoundTrip(_ *http.Request) (*http.Response, error) {
return response, nil
}

return getFulcioResponse()
return getFulcioResponse(f.detachedSct)
}

func Test_GetCertificate(t *testing.T) {
Expand Down Expand Up @@ -135,4 +148,12 @@ func Test_GetCertificate(t *testing.T) {
cert, err = retryFulcio.GetCertificate(ctx, keypair, certOpts)
assert.Nil(t, cert)
assert.NotNil(t, err)

// Test detached SCT
detachedOpts := &FulcioOptions{Retries: 1, Transport: &mockFulcio{detachedSct: true}}
detachedFulcio := NewFulcio(detachedOpts)

cert, err = detachedFulcio.GetCertificate(ctx, keypair, certOpts)
assert.NotNil(t, cert)
assert.NoError(t, err)
}

0 comments on commit 8a157ab

Please sign in to comment.