mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
246 lines
6.8 KiB
Go
246 lines
6.8 KiB
Go
package config
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestRejectRemovedProxyOptOut(t *testing.T) {
|
||
|
|
cases := []struct {
|
||
|
|
name string
|
||
|
|
configYAML string
|
||
|
|
env map[string]string
|
||
|
|
wantErr bool
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "no config file and no env",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "config without proxy keys",
|
||
|
|
configYAML: "paranoid: false\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "proxy.enabled false in config",
|
||
|
|
configYAML: "proxy:\n enabled: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "proxy.enabled true in config",
|
||
|
|
configYAML: "proxy:\n enabled: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "proxy section without enabled key",
|
||
|
|
configYAML: "proxy:\n install_only: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "legacy proxy_mode false in config",
|
||
|
|
configYAML: "proxy_mode: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "legacy proxy_mode true in config",
|
||
|
|
configYAML: "proxy_mode: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "legacy proxy_mode false ignored when proxy section exists",
|
||
|
|
configYAML: "proxy_mode: false\nproxy:\n install_only: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_ENABLED false in env",
|
||
|
|
env: map[string]string{"PMG_PROXY_ENABLED": "false"},
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_MODE false in env",
|
||
|
|
env: map[string]string{"PMG_PROXY_MODE": "false"},
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "env true wins over config false",
|
||
|
|
configYAML: "proxy:\n enabled: false\n",
|
||
|
|
env: map[string]string{"PMG_PROXY_ENABLED": "true"},
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "unrecognized PMG_PROXY_ENABLED value falls back to proxy default",
|
||
|
|
env: map[string]string{"PMG_PROXY_ENABLED": "off"},
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "proxy.enabled numeric 0 in config",
|
||
|
|
configYAML: "proxy:\n enabled: 0\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "legacy proxy_mode numeric 0 in config",
|
||
|
|
configYAML: "proxy_mode: 0\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_MODE true does not override proxy.enabled false in file",
|
||
|
|
configYAML: "proxy:\n enabled: false\n",
|
||
|
|
env: map[string]string{"PMG_PROXY_MODE": "true"},
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_MODE false is inert when proxy section exists",
|
||
|
|
configYAML: "proxy:\n install_only: true\n",
|
||
|
|
env: map[string]string{"PMG_PROXY_MODE": "false"},
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "null proxy section makes legacy proxy_mode inert",
|
||
|
|
configYAML: "proxy:\nproxy_mode: false\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_MODE true wins over flat proxy_mode false in file",
|
||
|
|
configYAML: "proxy_mode: false\n",
|
||
|
|
env: map[string]string{"PMG_PROXY_MODE": "true"},
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_ENABLED true wins over legacy flat proxy_mode false",
|
||
|
|
configYAML: "proxy_mode: false\n",
|
||
|
|
env: map[string]string{"PMG_PROXY_ENABLED": "true"},
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "capitalized Proxy section with enabled false",
|
||
|
|
configYAML: "Proxy:\n enabled: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "capitalized Enabled key in proxy section",
|
||
|
|
configYAML: "proxy:\n Enabled: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "literal dotted proxy.enabled key",
|
||
|
|
configYAML: "proxy.enabled: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "capitalized legacy Proxy_Mode key",
|
||
|
|
configYAML: "Proxy_Mode: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "literal dotted proxy.enabled true is not an opt-out",
|
||
|
|
configYAML: "proxy.enabled: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "case-variant Proxy section does not gate the legacy flat key",
|
||
|
|
configYAML: "Proxy:\n install_only: true\nproxy_mode: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "dotted proxy.enabled false was overridden by legacy proxy_mode true",
|
||
|
|
configYAML: "proxy.enabled: false\nproxy_mode: true\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "null proxy key with dotted proxy.enabled false is deterministic",
|
||
|
|
configYAML: "proxy:\nproxy.enabled: false\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "PMG_PROXY_MODE unparseable value coerced to false like cast.ToBool",
|
||
|
|
env: map[string]string{"PMG_PROXY_MODE": "off"},
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "flat proxy_mode unparseable value coerced to false",
|
||
|
|
configYAML: "proxy_mode: \"off\"\n",
|
||
|
|
wantErr: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "unrecognized proxy.enabled value falls back to proxy default",
|
||
|
|
configYAML: "proxy:\n enabled: yes\n",
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tc := range cases {
|
||
|
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
t.Setenv("PMG_CONFIG_DIR", tmpDir)
|
||
|
|
|
||
|
|
if tc.configYAML != "" {
|
||
|
|
err := os.WriteFile(filepath.Join(tmpDir, "config.yml"), []byte(tc.configYAML), 0o644)
|
||
|
|
require.NoError(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
for key, value := range tc.env {
|
||
|
|
t.Setenv(key, value)
|
||
|
|
}
|
||
|
|
|
||
|
|
initConfig()
|
||
|
|
|
||
|
|
err := RejectRemovedProxyOptOut()
|
||
|
|
if tc.wantErr {
|
||
|
|
require.Error(t, err)
|
||
|
|
require.Contains(t, err.Error(), "removed proxy opt-out is still configured")
|
||
|
|
} else {
|
||
|
|
require.NoError(t, err)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// A locked (managed) config ignored env vars entirely in the old resolution,
|
||
|
|
// so under lockdown env opt-outs must not trigger and env enables must not
|
||
|
|
// rescue a file opt-out.
|
||
|
|
func TestRejectRemovedProxyOptOutLockedIgnoresEnv(t *testing.T) {
|
||
|
|
t.Run("env opt-out is inert under lockdown", func(t *testing.T) {
|
||
|
|
globalDir := t.TempDir()
|
||
|
|
require.NoError(t, os.WriteFile(filepath.Join(globalDir, "config.yml"), []byte("global_lockdown: true\n"), 0o644))
|
||
|
|
|
||
|
|
useManagedConfigDir(t, globalDir)
|
||
|
|
t.Setenv("PMG_PROXY_ENABLED", "false")
|
||
|
|
initConfig()
|
||
|
|
|
||
|
|
require.True(t, Get().IsLocked())
|
||
|
|
require.NoError(t, RejectRemovedProxyOptOut())
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("env enable cannot rescue a file opt-out under lockdown", func(t *testing.T) {
|
||
|
|
globalDir := t.TempDir()
|
||
|
|
require.NoError(t, os.WriteFile(filepath.Join(globalDir, "config.yml"), []byte("global_lockdown: true\nproxy_mode: false\n"), 0o644))
|
||
|
|
|
||
|
|
useManagedConfigDir(t, globalDir)
|
||
|
|
t.Setenv("PMG_PROXY_ENABLED", "true")
|
||
|
|
t.Setenv("PMG_PROXY_MODE", "true")
|
||
|
|
initConfig()
|
||
|
|
|
||
|
|
require.True(t, Get().IsLocked())
|
||
|
|
require.Error(t, RejectRemovedProxyOptOut())
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// Colliding spellings must resolve the same way on every invocation: map
|
||
|
|
// iteration order varies per parse, so repeat the check to catch order
|
||
|
|
// dependent resolution (this was an observed 42-in-50 flake before).
|
||
|
|
func TestRejectRemovedProxyOptOutDeterministic(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
t.Setenv("PMG_CONFIG_DIR", tmpDir)
|
||
|
|
|
||
|
|
configYAML := "proxy:\nproxy.enabled: false\n"
|
||
|
|
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "config.yml"), []byte(configYAML), 0o644))
|
||
|
|
initConfig()
|
||
|
|
|
||
|
|
for range 25 {
|
||
|
|
require.Error(t, RejectRemovedProxyOptOut())
|
||
|
|
}
|
||
|
|
}
|