package main import ( "context" omni "git.yuntuo.hk/k2safe/go-omni" "git.yuntuo.hk/k2safe/go-omni/auth" "git.yuntuo.hk/k2safe/go-omni/config" "git.yuntuo.hk/k2safe/go-omni/internal/testutil" "git.yuntuo.hk/k2safe/go-omni/storage/local" "git.yuntuo.hk/k2safe/go-omni/telemetry" "io" "net" "net/http" "strings" "testing" "time" ) func TestPlatformTLSAdapters(t *testing.T) { for _, name := range []string{omni.TransportNetHTTP, omni.TransportNative, omni.TransportHTTP2} { t.Run(name, func(t *testing.T) { cfg := config.Default() cfg.Transport = name cert, key, tlsClient := testutil.CertificateFiles(t) cfg.TLS = config.TLSConfig{CertFile: cert, KeyFile: key} store, _ := local.New(t.TempDir(), 64<<10) tr, _ := telemetry.New(telemetry.Config{Service: "platformTest", SampleRatio: 1}) defer tr.Close() app, err := newApp(cfg, dependencies{Files: store, Auth: auth.StaticAuthenticator{"writer": {UserID: "u", TenantID: "t", Roles: []string{"writer"}}, "reader": {UserID: "r", TenantID: "t"}}, Tracing: tr}) if err != nil { t.Fatal(err) } listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(context.Background()) done := make(chan error, 1) go func() { done <- app.ServeContext(ctx, listener) }() defer func() { cancel() select { case err := <-done: if err != nil { t.Error(err) } case <-time.After(5 * time.Second): listener.Close() t.Error("shutdown timeout") } }() client := &http.Client{Timeout: 3 * time.Second, Transport: &http.Transport{TLSClientConfig: tlsClient, ForceAttemptHTTP2: true}} defer client.CloseIdleConnections() request := func(method, path, body, token string) (int, string) { t.Helper() r, _ := http.NewRequest(method, "https://"+listener.Addr().String()+path, strings.NewReader(body)) r.Header.Set("Authorization", "Bearer "+token) r.Header.Set("Content-Type", "application/json") response, err := client.Do(r) if err != nil { t.Fatal(err) } raw, err := io.ReadAll(response.Body) response.Body.Close() if err != nil { t.Fatal(err) } if response.TLS == nil || len(response.TLS.VerifiedChains) == 0 { t.Fatal("TLS unverified") } if name == omni.TransportHTTP2 && response.ProtoMajor != 2 { t.Fatal("protocol") } return response.StatusCode, string(raw) } for _, test := range []struct { token string status int }{{"", 401}, {"reader", 403}, {"writer", 201}} { status, body := request("POST", "/api/files", `{"name":"hello.txt","content":"hello"}`, test.token) if status != test.status { t.Fatal(status, body) } } object, err := store.Get(context.Background(), "t/hello.txt") if err != nil { t.Fatal(err) } raw, _ := io.ReadAll(object.Body) object.Body.Close() if string(raw) != "hello" { t.Fatal(string(raw)) } if status, _ := request("POST", "/api/files", `{"name":"../escape","content":"x"}`, "writer"); status != 400 { t.Fatal(status) } if status, body := request("GET", "/openapi.json", "", "writer"); status != 200 || !strings.Contains(body, `"/api/files"`) { t.Fatal(status, body) } }) } }