- Introduced new endpoints for managing identity providers, including retrieval of redirect URIs and testing/syncing providers. - Enhanced organization settings to include identity provider configurations, allowing for self-enrollment and domain restrictions. - Implemented caching for access policies and added validation for identity provider secrets. - Added integration tests to ensure proper functionality of identity provider management and policy enforcement.
189 lines
5.7 KiB
Go
189 lines
5.7 KiB
Go
//go:build integration
|
|
|
|
package admin_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/integrationtest"
|
|
)
|
|
|
|
func TestAdminOrgSettings(t *testing.T) {
|
|
h := integrationtest.RequireHarness(t)
|
|
adminClient, _ := integrationtest.RequireAdminClient(t, h)
|
|
|
|
getResp, err := adminClient.Get("/api/v1/admin/org/settings")
|
|
integrationtest.FailIf(err, t, "get org settings")
|
|
integrationtest.FailUnlessStatus(t, getResp, 200)
|
|
|
|
var initial map[string]any
|
|
integrationtest.DecodeJSON(t, getResp, &initial)
|
|
policy, ok := initial["policy"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing policy: %#v", initial)
|
|
}
|
|
storage, ok := policy["storage_quotas"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing storage_quotas: %#v", policy)
|
|
}
|
|
if storage["default_mail_gib"] == nil {
|
|
t.Fatalf("expected default_mail_gib in policy")
|
|
}
|
|
|
|
putResp, err := adminClient.Put("/api/v1/admin/org/settings", map[string]any{
|
|
"policy": map[string]any{
|
|
"storage_quotas": map[string]any{
|
|
"default_mail_gib": 10,
|
|
},
|
|
"usage_quotas": map[string]any{
|
|
"llm_requests_per_day": 200,
|
|
},
|
|
},
|
|
})
|
|
integrationtest.FailIf(err, t, "put org settings")
|
|
integrationtest.FailUnlessStatus(t, putResp, 200)
|
|
|
|
var updated map[string]any
|
|
integrationtest.DecodeJSON(t, putResp, &updated)
|
|
updatedPolicy, ok := updated["policy"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing policy after update: %#v", updated)
|
|
}
|
|
updatedStorage, ok := updatedPolicy["storage_quotas"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing storage_quotas after update")
|
|
}
|
|
if updatedStorage["default_mail_gib"] != float64(10) {
|
|
t.Fatalf("default_mail_gib = %v, want 10", updatedStorage["default_mail_gib"])
|
|
}
|
|
}
|
|
|
|
func TestAdminOrgSettingsIdentityProvidersSecrets(t *testing.T) {
|
|
h := integrationtest.RequireHarness(t)
|
|
adminClient, _ := integrationtest.RequireAdminClient(t, h)
|
|
|
|
providerID := "test-oauth-provider"
|
|
putResp, err := adminClient.Put("/api/v1/admin/org/settings", map[string]any{
|
|
"policy": map[string]any{
|
|
"identity_providers": map[string]any{
|
|
"allow_self_enrollment": true,
|
|
"providers": []any{
|
|
map[string]any{
|
|
"id": providerID,
|
|
"name": "Google Workspace",
|
|
"slug": "google-workspace",
|
|
"type": "oauth",
|
|
"enabled": true,
|
|
"oauth": map[string]any{
|
|
"provider": "google",
|
|
"client_id": "client-id",
|
|
"client_secret": "super-secret",
|
|
"scopes": "openid email profile",
|
|
},
|
|
"allowed_email_domains": []any{"company.com"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
integrationtest.FailIf(err, t, "put identity providers")
|
|
integrationtest.FailUnlessStatus(t, putResp, 200)
|
|
|
|
var afterPut map[string]any
|
|
integrationtest.DecodeJSON(t, putResp, &afterPut)
|
|
secrets, ok := afterPut["secrets"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing secrets: %#v", afterPut)
|
|
}
|
|
idpSecrets, ok := secrets["identity_providers"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing identity provider secrets: %#v", secrets)
|
|
}
|
|
providerSecrets, ok := idpSecrets[providerID].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing provider secrets entry: %#v", idpSecrets)
|
|
}
|
|
oauthSecret, ok := providerSecrets["oauth_client_secret"].(map[string]any)
|
|
if !ok || oauthSecret["configured"] != true {
|
|
t.Fatalf("oauth secret not configured: %#v", providerSecrets)
|
|
}
|
|
|
|
policy, ok := afterPut["policy"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing policy")
|
|
}
|
|
idpPolicy, ok := policy["identity_providers"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing identity_providers policy")
|
|
}
|
|
providers, ok := idpPolicy["providers"].([]any)
|
|
if !ok || len(providers) != 1 {
|
|
t.Fatalf("expected one provider")
|
|
}
|
|
provider, ok := providers[0].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("invalid provider payload")
|
|
}
|
|
oauth, ok := provider["oauth"].(map[string]any)
|
|
if !ok || oauth["client_secret"] != "" {
|
|
t.Fatalf("client_secret should be masked on GET")
|
|
}
|
|
}
|
|
|
|
func TestAdminOrgSettingsVirusTotalSecret(t *testing.T) {
|
|
h := integrationtest.RequireHarness(t)
|
|
adminClient, _ := integrationtest.RequireAdminClient(t, h)
|
|
|
|
putResp, err := adminClient.Put("/api/v1/admin/org/settings", map[string]any{
|
|
"policy": map[string]any{
|
|
"file_policies": map[string]any{
|
|
"virus_scan_enabled": true,
|
|
"virustotal_api_key": "vt-test-secret-key",
|
|
},
|
|
},
|
|
})
|
|
integrationtest.FailIf(err, t, "put org settings with virustotal key")
|
|
integrationtest.FailUnlessStatus(t, putResp, 200)
|
|
|
|
var afterPut map[string]any
|
|
integrationtest.DecodeJSON(t, putResp, &afterPut)
|
|
secrets, ok := afterPut["secrets"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing secrets: %#v", afterPut)
|
|
}
|
|
vtSecret, ok := secrets["virustotal_api_key"].(map[string]any)
|
|
if !ok || vtSecret["configured"] != true {
|
|
t.Fatalf("virustotal_api_key not configured: %#v", secrets)
|
|
}
|
|
filePolicies, ok := afterPut["policy"].(map[string]any)["file_policies"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing file_policies")
|
|
}
|
|
if filePolicies["virustotal_api_key"] != "" {
|
|
t.Fatalf("virustotal_api_key should be masked on GET, got %q", filePolicies["virustotal_api_key"])
|
|
}
|
|
|
|
// Empty patch must preserve stored secret.
|
|
preserveResp, err := adminClient.Put("/api/v1/admin/org/settings", map[string]any{
|
|
"policy": map[string]any{
|
|
"file_policies": map[string]any{
|
|
"virus_scan_enabled": false,
|
|
"virustotal_api_key": "",
|
|
},
|
|
},
|
|
})
|
|
integrationtest.FailIf(err, t, "preserve virustotal key")
|
|
integrationtest.FailUnlessStatus(t, preserveResp, 200)
|
|
|
|
var preserved map[string]any
|
|
integrationtest.DecodeJSON(t, preserveResp, &preserved)
|
|
preservedSecrets, ok := preserved["secrets"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("missing secrets after preserve")
|
|
}
|
|
vtPreserved, ok := preservedSecrets["virustotal_api_key"].(map[string]any)
|
|
if !ok || vtPreserved["configured"] != true {
|
|
t.Fatalf("virustotal key not preserved: %#v", preservedSecrets)
|
|
}
|
|
}
|