Skip to main content
Glama
beelzebub-cloud_test.go10.5 kB
package plugins import ( "fmt" "net/http" "regexp" "testing" "time" "github.com/go-resty/resty/v2" "github.com/jarcoal/httpmock" "github.com/mariocandela/beelzebub/v3/parser" "github.com/mariocandela/beelzebub/v3/tracer" "github.com/stretchr/testify/assert" ) func TestBuildSendEventFailValidation(t *testing.T) { beelzebubCloud := InitBeelzebubCloud("", "", false) _, err := beelzebubCloud.SendEvent(tracer.Event{}) assert.Equal(t, "authToken is empty", err.Error()) } func TestBuildSendEventWithResults(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" // Given httpmock.RegisterResponder("POST", fmt.Sprintf("%s/events", uri), func(req *http.Request) (*http.Response, error) { resp, err := httpmock.NewJsonResponse(200, &tracer.Event{}) if err != nil { return httpmock.NewStringResponse(500, ""), nil } return resp, nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, err := beelzebubCloud.SendEvent(tracer.Event{}) //Then assert.Equal(t, true, result) assert.Nil(t, err) } func TestBuildSendEventErro(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081/events" // Given httpmock.RegisterResponder("POST", uri, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(500, ""), nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, _ := beelzebubCloud.SendEvent(tracer.Event{}) //Then assert.Equal(t, false, result) } func TestGetHoneypotsConfigurationsWithResults(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" // Given httpmock.RegisterResponder("GET", fmt.Sprintf("%s/honeypots", uri), func(req *http.Request) (*http.Response, error) { resp, err := httpmock.NewJsonResponse(200, &[]HoneypotConfigResponseDTO{ { ID: "123456", Config: "apiVersion: \"v1\"\nprotocol: \"ssh\"\naddress: \":2222\"\ndescription: \"SSH interactive ChatGPT\"\ncommands:\n - regex: \"^(.+)$\"\n plugin: \"LLMHoneypot\"\nserverVersion: \"OpenSSH\"\nserverName: \"ubuntu\"\npasswordRegex: \"^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$\"\ndeadlineTimeoutSeconds: 60\nplugin:\n llmModel: \"gpt-4o\"\n openAISecretKey: \"1234\"\n", TokenID: "1234567", }, }) if err != nil { return httpmock.NewStringResponse(500, ""), nil } return resp, nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, configurationsHash, err := beelzebubCloud.GetHoneypotsConfigurations() //Then assert.Equal(t, &[]parser.BeelzebubServiceConfiguration{ { ApiVersion: "v1", Protocol: "ssh", Address: ":2222", Description: "SSH interactive ChatGPT", Commands: []parser.Command{ { RegexStr: "^(.+)$", Regex: regexp.MustCompile("^(.+)$"), Plugin: "LLMHoneypot", }, }, ServerVersion: "OpenSSH", ServerName: "ubuntu", PasswordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$", DeadlineTimeoutSeconds: 60, Plugin: parser.Plugin{ LLMModel: "gpt-4o", OpenAISecretKey: "1234", }, }, }, &result) assert.Equal(t, "ce1980af6e5f88063341fa4ccc12ff7355fa4f283872da181959a12b51dea041", configurationsHash) assert.Nil(t, err) } func TestGetHoneypotsConfigurationsWithErrorValidation(t *testing.T) { //Given beelzebubCloud := InitBeelzebubCloud("", "", false) //When result, _, err := beelzebubCloud.GetHoneypotsConfigurations() //Then assert.Nil(t, result) assert.Equal(t, "authToken is empty", err.Error()) } func TestGetHoneypotsConfigurationsWithErrorAPI(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" // Given httpmock.RegisterResponder("GET", fmt.Sprintf("%s/honeypots", uri), func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(500, ""), nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, _, err := beelzebubCloud.GetHoneypotsConfigurations() //Then assert.Nil(t, result) assert.Equal(t, "Response code: 500, error: ", err.Error()) } func TestGetHoneypotsConfigurationsWithErrorUnmarshal(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" // Given httpmock.RegisterResponder("GET", fmt.Sprintf("%s/honeypots", uri), func(req *http.Request) (*http.Response, error) { resp, err := httpmock.NewJsonResponse(200, "error") if err != nil { return httpmock.NewStringResponse(500, ""), nil } return resp, nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, _, err := beelzebubCloud.GetHoneypotsConfigurations() //Then assert.Nil(t, result) assert.Equal(t, "json: cannot unmarshal string into Go value of type []plugins.HoneypotConfigResponseDTO", err.Error()) } func TestGetHoneypotsConfigurationsWithErrorDeserializeYaml(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" // Given httpmock.RegisterResponder("GET", fmt.Sprintf("%s/honeypots", uri), func(req *http.Request) (*http.Response, error) { resp, err := httpmock.NewJsonResponse(200, &[]HoneypotConfigResponseDTO{ { ID: "123456", Config: "error", TokenID: "1234567", }, }) if err != nil { return httpmock.NewStringResponse(500, ""), nil } return resp, nil }, ) beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client //When result, _, err := beelzebubCloud.GetHoneypotsConfigurations() //Then assert.Nil(t, result) assert.Equal(t, "yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `error` into parser.BeelzebubServiceConfiguration", err.Error()) } func TestVerifyConfigurationsChanged(t *testing.T) { client := resty.New() httpmock.ActivateNonDefault(client.GetClient()) defer httpmock.DeactivateAndReset() uri := "localhost:8081" callCount := 0 httpmock.RegisterResponder("GET", fmt.Sprintf("%s/honeypots", uri), func(req *http.Request) (*http.Response, error) { callCount++ config := "apiVersion: \"v1\"\nprotocol: \"ssh\"\naddress: \":2222\"\ndescription: \"SSH interactive ChatGPT\"\ncommands:\n - regex: \"^(.+)$\"\n plugin: \"LLMHoneypot\"\nserverVersion: \"OpenSSH\"\nserverName: \"ubuntu\"\npasswordRegex: \"^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$\"\ndeadlineTimeoutSeconds: 60\nplugin:\n llmModel: \"gpt-4o\"\n openAISecretKey: \"1234\"\n" if callCount > 1 { config = "apiVersion: \"v1\"\nprotocol: \"ssh\"\naddress: \":2222\"\ndescription: \"SSH interactive ChatGPT MODIFIED\"\ncommands:\n - regex: \"^(.+)$\"\n plugin: \"LLMHoneypot\"\nserverVersion: \"OpenSSH\"\nserverName: \"ubuntu\"\npasswordRegex: \"^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$\"\ndeadlineTimeoutSeconds: 60\nplugin:\n llmModel: \"gpt-3.5-turbo\"\n openAISecretKey: \"1234\"\n" } resp, err := httpmock.NewJsonResponse(200, &[]HoneypotConfigResponseDTO{ { ID: "123456", Config: config, TokenID: "1234567", }, }) if err != nil { return httpmock.NewStringResponse(500, ""), nil } return resp, nil }, ) var exitInvoked bool = false exitCalled := make(chan bool) exitFunction = func(c int) { exitInvoked = true exitCalled <- true } beelzebubCloud := InitBeelzebubCloud(uri, "sdjdnklfjndslkjanfk", false) beelzebubCloud.client = client beelzebubCloud.PollingInterval = 100 * time.Millisecond go func() { err := beelzebubCloud.verifyConfigurationsChanged() if err != nil { t.Errorf("verifyConfigurationsChanged returned with error: %v", err) } }() select { case <-exitCalled: assert.True(t, exitInvoked, "exitFunction should have been invoked") assert.Greater(t, callCount, 1, "Should have made at least 2 API calls") case <-time.After(2 * time.Second): t.Fatal("Test timed out waiting for exitFunction to be called") } } func TestMapToEventDTO(t *testing.T) { event := tracer.Event{ DateTime: "2025-05-01T16:18:13Z", RemoteAddr: "1.1.1.1:12345", Protocol: "SSH", Command: "cd /tmp", CommandOutput: "", Status: "Interaction", Msg: "New SSH Terminal Session", ID: "4f104892-738f-47ac-950f-6afce1b742c7", Environ: "qwerty", User: "root", Password: "root", Client: "ssh", Cookies: "qwerty", UserAgent: "qwerty", HostHTTPRequest: "beelzebub-honeypot.com", Body: "qwerty", HTTPMethod: "GET", RequestURI: "/qwerty", Description: "qwerty", SourceIp: "1.1.1.1", SourcePort: "12345", TLSServerName: "beelzebub-honeypot.com", } beelzebubCloud := InitBeelzebubCloud("localhost:8081", "sdjdnklfjndslkjanfk", false) eventDTO, err := beelzebubCloud.mapToEventDTO(event) assert.Nil(t, err) assert.Equal(t, EventDTO{ DateTime: "2025-05-01T16:18:13Z", RemoteAddr: "1.1.1.1:12345", Protocol: "SSH", Command: "cd /tmp", CommandOutput: "", Status: "Interaction", Msg: "New SSH Terminal Session", ID: "4f104892-738f-47ac-950f-6afce1b742c7", Environ: "qwerty", User: "root", Password: "root", Client: "ssh", Cookies: "qwerty", UserAgent: "qwerty", HostHTTPRequest: "beelzebub-honeypot.com", Body: "qwerty", HTTPMethod: "GET", RequestURI: "/qwerty", Description: "qwerty", SourceIp: "1.1.1.1", SourcePort: "12345", TLSServerName: "beelzebub-honeypot.com", }, eventDTO) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mariocandela/beelzebub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server