| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- //go:build unit
- package service
- import (
- "testing"
- "github.com/Wei-Shaw/sub2api/internal/config"
- "github.com/Wei-Shaw/sub2api/internal/pkg/xai"
- "github.com/stretchr/testify/require"
- )
- func TestGrokAPIKeyURLPolicyFollowsGlobalSecurityConfig(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeAPIKey,
- Credentials: map[string]any{
- "base_url": "http://grok.example.test/v1",
- },
- }
- t.Run("insecure HTTP enabled with allowlist disabled", func(t *testing.T) {
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = false
- cfg.Security.URLAllowlist.AllowInsecureHTTP = true
- responsesURL, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "http://grok.example.test/v1/responses", responsesURL)
- chatURL, err := buildGrokChatCompletionsURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "http://grok.example.test/v1/chat/completions", chatURL)
- mediaURL, err := buildGrokMediaURL(account, cfg, GrokMediaEndpointImagesGenerations, "")
- require.NoError(t, err)
- require.Equal(t, "http://grok.example.test/v1/images/generations", mediaURL)
- contentURL, err := buildGrokMediaURL(account, cfg, GrokMediaEndpointVideoContent, "request 123")
- require.NoError(t, err)
- require.Equal(t, "http://grok.example.test/v1/videos/request%20123/content", contentURL)
- })
- t.Run("insecure HTTP disabled", func(t *testing.T) {
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = false
- cfg.Security.URLAllowlist.AllowInsecureHTTP = false
- _, err := buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- })
- t.Run("enabled allowlist remains HTTPS only", func(t *testing.T) {
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.AllowInsecureHTTP = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"grok.example.test"}
- _, err := buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- })
- }
- func TestGrokAPIKeyURLPolicyAppliesAllowlistAndPrivateHostControls(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeAPIKey,
- Credentials: map[string]any{
- "base_url": "https://grok.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"grok.example.test"}
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "https://grok.example.test/v1/responses", target)
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"other.example.test"}
- _, err = buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- account.Credentials["base_url"] = "https://127.0.0.1/v1"
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"127.0.0.1"}
- _, err = buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- cfg.Security.URLAllowlist.AllowPrivateHosts = true
- target, err = buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "https://127.0.0.1/v1/responses", target)
- }
- func TestGrokAPIKeyURLPolicyRedactsMalformedConfiguredURL(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeAPIKey,
- Credentials: map[string]any{
- "base_url": "https://%zz:secret@grok.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.AllowInsecureHTTP = true
- _, err := buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- require.NotContains(t, err.Error(), "secret")
- }
- func TestGrokOAuthURLPolicy(t *testing.T) {
- t.Run("default CLI gateway always allowed under restrictive allowlist", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{},
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"other.example.test"}
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultCLIBaseURL+"/responses", target)
- })
- t.Run("stored official API endpoint is honored (manual endpoint switch)", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": xai.DefaultBaseURL,
- },
- }
- cfg := &config.Config{}
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultBaseURL+"/responses", target)
- })
- t.Run("stored regional API endpoint is trusted even under restrictive allowlist", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://us-west-2.api.x.ai/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"other.example.test"}
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "https://us-west-2.api.x.ai/v1/responses", target)
- })
- t.Run("custom forwarding address follows operator policy", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://relay.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = false
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "https://relay.example.test/v1/responses", target)
- })
- t.Run("custom path prefix is preserved", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://relay.example.test/xai/v1",
- },
- }
- cfg := &config.Config{}
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "https://relay.example.test/xai/v1/responses", target)
- })
- t.Run("custom forwarding address rejected by allowlist", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://relay.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"other.example.test"}
- _, err := buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- })
- t.Run("insecure HTTP custom address requires operator opt-in", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "http://relay.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = false
- cfg.Security.URLAllowlist.AllowInsecureHTTP = false
- _, err := buildGrokResponsesURL(account, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- cfg.Security.URLAllowlist.AllowInsecureHTTP = true
- target, err := buildGrokResponsesURL(account, cfg)
- require.NoError(t, err)
- require.Equal(t, "http://relay.example.test/v1/responses", target)
- })
- t.Run("unsafe override switch does not relax the operator allowlist for custom hosts", func(t *testing.T) {
- // XAI_ALLOW_UNSAFE_URL_OVERRIDES relaxes the trusted-host validator to
- // accept-any; a custom OAuth forwarding host must still be governed by
- // the operator allowlist so the bearer token cannot reach arbitrary hosts.
- t.Setenv(xai.EnvAllowUnsafeURLOverrides, "true")
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"cli-chat-proxy.grok.com"}
- custom := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "http://10.0.0.1/v1",
- },
- }
- _, err := buildGrokResponsesURL(custom, cfg)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- // The official gateway still resolves even under the restrictive allowlist.
- official := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{},
- }
- target, err := buildGrokResponsesURL(official, cfg)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultCLIBaseURL+"/responses", target)
- })
- }
- func TestBuildGrokBillingURLUsesCLIForOfficialAPIHosts(t *testing.T) {
- for _, baseURL := range []string{xai.DefaultBaseURL, "https://us-west-2.api.x.ai/v1"} {
- account := &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Credentials: map[string]any{"base_url": baseURL}}
- weekly, err := buildGrokBillingURL(account, &config.Config{}, true)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultCLIBaseURL+xai.BillingWeeklyPath, weekly)
- }
- }
- func TestBuildGrokBillingURLKeepsCustomRelay(t *testing.T) {
- account := &Account{Platform: PlatformGrok, Type: AccountTypeOAuth, Credentials: map[string]any{
- "base_url": "https://relay.example.test/xai/v1",
- }}
- monthly, err := buildGrokBillingURL(account, &config.Config{}, false)
- require.NoError(t, err)
- require.Equal(t, "https://relay.example.test/xai/v1"+xai.BillingMonthlyPath, monthly)
- }
- func TestGrokBillingURLFollowsAccountBaseURL(t *testing.T) {
- t.Run("oauth default stays on CLI gateway", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{},
- }
- weeklyURL, err := buildGrokBillingURL(account, nil, true)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultCLIBaseURL+"/billing?format=credits", weeklyURL)
- monthlyURL, err := buildGrokBillingURL(account, nil, false)
- require.NoError(t, err)
- require.Equal(t, xai.DefaultCLIBaseURL+"/billing", monthlyURL)
- })
- t.Run("oauth custom forwarding address carries billing probes", func(t *testing.T) {
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://relay.example.test/v1",
- },
- }
- weeklyURL, err := buildGrokBillingURL(account, nil, true)
- require.NoError(t, err)
- require.Equal(t, "https://relay.example.test/v1/billing?format=credits", weeklyURL)
- })
- t.Run("billing probe honors the operator allowlist like forwarding", func(t *testing.T) {
- // Probe paths must share the forwarding URL policy so a custom host the
- // allowlist rejects cannot receive the OAuth bearer via a billing probe.
- account := &Account{
- Platform: PlatformGrok,
- Type: AccountTypeOAuth,
- Credentials: map[string]any{
- "base_url": "https://relay.example.test/v1",
- },
- }
- cfg := &config.Config{}
- cfg.Security.URLAllowlist.Enabled = true
- cfg.Security.URLAllowlist.UpstreamHosts = []string{"cli-chat-proxy.grok.com"}
- _, err := buildGrokBillingURL(account, cfg, true)
- require.EqualError(t, err, "invalid base url: base URL rejected by URL security policy")
- })
- }
|