- Network-policy SPIRE plugin extension - Governance event notification with merkle anchoring - Shellstream specs for consent channels + HFL embedded ABI - All 17 audit findings from AUDIT.md remediated - SSH credential composer + substrate key manager updates - Test coverage for config + sshcert packages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
145 lines
4.1 KiB
Go
145 lines
4.1 KiB
Go
package oidc
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewVerifierRequiresIssuer(t *testing.T) {
|
|
_, err := NewVerifier(Config{})
|
|
if err == nil {
|
|
t.Fatal("expected error for empty issuer")
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierRequiresHTTPSIssuer(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
issuer string
|
|
wantErr string
|
|
}{
|
|
{"http rejected", "http://accounts.example.com", "https://"},
|
|
{"file rejected", "file:///etc/keys", "https://"},
|
|
{"empty scheme", "accounts.example.com", "https://"},
|
|
{"https accepted", "https://accounts.example.com", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
_, err := NewVerifier(Config{Issuer: tt.issuer, Audience: "spire"})
|
|
if tt.wantErr == "" {
|
|
// Should pass issuer validation (may still fail with "not yet implemented")
|
|
if err != nil && strings.Contains(err.Error(), "https://") {
|
|
t.Fatalf("issuer %q should be accepted, got: %v", tt.issuer, err)
|
|
}
|
|
} else {
|
|
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
|
t.Fatalf("issuer %q: expected error containing %q, got: %v", tt.issuer, tt.wantErr, err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierRejectsNonURLIssuer(t *testing.T) {
|
|
// A string with no scheme gets scheme "" which isn't https
|
|
_, err := NewVerifier(Config{Issuer: "not-a-url", Audience: "spire"})
|
|
if err == nil {
|
|
t.Fatal("expected error for non-URL issuer")
|
|
}
|
|
if !strings.Contains(err.Error(), "https://") {
|
|
t.Errorf("expected https scheme error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierRequiresAudience(t *testing.T) {
|
|
_, err := NewVerifier(Config{Issuer: "https://accounts.example.com"})
|
|
if err == nil {
|
|
t.Fatal("expected error for empty audience")
|
|
}
|
|
if !strings.Contains(err.Error(), "audience is required") {
|
|
t.Errorf("expected audience error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierValidatesJWKSURL(t *testing.T) {
|
|
_, err := NewVerifier(Config{
|
|
Issuer: "https://accounts.example.com",
|
|
Audience: "spire",
|
|
JWKSURL: "http://insecure.example.com/keys",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error for http JWKS URL")
|
|
}
|
|
if !strings.Contains(err.Error(), "https://") {
|
|
t.Errorf("expected https scheme error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierAcceptsHTTPSJWKSURL(t *testing.T) {
|
|
_, err := NewVerifier(Config{
|
|
Issuer: "https://accounts.example.com",
|
|
Audience: "spire",
|
|
JWKSURL: "https://keys.example.com/.well-known/jwks.json",
|
|
})
|
|
// Should pass URL validation (may fail with "not yet implemented")
|
|
if err != nil && strings.Contains(err.Error(), "https://") {
|
|
t.Fatalf("valid JWKS URL should be accepted, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNewVerifierNotYetImplemented(t *testing.T) {
|
|
_, err := NewVerifier(Config{
|
|
Issuer: "https://accounts.example.com",
|
|
Audience: "spire",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected not-yet-implemented error")
|
|
}
|
|
if !strings.Contains(err.Error(), "not yet implemented") {
|
|
t.Errorf("expected not-yet-implemented, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateAudienceMatch(t *testing.T) {
|
|
err := ValidateAudience([]string{"api", "spire", "web"}, "spire")
|
|
if err != nil {
|
|
t.Fatalf("expected audience match, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateAudienceMismatch(t *testing.T) {
|
|
err := ValidateAudience([]string{"api", "web"}, "spire")
|
|
if err == nil {
|
|
t.Fatal("expected error for audience mismatch")
|
|
}
|
|
if !strings.Contains(err.Error(), "does not contain") {
|
|
t.Errorf("expected audience mismatch error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateAudienceEmptyExpected(t *testing.T) {
|
|
err := ValidateAudience([]string{"spire"}, "")
|
|
if err == nil {
|
|
t.Fatal("expected error for empty expected audience")
|
|
}
|
|
if !strings.Contains(err.Error(), "must not be empty") {
|
|
t.Errorf("expected empty audience error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateAudienceEmptyList(t *testing.T) {
|
|
err := ValidateAudience(nil, "spire")
|
|
if err == nil {
|
|
t.Fatal("expected error for empty audience list")
|
|
}
|
|
}
|
|
|
|
func TestRequireHTTPSNoHost(t *testing.T) {
|
|
err := requireHTTPS("https://", "test")
|
|
if err == nil {
|
|
t.Fatal("expected error for URL with no host")
|
|
}
|
|
if !strings.Contains(err.Error(), "no host") {
|
|
t.Errorf("expected no-host error, got: %v", err)
|
|
}
|
|
}
|