diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3474f1e..c402ca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: with: go-version: 1.20.0 - - name: Dependences + - name: Dependencies run: go mod download - name: Vet @@ -33,17 +33,13 @@ jobs: go test ./... -v -coverprofile coverage.tmp.out -covermode count go tool cover -func coverage.tmp.out - - name: Integration tests - run: | - INTEGRATION=1 go test ./... -v - - name: Quality Gate - Test coverage shall be above threshold env: TESTCOVERAGE_THRESHOLD: 70 run: | echo "Quality Gate: checking test coverage is above threshold ..." echo "Threshold : $TESTCOVERAGE_THRESHOLD %" - # Excluded the concrete strategy from the coverage calculation, this will be tested in the integration tests + # Excluded the concrete strategy from the coverage calculation, because tested by integration tests cat coverage.tmp.out | grep -v "secureShellStrategy.go" | grep -v "hypertextTransferProtocolStrategy.go" | grep -v "transmissionControlProtocolStrategy.go" > coverage.out totalCoverage=`go tool cover -func=coverage.out | grep total | grep -Eo '[0-9]+\.[0-9]+'` echo "Current test coverage : $totalCoverage %" @@ -54,3 +50,26 @@ jobs: echo "Failed" exit 1 fi + + - name: Start integration test dependencies + run: | + make test.dependencies.start + + - name: Wait for RabbitMQ to be ready + run: | + sleep 2 + count=0 + until docker exec rabbitmq rabbitmqctl list_queues > /dev/null 2>&1; do + count=$((count+1)) + if [ $count -gt 10 ]; then + echo "RabbitMQ did not start within the specified time" + exit 1 + fi + echo "Waiting for RabbitMQ to start..." + sleep 5 + done + + - name: Integration tests + run: | + make test.integration.verbose + make test.dependencies.down diff --git a/.gitignore b/.gitignore index feff9ac..f4adb17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store .idea -logs \ No newline at end of file +logs +.vscode \ No newline at end of file diff --git a/Makefile b/Makefile index 20a623a..52840b7 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,12 @@ test.unit: test.unit.verbose: go test ./... -v +test.dependencies.start: + ${DOCKER_COMPOSE} -f ./integration_test/docker-compose.yml up -d + +test.dependencies.down: + ${DOCKER_COMPOSE} -f ./integration_test/docker-compose.yml down + test.integration: INTEGRATION=1 go test ./... diff --git a/integration_test/configurations/beelzebub.yaml b/integration_test/configurations/beelzebub.yaml index 5b2fe43..f9bb674 100644 --- a/integration_test/configurations/beelzebub.yaml +++ b/integration_test/configurations/beelzebub.yaml @@ -5,5 +5,5 @@ core: logDisableTimestamp: true logsPath: ./logs tracing: - rabbitMQEnabled: false - rabbitMQURI: "" + rabbitMQEnabled: true + rabbitMQURI: "amqp://integration:integration@localhost:5672/" diff --git a/integration_test/docker-compose.yml b/integration_test/docker-compose.yml new file mode 100644 index 0000000..65afa75 --- /dev/null +++ b/integration_test/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.9" +services: + rabbitmq: + image: rabbitmq:3-alpine + container_name: 'rabbitmq' + ports: + - 5672:5672 + environment: + - RABBITMQ_DEFAULT_USER=integration + - RABBITMQ_DEFAULT_PASS=integration \ No newline at end of file diff --git a/integration_test/integration_test.go b/integration_test/integration_test.go index fb1fffe..9758d2c 100644 --- a/integration_test/integration_test.go +++ b/integration_test/integration_test.go @@ -3,14 +3,18 @@ package integration import ( "beelzebub/builder" "beelzebub/parser" - "github.com/go-resty/resty/v2" - "github.com/melbahja/goph" - "github.com/stretchr/testify/suite" - "golang.org/x/crypto/ssh" + "beelzebub/tracer" + "encoding/json" "net" "net/http" "os" "testing" + + "github.com/go-resty/resty/v2" + "github.com/melbahja/goph" + amqp "github.com/rabbitmq/amqp091-go" + "github.com/stretchr/testify/suite" + "golang.org/x/crypto/ssh" ) type IntegrationTestSuite struct { @@ -19,6 +23,7 @@ type IntegrationTestSuite struct { httpHoneypotHost string tcpHoneypotHost string sshHoneypotHost string + rabbitMQURI string } func TestIntegrationTestSuite(t *testing.T) { @@ -41,6 +46,7 @@ func (suite *IntegrationTestSuite) SetupSuite() { coreConfigurations, err := parser.ReadConfigurationsCore() suite.Require().NoError(err) + suite.rabbitMQURI = coreConfigurations.Core.Tracing.RabbitMQURI beelzebubServicesConfiguration, err := parser.ReadConfigurationsServices() suite.Require().NoError(err) @@ -108,7 +114,35 @@ func (suite *IntegrationTestSuite) TestInvokeSSHHoneypot() { suite.Equal("root@ubuntu:~$ ", string(out)) } -//TODO test rabbitmq +func (suite *IntegrationTestSuite) TestRabbitMQ() { + conn, err := amqp.Dial(suite.rabbitMQURI) + suite.Require().NoError(err) + defer conn.Close() + + ch, err := conn.Channel() + suite.Require().NoError(err) + defer ch.Close() + + msgs, err := ch.Consume("event", "", true, false, false, false, nil) + suite.Require().NoError(err) + + //Invoke HTTP Honeypot + response, err := resty.New().R().Get(suite.httpHoneypotHost + "/index.php") + + suite.Require().NoError(err) + suite.Equal(http.StatusOK, response.StatusCode()) + + for msg := range msgs { + var event tracer.Event + err := json.Unmarshal(msg.Body, &event) + suite.Require().NoError(err) + + suite.Equal("GET", event.HTTPMethod) + suite.Equal("/index.php", event.RequestURI) + break + } + +} func (suite *IntegrationTestSuite) TestShutdownBeelzebub() { suite.Require().NoError(suite.beelzebubBuilder.Close())