-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Final challenge result removal 🎉 (#626)
* Move uri principal to package Signed-off-by: Nathan Smith <[email protected]> * Move username principal to package Signed-off-by: Nathan Smith <[email protected]>
- Loading branch information
Showing
6 changed files
with
588 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,246 +16,17 @@ | |
package challenges | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"crypto" | ||
"crypto/ecdsa" | ||
"crypto/elliptic" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/sha256" | ||
"crypto/x509" | ||
"encoding/asn1" | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
"testing" | ||
|
||
"github.com/coreos/go-oidc/v3/oidc" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/sigstore/fulcio/pkg/config" | ||
"github.com/sigstore/sigstore/pkg/cryptoutils" | ||
) | ||
|
||
func TestEmbedChallengeResult(t *testing.T) { | ||
tests := map[string]struct { | ||
Challenge ChallengeResult | ||
WantErr bool | ||
WantFacts map[string]func(x509.Certificate) error | ||
}{ | ||
`Good URI value`: { | ||
Challenge: ChallengeResult{ | ||
Issuer: `foo.example.com`, | ||
TypeVal: URIValue, | ||
Value: "https://foo.example.com", | ||
}, | ||
WantErr: false, | ||
WantFacts: map[string]func(x509.Certificate) error{ | ||
`Issuer is foo.example.com`: factIssuerIs(`foo.example.com`), | ||
`SAN is https://foo.example.com`: func(cert x509.Certificate) error { | ||
WantURI, err := url.Parse("https://foo.example.com") | ||
if err != nil { | ||
return err | ||
} | ||
if len(cert.URIs) != 1 { | ||
return errors.New("no URI SAN set") | ||
} | ||
if diff := cmp.Diff(cert.URIs[0], WantURI); diff != "" { | ||
return errors.New(diff) | ||
} | ||
return nil | ||
}, | ||
}, | ||
}, | ||
`Bad URI value fails`: { | ||
Challenge: ChallengeResult{ | ||
Issuer: `foo.example.com`, | ||
TypeVal: URIValue, | ||
Value: "\nnoooooo", | ||
}, | ||
WantErr: true, | ||
}, | ||
`Good username value`: { | ||
Challenge: ChallengeResult{ | ||
Issuer: `foo.example.com`, | ||
TypeVal: UsernameValue, | ||
Value: "[email protected]", | ||
}, | ||
WantErr: false, | ||
WantFacts: map[string]func(x509.Certificate) error{ | ||
`Issuer is foo.example.com`: factIssuerIs(`foo.example.com`), | ||
`SAN is [email protected]`: func(cert x509.Certificate) error { | ||
if len(cert.EmailAddresses) != 1 { | ||
return errors.New("no email SAN set") | ||
} | ||
if cert.EmailAddresses[0] != "[email protected]" { | ||
return errors.New("wrong email") | ||
} | ||
return nil | ||
}, | ||
}, | ||
}, | ||
`No issuer should fail to render extensions`: { | ||
Challenge: ChallengeResult{ | ||
Issuer: ``, | ||
TypeVal: URIValue, | ||
Value: "https://foo.example.com/foo/bar", | ||
}, | ||
WantErr: true, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
var cert x509.Certificate | ||
err := test.Challenge.Embed(context.TODO(), &cert) | ||
if err != nil { | ||
if !test.WantErr { | ||
t.Error(err) | ||
} | ||
return | ||
} else if test.WantErr { | ||
t.Error("expected error") | ||
} | ||
for factName, fact := range test.WantFacts { | ||
t.Run(factName, func(t *testing.T) { | ||
if err := fact(cert); err != nil { | ||
t.Error(err) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func factIssuerIs(issuer string) func(x509.Certificate) error { | ||
return factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, issuer) | ||
} | ||
|
||
func factExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { | ||
return func(cert x509.Certificate) error { | ||
for _, ext := range cert.ExtraExtensions { | ||
if ext.Id.Equal(oid) { | ||
if !bytes.Equal(ext.Value, []byte(value)) { | ||
return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, ext.Value) | ||
} | ||
return nil | ||
} | ||
} | ||
return errors.New("extension not set") | ||
} | ||
} | ||
|
||
func TestURI(t *testing.T) { | ||
cfg := &config.FulcioConfig{ | ||
OIDCIssuers: map[string]config.OIDCIssuer{ | ||
"https://accounts.example.com": { | ||
IssuerURL: "https://accounts.example.com", | ||
ClientID: "sigstore", | ||
SubjectDomain: "https://example.com", | ||
Type: config.IssuerTypeURI, | ||
}, | ||
}, | ||
} | ||
ctx := config.With(context.Background(), cfg) | ||
subject := "https://example.com/users/1" | ||
issuer := "https://accounts.example.com" | ||
token := &oidc.IDToken{Subject: subject, Issuer: issuer} | ||
|
||
principal, err := uri(ctx, token) | ||
if err != nil { | ||
t.Errorf("Expected test success, got %v", err) | ||
} | ||
if principal.Name(ctx) != token.Subject { | ||
t.Errorf("Expected subject %v, got %v", token.Subject, principal.Name(ctx)) | ||
} | ||
raw, ok := principal.(*ChallengeResult) | ||
if !ok { | ||
t.Fatal("expected principal to be a ChallengeResult") | ||
} | ||
if raw.Issuer != issuer { | ||
t.Errorf("Expected issuer %s, got %s", issuer, raw.Issuer) | ||
} | ||
if raw.Value != subject { | ||
t.Errorf("Expected subject value %s, got %s", subject, raw.Value) | ||
} | ||
if raw.TypeVal != URIValue { | ||
t.Errorf("Expected type %v, got %v", URIValue, raw.TypeVal) | ||
} | ||
if raw.subject != token.Subject { | ||
t.Errorf("Expected subject %v, got %v", token.Subject, raw.subject) | ||
} | ||
} | ||
|
||
func TestUsername(t *testing.T) { | ||
cfg := &config.FulcioConfig{ | ||
OIDCIssuers: map[string]config.OIDCIssuer{ | ||
"https://accounts.example.com": { | ||
IssuerURL: "https://accounts.example.com", | ||
ClientID: "sigstore", | ||
SubjectDomain: "example.com", | ||
Type: config.IssuerTypeUsername, | ||
}, | ||
}, | ||
} | ||
ctx := config.With(context.Background(), cfg) | ||
usernameVal := "foobar" | ||
usernameWithEmail := "[email protected]" | ||
issuer := "https://accounts.example.com" | ||
token := &oidc.IDToken{Subject: usernameVal, Issuer: issuer} | ||
|
||
principal, err := username(ctx, token) | ||
if err != nil { | ||
t.Errorf("Expected test success, got %v", err) | ||
} | ||
if principal.Name(ctx) != token.Subject { | ||
t.Errorf("Expected subject %s, got %s", token.Subject, principal.Name(ctx)) | ||
} | ||
raw, ok := principal.(*ChallengeResult) | ||
if !ok { | ||
t.Fatal("expected principal to be a ChallengeResult") | ||
} | ||
|
||
if raw.Issuer != issuer { | ||
t.Errorf("Expected issuer %s, got %s", issuer, raw.Issuer) | ||
} | ||
if raw.Value != usernameWithEmail { | ||
t.Errorf("Expected subject value %s, got %s", usernameWithEmail, raw.Value) | ||
} | ||
if raw.TypeVal != UsernameValue { | ||
t.Errorf("Expected type %v, got %v", UsernameValue, raw.TypeVal) | ||
} | ||
if raw.subject != token.Subject { | ||
t.Errorf("Expected subject %s, got %s", token.Subject, raw.subject) | ||
} | ||
} | ||
|
||
func TestUsernameInvalidChar(t *testing.T) { | ||
cfg := &config.FulcioConfig{ | ||
OIDCIssuers: map[string]config.OIDCIssuer{ | ||
"https://accounts.example.com": { | ||
IssuerURL: "https://accounts.example.com", | ||
ClientID: "sigstore", | ||
SubjectDomain: "example.com", | ||
Type: config.IssuerTypeUsername, | ||
}, | ||
}, | ||
} | ||
ctx := config.With(context.Background(), cfg) | ||
usernameVal := "[email protected]" | ||
issuer := "https://accounts.example.com" | ||
token := &oidc.IDToken{Subject: usernameVal, Issuer: issuer} | ||
|
||
_, err := username(ctx, token) | ||
if err == nil { | ||
t.Errorf("expected test failure, got no error") | ||
} | ||
msg := "username cannot contain @ character" | ||
if err.Error() != msg { | ||
t.Errorf("unexpected test failure message, got %s, expected %s", err.Error(), msg) | ||
} | ||
} | ||
|
||
func failErr(t *testing.T, err error) { | ||
if err != nil { | ||
t.Fatal(err) | ||
|
Oops, something went wrong.