实现首轮协议与 Transit 签名 PoC

This commit is contained in:
2026-09-11 15:52:19 +00:00
parent cc30a7cb6a
commit ab5dbebca7
13 changed files with 1023 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
package httpapi
import (
"errors"
"net/http"
"github.com/go-chi/chi/v5"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
type Endpoints struct {
Metadata http.Handler
Token http.Handler
JWKS http.Handler
Health http.Handler
Ready http.Handler
}
type Telemetry struct {
TracerProvider trace.TracerProvider
MeterProvider metric.MeterProvider
Propagators propagation.TextMapPropagator
}
func NewRouter(endpoints Endpoints, telemetry Telemetry) (http.Handler, error) {
if endpoints.Metadata == nil || endpoints.Token == nil || endpoints.JWKS == nil || endpoints.Health == nil || endpoints.Ready == nil {
return nil, errors.New("all HTTP endpoints are required")
}
router := chi.NewRouter()
router.Get("/.well-known/oauth-authorization-server", endpoints.Metadata.ServeHTTP)
router.Post("/oauth2/token", endpoints.Token.ServeHTTP)
router.Get("/oauth2/jwks", endpoints.JWKS.ServeHTTP)
router.Get("/healthz", endpoints.Health.ServeHTTP)
router.Get("/readyz", endpoints.Ready.ServeHTTP)
options := make([]otelhttp.Option, 0, 3)
if telemetry.TracerProvider != nil {
options = append(options, otelhttp.WithTracerProvider(telemetry.TracerProvider))
}
if telemetry.MeterProvider != nil {
options = append(options, otelhttp.WithMeterProvider(telemetry.MeterProvider))
}
if telemetry.Propagators != nil {
options = append(options, otelhttp.WithPropagators(telemetry.Propagators))
}
return otelhttp.NewHandler(router, "workload-sts.http", options...), nil
}
+95
View File
@@ -0,0 +1,95 @@
package httpapi
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
)
func TestRouterExposesOnlySpecifiedMethods(t *testing.T) {
endpoint := http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
response.WriteHeader(http.StatusNoContent)
})
router, err := NewRouter(Endpoints{
Metadata: endpoint,
Token: endpoint,
JWKS: endpoint,
Health: endpoint,
Ready: endpoint,
}, Telemetry{})
if err != nil {
t.Fatalf("NewRouter() error = %v", err)
}
tests := []struct {
method string
path string
status int
}{
{http.MethodGet, "/.well-known/oauth-authorization-server", http.StatusNoContent},
{http.MethodPost, "/oauth2/token", http.StatusNoContent},
{http.MethodGet, "/oauth2/jwks", http.StatusNoContent},
{http.MethodGet, "/healthz", http.StatusNoContent},
{http.MethodGet, "/readyz", http.StatusNoContent},
{http.MethodGet, "/oauth2/token", http.StatusMethodNotAllowed},
{http.MethodPost, "/oauth2/jwks", http.StatusMethodNotAllowed},
{http.MethodGet, "/unknown", http.StatusNotFound},
}
for _, test := range tests {
t.Run(test.method+" "+test.path, func(t *testing.T) {
request := httptest.NewRequest(test.method, test.path, nil)
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != test.status {
t.Fatalf("status = %d, want %d", response.Code, test.status)
}
})
}
}
func TestRouterRequiresEveryEndpoint(t *testing.T) {
if _, err := NewRouter(Endpoints{}, Telemetry{}); err == nil {
t.Fatal("NewRouter() error = nil, want missing endpoint error")
}
}
func TestRouterTelemetryDoesNotCaptureCredentialValues(t *testing.T) {
const canary = "canary-secret-token"
recorder := tracetest.NewSpanRecorder()
tracerProvider := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(recorder))
t.Cleanup(func() { _ = tracerProvider.Shutdown(t.Context()) })
endpoint := http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
response.WriteHeader(http.StatusNoContent)
})
router, err := NewRouter(Endpoints{
Metadata: endpoint,
Token: endpoint,
JWKS: endpoint,
Health: endpoint,
Ready: endpoint,
}, Telemetry{TracerProvider: tracerProvider})
if err != nil {
t.Fatalf("NewRouter() error = %v", err)
}
request := httptest.NewRequest(http.MethodGet, "/oauth2/jwks?subject_token="+canary, nil)
request.Header.Set("Authorization", "Bearer "+canary)
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
spans := recorder.Ended()
if len(spans) != 1 {
t.Fatalf("ended spans = %d, want 1", len(spans))
}
for _, attribute := range spans[0].Attributes() {
if strings.Contains(attribute.Value.Emit(), canary) {
t.Fatalf("span attribute %q captured credential canary", attribute.Key)
}
}
}