Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added HTTP_SKIP_CERT_VALIDATION and http implementation to http util #147

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ee3afb6
Added HTTP_SKIP_CERT_VALIDATION and http implementation to http util
MaartendeKruijf May 6, 2024
c3de6f3
Added logging to http for request response
MaartendeKruijf May 6, 2024
e5def20
added insecure testing to http test + a docker compose file for setti…
RabbITCybErSeC May 8, 2024
8e25c8a
added a docker installer to ci
RabbITCybErSeC May 8, 2024
f2c8f46
ci change for different github action
RabbITCybErSeC May 8, 2024
bc7a11e
change usage of docker action to different step
RabbITCybErSeC May 8, 2024
3e8a872
move of step in ci
RabbITCybErSeC May 8, 2024
6eabc90
timeout added to ci
RabbITCybErSeC May 8, 2024
bdd4eba
change in docker binary
RabbITCybErSeC May 8, 2024
3903643
ci debug added docker version to see if it lives in container
RabbITCybErSeC May 8, 2024
48948cc
setup docker
RabbITCybErSeC May 8, 2024
5cb9723
different action ci docker setup
RabbITCybErSeC May 8, 2024
4c98bfd
ci ohter command
RabbITCybErSeC May 8, 2024
202fbda
removed go container and install go directly in ubuntu container
RabbITCybErSeC May 8, 2024
1a062fd
added go run version
RabbITCybErSeC May 8, 2024
fd64b9a
typo on setup action for go
RabbITCybErSeC May 8, 2024
7947e2b
removed redundant run
RabbITCybErSeC May 8, 2024
c3bfb45
added sudo and seperate step for docker container spin up
RabbITCybErSeC May 8, 2024
ac5ba81
fix in docker compose path
RabbITCybErSeC May 8, 2024
1f08648
fix in password chnage
RabbITCybErSeC May 8, 2024
d064c42
ädded test for insecure connection that should fail
RabbITCybErSeC May 8, 2024
3ec3a7b
added assertions
RabbITCybErSeC May 8, 2024
dd43add
moved insecure tests to integration
RabbITCybErSeC May 8, 2024
bcd50c8
fixed import issues http utils for integration test file
RabbITCybErSeC May 8, 2024
1d62618
fixed import of assertion package
RabbITCybErSeC May 8, 2024
991e60f
removal of redundant error checks
RabbITCybErSeC May 8, 2024
b0bc78a
moved assertion higher op in tests
RabbITCybErSeC May 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ LOG_FORMAT: "json"

ENABLE_FINS: false
MQTT_BROKER: "localhost"
MQTT_PORT: 1883
MQTT_PORT: 1883

HTTP_SKIP_CERT_VALIDATION: false
21 changes: 13 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,28 @@ jobs:
test:
name: Run ci-tests
runs-on: ubuntu-latest
container:
image: golang:latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22.2' #
- name: Make repo safe
run: git config --global --add safe.directory /__w/SOARCA/SOARCA
- name: Install swaggo
run: go install github.com/swaggo/swag/cmd/swag@latest
run: go install github.com/swaggo/swag/cmd/swag@latest
timeout-minutes: 12
- name: Start docker containers for test
run: docker-compose -f "docker/testing/httpbin-test/docker-compose.yml" up -d --build
- name: Run tests
run: |
apt update
apt install openssh-server -y
useradd sshtest
echo "sshtest:pdKY77qNxpI5MAizirtjCVOcm0KFKIs" | chpasswd
service ssh start
sudo apt update
MaartendeKruijf marked this conversation as resolved.
Show resolved Hide resolved
sudo apt install openssh-server -y
sudo useradd sshtest
echo "sshtest:pdKY77qNxpI5MAizirtjCVOcm0KFKIs" | sudo chpasswd
sudo service ssh start
make ci-test

1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ services:
DB_PASSWORD: "rootpassword"
PLAYBOOK_API_LOG_LEVEL: trace
DATABASE: "false"
HTTP_SKIP_CERT_VALIDATION: false
ports:
- 127.0.0.1:8080:8080
depends_on:
Expand Down
1 change: 1 addition & 0 deletions docker/soarca/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ services:
ENABLE_FINS: true
MQTT_BROKER: "mosquitto"
MQTT_PORT: 1883
HTTP_SKIP_CERT_VALIDATION: false
networks:
- db-net
ports:
Expand Down
14 changes: 14 additions & 0 deletions docker/testing/httpbin-test/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: '2'

services:
httpbin:
image: kennethreitz/httpbin
proxy:
image: fsouza/docker-ssl-proxy
environment:
DOMAIN: localhost
TARGET_HOST: httpbin
links:
- httpbin
ports:
- 443:443
3 changes: 3 additions & 0 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ func (controller *Controller) NewDecomposer() decomposer.IDecomposer {
ssh := new(ssh.SshCapability)
capabilities := map[string]capability.ICapability{ssh.GetType(): ssh}

skip, _ := strconv.ParseBool(utils.GetEnv("HTTP_SKIP_CERT_VALIDATION", "false"))

httpUtil := new(httpUtil.HttpRequest)
httpUtil.SkipCertificateValidation(skip)
http := http.New(httpUtil)
capabilities[http.GetType()] = http

Expand Down
76 changes: 64 additions & 12 deletions test/integration/capability/http/http_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package http_integrations_test

import (
"fmt"
"testing"

"soarca/internal/capability/http"
"soarca/models/cacao"
"soarca/models/execution"
httpUtil "soarca/utils/http"
"testing"

"github.com/go-playground/assert/v2"
"github.com/google/uuid"
)

Expand All @@ -26,15 +28,15 @@ func TestHttpConnection(t *testing.T) {
Headers: map[string][]string{"accept": {"application/json"}},
}

var variable1 = cacao.Variable{
variable1 := cacao.Variable{
Type: "string",
Name: "test_auth",
Value: "",
}

var executionId, _ = uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
var playbookId, _ = uuid.Parse("playbook--d09351a2-a075-40c8-8054-0b7c423db83f")
var stepId, _ = uuid.Parse("action--81eff59f-d084-4324-9e0a-59e353dbd28f")
executionId, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
playbookId, _ := uuid.Parse("playbook--d09351a2-a075-40c8-8054-0b7c423db83f")
stepId, _ := uuid.Parse("action--81eff59f-d084-4324-9e0a-59e353dbd28f")

metadata := execution.Metadata{ExecutionId: executionId, PlaybookId: playbookId.String(), StepId: stepId.String()}
// But what to do if there is no target and no AuthInfo?
Expand Down Expand Up @@ -74,9 +76,9 @@ func TestHttpOAuth2(t *testing.T) {
Headers: map[string][]string{"accept": {"application/json"}},
}

var executionId, _ = uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
var playbookId, _ = uuid.Parse("d09351a2-a075-40c8-8054-0b7c423db83f")
var stepId, _ = uuid.Parse("81eff59f-d084-4324-9e0a-59e353dbd28f")
executionId, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
playbookId, _ := uuid.Parse("d09351a2-a075-40c8-8054-0b7c423db83f")
stepId, _ := uuid.Parse("81eff59f-d084-4324-9e0a-59e353dbd28f")
metadata := execution.Metadata{ExecutionId: executionId, PlaybookId: playbookId.String(), StepId: stepId.String()}
results, err := httpCapability.Execute(
metadata,
Expand All @@ -100,7 +102,7 @@ func TestHttpBasicAuth(t *testing.T) {

target := cacao.AgentTarget{
Address: map[cacao.NetAddressType][]string{
"url": []string{url},
"url": {url},
},
AuthInfoIdentifier: "d0c7e6a0-f7fe-464e-9935-e6b3443f5b91",
}
Expand All @@ -117,9 +119,9 @@ func TestHttpBasicAuth(t *testing.T) {
Command: "GET / HTTP/1.1",
Headers: map[string][]string{"accept": {"application/json"}},
}
var executionId, _ = uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
var playbookId, _ = uuid.Parse("d09351a2-a075-40c8-8054-0b7c423db83f")
var stepId, _ = uuid.Parse("81eff59f-d084-4324-9e0a-59e353dbd28f")
executionId, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
playbookId, _ := uuid.Parse("d09351a2-a075-40c8-8054-0b7c423db83f")
stepId, _ := uuid.Parse("81eff59f-d084-4324-9e0a-59e353dbd28f")
metadata := execution.Metadata{ExecutionId: executionId, PlaybookId: playbookId.String(), StepId: stepId.String()}
results, err := httpCapability.Execute(
metadata,
Expand All @@ -133,3 +135,53 @@ func TestHttpBasicAuth(t *testing.T) {
}
fmt.Println(results)
}

func TestInsecureHTTPConnection(t *testing.T) {
httpRequest := httpUtil.HttpRequest{}

target := cacao.AgentTarget{
Address: map[cacao.NetAddressType][]string{
"url": {"https://localhost/get"},
},
}
command := cacao.Command{
Type: "http-api",
Command: "GET / HTTP/1.1",
Headers: map[string][]string{"accept": {"application/json"}},
}
httpOptions := httpUtil.HttpOptions{
Command: &command,
Target: &target,
}
httpRequest.SkipCertificateValidation(true)
response, err := httpRequest.Request(httpOptions)
assert.Equal(t, err, nil)
t.Log(string(response))
if len(response) == 0 {
t.Error("empty response")
}
t.Log(string(response))
}

func TestInsecureHTTPConnectionWithFailure(t *testing.T) {
httpRequest := httpUtil.HttpRequest{}

target := cacao.AgentTarget{
Address: map[cacao.NetAddressType][]string{
"url": {"https://localhost/get"},
},
}
command := cacao.Command{
Type: "http-api",
Command: "GET / HTTP/1.1",
Headers: map[string][]string{"accept": {"application/json"}},
}
httpOptions := httpUtil.HttpOptions{
Command: &command,
Target: &target,
}

response, err := httpRequest.Request(httpOptions)
assert.NotEqual(t, err, nil)
t.Log(string(response))
}
1 change: 1 addition & 0 deletions test/unittest/utils/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type httpBinResponseBody struct {
}

// Test general http options, we do not check responses body, as these are variable for the general connection tests

func TestHttpGetConnection(t *testing.T) {
httpRequest := http.HttpRequest{}

Expand Down
17 changes: 15 additions & 2 deletions utils/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package http

import (
"bytes"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
Expand Down Expand Up @@ -35,7 +36,9 @@ type IHttpRequest interface {
Request(httpOptions HttpOptions) ([]byte, error)
}

type HttpRequest struct{}
type HttpRequest struct {
skipCertificateValidation bool
}

// https://gist.githubusercontent.com/ahmetozer/ffa4cd0b319aff32ea9ed0068c8b81cf/raw/fc8742e6e087451e954bf0da214794a620356a4d/IPv4-IPv6-domain-regex.go
const (
Expand All @@ -44,14 +47,22 @@ const (
domainRegex = `^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$`
)

func (httpRequest *HttpRequest) SkipCertificateValidation(skip bool) {
httpRequest.skipCertificateValidation = skip
}

func (httpRequest *HttpRequest) Request(httpOptions HttpOptions) ([]byte, error) {
log = logger.Logger(component, logger.Info, "", logger.Json)
request, err := httpOptions.setupRequest()
if err != nil {
return []byte{}, err
}

client := &http.Client{}
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: httpRequest.skipCertificateValidation},
}

client := &http.Client{Transport: transport}
log.Trace(request)
response, err := client.Do(request)
if err != nil {
Expand Down Expand Up @@ -112,6 +123,8 @@ func (httpRequest *HttpOptions) handleResponse(response *http.Response) ([]byte,
return []byte{}, err
}
sc := response.StatusCode
log.Trace(fmt.Sprint(sc))
log.Trace(string(responseBytes))
if sc < 200 || sc > 299 {
return []byte{}, errors.New(string(responseBytes))
}
Expand Down