89 lines
2.6 KiB
Go
89 lines
2.6 KiB
Go
|
|
package signer
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestSignDSSE_HappyPath(t *testing.T) {
|
||
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if r.URL.Path != "/api/v1/sign/dsse" {
|
||
|
|
t.Errorf("unexpected path %q", r.URL.Path)
|
||
|
|
}
|
||
|
|
if got := r.Header.Get("Authorization"); got != "Bearer tok" {
|
||
|
|
t.Errorf("auth header = %q", got)
|
||
|
|
}
|
||
|
|
var body signRequest
|
||
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||
|
|
t.Fatalf("decode: %v", err)
|
||
|
|
}
|
||
|
|
if body.KeyRef != "key-x" {
|
||
|
|
t.Errorf("keyRef = %q", body.KeyRef)
|
||
|
|
}
|
||
|
|
resp := signResponse{
|
||
|
|
Envelope: Envelope{PayloadType: "application/vnd.in-toto+json", Payload: "aGk"},
|
||
|
|
ContentHash: "sha256:deadbeef",
|
||
|
|
SignedAt: time.Now(),
|
||
|
|
}
|
||
|
|
w.Header().Set("Content-Type", "application/json")
|
||
|
|
_ = json.NewEncoder(w).Encode(resp)
|
||
|
|
}))
|
||
|
|
defer srv.Close()
|
||
|
|
|
||
|
|
c := Client{BaseURL: srv.URL, TokenSource: StaticToken("tok")}
|
||
|
|
env, hash, err := c.SignDSSE(context.Background(), "key-x", Statement{"_type": "x"})
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("SignDSSE: %v", err)
|
||
|
|
}
|
||
|
|
if hash != "sha256:deadbeef" {
|
||
|
|
t.Errorf("hash = %q", hash)
|
||
|
|
}
|
||
|
|
if env.PayloadType != "application/vnd.in-toto+json" {
|
||
|
|
t.Errorf("payloadType = %q", env.PayloadType)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignDSSE_5xxMapsToUnavailable(t *testing.T) {
|
||
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||
|
|
http.Error(w, "boom", http.StatusInternalServerError)
|
||
|
|
}))
|
||
|
|
defer srv.Close()
|
||
|
|
c := Client{BaseURL: srv.URL}
|
||
|
|
_, _, err := c.SignDSSE(context.Background(), "k", Statement{"_type": "x"})
|
||
|
|
if !errors.Is(err, ErrSignerUnavailable) {
|
||
|
|
t.Fatalf("want ErrSignerUnavailable, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignDSSE_ConnRefusedMapsToUnavailable(t *testing.T) {
|
||
|
|
// Nonexistent address — the dial will fail immediately.
|
||
|
|
c := Client{
|
||
|
|
BaseURL: "http://127.0.0.1:1", // reserved, almost always refused
|
||
|
|
HTTPClient: &http.Client{Timeout: 500 * time.Millisecond},
|
||
|
|
}
|
||
|
|
_, _, err := c.SignDSSE(context.Background(), "k", Statement{"_type": "x"})
|
||
|
|
if !errors.Is(err, ErrSignerUnavailable) {
|
||
|
|
t.Fatalf("want ErrSignerUnavailable, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignDSSE_4xxDoesNotLookUnavailable(t *testing.T) {
|
||
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusForbidden)
|
||
|
|
}))
|
||
|
|
defer srv.Close()
|
||
|
|
c := Client{BaseURL: srv.URL}
|
||
|
|
_, _, err := c.SignDSSE(context.Background(), "k", Statement{"_type": "x"})
|
||
|
|
if err == nil {
|
||
|
|
t.Fatalf("expected error")
|
||
|
|
}
|
||
|
|
if errors.Is(err, ErrSignerUnavailable) {
|
||
|
|
t.Fatalf("4xx must not be reported as ErrSignerUnavailable: %v", err)
|
||
|
|
}
|
||
|
|
}
|