github.com/crowdsecurity/crowdsec@v1.6.1/pkg/csconfig/api_test.go (about) 1 package csconfig 2 3 import ( 4 "net" 5 "os" 6 "strings" 7 "testing" 8 9 log "github.com/sirupsen/logrus" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "gopkg.in/yaml.v3" 13 14 "github.com/crowdsecurity/go-cs-lib/cstest" 15 "github.com/crowdsecurity/go-cs-lib/ptr" 16 ) 17 18 func TestLoadLocalApiClientCfg(t *testing.T) { 19 tests := []struct { 20 name string 21 input *LocalApiClientCfg 22 expected *ApiCredentialsCfg 23 expectedErr string 24 }{ 25 { 26 name: "basic valid configuration", 27 input: &LocalApiClientCfg{ 28 CredentialsFilePath: "./testdata/lapi-secrets.yaml", 29 }, 30 expected: &ApiCredentialsCfg{ 31 URL: "http://localhost:8080/", 32 Login: "test", 33 Password: "testpassword", 34 }, 35 }, 36 { 37 name: "invalid configuration", 38 input: &LocalApiClientCfg{ 39 CredentialsFilePath: "./testdata/bad_lapi-secrets.yaml", 40 }, 41 expected: &ApiCredentialsCfg{}, 42 expectedErr: "field unknown_key not found in type csconfig.ApiCredentialsCfg", 43 }, 44 { 45 name: "invalid configuration filepath", 46 input: &LocalApiClientCfg{ 47 CredentialsFilePath: "./testdata/nonexist_lapi-secrets.yaml", 48 }, 49 expected: nil, 50 expectedErr: "open ./testdata/nonexist_lapi-secrets.yaml: " + cstest.FileNotFoundMessage, 51 }, 52 { 53 name: "valid configuration with insecure skip verify", 54 input: &LocalApiClientCfg{ 55 CredentialsFilePath: "./testdata/lapi-secrets.yaml", 56 InsecureSkipVerify: ptr.Of(false), 57 }, 58 expected: &ApiCredentialsCfg{ 59 URL: "http://localhost:8080/", 60 Login: "test", 61 Password: "testpassword", 62 }, 63 }, 64 } 65 66 for _, tc := range tests { 67 tc := tc 68 t.Run(tc.name, func(t *testing.T) { 69 err := tc.input.Load() 70 cstest.RequireErrorContains(t, err, tc.expectedErr) 71 72 if tc.expectedErr != "" { 73 return 74 } 75 76 assert.Equal(t, tc.expected, tc.input.Credentials) 77 }) 78 } 79 } 80 81 func TestLoadOnlineApiClientCfg(t *testing.T) { 82 tests := []struct { 83 name string 84 input *OnlineApiClientCfg 85 expected *ApiCredentialsCfg 86 expectedErr string 87 }{ 88 { 89 name: "basic valid configuration", 90 input: &OnlineApiClientCfg{ 91 CredentialsFilePath: "./testdata/online-api-secrets.yaml", 92 }, 93 expected: &ApiCredentialsCfg{ 94 URL: "http://crowdsec.api", 95 Login: "test", 96 Password: "testpassword", 97 }, 98 }, 99 { 100 name: "invalid configuration", 101 input: &OnlineApiClientCfg{ 102 CredentialsFilePath: "./testdata/bad_lapi-secrets.yaml", 103 }, 104 expected: &ApiCredentialsCfg{}, 105 expectedErr: "failed unmarshaling api server credentials", 106 }, 107 { 108 name: "missing field configuration", 109 input: &OnlineApiClientCfg{ 110 CredentialsFilePath: "./testdata/bad_online-api-secrets.yaml", 111 }, 112 expected: nil, 113 }, 114 { 115 name: "invalid configuration filepath", 116 input: &OnlineApiClientCfg{ 117 CredentialsFilePath: "./testdata/nonexist_online-api-secrets.yaml", 118 }, 119 expected: &ApiCredentialsCfg{}, 120 expectedErr: "open ./testdata/nonexist_online-api-secrets.yaml: " + cstest.FileNotFoundMessage, 121 }, 122 } 123 124 for _, tc := range tests { 125 tc := tc 126 t.Run(tc.name, func(t *testing.T) { 127 err := tc.input.Load() 128 cstest.RequireErrorContains(t, err, tc.expectedErr) 129 130 if tc.expectedErr != "" { 131 return 132 } 133 134 assert.Equal(t, tc.expected, tc.input.Credentials) 135 }) 136 } 137 } 138 139 func TestLoadAPIServer(t *testing.T) { 140 tmpLAPI := &LocalApiServerCfg{ 141 ProfilesPath: "./testdata/profiles.yaml", 142 } 143 err := tmpLAPI.LoadProfiles() 144 require.NoError(t, err) 145 146 logLevel := log.InfoLevel 147 config := &Config{} 148 fcontent, err := os.ReadFile("./testdata/config.yaml") 149 require.NoError(t, err) 150 151 configData := os.ExpandEnv(string(fcontent)) 152 153 dec := yaml.NewDecoder(strings.NewReader(configData)) 154 dec.KnownFields(true) 155 156 err = dec.Decode(&config) 157 require.NoError(t, err) 158 159 tests := []struct { 160 name string 161 input *Config 162 expected *LocalApiServerCfg 163 expectedErr string 164 }{ 165 { 166 name: "basic valid configuration", 167 input: &Config{ 168 Self: []byte(configData), 169 API: &APICfg{ 170 Server: &LocalApiServerCfg{ 171 ListenURI: "http://crowdsec.api", 172 OnlineClient: &OnlineApiClientCfg{ 173 CredentialsFilePath: "./testdata/online-api-secrets.yaml", 174 }, 175 ProfilesPath: "./testdata/profiles.yaml", 176 PapiLogLevel: &logLevel, 177 }, 178 }, 179 DbConfig: &DatabaseCfg{ 180 Type: "sqlite", 181 DbPath: "./testdata/test.db", 182 }, 183 Common: &CommonCfg{ 184 LogDir: "./testdata", 185 LogMedia: "stdout", 186 }, 187 DisableAPI: false, 188 }, 189 expected: &LocalApiServerCfg{ 190 Enable: ptr.Of(true), 191 ListenURI: "http://crowdsec.api", 192 TLS: nil, 193 DbConfig: &DatabaseCfg{ 194 DbPath: "./testdata/test.db", 195 Type: "sqlite", 196 MaxOpenConns: ptr.Of(DEFAULT_MAX_OPEN_CONNS), 197 UseWal: ptr.Of(true), // autodetected 198 DecisionBulkSize: defaultDecisionBulkSize, 199 }, 200 ConsoleConfigPath: DefaultConfigPath("console.yaml"), 201 ConsoleConfig: &ConsoleConfig{ 202 ShareManualDecisions: ptr.Of(false), 203 ShareTaintedScenarios: ptr.Of(true), 204 ShareCustomScenarios: ptr.Of(true), 205 ShareContext: ptr.Of(false), 206 ConsoleManagement: ptr.Of(false), 207 }, 208 LogDir: "./testdata", 209 LogMedia: "stdout", 210 OnlineClient: &OnlineApiClientCfg{ 211 CredentialsFilePath: "./testdata/online-api-secrets.yaml", 212 Credentials: &ApiCredentialsCfg{ 213 URL: "http://crowdsec.api", 214 Login: "test", 215 Password: "testpassword", 216 }, 217 }, 218 Profiles: tmpLAPI.Profiles, 219 ProfilesPath: "./testdata/profiles.yaml", 220 UseForwardedForHeaders: false, 221 PapiLogLevel: &logLevel, 222 }, 223 }, 224 { 225 name: "basic invalid configuration", 226 input: &Config{ 227 Self: []byte(configData), 228 API: &APICfg{ 229 Server: &LocalApiServerCfg{ 230 ListenURI: "http://crowdsec.api", 231 }, 232 }, 233 Common: &CommonCfg{ 234 LogDir: "./testdata/", 235 LogMedia: "stdout", 236 }, 237 DisableAPI: false, 238 }, 239 expected: &LocalApiServerCfg{ 240 Enable: ptr.Of(true), 241 PapiLogLevel: &logLevel, 242 }, 243 expectedErr: "no database configuration provided", 244 }, 245 } 246 247 for _, tc := range tests { 248 tc := tc 249 t.Run(tc.name, func(t *testing.T) { 250 err := tc.input.LoadAPIServer(false) 251 cstest.RequireErrorContains(t, err, tc.expectedErr) 252 253 if tc.expectedErr != "" { 254 return 255 } 256 257 assert.Equal(t, tc.expected, tc.input.API.Server) 258 }) 259 } 260 } 261 262 func mustParseCIDRNet(t *testing.T, s string) *net.IPNet { 263 _, ipNet, err := net.ParseCIDR(s) 264 require.NoError(t, err) 265 266 return ipNet 267 } 268 269 func TestParseCapiWhitelists(t *testing.T) { 270 tests := []struct { 271 name string 272 input string 273 expected *CapiWhitelist 274 expectedErr string 275 }{ 276 { 277 name: "empty file", 278 input: "", 279 expected: &CapiWhitelist{ 280 Ips: []net.IP{}, 281 Cidrs: []*net.IPNet{}, 282 }, 283 expectedErr: "empty file", 284 }, 285 { 286 name: "empty ip and cidr", 287 input: `{"ips": [], "cidrs": []}`, 288 expected: &CapiWhitelist{ 289 Ips: []net.IP{}, 290 Cidrs: []*net.IPNet{}, 291 }, 292 }, 293 { 294 name: "some ip", 295 input: `{"ips": ["1.2.3.4"]}`, 296 expected: &CapiWhitelist{ 297 Ips: []net.IP{net.IPv4(1, 2, 3, 4)}, 298 Cidrs: []*net.IPNet{}, 299 }, 300 }, 301 { 302 name: "some cidr", 303 input: `{"cidrs": ["1.2.3.0/24"]}`, 304 expected: &CapiWhitelist{ 305 Ips: []net.IP{}, 306 Cidrs: []*net.IPNet{mustParseCIDRNet(t, "1.2.3.0/24")}, 307 }, 308 }, 309 } 310 311 for _, tc := range tests { 312 tc := tc 313 t.Run(tc.name, func(t *testing.T) { 314 wl, err := parseCapiWhitelists(strings.NewReader(tc.input)) 315 cstest.RequireErrorContains(t, err, tc.expectedErr) 316 317 if tc.expectedErr != "" { 318 return 319 } 320 321 assert.Equal(t, tc.expected, wl) 322 }) 323 } 324 }