update tests
This commit is contained in:
parent
72ff2fbc12
commit
60a5aa3800
10 changed files with 898 additions and 96 deletions
|
@ -1,7 +1,6 @@
|
||||||
package cwapi
|
package cwapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -169,20 +168,13 @@ func (ctx *ApiCtx) Signin() error {
|
||||||
func (ctx *ApiCtx) RegisterMachine(machineID string, password string) error {
|
func (ctx *ApiCtx) RegisterMachine(machineID string, password string) error {
|
||||||
ctx.Creds.User = machineID
|
ctx.Creds.User = machineID
|
||||||
ctx.Creds.Password = password
|
ctx.Creds.Password = password
|
||||||
|
jsonResp := &ApiResp{}
|
||||||
|
|
||||||
req, err := ctx.Http.New().Post(ctx.RegisterPath).BodyJSON(ctx.Creds).Request()
|
resp, err := ctx.Http.Post(ctx.RegisterPath).BodyJSON(ctx.Creds).ReceiveSuccess(jsonResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("api register machine: HTTP request creation failed: %s", err)
|
return fmt.Errorf("api register machine: HTTP request creation failed: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("api register: URL: '%s'", req.URL)
|
|
||||||
|
|
||||||
httpClient := http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, err := httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api register machine: API call failed : %s", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("api register machine: unable to read API response body: %s", err.Error())
|
return fmt.Errorf("api register machine: unable to read API response body: %s", err.Error())
|
||||||
|
@ -192,10 +184,8 @@ func (ctx *ApiCtx) RegisterMachine(machineID string, password string) error {
|
||||||
return fmt.Errorf("api register machine: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
return fmt.Errorf("api register machine: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonResp := ApiResp{}
|
if jsonResp.Message == "" || jsonResp.Message != "OK" || jsonResp.StatusCode != 200 {
|
||||||
err = json.Unmarshal(body, &jsonResp)
|
return fmt.Errorf("api signin failed. http response: %s", body)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api register machine: unable to unmarshall api response '%s': %s", string(body), err.Error())
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -203,19 +193,14 @@ func (ctx *ApiCtx) RegisterMachine(machineID string, password string) error {
|
||||||
func (ctx *ApiCtx) ResetPassword(machineID string, password string) error {
|
func (ctx *ApiCtx) ResetPassword(machineID string, password string) error {
|
||||||
ctx.Creds.User = machineID
|
ctx.Creds.User = machineID
|
||||||
ctx.Creds.Password = password
|
ctx.Creds.Password = password
|
||||||
|
jsonResp := &ApiResp{}
|
||||||
|
|
||||||
data := map[string]string{"machine_id": ctx.Creds.User, "password": ctx.Creds.Password}
|
data := map[string]string{"machine_id": ctx.Creds.User, "password": ctx.Creds.Password}
|
||||||
req, err := ctx.Http.New().Post(ctx.ResetPwdPath).BodyJSON(data).Request()
|
resp, err := ctx.Http.Post(ctx.ResetPwdPath).BodyJSON(data).ReceiveSuccess(jsonResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("api reset password: HTTP request creation failed: %s", err)
|
return fmt.Errorf("api reset password: HTTP request creation failed: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("api reset: URL: '%s'", req.URL)
|
|
||||||
|
|
||||||
httpClient := http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, err := httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api reset password: API call failed : %s", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
@ -227,13 +212,8 @@ func (ctx *ApiCtx) ResetPassword(machineID string, password string) error {
|
||||||
return fmt.Errorf("api reset password: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
return fmt.Errorf("api reset password: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonResp := ApiResp{}
|
if jsonResp.Message == "" || jsonResp.Message != "password updated successfully" || jsonResp.StatusCode != 200 {
|
||||||
err = json.Unmarshal(body, &jsonResp)
|
return fmt.Errorf("api signin failed. http response: %s", body)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api reset password: unable to unmarshall api response '%s': %s", string(body), err.Error())
|
|
||||||
}
|
|
||||||
if jsonResp.StatusCode != 200 {
|
|
||||||
return fmt.Errorf("api reset password: return bad HTTP code (%d): %s", jsonResp.StatusCode, string(body))
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,51 @@
|
||||||
package cwapi
|
package cwapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dghubble/sling"
|
"github.com/dghubble/sling"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/tomb.v2"
|
"gopkg.in/tomb.v2"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const configFile = "./tests/api_config.yaml"
|
func assertConfigFileEqual(t *testing.T, filepath1 string, filepath2 string) {
|
||||||
const apiVersion = "v1"
|
file1, err := ioutil.ReadFile(filepath1)
|
||||||
const apiURL = "https://my_test_endpoint"
|
if err != nil {
|
||||||
|
t.Fatalf("unable to read file '%s': %s", filepath1, err)
|
||||||
var apiBaseURL = fmt.Sprintf("%s/%s/", apiURL, apiVersion)
|
|
||||||
|
|
||||||
var httpClientMock = &http.Client{
|
|
||||||
Transport: newMockTransport(),
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockTransport struct{}
|
|
||||||
|
|
||||||
func newMockTransport() http.RoundTripper {
|
|
||||||
return &mockTransport{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement http.RoundTripper
|
|
||||||
func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
var responseBody string
|
|
||||||
var statusCode int
|
|
||||||
// Create mocked http.Response
|
|
||||||
response := &http.Response{
|
|
||||||
Header: make(http.Header),
|
|
||||||
Request: req,
|
|
||||||
}
|
}
|
||||||
response.Header.Set("Content-Type", "application/json")
|
apiCtx1 := &ApiCtx{}
|
||||||
if req.URL.Path == "/v1/signin" {
|
if err := yaml.UnmarshalStrict(file1, &apiCtx1); err != nil {
|
||||||
responseBody = `{"statusCode": 200, "message": "crowdsec_api_token"}`
|
t.Fatalf("unable to unmarshall configuration file '%s' : %s", filepath1, err)
|
||||||
statusCode = 200
|
|
||||||
}
|
}
|
||||||
response.StatusCode = statusCode
|
|
||||||
response.Body = ioutil.NopCloser(strings.NewReader(responseBody))
|
file2, err := ioutil.ReadFile(filepath2)
|
||||||
return response, nil
|
if err != nil {
|
||||||
|
t.Fatalf("unable to read file '%s': %s", filepath2, err)
|
||||||
|
}
|
||||||
|
apiCtx2 := &ApiCtx{}
|
||||||
|
if err := yaml.UnmarshalStrict(file2, &apiCtx2); err != nil {
|
||||||
|
t.Fatalf("unable to unmarshall configuration file '%s' : %s", filepath2, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, apiCtx1, apiCtx2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSignin(t *testing.T) {
|
func TestWriteConfig(t *testing.T) {
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
apiCtx *ApiCtx
|
name string
|
||||||
err error
|
configPath string
|
||||||
|
compareToFile string
|
||||||
|
expectedErr bool
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
apiCtx: &ApiCtx{
|
name: "basic write config",
|
||||||
|
configPath: "./tests/tmp_api_config.yaml",
|
||||||
|
compareToFile: "./tests/api_config.yaml",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
ApiVersion: "v1",
|
ApiVersion: "v1",
|
||||||
PullPath: "pull",
|
PullPath: "pull",
|
||||||
PushPath: "signals",
|
PushPath: "signals",
|
||||||
|
@ -62,6 +54,237 @@ func TestSignin(t *testing.T) {
|
||||||
ResetPwdPath: "resetpassword",
|
ResetPwdPath: "resetpassword",
|
||||||
EnrollPath: "enroll",
|
EnrollPath: "enroll",
|
||||||
BaseURL: "https://my_testendpoint.com",
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "test",
|
||||||
|
CfgPassword: "test",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "test",
|
||||||
|
Password: "test",
|
||||||
|
},
|
||||||
|
Muted: false,
|
||||||
|
DebugDump: false,
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
err := test.givenAPICtx.WriteConfig(test.configPath)
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an error", test.name)
|
||||||
|
}
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' returned an error", test.name)
|
||||||
|
}
|
||||||
|
if test.expectedErr {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
assertConfigFileEqual(t, test.configPath, test.compareToFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
configPath string
|
||||||
|
expectedErr bool
|
||||||
|
expectedAPICtx *ApiCtx
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic load config",
|
||||||
|
configPath: "./tests/api_config.yaml",
|
||||||
|
expectedErr: false,
|
||||||
|
expectedAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PullPath: "pull",
|
||||||
|
PushPath: "signals",
|
||||||
|
SigninPath: "signin",
|
||||||
|
RegisterPath: "register",
|
||||||
|
ResetPwdPath: "resetpassword",
|
||||||
|
EnrollPath: "enroll",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "test",
|
||||||
|
CfgPassword: "test",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "test",
|
||||||
|
Password: "test",
|
||||||
|
},
|
||||||
|
Muted: false,
|
||||||
|
DebugDump: false,
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "load config with bad api version",
|
||||||
|
configPath: "./tests/api_config_bad_api_version.yaml",
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "load config with bad format file",
|
||||||
|
configPath: "./tests/api_config_bad_format.yaml",
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
apiCtx := &ApiCtx{}
|
||||||
|
err := apiCtx.LoadConfig(test.configPath)
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an error", test.name)
|
||||||
|
}
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' return an error : %s", test.name, err)
|
||||||
|
}
|
||||||
|
if test.expectedErr {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
apiCtx.Http = test.expectedAPICtx.Http // if we don't do that, assert will fail
|
||||||
|
assert.Equal(t, test.expectedAPICtx, apiCtx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignin(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
|
expectedErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic api signin",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
SigninPath: "signin",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin missing credentials",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
SigninPath: "signin",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin unknown api PATH",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
SigninPath: "unknown_path",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin malformed response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
SigninPath: "malformed_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin bad response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
SigninPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
err := test.givenAPICtx.Signin()
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' failed : %s", test.name, err)
|
||||||
|
}
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an err", test.name)
|
||||||
|
}
|
||||||
|
log.Printf("test '%s' : OK", test.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterMachine(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
|
expectedErr bool
|
||||||
|
expectedAPICtx *ApiCtx
|
||||||
|
expectedAPICreds *ApiCreds
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic api register machine",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
RegisterPath: "register",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
expectedAPICreds: &ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api register unknown api PATH",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
RegisterPath: "unknown_path",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
CfgUser: "machine_id",
|
CfgUser: "machine_id",
|
||||||
CfgPassword: "machine_password",
|
CfgPassword: "machine_password",
|
||||||
Creds: ApiCreds{
|
Creds: ApiCreds{
|
||||||
|
@ -69,27 +292,160 @@ func TestSignin(t *testing.T) {
|
||||||
Password: "machine_password",
|
Password: "machine_password",
|
||||||
Profile: "crowdsec/test1,crowdsec/test2",
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
},
|
},
|
||||||
Muted: false,
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
DebugDump: false,
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api register malformed response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
RegisterPath: "malformed_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
PusherTomb: tomb.Tomb{},
|
PusherTomb: tomb.Tomb{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "api register bad response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
RegisterPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if err := test.apiCtx.Signin(); err != nil {
|
err := test.givenAPICtx.RegisterMachine(test.givenAPICtx.CfgUser, test.givenAPICtx.CfgPassword)
|
||||||
t.Fatalf(err.Error())
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' failed : %s", test.name, err)
|
||||||
}
|
}
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an err", test.name)
|
||||||
|
}
|
||||||
|
if test.expectedAPICreds != nil {
|
||||||
|
assert.Equal(t, *test.expectedAPICreds, test.givenAPICtx.Creds)
|
||||||
|
}
|
||||||
|
log.Printf("test '%s' : OK", test.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func TestRegister(t *testing.T) {
|
func TestResetPassword(t *testing.T) {
|
||||||
prepTest()
|
|
||||||
|
|
||||||
if err := apiCtx.RegisterMachine(); err != nil {
|
tests := []struct {
|
||||||
t.Fatalf(err.Error())
|
name string
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
|
expectedErr bool
|
||||||
|
expectedAPICtx *ApiCtx
|
||||||
|
expectedAPICreds *ApiCreds
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic api machine reset password",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
ResetPwdPath: "resetpassword",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "new_machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
expectedAPICreds: &ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "new_machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api reset password unknown api PATH",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
ResetPwdPath: "unknown_path",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api reset password malformed response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
ResetPwdPath: "malformed_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
PusherTomb: tomb.Tomb{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api reset password bad response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
ResetPwdPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api reset password unknown user",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
ResetPwdPath: "resestpassword_unknown_user",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
err := test.givenAPICtx.ResetPassword(test.givenAPICtx.CfgUser, test.givenAPICtx.CfgPassword)
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' failed : %s", test.name, err)
|
||||||
|
}
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an err", test.name)
|
||||||
|
}
|
||||||
|
if test.expectedAPICreds != nil {
|
||||||
|
assert.Equal(t, *test.expectedAPICreds, test.givenAPICtx.Creds)
|
||||||
|
}
|
||||||
|
log.Printf("test '%s' : OK", test.name)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -3,25 +3,18 @@ package cwapi
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ctx *ApiCtx) Enroll(userID string) error {
|
func (ctx *ApiCtx) Enroll(userID string) error {
|
||||||
toPush := map[string]string{"user_id": userID}
|
toPush := map[string]string{"user_id": userID}
|
||||||
|
jsonResp := &ApiResp{}
|
||||||
|
|
||||||
req, err := ctx.Http.New().Post(ctx.EnrollPath).BodyJSON(&toPush).Request()
|
resp, err := ctx.Http.Post(ctx.EnrollPath).BodyJSON(&toPush).ReceiveSuccess(jsonResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("api enroll: HTTP request creation failed: %s", err)
|
return fmt.Errorf("api enroll: HTTP request creation failed: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("api enroll: URL: '%s'", req.URL)
|
|
||||||
httpClient := http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, err := httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api enroll: API call failed : %s", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -31,6 +24,9 @@ func (ctx *ApiCtx) Enroll(userID string) error {
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
return fmt.Errorf("api enroll: user '%s' return bad HTTP code (%d): %s", userID, resp.StatusCode, string(body))
|
return fmt.Errorf("api enroll: user '%s' return bad HTTP code (%d): %s", userID, resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
if jsonResp.Message == "" || jsonResp.Message != "OK" || jsonResp.StatusCode != 200 {
|
||||||
|
return fmt.Errorf("api user enroll failed. http response: %s", body)
|
||||||
|
}
|
||||||
log.Printf("user '%s' is enrolled successfully", string(userID))
|
log.Printf("user '%s' is enrolled successfully", string(userID))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
103
pkg/cwapi/enroll_test.go
Normal file
103
pkg/cwapi/enroll_test.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package cwapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/dghubble/sling"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnroll(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
|
expectedErr bool
|
||||||
|
userID string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic api user enroll",
|
||||||
|
expectedErr: false,
|
||||||
|
userID: "1234",
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
EnrollPath: "enroll",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin unknown api PATH",
|
||||||
|
expectedErr: true,
|
||||||
|
userID: "1234",
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
EnrollPath: "unknown_path",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin malformed response",
|
||||||
|
expectedErr: true,
|
||||||
|
userID: "1234",
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
EnrollPath: "malformed_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api signin bad response",
|
||||||
|
expectedErr: true,
|
||||||
|
userID: "1234",
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
EnrollPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
Http: sling.New().Client(httpClientMock).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
err := test.givenAPICtx.Enroll(test.userID)
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' failed : %s", test.name, err)
|
||||||
|
}
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an err", test.name)
|
||||||
|
}
|
||||||
|
log.Printf("test '%s' : OK", test.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
@ -22,18 +21,11 @@ func (ctx *ApiCtx) pushSignals() error {
|
||||||
if len(ctx.toPush) == 0 {
|
if len(ctx.toPush) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
jsonResp := &ApiResp{}
|
||||||
req, err := ctx.Http.New().Put(ctx.PushPath).BodyJSON(&ctx.toPush).Request()
|
resp, err := ctx.Http.New().Put(ctx.PushPath).BodyJSON(&ctx.toPush).ReceiveSuccess(jsonResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("api push signal: HTTP request creation failed: %s", err)
|
return fmt.Errorf("api push signal: HTTP request creation failed: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("api push: URL: '%s'", req.URL)
|
|
||||||
|
|
||||||
httpClient := http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, err := httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("api push signal: API call failed : %s", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -57,6 +49,11 @@ func (ctx *ApiCtx) pushSignals() error {
|
||||||
return fmt.Errorf("api push signal: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
return fmt.Errorf("api push signal: return bad HTTP code (%d): %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != 401 && (jsonResp.Message == "" || jsonResp.Message != "OK" || jsonResp.StatusCode != 200) {
|
||||||
|
return fmt.Errorf("api push failed. http response: %s", body)
|
||||||
|
}
|
||||||
|
|
||||||
if len(ctx.toPush) > 0 {
|
if len(ctx.toPush) > 0 {
|
||||||
log.Infof("api push signal: pushed %d signals successfully", len(ctx.toPush))
|
log.Infof("api push signal: pushed %d signals successfully", len(ctx.toPush))
|
||||||
}
|
}
|
||||||
|
|
248
pkg/cwapi/signals_test.go
Normal file
248
pkg/cwapi/signals_test.go
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
package cwapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
"github.com/dghubble/sling"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var signalList = []types.Event{
|
||||||
|
{
|
||||||
|
Overflow: types.SignalOccurence{
|
||||||
|
Scenario: "crowdsec/test",
|
||||||
|
Bucket_id: "1234",
|
||||||
|
Events_count: 1,
|
||||||
|
Events_sequence: []types.EventSequence{},
|
||||||
|
Start_at: time.Now(),
|
||||||
|
BanApplications: []types.BanApplication{},
|
||||||
|
Stop_at: time.Now(),
|
||||||
|
Source_ip: "1.2.3.4",
|
||||||
|
Source_range: "1.2.3.0/24",
|
||||||
|
Source_AutonomousSystemNumber: "1234",
|
||||||
|
Source_AutonomousSystemOrganization: "TestAS",
|
||||||
|
Source_Country: "FR",
|
||||||
|
Dest_ip: "1.2.3.5",
|
||||||
|
Capacity: 1,
|
||||||
|
Whitelisted: false,
|
||||||
|
Simulation: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Overflow: types.SignalOccurence{
|
||||||
|
Scenario: "crowdsec/test",
|
||||||
|
Bucket_id: "1235",
|
||||||
|
Events_count: 1,
|
||||||
|
Events_sequence: []types.EventSequence{},
|
||||||
|
Start_at: time.Now(),
|
||||||
|
BanApplications: []types.BanApplication{},
|
||||||
|
Stop_at: time.Now(),
|
||||||
|
Source_ip: "1.2.3.5",
|
||||||
|
Source_range: "1.2.3.0/24",
|
||||||
|
Source_AutonomousSystemNumber: "1234",
|
||||||
|
Source_AutonomousSystemOrganization: "TestAS",
|
||||||
|
Source_Country: "FR",
|
||||||
|
Dest_ip: "1.2.3.6",
|
||||||
|
Capacity: 1,
|
||||||
|
Whitelisted: false,
|
||||||
|
Simulation: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPushSignal(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
givenAPICtx *ApiCtx
|
||||||
|
expectedErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic api push signal",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal unknown api PATH",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "unknown_path",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal malformed response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "malformed_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal bad response",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal empty signal list",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: []types.Event{},
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal expired token",
|
||||||
|
expectedErr: false,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals_token_expired",
|
||||||
|
SigninPath: "signin",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
tokenExpired: false,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal unable to renew expired token",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals_token_renew_fail",
|
||||||
|
SigninPath: "signin",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
tokenExpired: false,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal bad response code",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals_bad_response_code",
|
||||||
|
SigninPath: "signin",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
tokenExpired: false,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "api push signal signin while token expired failed",
|
||||||
|
expectedErr: true,
|
||||||
|
givenAPICtx: &ApiCtx{
|
||||||
|
ApiVersion: "v1",
|
||||||
|
PushPath: "signals_token_expired",
|
||||||
|
SigninPath: "bad_response",
|
||||||
|
BaseURL: "https://my_testendpoint.com",
|
||||||
|
CfgUser: "machine_id",
|
||||||
|
CfgPassword: "machine_password",
|
||||||
|
Creds: ApiCreds{
|
||||||
|
User: "machine_id",
|
||||||
|
Password: "machine_password",
|
||||||
|
Profile: "crowdsec/test1,crowdsec/test2",
|
||||||
|
},
|
||||||
|
toPush: signalList,
|
||||||
|
tokenExpired: false,
|
||||||
|
Http: sling.New().Client(newMockClient()).Base(apiBaseURL),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
err := test.givenAPICtx.pushSignals()
|
||||||
|
if !test.expectedErr && err != nil {
|
||||||
|
t.Fatalf("test '%s' failed : %s", test.name, err)
|
||||||
|
}
|
||||||
|
if test.expectedErr && err == nil {
|
||||||
|
t.Fatalf("test '%s' should return an err", test.name)
|
||||||
|
}
|
||||||
|
if test.expectedErr {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("test '%s' : OK", test.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
version: v1
|
version: v1
|
||||||
url: https://test_endpoint
|
url: https://my_testendpoint.com
|
||||||
signin_path: signin
|
signin_path: signin
|
||||||
push_path: signals
|
push_path: signals
|
||||||
pull_path: pull
|
pull_path: pull
|
||||||
|
|
10
pkg/cwapi/tests/api_config_bad_api_version.yaml
Normal file
10
pkg/cwapi/tests/api_config_bad_api_version.yaml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
version: v0
|
||||||
|
url: https://test_endpoint
|
||||||
|
signin_path: signin
|
||||||
|
push_path: signals
|
||||||
|
pull_path: pull
|
||||||
|
enroll_path: enroll
|
||||||
|
reset_pwd_path: resetpassword
|
||||||
|
register_path: register
|
||||||
|
machine_id: test
|
||||||
|
password: test
|
11
pkg/cwapi/tests/api_config_bad_format.yaml
Normal file
11
pkg/cwapi/tests/api_config_bad_format.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
bad_key: test
|
||||||
|
version: v1
|
||||||
|
url: https://test_endpoint
|
||||||
|
signin_path: signin
|
||||||
|
push_path: signals
|
||||||
|
pull_path: pull
|
||||||
|
enroll_path: enroll
|
||||||
|
reset_pwd_path: resetpassword
|
||||||
|
register_path: register
|
||||||
|
machine_id: test
|
||||||
|
password: test
|
101
pkg/cwapi/utils_test.go
Normal file
101
pkg/cwapi/utils_test.go
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
package cwapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const configFile = "./tests/api_config.yaml"
|
||||||
|
const apiVersion = "v1"
|
||||||
|
const apiURL = "https://my_test_endpoint"
|
||||||
|
|
||||||
|
var apiBaseURL = fmt.Sprintf("%s/%s/", apiURL, apiVersion)
|
||||||
|
|
||||||
|
var httpClientMock = &http.Client{
|
||||||
|
Transport: newMockTransport(),
|
||||||
|
Timeout: time.Second * 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockTransport struct {
|
||||||
|
nbTryTokenOK int // to test token expiration
|
||||||
|
nbTryTokenNOK int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockTransport() http.RoundTripper {
|
||||||
|
return &mockTransport{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockClient() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: newMockTransport(),
|
||||||
|
Timeout: time.Second * 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement http.RoundTripper
|
||||||
|
func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
var responseBody string
|
||||||
|
var statusCode int
|
||||||
|
// Create mocked http.Response
|
||||||
|
response := &http.Response{
|
||||||
|
Header: make(http.Header),
|
||||||
|
Request: req,
|
||||||
|
}
|
||||||
|
response.Header.Set("Content-Type", "application/json")
|
||||||
|
switch req.URL.Path {
|
||||||
|
case "/v1/signin":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "crowdsec_api_token"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/register":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "OK"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/signals":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "OK"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/signals_token_expired":
|
||||||
|
if t.nbTryTokenOK == 0 {
|
||||||
|
responseBody = `{"statusCode": 200, "message": "crowdsec_api_token"}`
|
||||||
|
statusCode = 401
|
||||||
|
t.nbTryTokenOK++
|
||||||
|
} else {
|
||||||
|
responseBody = `{"statusCode": 200, "message": "OK"}`
|
||||||
|
statusCode = 200
|
||||||
|
}
|
||||||
|
case "/v1/signals_token_renew_fail":
|
||||||
|
if t.nbTryTokenNOK == 0 {
|
||||||
|
responseBody = `{"statusCode": 200, "message": "crowdsec_api_token"}`
|
||||||
|
statusCode = 401
|
||||||
|
t.nbTryTokenNOK++
|
||||||
|
} else {
|
||||||
|
responseBody = `{"statusCode": 500, "message": "token expired"}`
|
||||||
|
statusCode = 500
|
||||||
|
}
|
||||||
|
case "/v1/signals_bad_response_code":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "OK"}`
|
||||||
|
statusCode = 500
|
||||||
|
case "/v1/enroll":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "OK"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/resetpassword":
|
||||||
|
responseBody = `{"statusCode": 200, "message": "password updated successfully"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/resetpassword_unknown_user":
|
||||||
|
responseBody = `{"statusCode": 500, "message": "User not found"}`
|
||||||
|
statusCode = 200
|
||||||
|
case "/v1/unknown_path":
|
||||||
|
statusCode = 404
|
||||||
|
responseBody = `{"error": "unknown URI"}`
|
||||||
|
case "/v1/malformed_response":
|
||||||
|
statusCode = 200
|
||||||
|
responseBody = `{"statusCode" : 200, "msg" : "api_token"`
|
||||||
|
case "/v1/bad_response":
|
||||||
|
statusCode = 200
|
||||||
|
responseBody = `{"statusCode" : 200, "msg" : "api_token"}`
|
||||||
|
}
|
||||||
|
response.StatusCode = statusCode
|
||||||
|
response.Body = ioutil.NopCloser(strings.NewReader(responseBody))
|
||||||
|
return response, nil
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue