82 lines
2.5 KiB
Go
82 lines
2.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.unkin.net/unkin/artifactapi/internal/testsupport"
|
|
)
|
|
|
|
func serve(h http.Handler, method, token string) int {
|
|
r := httptest.NewRequest(method, "/x", nil)
|
|
if token != "" {
|
|
r.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
return w.Code
|
|
}
|
|
|
|
var ok = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) })
|
|
|
|
func TestBearerOIDC(t *testing.T) {
|
|
iss := testsupport.NewOIDCIssuer()
|
|
defer iss.Close()
|
|
h := NewBearerOIDC(iss.URL, []string{"other", "artifactapi"}).Require(ok)
|
|
|
|
otherKey, _ := rsa.GenerateKey(rand.Reader, 2048)
|
|
cases := []struct {
|
|
name string
|
|
token string
|
|
want int
|
|
}{
|
|
{"valid", iss.Token(nil, "artifactapi", "ci", time.Hour), http.StatusNoContent},
|
|
{"missing", "", http.StatusUnauthorized},
|
|
{"garbage", "not.a.jwt", http.StatusUnauthorized},
|
|
{"bad signature", iss.Token(otherKey, "artifactapi", "ci", time.Hour), http.StatusUnauthorized},
|
|
{"wrong aud", iss.Token(nil, "nope", "ci", time.Hour), http.StatusUnauthorized},
|
|
{"expired", iss.Token(nil, "artifactapi", "ci", -time.Hour), http.StatusUnauthorized},
|
|
}
|
|
for _, c := range cases {
|
|
if got := serve(h, http.MethodPost, c.token); got != c.want {
|
|
t.Errorf("%s: status %d, want %d", c.name, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBearerOIDCIssuerDown(t *testing.T) {
|
|
iss := testsupport.NewOIDCIssuer()
|
|
b := NewBearerOIDC(iss.URL, []string{"artifactapi"})
|
|
tok := iss.Token(nil, "artifactapi", "ci", time.Hour)
|
|
iss.Close()
|
|
if got := serve(b.Require(ok), http.MethodPost, tok); got != http.StatusServiceUnavailable {
|
|
t.Errorf("issuer down: status %d, want 503", got)
|
|
}
|
|
}
|
|
|
|
func TestBearerOIDCDisabled(t *testing.T) {
|
|
if got := serve(NewBearerOIDC("", nil).RequireWrites(ok), http.MethodDelete, ""); got != http.StatusNoContent {
|
|
t.Errorf("disabled: status %d, want 204", got)
|
|
}
|
|
}
|
|
|
|
func TestRequireWritesLeavesReadsOpen(t *testing.T) {
|
|
iss := testsupport.NewOIDCIssuer()
|
|
defer iss.Close()
|
|
h := NewBearerOIDC(iss.URL, []string{"artifactapi"}).RequireWrites(ok)
|
|
for _, m := range []string{http.MethodGet, http.MethodHead, http.MethodOptions} {
|
|
if got := serve(h, m, ""); got != http.StatusNoContent {
|
|
t.Errorf("%s: status %d, want 204", m, got)
|
|
}
|
|
}
|
|
for _, m := range []string{http.MethodPost, http.MethodPut, http.MethodDelete} {
|
|
if got := serve(h, m, ""); got != http.StatusUnauthorized {
|
|
t.Errorf("%s: status %d, want 401", m, got)
|
|
}
|
|
}
|
|
}
|