58 lines
2.0 KiB
Go
58 lines
2.0 KiB
Go
package identityprovider
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"vpn-platform/backend/internal/store"
|
|
)
|
|
|
|
func TestAdminNeverEchoesFeishuSecretAndKeepsEncryptedValue(t *testing.T) {
|
|
dir := t.TempDir()
|
|
t.Setenv("VPN_DATA_DIR", dir)
|
|
if err := store.Init(dir); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
gin.SetMode(gin.TestMode)
|
|
server := gin.New()
|
|
p := New()
|
|
server.PUT("/config", func(c *gin.Context) { c.Set("username", "admin"); p.Configure(c) })
|
|
server.GET("/config", p.Status)
|
|
body := []byte(`{"app_id":"cli_test","app_secret":"feishu-private-value","tenant_key":"tenant_1","enabled":false}`)
|
|
resp := httptest.NewRecorder()
|
|
request := httptest.NewRequest(http.MethodPut, "/config", bytes.NewReader(body))
|
|
request.RemoteAddr = "127.0.0.1:12345"
|
|
request.Header.Set("X-Forwarded-Proto", "https")
|
|
server.ServeHTTP(resp, request)
|
|
if resp.Code != 200 || strings.Contains(resp.Body.String(), "feishu-private-value") {
|
|
t.Fatalf("unsafe response: %d %s", resp.Code, resp.Body.String())
|
|
}
|
|
rejected := httptest.NewRecorder()
|
|
server.ServeHTTP(rejected, httptest.NewRequest(http.MethodPut, "/config", bytes.NewReader(body)))
|
|
if rejected.Code != http.StatusForbidden {
|
|
t.Fatal("plaintext management request accepted credentials")
|
|
}
|
|
cfg, err := current()
|
|
if err != nil || cfg.AppSecret == "feishu-private-value" {
|
|
t.Fatal("app secret stored in plaintext")
|
|
}
|
|
plain, err := store.DecryptSecret(cfg.AppSecret)
|
|
if err != nil || plain != "feishu-private-value" {
|
|
t.Fatal("app secret not recoverable")
|
|
}
|
|
var saved map[string]any
|
|
if json.Unmarshal(resp.Body.Bytes(), &saved) != nil || saved["client_id"] == "" || saved["client_secret"] != nil {
|
|
t.Fatal("client secret must remain server-side")
|
|
}
|
|
resp = httptest.NewRecorder()
|
|
server.ServeHTTP(resp, httptest.NewRequest(http.MethodGet, "/config", nil))
|
|
if resp.Code != 200 || strings.Contains(resp.Body.String(), "feishu-private-value") || strings.Contains(resp.Body.String(), cfg.ClientSecret) {
|
|
t.Fatal("secret leaked from status")
|
|
}
|
|
}
|