From 0c67f1f5ca39588ef0eebe3055e1025cce4e6220 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Fri, 27 Mar 2020 17:05:27 -0700 Subject: [PATCH 01/17] Create Site --- api.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/api.go b/api.go index b7d7d3e..931420a 100644 --- a/api.go +++ b/api.go @@ -1727,3 +1727,24 @@ func (sc *Client) GetTimeseries(corpName, siteName string, query url.Values) ([] return t.Data, nil } + +func (sc *Client) CreateSite(corpName, siteName string, body CustomAlertBody) (string, error) { + return fmt.Sprintf("Janithet Corp %s, Site %s", corpName, siteName), nil + // b, err := json.Marshal(body) + // if err != nil { + // return CustomAlert{}, err + // } + + // resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), string(b)) + // if err != nil { + // return CustomAlert{}, err + // } + + // var c CustomAlert + // err = json.Unmarshal(resp, &c) + // if err != nil { + // return CustomAlert{}, err + // } + + // return c, nil +} From c205086ad01fcd2080e4c65e91f704565be3c415 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Mon, 30 Mar 2020 18:09:52 -0700 Subject: [PATCH 02/17] The CreateCustomAlert Method was using PATCH but requires POST Added functions to create and delete sites not committing the test files yet --- api.go | 49 ++++++++++++++++++++++++++++++++----------------- go.mod | 2 ++ go.sum | 10 ++++++++++ 3 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 go.sum diff --git a/api.go b/api.go index 931420a..42a9276 100644 --- a/api.go +++ b/api.go @@ -578,7 +578,7 @@ func (sc *Client) CreateCustomAlert(corpName, siteName string, body CustomAlertB return CustomAlert{}, err } - resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), string(b)) + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), string(b)) if err != nil { return CustomAlert{}, err } @@ -1728,23 +1728,38 @@ func (sc *Client) GetTimeseries(corpName, siteName string, query url.Values) ([] return t.Data, nil } -func (sc *Client) CreateSite(corpName, siteName string, body CustomAlertBody) (string, error) { - return fmt.Sprintf("Janithet Corp %s, Site %s", corpName, siteName), nil - // b, err := json.Marshal(body) - // if err != nil { - // return CustomAlert{}, err - // } +// CreateSiteBody is the structure required to create a Site. +type CreateSiteBody struct { + Name string `json:"name"` + DisplayName string `json:"displayName,omitempty"` + AgentLevel string `json:"agentLevel,omitempty"` + BlockHTTPCode int `json:"blockHTTPCode,omitempty"` + BlockDurationSeconds int `json:"blockDurationSeconds,omitempty"` +} - // resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), string(b)) - // if err != nil { - // return CustomAlert{}, err - // } +// CreateSite Creates a site in a corp. +func (sc *Client) CreateSite(corpName string, body CreateSiteBody) (Site, error) { + b, err := json.Marshal(body) + if err != nil { + return Site{}, err + } - // var c CustomAlert - // err = json.Unmarshal(resp, &c) - // if err != nil { - // return CustomAlert{}, err - // } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites", corpName), string(b)) + if err != nil { + return Site{}, err + } - // return c, nil + var site Site + err = json.Unmarshal(resp, &site) + if err != nil { + return Site{}, err + } + return site, nil +} + +// DeleteSite deltes the site +func (sc *Client) DeleteSite(corpName string, siteName string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s", corpName, siteName), "") + + return err } diff --git a/go.mod b/go.mod index 7c33e68..cbcd89b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/signalsciences/go-sigsci go 1.12 + +require github.com/stretchr/testify v1.5.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a80206a --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 653c50154d4286f16bbcaa85cfbf5f9ea89c6f53 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Wed, 1 Apr 2020 12:12:13 -0700 Subject: [PATCH 03/17] Adds structs to represent Site Rule Adds create and delete methods for Site Rules --- api.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/api.go b/api.go index 42a9276..67d4e0f 100644 --- a/api.go +++ b/api.go @@ -1763,3 +1763,65 @@ func (sc *Client) DeleteSite(corpName string, siteName string) error { return err } + +// Conditions contains rule condition +type Condition struct { + Type string `json:"type"` + GroupOperator string `json:"groupOperator"` + Field string `json:"field"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +// Action contains the rule action +type Action struct { + Type string `json:"type"` +} + +// CreateSiteRulesBody contains the rule for the site +type CreateSiteRulesBody struct { + Type string `json:"type"` + GroupOperator string `json:"groupOperator"` + Enabled bool `json:"enabled"` + Reason string `json:"reason"` + Signal string `json:"signal"` + Expiration string `json:"expiration"` + Conditions []Condition `json:"conditions"` + Actions []Action `json:"actions"` +} + +// ResponseSiteRulesBody contains the response from creating the rule +type ResponseSiteRulesBody struct { + *CreateSiteRulesBody + ID string `json:"id"` + CreatedBy string `json:"createdby"` + Created string `json:"created"` + Updated string `json:"updated"` +} + +// type Message struct { +// Message string `json:"message"` +// } +// CreateSiteRules creates a rule and returns the response +func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteRulesBody{}, err + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), string(b)) + if err != nil { + return ResponseSiteRulesBody{}, err + } + var responseSiteRules ResponseSiteRulesBody + err = json.Unmarshal(resp, &responseSiteRules) + if err != nil { + return ResponseSiteRulesBody{}, err + } + return responseSiteRules, nil +} + +// DeleteSiteRule deletes a rule and returns an error +func (sc *Client) DeleteSiteRule(corpName string, siteName string, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") + return err +} From f16930d9aa809db8076c5a379cabef8bce762a79 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Thu, 2 Apr 2020 23:29:55 +0000 Subject: [PATCH 04/17] add ListSiteRules and UpdateSiteRule functions --- api.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/api.go b/api.go index 67d4e0f..50870c1 100644 --- a/api.go +++ b/api.go @@ -1733,6 +1733,7 @@ type CreateSiteBody struct { Name string `json:"name"` DisplayName string `json:"displayName,omitempty"` AgentLevel string `json:"agentLevel,omitempty"` + AgentAnonMode string `json:"agentAnonMode,omiempty"` BlockHTTPCode int `json:"blockHTTPCode,omitempty"` BlockDurationSeconds int `json:"blockDurationSeconds,omitempty"` } @@ -1764,13 +1765,14 @@ func (sc *Client) DeleteSite(corpName string, siteName string) error { return err } -// Conditions contains rule condition +// Condition contains rule condition type Condition struct { - Type string `json:"type"` - GroupOperator string `json:"groupOperator"` - Field string `json:"field"` - Operator string `json:"operator"` - Value string `json:"value"` + Type string `json:"type"` + GroupOperator string `json:"groupOperator"` + Field string `json:"field"` + Operator string `json:"operator"` + Value string `json:"value"` + Conditions []Condition `json:"conditions"` } // Action contains the rule action @@ -1799,9 +1801,6 @@ type ResponseSiteRulesBody struct { Updated string `json:"updated"` } -// type Message struct { -// Message string `json:"message"` -// } // CreateSiteRules creates a rule and returns the response func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { b, err := json.Marshal(body) @@ -1820,8 +1819,49 @@ func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateS return responseSiteRules, nil } +// UpdateSiteRule updates a rule and returns a response +func (sc *Client) UpdateSiteRule(corpName string, siteName string, id string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteRulesBody{}, err + } + resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), string(b)) + if err != nil { + return ResponseSiteRulesBody{}, err + } + var responseSiteRules ResponseSiteRulesBody + err = json.Unmarshal(resp, &responseSiteRules) + if err != nil { + return ResponseSiteRulesBody{}, err + } + return responseSiteRules, nil +} + // DeleteSiteRule deletes a rule and returns an error func (sc *Client) DeleteSiteRule(corpName string, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") return err } + +// ResponseSiteRulesListData contains the returned rules +type ResponseSiteRulesListData struct { + TotalCount int `json:"totalCount"` + Data []ResponseSiteRulesBody `json:"data"` +} + +// ListSiteRules Lists the Site Rules +func (sc *Client) ListSiteRules(corpName string, siteName string) ([]ResponseSiteRulesBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") + + if err != nil { + return []ResponseSiteRulesBody{}, err + } + + var responseRulesList ResponseSiteRulesListData + err = json.Unmarshal(resp, &responseRulesList) + if err != nil { + return []ResponseSiteRulesBody{}, err + } + + return responseRulesList.Data, nil +} From 58fdd906765ec064cab69273462026a53795b22b Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Fri, 3 Apr 2020 16:00:43 -0700 Subject: [PATCH 05/17] adds devcontainer files Add GetSiteByRuleId to the api add api_test --- .devcontainer/Dockerfile | 82 +++++++ .devcontainer/devcontainer.json | 27 +++ Makefile | 6 + api.go | 30 ++- api_test.go | 407 +++++++++++++++++++++++++++++++- 5 files changed, 538 insertions(+), 14 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..68908e3 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,82 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +FROM golang:1 + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive + +# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser" +# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs +# will be updated to match your local UID/GID (when using the dockerFile property). +# See https://aka.ms/vscode-remote/containers/non-root-user for details. +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Configure apt, install packages and tools +RUN apt-get update \ + && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ + # + # Verify git, process tools, lsb-release (common in install instructions for CLIs) installed + && apt-get -y install git openssh-client less iproute2 procps lsb-release \ + # + # Install Go tools w/module support + && mkdir -p /tmp/gotools \ + && cd /tmp/gotools \ + && GO111MODULE=on go get -v golang.org/x/tools/gopls@latest 2>&1 \ + && GO111MODULE=on go get -v \ + honnef.co/go/tools/...@latest \ + golang.org/x/tools/cmd/gorename@latest \ + golang.org/x/tools/cmd/goimports@latest \ + golang.org/x/tools/cmd/guru@latest \ + golang.org/x/lint/golint@latest \ + github.com/mdempsky/gocode@latest \ + github.com/cweill/gotests/...@latest \ + github.com/haya14busa/goplay/cmd/goplay@latest \ + github.com/sqs/goreturns@latest \ + github.com/josharian/impl@latest \ + github.com/davidrjenni/reftools/cmd/fillstruct@latest \ + github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \ + github.com/ramya-rao-a/go-outline@latest \ + github.com/acroca/go-symbols@latest \ + github.com/godoctor/godoctor@latest \ + github.com/rogpeppe/godef@latest \ + github.com/zmb3/gogetdoc@latest \ + github.com/fatih/gomodifytags@latest \ + github.com/mgechev/revive@latest \ + github.com/go-delve/delve/cmd/dlv@latest 2>&1 \ + # + # Install Go tools w/o module support + && go get -v github.com/alecthomas/gometalinter 2>&1 \ + # + # Install gocode-gomod + && go get -x -d github.com/stamblerre/gocode 2>&1 \ + && go build -o gocode-gomod github.com/stamblerre/gocode \ + && mv gocode-gomod $GOPATH/bin/ \ + # + # Install golangci-lint + && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin 2>&1 \ + # + # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. + && groupadd --gid $USER_GID $USERNAME \ + && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ + # [Optional] Add sudo support + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + # Add write permission for /go/pkg + && chmod -R a+w /go/pkg \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* /go/src /tmp/gotools + +# Update this to "on" or "off" as appropriate +ENV GO111MODULE=auto + +# Switch back to dialog for any ad-hoc use of apt-get +ENV DEBIAN_FRONTEND=dialog diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..ce463bf --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.106.0/containers/go +{ + "name": "Go", + "dockerFile": "Dockerfile", + "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "go.gopath": "/go" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-vscode.go" + ] + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "go version", + + // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode" +} \ No newline at end of file diff --git a/Makefile b/Makefile index 35ab572..6e45d57 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,9 @@ lint: go vet test -z $(gofmt -s -l .) +test: + go test -v +publish: test + git tag -fa v0.3.0 + git push origin --tags + diff --git a/api.go b/api.go index 50870c1..4098a91 100644 --- a/api.go +++ b/api.go @@ -1811,12 +1811,7 @@ func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateS if err != nil { return ResponseSiteRulesBody{}, err } - var responseSiteRules ResponseSiteRulesBody - err = json.Unmarshal(resp, &responseSiteRules) - if err != nil { - return ResponseSiteRulesBody{}, err - } - return responseSiteRules, nil + return getResponseSiteRulesBody(resp) } // UpdateSiteRule updates a rule and returns a response @@ -1829,12 +1824,7 @@ func (sc *Client) UpdateSiteRule(corpName string, siteName string, id string, bo if err != nil { return ResponseSiteRulesBody{}, err } - var responseSiteRules ResponseSiteRulesBody - err = json.Unmarshal(resp, &responseSiteRules) - if err != nil { - return ResponseSiteRulesBody{}, err - } - return responseSiteRules, nil + return getResponseSiteRulesBody(resp) } // DeleteSiteRule deletes a rule and returns an error @@ -1842,6 +1832,22 @@ func (sc *Client) DeleteSiteRule(corpName string, siteName string, id string) er _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") return err } +func (sc *Client) GetSiteRuleById(corpName string, siteName string, id string) (ResponseSiteRulesBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") + if err != nil { + return ResponseSiteRulesBody{}, err + } + return getResponseSiteRulesBody(resp) +} + +func getResponseSiteRulesBody(response []byte) (ResponseSiteRulesBody, error) { + var responseSiteRules ResponseSiteRulesBody + err := json.Unmarshal(response, &responseSiteRules) + if err != nil { + return ResponseSiteRulesBody{}, err + } + return responseSiteRules, nil +} // ResponseSiteRulesListData contains the returned rules type ResponseSiteRulesListData struct { diff --git a/api_test.go b/api_test.go index c5e5fc0..3982645 100644 --- a/api_test.go +++ b/api_test.go @@ -1,12 +1,27 @@ package sigsci import ( + "encoding/json" "log" + "os" + "testing" + + "github.com/stretchr/testify/assert" ) +type TestCreds struct { + email string + token string +} + +var testcreds = TestCreds{ + email: os.Getenv("SIGSCI_EMAIL"), + token: os.Getenv("SIGSCI_TOKEN"), //"6b62cee3-bd06-487e-9283-d565078b7a8f", +} + func ExampleClient_InviteUser() { - email := "[email]" - password := "[password]" + email := testcreds.email + password := testcreds.token sc, err := NewClient(email, password) if err != nil { log.Fatal(err) @@ -21,3 +36,391 @@ func ExampleClient_InviteUser() { log.Fatal(err) } } + +func TestGoUserTokenClient(t *testing.T) { + testCases := []struct { + name string + email string + token string + }{ + { + name: "working user pass creds", + email: testcreds.email, + token: testcreds.token, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + sc := NewTokenClient(testCase.email, testCase.token) + if corps, err := sc.ListCorps(); err != nil { + t.Fatal(err) + } else { + assert.Equal(t, "splunk-testcorp", corps[0].Name) + } + }) + } +} +func TestCreateSite(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-testcorp" + + siteBody := CreateSiteBody{ + Name: "janitha-test-site", + DisplayName: "Janitha Test Site", + AgentLevel: "Log", + BlockHTTPCode: 406, + BlockDurationSeconds: 86400, + AgentAnonMode: "off", + } + _, err := sc.CreateSite(corp, siteBody) + if err == nil { + t.Fatal("Can create more than one site. Clean up not implemented") + } + assert.Equal(t, "Site limit reached", err.Error()) + +} +func TestDeleteSite(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-testcorp" + site := "janitha-test-site" //do not have permission at the moment anyway + err := sc.DeleteSite(corp, site) + if err == nil { + t.Fatalf("This site %s should not exist", site) + } + assert.Equal(t, "Site not found", err.Error()) +} +func TestGetAlerts(t *testing.T) { + t.Skip() + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + alert, err := sc.GetCustomAlert(corp, site, "5e828777a981ef01c7107035") + if err != nil { + t.Fatal(err) + } + t.Logf("%+v", alert) +} +func TestCreateCustomSiteAlert(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + customAlertBody := CustomAlertBody{ + TagName: "CMDEXE", + LongName: "Janitha Long Name", + Action: "flagged", + Enabled: true, + Interval: 1, + Threshold: 1, + } + alert, err := sc.CreateCustomAlert(corp, site, customAlertBody) //changed the method to POST + if err != nil { + t.Fatal(err) + } + assert.Equal(t, true, alert.Enabled) + customAlertBody = CustomAlertBody{ + TagName: "CMDEXE", + LongName: "Janitha Long Name", + Action: "flagged", + Enabled: false, + Interval: 1, + Threshold: 1, + } + alertup, err := sc.UpdateCustomAlert(corp, site, alert.ID, customAlertBody) + assert.Equal(t, false, alertup.Enabled) + assert.Equal(t, alert.ID, alertup.ID) + err = sc.DeleteCustomAlert(corp, site, alert.ID) + _, err = sc.GetCustomAlert(corp, site, alert.ID) + if err == nil { //expect a failure because the ID does not exist + t.Fatal(err) + } + // assert.Equal(t, alert.ID, alertdel.ID) +} + +func TestCreateSiteRules(t *testing.T) { + + siteRulesBody := CreateSiteRulesBody{ + Type: "signal", + GroupOperator: "all", + Enabled: true, + Reason: "Example site rule", + Signal: "SQLI", + Expiration: "", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "1.2.3.4", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "5.6.7.8", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + } + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + rules, err := sc.CreateSiteRules(corp, site, siteRulesBody) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, siteRulesBody, *rules.CreateSiteRulesBody) + err = sc.DeleteSiteRule(corp, site, rules.ID) + if err != nil { + t.Fatal(err) + } +} +func TestUpdateSiteRules(t *testing.T) { + + siteRulesBody := CreateSiteRulesBody{ + Type: "signal", + GroupOperator: "all", + Enabled: true, + Reason: "Example site rule", + Signal: "SQLI", + Expiration: "", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "1.2.3.4", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "5.6.7.8", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + } + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + rule, err := sc.CreateSiteRules(corp, site, siteRulesBody) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, siteRulesBody, *rule.CreateSiteRulesBody) + + siteUpdatedBody := CreateSiteRulesBody{ + Type: "signal", + GroupOperator: "all", + Enabled: true, + Reason: "Example site rule", + Signal: "SQLI", + Expiration: "", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "1.2.3.4", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "9.10.11.12", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + } + updatedRule, err := sc.UpdateSiteRule(corp, site, *&rule.ID, siteUpdatedBody) + assert.Equal(t, siteUpdatedBody, *updatedRule.CreateSiteRulesBody) + err = sc.DeleteSiteRule(corp, site, rule.ID) + if err != nil { + t.Fatal(err) + } +} +func TestListSiteRules(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + _, err := sc.ListSiteRules(corp, site) + if err != nil { + t.Fatal(err) + } +} + +func TestUnMarshalListData(t *testing.T) { + resp := []byte(`{ + "totalCount": 1, + "data": [ + { + "id": "5e84ec28bf612801c7f0f109", + "siteNames": [ + "splunk-test" + ], + "type": "signal", + "enabled": true, + "groupOperator": "all", + "conditions": [ + { + "type": "single", + "field": "ip", + "operator": "equals", + "value": "1.2.3.4" + } + ], + "actions": [ + { + "type": "excludeSignal" + } + ], + "signal": "SQLI", + "reason": "Example site rule", + "expiration": "", + "createdBy": "janitha.jayaweera@gmail.com", + "created": "2020-04-01T19:31:52Z", + "updated": "2020-04-01T19:31:52Z" + } + ] + }`) + + var responseRulesList ResponseSiteRulesListData + err := json.Unmarshal(resp, &responseRulesList) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 1, responseRulesList.TotalCount) + assert.Equal(t, 1, len(responseRulesList.Data)) + assert.Equal(t, "5e84ec28bf612801c7f0f109", responseRulesList.Data[0].ID) +} + +func TestDeleteAllSiteRules(t *testing.T) { + t.SkipNow() + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + respList, err := sc.ListSiteRules(corp, site) + if err != nil { + t.Fatal(err) + } + // assert.Equal(t, 0, len(respList)) + for _, rule := range respList { + sc.DeleteSiteRule(corp, site, rule.ID) + } + respList, err = sc.ListSiteRules(corp, site) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 0, len(respList)) +} + +func TestGetSiteRuleById(t *testing.T) { + siteRulesBody := CreateSiteRulesBody{ + Type: "signal", + GroupOperator: "all", + Enabled: true, + Reason: "Example site rule", + Signal: "SQLI", + Expiration: "", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "1.2.3.4", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "5.6.7.8", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + } + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + rule, err := sc.CreateSiteRules(corp, site, siteRulesBody) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, siteRulesBody, *rule.CreateSiteRulesBody) + + readRule, err := sc.GetSiteRuleById(corp, site, *&rule.ID) + + if err != nil { + t.Fatal(err) + } + assert.Equal(t, siteRulesBody, *readRule.CreateSiteRulesBody) + + err = sc.DeleteSiteRule(corp, site, rule.ID) + if err != nil { + t.Fatal(err) + } +} +func TestSigSciAPI(t *testing.T) { + testCases := map[string]map[string]func(t *testing.T){ + "Site": { + "create": TestCreateSite, + "delete": TestDeleteSite, + }, + "Rule": { + "list": TestListSiteRules, + "createdelete": TestCreateSiteRules, + "createreaddelete": TestGetSiteRuleById, + "createupdatedelete": TestUpdateSiteRules, + "delete": TestDeleteAllSiteRules, + }, + } + for group, m := range testCases { + m := m + t.Run(group, func(t *testing.T) { + for name, tc := range m { + tc := tc + t.Run(name, func(t *testing.T) { + tc(t) + }) + } + }) + } +} From f2efe0a63565afcb19267b388c02fefaa6ec424c Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Tue, 14 Apr 2020 15:15:35 -0700 Subject: [PATCH 06/17] Adds apis for site redactions and lists. Readactions returns all redactions I assume that the list is ordered and the last one is taken to be the one that was created. A test checks for this Test for alerts and lists also added. gitignore adds settings and launch file --- .gitignore | 2 + api.go | 284 ++++++++++++++++++++++++++++++++++++++++++++++++---- api_test.go | 229 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 475 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index ea5c68e..3e88108 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ *.out .idea/ +.vscode/settings.json +.vscode/launch.json diff --git a/api.go b/api.go index 4098a91..c965a51 100644 --- a/api.go +++ b/api.go @@ -530,14 +530,11 @@ func (sc *Client) UpdateSite(corpName, siteName string, body UpdateSiteBody) (Si // CustomAlert contains the data for a custom alert type CustomAlert struct { + *CustomAlertBody ID string - SiteID string - TagName string - Interval int - Threshold int - Enabled bool - Action string Created time.Time + CreatedBy string + Updated time.Time } // customAlertsResponse is the response for the alerts endpoint @@ -546,7 +543,7 @@ type customAlertsResponse struct { } // ListCustomAlerts lists custom alerts for a given corp and site. -func (sc *Client) ListCustomAlerts(corpName, siteName string) ([]CustomAlert, error) { +func (sc Client) ListCustomAlerts(corpName, siteName string) ([]CustomAlert, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), "") if err != nil { return []CustomAlert{}, err @@ -572,7 +569,7 @@ type CustomAlertBody struct { } // CreateCustomAlert creates a custom alert. -func (sc *Client) CreateCustomAlert(corpName, siteName string, body CustomAlertBody) (CustomAlert, error) { +func (sc Client) CreateCustomAlert(corpName, siteName string, body CustomAlertBody) (CustomAlert, error) { b, err := json.Marshal(body) if err != nil { return CustomAlert{}, err @@ -593,7 +590,7 @@ func (sc *Client) CreateCustomAlert(corpName, siteName string, body CustomAlertB } // GetCustomAlert gets a custom alert by ID -func (sc *Client) GetCustomAlert(corpName, siteName, id string) (CustomAlert, error) { +func (sc Client) GetCustomAlert(corpName, siteName, id string) (CustomAlert, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") if err != nil { return CustomAlert{}, err @@ -609,15 +606,15 @@ func (sc *Client) GetCustomAlert(corpName, siteName, id string) (CustomAlert, er } // UpdateCustomAlert updates a custom alert by id. -func (sc *Client) UpdateCustomAlert(corpName, siteName, id string, body CustomAlertBody) (CustomAlert, error) { +func (sc Client) UpdateCustomAlert(corpName, siteName, id string, body CustomAlertBody) (CustomAlert, error) { b, err := json.Marshal(body) if err != nil { - return CustomAlert{}, err + return CustomAlert{}, fmt.Errorf("%s with input %#v", err.Error(), string(b)) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), string(b)) if err != nil { - return CustomAlert{}, err + return CustomAlert{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } var c CustomAlert @@ -630,7 +627,7 @@ func (sc *Client) UpdateCustomAlert(corpName, siteName, id string, body CustomAl } // DeleteCustomAlert deletes a custom alert. -func (sc *Client) DeleteCustomAlert(corpName, siteName, id string) error { +func (sc Client) DeleteCustomAlert(corpName, siteName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") return err @@ -1801,6 +1798,12 @@ type ResponseSiteRulesBody struct { Updated string `json:"updated"` } +// ResponseSiteRulesListData contains the returned rules +type ResponseSiteRulesListData struct { + TotalCount int `json:"totalCount"` + Data []ResponseSiteRulesBody `json:"data"` +} + // CreateSiteRules creates a rule and returns the response func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { b, err := json.Marshal(body) @@ -1809,7 +1812,7 @@ func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateS } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), string(b)) if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRulesBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } return getResponseSiteRulesBody(resp) } @@ -1822,7 +1825,7 @@ func (sc *Client) UpdateSiteRule(corpName string, siteName string, id string, bo } resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRulesBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } return getResponseSiteRulesBody(resp) } @@ -1849,12 +1852,6 @@ func getResponseSiteRulesBody(response []byte) (ResponseSiteRulesBody, error) { return responseSiteRules, nil } -// ResponseSiteRulesListData contains the returned rules -type ResponseSiteRulesListData struct { - TotalCount int `json:"totalCount"` - Data []ResponseSiteRulesBody `json:"data"` -} - // ListSiteRules Lists the Site Rules func (sc *Client) ListSiteRules(corpName string, siteName string) ([]ResponseSiteRulesBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") @@ -1871,3 +1868,248 @@ func (sc *Client) ListSiteRules(corpName string, siteName string) ([]ResponseSit return responseRulesList.Data, nil } + +// CreateSiteListBody Create Site List Request +type CreateSiteListBody struct { + Name string `json:"name"` //Descriptive list name + Type string `json:"type"` //List types (string, ip, country, wildcard) + Description string `json:"description"` //Optional list description + Entries []string `json:"entries"` //List entries + // *UpdateSiteListBody +} + +// UpdateSiteListBody update site list +type UpdateSiteListBody struct { + Description string `json:"description"` //Optional list description + Entries Entries `json:"entries"` //List entries +} + +//Entries List entries +type Entries struct { + Additions []string `json:"additions"` //List additions + Deletions []string `json:"deletions"` // List deletions +} + +// ResponseSiteListBody contains the response from creating the rule +type ResponseSiteListBody struct { + *CreateSiteListBody + ID string `json:"id"` //Site-specific unique ID of the list + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created string `json:"created"` //Created RFC3339 date time + Updated string `json:"updated"` //Last updated RFC3339 date time +} + +//ResponseSiteListListData contains the returned rules +type ResponseSiteListListData struct { + TotalCount int `json:"totalCount"` + Data []ResponseSiteListBody `json:"data"` //Site List data +} + +//CreateSiteList Create a site list +func (sc Client) CreateSiteList(corpName string, siteName string, body CreateSiteListBody) (ResponseSiteListBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteListBody{}, err + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/lists", corpName, siteName), string(b)) + if err != nil { + return ResponseSiteListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseSiteListBody(resp) +} + +func getResponseSiteListBody(response []byte) (ResponseSiteListBody, error) { + var responseBody ResponseSiteListBody + err := json.Unmarshal(response, &responseBody) + if err != nil { + return ResponseSiteListBody{}, err + } + return responseBody, nil +} + +// UpdateSiteListByID updates a site list and returns a response +func (sc Client) UpdateSiteListByID(corpName string, siteName string, id string, body UpdateSiteListBody) (ResponseSiteListBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteListBody{}, err + } + resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), string(b)) + if err != nil { + return ResponseSiteListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseSiteListBody(resp) +} + +// DeleteSiteListByID deletes a rule and returns an error +func (sc Client) DeleteSiteListByID(corpName string, siteName string, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") + return err +} + +// GetSiteListByID get site list by ID +func (sc Client) GetSiteListByID(corpName string, siteName string, id string) (ResponseSiteListBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") + if err != nil { + return ResponseSiteListBody{}, err + } + return getResponseSiteListBody(resp) +} + +// CreateSiteRedactionBody Create redaction Request +type CreateSiteRedactionBody struct { + Field string `json:"field"` //Field name + RedactionType int `json:"redactionType"` //Type of redaction (0: Request Parameter, 1: Request Header, 2: Response Header) +} + +//UpdateSiteRedactionBody update site redaction +type UpdateSiteRedactionBody CreateSiteRedactionBody + +// ResponseSiteRedactionBody redaction response +type ResponseSiteRedactionBody struct { + *CreateSiteRedactionBody + ID string `json:"id"` //Site-specific unique ID of the list + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created string `json:"created"` //Created RFC3339 date time + // Updated string `json:"updated"` //Last updated RFC3339 date time +} + +//ResponseSiteRedactionBodyList redaction response list +type ResponseSiteRedactionBodyList struct { + // TotalCount int `json:"totalCount"` + Data []ResponseSiteRedactionBody `json:"data"` //Site Redaction data +} + +//CreateSiteRedaction Create a site list +func (sc Client) CreateSiteRedaction(corpName string, siteName string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteRedactionBody{}, err + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), string(b)) + if err != nil { + return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + redactionsData, err := getResponseSiteRedactionListBody(resp) + // if len(redactionsData.Data) > 1 { + // fn := runtime.FuncForPC(splitTuple(runtime.Caller(0))[0].(uintptr)).Name() + // return ResponseSiteRedactionBody{}, fmt.Errorf("%s was expecting a single result got #%v", fn, redactionsData) + // } + return redactionsData.Data[len(redactionsData.Data)-1], err +} + +func splitTuple(tuple ...interface{}) []interface{} { + return tuple +} + +func getResponseSiteRedactionListBody(response []byte) (ResponseSiteRedactionBodyList, error) { + var responseBody ResponseSiteRedactionBodyList + err := json.Unmarshal(response, &responseBody) + if err != nil { + return ResponseSiteRedactionBodyList{}, err + } + return responseBody, nil +} + +func getResponseSiteRedactionBody(response []byte) (ResponseSiteRedactionBody, error) { + var responseBody ResponseSiteRedactionBody + err := json.Unmarshal(response, &responseBody) + if err != nil { + return ResponseSiteRedactionBody{}, err + } + return responseBody, nil +} + +// UpdateSiteRedactionByID updates a site redaction and returns a response +func (sc Client) UpdateSiteRedactionByID(corpName string, siteName string, id string, body UpdateSiteRedactionBody) (ResponseSiteRedactionBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSiteRedactionBody{}, err + } + resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), string(b)) + if err != nil { + return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + // log.Printf("%#v", string(resp)) + return getResponseSiteRedactionBody(resp) + // if err != nil { + // return ResponseSiteRedactionBodyList{}, err + // } + // return ResponseSiteRedactionBodyList{ + // Data: []ResponseSiteRedactionBody{singleResp}, + // }, nil +} + +//GetSiteRedactionByID get a site redaction by id +func (sc Client) GetSiteRedactionByID(corpName, siteName, id string) (ResponseSiteRedactionBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") + if err != nil { + return ResponseSiteRedactionBody{}, err + } + return getResponseSiteRedactionBody(resp) + // if err != nil { + // return ResponseSiteRedactionBodyList{}, err + // } + // fmt.Printf("%#v", string(resp)) + // return ResponseSiteRedactionBodyList{ + // Data: []ResponseSiteRedactionBody{singleResp}, + // }, nil + // return ResponseSiteRedactionBodyList{}, nil +} + +// DeleteSiteRedactionByID deletes a redaction and returns an error +func (sc Client) DeleteSiteRedactionByID(corpName string, siteName string, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") + return err +} + +// ListSiteRedactions Lists the Sites Redactions +func (sc *Client) ListSiteRedactions(corpName string, siteName string) (ResponseSiteRedactionBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), "") + + if err != nil { + return ResponseSiteRedactionBodyList{}, err + } + + var responseRulesList ResponseSiteRulesListData + err = json.Unmarshal(resp, &responseRulesList) + if err != nil { + return ResponseSiteRedactionBodyList{}, err + } + + return getResponseSiteRedactionListBody(resp) +} + +// GetSiteListByID get site list by ID +// func (sc Client) GetSiteListByID(corpName string, siteName string, id string) (ResponseSiteListBody, error) { +// resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") +// if err != nil { +// return ResponseSiteListBody{}, err +// } +// return getResponseSiteListBody(resp) +// } + +// func getResponseSiteRulesBody(response []byte) (ResponseSiteRulesBody, error) { +// var responseSiteRules ResponseSiteRulesBody +// err := json.Unmarshal(response, &responseSiteRules) +// if err != nil { +// return ResponseSiteRulesBody{}, err +// } +// return responseSiteRules, nil +// } + +// // ListSiteRules Lists the Site Rules +// func (sc *Client) ListSiteLists(corpName string, siteName string) ([]ResponseSiteRulesBody, error) { +// resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") + +// if err != nil { +// return []ResponseSiteRulesBody{}, err +// } + +// var responseRulesList ResponseSiteRulesListData +// err = json.Unmarshal(resp, &responseRulesList) +// if err != nil { +// return []ResponseSiteRulesBody{}, err +// } + +// return responseRulesList.Data, nil +// } diff --git a/api_test.go b/api_test.go index 3982645..7c8617b 100644 --- a/api_test.go +++ b/api_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "log" "os" + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -60,7 +61,7 @@ func TestGoUserTokenClient(t *testing.T) { }) } } -func TestCreateSite(t *testing.T) { +func TestCreateDeleteSite(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-testcorp" @@ -70,24 +71,17 @@ func TestCreateSite(t *testing.T) { AgentLevel: "Log", BlockHTTPCode: 406, BlockDurationSeconds: 86400, - AgentAnonMode: "off", + AgentAnonMode: "", } - _, err := sc.CreateSite(corp, siteBody) - if err == nil { - t.Fatal("Can create more than one site. Clean up not implemented") + siteresponse, err := sc.CreateSite(corp, siteBody) + if err != nil { + t.Fatal(err) } - assert.Equal(t, "Site limit reached", err.Error()) - -} -func TestDeleteSite(t *testing.T) { - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-testcorp" - site := "janitha-test-site" //do not have permission at the moment anyway - err := sc.DeleteSite(corp, site) - if err == nil { - t.Fatalf("This site %s should not exist", site) + assert.Equal(t, "Janitha Test Site", siteresponse.DisplayName) + err = sc.DeleteSite(corp, siteBody.Name) + if err != nil { + t.Logf("%#v", err) } - assert.Equal(t, "Site not found", err.Error()) } func TestGetAlerts(t *testing.T) { t.Skip() @@ -324,7 +318,7 @@ func TestUnMarshalListData(t *testing.T) { } func TestDeleteAllSiteRules(t *testing.T) { - t.SkipNow() + // t.SkipNow() sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" @@ -398,11 +392,12 @@ func TestGetSiteRuleById(t *testing.T) { t.Fatal(err) } } + func TestSigSciAPI(t *testing.T) { + t.SkipNow() testCases := map[string]map[string]func(t *testing.T){ "Site": { - "create": TestCreateSite, - "delete": TestDeleteSite, + "createdelete": TestCreateDeleteSite, }, "Rule": { "list": TestListSiteRules, @@ -424,3 +419,199 @@ func TestSigSciAPI(t *testing.T) { }) } } + +func TestCreateReadUpdateDeleteSiteList(t *testing.T) { + testCases := []struct { + createFunc func(string, string, CreateSiteListBody) (ResponseSiteListBody, error) + deleteFunc func(string, string, string) error + createBody interface{} + createBodyType string + }{ + { + NewTokenClient(testcreds.email, testcreds.token).CreateSiteList, //this is method I think these works for functions + NewTokenClient(testcreds.email, testcreds.token).DeleteSiteListByID, + CreateSiteListBody{ + Name: "My new List", + Type: "ip", + Description: "Some IPs we are putting in a list", + Entries: []string{ + "4.5.6.7", + "2.3.4.5", + "1.2.3.4", + }, + }, + "CreateSiteListBody", + }, + } + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + + // createresp, err := sc.CreateSiteList(corp, site, siteListBody) + mytype := reflect.TypeOf(testCases[0].createBody) + // myval := reflect.ValueOf(testCases[0].createBody) + + // t.Logf("%v, %v", mytype, myval) + assert.Equal(t, mytype, reflect.TypeOf(CreateSiteListBody{})) + createresp, err := testCases[0].createFunc(corp, site, testCases[0].createBody.(CreateSiteListBody)) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, testCases[0].createBody.(CreateSiteListBody), *createresp.CreateSiteListBody) + readresp, err := sc.GetSiteListByID(corp, site, createresp.ID) + assert.Equal(t, testCases[0].createBody.(CreateSiteListBody), *readresp.CreateSiteListBody) + + updateSiteListBody := UpdateSiteListBody{ + Description: "Some IPs we are updating in the list", + Entries: Entries{ + Additions: []string{"3.4.5.6"}, + Deletions: []string{"4.5.6.7"}, + }, + } + updatedresp, err := sc.UpdateSiteListByID(corp, site, readresp.ID, updateSiteListBody) + if err != nil { + t.Fatal(err) + } + assert.NotEqual(t, testCases[0].createBody.(CreateSiteListBody), *updatedresp.CreateSiteListBody) + err = sc.DeleteSiteListByID(corp, site, readresp.ID) + if err != nil { + t.Fatal(err) + } +} + +func TestCreateMultipleRedactions(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + + createSiteRedactionBody := CreateSiteRedactionBody{ + Field: "privatefield", + RedactionType: 2, + } + createresp, err := sc.CreateSiteRedaction(corp, site, createSiteRedactionBody) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createSiteRedactionBody, *createresp.CreateSiteRedactionBody) + + createSiteRedactionBody2 := CreateSiteRedactionBody{ + Field: "cookie", + RedactionType: 2, + } + createresp2, err := sc.CreateSiteRedaction(corp, site, createSiteRedactionBody2) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createSiteRedactionBody2, *createresp2.CreateSiteRedactionBody) + + createSiteRedactionBody3 := CreateSiteRedactionBody{ + Field: "cookie", + RedactionType: 1, + } + createresp3, err := sc.CreateSiteRedaction(corp, site, createSiteRedactionBody3) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createSiteRedactionBody3, *createresp3.CreateSiteRedactionBody) + + err = sc.DeleteSiteRedactionByID(corp, site, createresp.ID) + if err != nil { + t.Fatal(err) + } + err = sc.DeleteSiteRedactionByID(corp, site, createresp2.ID) + if err != nil { + t.Fatal(err) + } + err = sc.DeleteSiteRedactionByID(corp, site, createresp3.ID) + if err != nil { + t.Fatal(err) + } +} +func TestCreatListUpdateDeleteRedaction(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + + createSiteRedactionBody := CreateSiteRedactionBody{ + Field: "privatefield", + RedactionType: 2, + } + createresp, err := sc.CreateSiteRedaction(corp, site, createSiteRedactionBody) + + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, createSiteRedactionBody, *createresp.CreateSiteRedactionBody) + + listresp, err := sc.ListSiteRedactions(corp, site) + assert.Equal(t, 1, len(listresp.Data)) + + readresp, err := sc.GetSiteRedactionByID(corp, site, createresp.ID) + assert.Equal(t, createSiteRedactionBody, *readresp.CreateSiteRedactionBody) + + updateSiteRedactionBody := UpdateSiteRedactionBody{ + Field: "cookie", + RedactionType: 1, + } + updatedresp, err := sc.UpdateSiteRedactionByID(corp, site, createresp.ID, updateSiteRedactionBody) + if err != nil { + t.Fatal(err) + } + + assert.NotEqual(t, createSiteRedactionBody, *updatedresp.CreateSiteRedactionBody) + assert.Equal(t, updateSiteRedactionBody.Field, *&updatedresp.CreateSiteRedactionBody.Field) + assert.Equal(t, updateSiteRedactionBody.RedactionType, *&updatedresp.CreateSiteRedactionBody.RedactionType) + + err = sc.DeleteSiteRedactionByID(corp, site, createresp.ID) + if err != nil { + t.Fatal(err) + } +} + +func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + + createCustomAlert := CustomAlertBody{ + TagName: "SQLI", + LongName: "Example Alert", + Interval: 1, + Threshold: 10, + Enabled: true, + Action: "flagged", + } + createresp, err := sc.CreateCustomAlert(corp, site, createCustomAlert) + // t.Logf("%#v", createresp.Data) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createCustomAlert, *createresp.CustomAlertBody) + readresp, err := sc.GetCustomAlert(corp, site, createresp.ID) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createCustomAlert, *readresp.CustomAlertBody) + + updateCustomAlert := CustomAlertBody{ + TagName: "SQLI", + LongName: "Example Alert Updated", + Interval: 10, + Threshold: 10, + Enabled: true, + Action: "flagged", + } + updateresp, err := sc.UpdateCustomAlert(corp, site, readresp.ID, updateCustomAlert) + if err != nil { + t.Fatal(err) + } + // t.Logf("%#v", updateresp) + assert.NotEqual(t, createCustomAlert, *updateresp.CustomAlertBody) + assert.Equal(t, updateCustomAlert, *updateresp.CustomAlertBody) + + err = sc.DeleteCustomAlert(corp, site, createresp.ID) + if err != nil { + t.Fatal(err) + } +} From 254205a5d4507a39f9c464e63819522fb6f3af17 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Fri, 17 Apr 2020 17:29:47 -0700 Subject: [PATCH 07/17] api_test combine crud operations into a single test api corp rules and lists. using the same List structure for corps and site. Did not combine the corp rules and site rules structures sitenames and corpscope are additions to it. To some extent influenced by the existing code that doesn't combine and update and create nor the response. --- api.go | 422 +++++++++++++++++++++++++++++++--------------------- api_test.go | 302 +++++++++++++++++++++---------------- go.mod | 4 +- 3 files changed, 429 insertions(+), 299 deletions(-) diff --git a/api.go b/api.go index c965a51..3dfa377 100644 --- a/api.go +++ b/api.go @@ -1419,7 +1419,6 @@ func (sc *Client) AddSiteMember(corpName, siteName, email string) (SiteMemberRes // DeleteSiteMember deletes a site member by email. func (sc *Client) DeleteSiteMember(corpName, siteName, email string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/members/%s", corpName, siteName, email), "") - return err } @@ -1727,250 +1726,261 @@ func (sc *Client) GetTimeseries(corpName, siteName string, query url.Values) ([] // CreateSiteBody is the structure required to create a Site. type CreateSiteBody struct { - Name string `json:"name"` - DisplayName string `json:"displayName,omitempty"` - AgentLevel string `json:"agentLevel,omitempty"` - AgentAnonMode string `json:"agentAnonMode,omiempty"` - BlockHTTPCode int `json:"blockHTTPCode,omitempty"` - BlockDurationSeconds int `json:"blockDurationSeconds,omitempty"` + Name string `json:"name,omitempty"` //Identifying name of the site + DisplayName string `json:"displayName,omitempty"` //Display name of the site + AgentLevel string `json:"agentLevel,omitempty"` //Agent action level - 'block', 'log' or 'off' + AgentAnonMode string `json:"agentAnonMode,omitempty"` //Agent IP anonimization mode - 'EU' or 'off' + BlockHTTPCode int `json:"blockHTTPCode,omitempty"` //HTTP response code to send when when traffic is being blocked + BlockDurationSeconds int `json:"blockDurationSeconds"` //Duration to block an IP in seconds } // CreateSite Creates a site in a corp. -func (sc *Client) CreateSite(corpName string, body CreateSiteBody) (Site, error) { +func (sc Client) CreateSite(corpName string, body CreateSiteBody) (Site, error) { b, err := json.Marshal(body) if err != nil { - return Site{}, err + return Site{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites", corpName), string(b)) if err != nil { - return Site{}, err + return Site{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } var site Site err = json.Unmarshal(resp, &site) if err != nil { - return Site{}, err + return Site{}, fmt.Errorf("%s with input %v", err.Error(), resp) } return site, nil } // DeleteSite deltes the site -func (sc *Client) DeleteSite(corpName string, siteName string) error { +func (sc Client) DeleteSite(corpName, siteName string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s", corpName, siteName), "") - return err + if err != nil { + return fmt.Errorf("%s could not delete %s in %s ", err.Error(), corpName, siteName) + } + return nil } // Condition contains rule condition type Condition struct { - Type string `json:"type"` - GroupOperator string `json:"groupOperator"` - Field string `json:"field"` - Operator string `json:"operator"` - Value string `json:"value"` - Conditions []Condition `json:"conditions"` + Type string `json:"type,omitempty"` //(group, single) + GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Field string `json:"field,omitempty"` //type: single - (scheme, method, path, useragent, domain, ip, responseCode, agentname, paramname, paramvalue, country, name, valueString, valueIp, signalType) + Operator string `json:"operator,omitempty"` //type: single - (equals, doesNotEqual, contains, doesNotContain, like, notLike, exists, doesNotExist, inList, notInList) + Value string `json:"value,omitempty"` //type: single - See request fields (https://docs.signalsciences.net/using-signal-sciences/features/rules/#request-fields) + Conditions []Condition `json:"conditions,omitempty"` } // Action contains the rule action type Action struct { - Type string `json:"type"` + Type string `json:"type,omitempty"` //(block, allow, exclude) } -// CreateSiteRulesBody contains the rule for the site -type CreateSiteRulesBody struct { - Type string `json:"type"` - GroupOperator string `json:"groupOperator"` - Enabled bool `json:"enabled"` - Reason string `json:"reason"` - Signal string `json:"signal"` - Expiration string `json:"expiration"` - Conditions []Condition `json:"conditions"` - Actions []Action `json:"actions"` +//CreateSiteRuleBody contains the rule for the site +type CreateSiteRuleBody struct { + Type string `json:"type,omitempty,omitempty"` //(group, single) + GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Enabled bool `json:"enabled,omitempty"` + Reason string `json:"reason,omitempty"` //Description of the rule + Signal string `json:"signal,omitempty"` //The signal id of the signal being excluded + Expiration string `json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string + Conditions []Condition `json:"conditions,omitempty"` + Actions []Action `json:"actions,omitempty"` } -// ResponseSiteRulesBody contains the response from creating the rule -type ResponseSiteRulesBody struct { - *CreateSiteRulesBody - ID string `json:"id"` - CreatedBy string `json:"createdby"` - Created string `json:"created"` - Updated string `json:"updated"` +// ResponseSiteRuleBody contains the response from creating the rule +type ResponseSiteRuleBody struct { + *CreateSiteRuleBody + ID string `json:"id"` //internal ID + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created time.Time `json:"created"` //Created RFC3339 date time + Updated time.Time `json:"updated"` //Last updated RFC3339 date time } -// ResponseSiteRulesListData contains the returned rules -type ResponseSiteRulesListData struct { - TotalCount int `json:"totalCount"` - Data []ResponseSiteRulesBody `json:"data"` +// ResponseSiteRuleListData contains the returned rules +type ResponseSiteRuleListData struct { + TotalCount int `json:"totalCount"` + Data []ResponseSiteRuleBody `json:"data"` } -// CreateSiteRules creates a rule and returns the response -func (sc *Client) CreateSiteRules(corpName string, siteName string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { +// CreateSiteRule creates a rule and returns the response +func (sc *Client) CreateSiteRule(corpName, siteName string, body CreateSiteRuleBody) (ResponseSiteRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), string(b)) if err != nil { - return ResponseSiteRulesBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } - return getResponseSiteRulesBody(resp) + return getResponseSiteRuleBody(resp) } -// UpdateSiteRule updates a rule and returns a response -func (sc *Client) UpdateSiteRule(corpName string, siteName string, id string, body CreateSiteRulesBody) (ResponseSiteRulesBody, error) { +// UpdateSiteRuleByID updates a rule and returns a response +func (sc Client) UpdateSiteRuleByID(corpName, siteName, id string, body CreateSiteRuleBody) (ResponseSiteRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseSiteRulesBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } - return getResponseSiteRulesBody(resp) + return getResponseSiteRuleBody(resp) } -// DeleteSiteRule deletes a rule and returns an error -func (sc *Client) DeleteSiteRule(corpName string, siteName string, id string) error { +// DeleteSiteRuleByID deletes a rule and returns an error +func (sc Client) DeleteSiteRuleByID(corpName, siteName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") - return err + if err != nil { + return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + } + return nil } -func (sc *Client) GetSiteRuleById(corpName string, siteName string, id string) (ResponseSiteRulesBody, error) { + +//GetSiteRuleByID get a site rule by id +func (sc Client) GetSiteRuleByID(corpName, siteName, id string) (ResponseSiteRuleBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRuleBody{}, fmt.Errorf("%s could not get %s in %s in %s", err.Error(), id, siteName, corpName) } - return getResponseSiteRulesBody(resp) + return getResponseSiteRuleBody(resp) } -func getResponseSiteRulesBody(response []byte) (ResponseSiteRulesBody, error) { - var responseSiteRules ResponseSiteRulesBody +func getResponseSiteRuleBody(response []byte) (ResponseSiteRuleBody, error) { + var responseSiteRules ResponseSiteRuleBody err := json.Unmarshal(response, &responseSiteRules) if err != nil { - return ResponseSiteRulesBody{}, err + return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), response) } return responseSiteRules, nil } // ListSiteRules Lists the Site Rules -func (sc *Client) ListSiteRules(corpName string, siteName string) ([]ResponseSiteRulesBody, error) { +func (sc *Client) ListSiteRules(corpName, siteName string) ([]ResponseSiteRuleBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") if err != nil { - return []ResponseSiteRulesBody{}, err + return []ResponseSiteRuleBody{}, err } - var responseRulesList ResponseSiteRulesListData + var responseRulesList ResponseSiteRuleListData err = json.Unmarshal(resp, &responseRulesList) if err != nil { - return []ResponseSiteRulesBody{}, err + return []ResponseSiteRuleBody{}, err } return responseRulesList.Data, nil } -// CreateSiteListBody Create Site List Request -type CreateSiteListBody struct { - Name string `json:"name"` //Descriptive list name - Type string `json:"type"` //List types (string, ip, country, wildcard) - Description string `json:"description"` //Optional list description - Entries []string `json:"entries"` //List entries +// CreateListBody Create List Request +type CreateListBody struct { + Name string `json:"name,omitempty"` //Descriptive list name + Type string `json:"type,omitempty"` //List types (string, ip, country, wildcard) + Description string `json:"description,omitempty"` //Optional list description + Entries []string `json:"entries,omitempty"` //List entries // *UpdateSiteListBody } -// UpdateSiteListBody update site list -type UpdateSiteListBody struct { - Description string `json:"description"` //Optional list description - Entries Entries `json:"entries"` //List entries +// UpdateListBody update list +type UpdateListBody struct { + Description string `json:"description,omitempty"` //Optional list description + Entries Entries `json:"entries,omitempty"` //List entries } //Entries List entries type Entries struct { - Additions []string `json:"additions"` //List additions - Deletions []string `json:"deletions"` // List deletions + Additions []string `json:"additions,omitempty"` //List additions + Deletions []string `json:"deletions,omitempty"` // List deletions } -// ResponseSiteListBody contains the response from creating the rule -type ResponseSiteListBody struct { - *CreateSiteListBody - ID string `json:"id"` //Site-specific unique ID of the list - CreatedBy string `json:"createdby"` //Email address of the user that created the item - Created string `json:"created"` //Created RFC3339 date time - Updated string `json:"updated"` //Last updated RFC3339 date time +// ResponseListBody contains the response from creating the list +type ResponseListBody struct { + *CreateListBody + ID string `json:"id"` //internal ID + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created time.Time `json:"created"` //Created RFC3339 date time + Updated time.Time `json:"updated"` //Last updated RFC3339 date time } -//ResponseSiteListListData contains the returned rules -type ResponseSiteListListData struct { - TotalCount int `json:"totalCount"` - Data []ResponseSiteListBody `json:"data"` //Site List data +//ResponseListListData contains the returned list +type ResponseListListData struct { + TotalCount int `json:"totalCount"` + Data []ResponseListBody `json:"data"` //Site List data } //CreateSiteList Create a site list -func (sc Client) CreateSiteList(corpName string, siteName string, body CreateSiteListBody) (ResponseSiteListBody, error) { +func (sc Client) CreateSiteList(corpName, siteName string, body CreateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteListBody{}, err + return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/lists", corpName, siteName), string(b)) if err != nil { - return ResponseSiteListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } - return getResponseSiteListBody(resp) + return getResponseListBody(resp) } -func getResponseSiteListBody(response []byte) (ResponseSiteListBody, error) { - var responseBody ResponseSiteListBody +func getResponseListBody(response []byte) (ResponseListBody, error) { + var responseBody ResponseListBody err := json.Unmarshal(response, &responseBody) if err != nil { - return ResponseSiteListBody{}, err + return ResponseListBody{}, err } return responseBody, nil } // UpdateSiteListByID updates a site list and returns a response -func (sc Client) UpdateSiteListByID(corpName string, siteName string, id string, body UpdateSiteListBody) (ResponseSiteListBody, error) { +func (sc Client) UpdateSiteListByID(corpName, siteName string, id string, body UpdateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteListBody{}, err + return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseSiteListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } - return getResponseSiteListBody(resp) + return getResponseListBody(resp) } // DeleteSiteListByID deletes a rule and returns an error -func (sc Client) DeleteSiteListByID(corpName string, siteName string, id string) error { +func (sc Client) DeleteSiteListByID(corpName, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") - return err + if err != nil { + return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + } + return nil } // GetSiteListByID get site list by ID -func (sc Client) GetSiteListByID(corpName string, siteName string, id string) (ResponseSiteListBody, error) { +func (sc Client) GetSiteListByID(corpName, siteName string, id string) (ResponseListBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") if err != nil { - return ResponseSiteListBody{}, err + return ResponseListBody{}, err } - return getResponseSiteListBody(resp) + return getResponseListBody(resp) } // CreateSiteRedactionBody Create redaction Request type CreateSiteRedactionBody struct { - Field string `json:"field"` //Field name - RedactionType int `json:"redactionType"` //Type of redaction (0: Request Parameter, 1: Request Header, 2: Response Header) + Field string `json:"field,omitempty"` //Field name + RedactionType int `json:"redactionType"` //Type of redaction (0: Request Parameter, 1: Request Header, 2: Response Header) } //UpdateSiteRedactionBody update site redaction -type UpdateSiteRedactionBody CreateSiteRedactionBody +// type UpdateSiteRedactionBody CreateSiteRedactionBody // ResponseSiteRedactionBody redaction response type ResponseSiteRedactionBody struct { *CreateSiteRedactionBody - ID string `json:"id"` //Site-specific unique ID of the list - CreatedBy string `json:"createdby"` //Email address of the user that created the item - Created string `json:"created"` //Created RFC3339 date time - // Updated string `json:"updated"` //Last updated RFC3339 date time + ID string `json:"id"` //internal ID + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created time.Time `json:"created"` //Created RFC3339 date time + Updated time.Time `json:"updated"` //Last updated RFC3339 date time } //ResponseSiteRedactionBodyList redaction response list @@ -1980,20 +1990,17 @@ type ResponseSiteRedactionBodyList struct { } //CreateSiteRedaction Create a site list -func (sc Client) CreateSiteRedaction(corpName string, siteName string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { +func (sc Client) CreateSiteRedaction(corpName, siteName string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRedactionBody{}, err + return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), string(b)) if err != nil { return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } redactionsData, err := getResponseSiteRedactionListBody(resp) - // if len(redactionsData.Data) > 1 { - // fn := runtime.FuncForPC(splitTuple(runtime.Caller(0))[0].(uintptr)).Name() - // return ResponseSiteRedactionBody{}, fmt.Errorf("%s was expecting a single result got #%v", fn, redactionsData) - // } + return redactionsData.Data[len(redactionsData.Data)-1], err } @@ -2020,23 +2027,16 @@ func getResponseSiteRedactionBody(response []byte) (ResponseSiteRedactionBody, e } // UpdateSiteRedactionByID updates a site redaction and returns a response -func (sc Client) UpdateSiteRedactionByID(corpName string, siteName string, id string, body UpdateSiteRedactionBody) (ResponseSiteRedactionBody, error) { +func (sc Client) UpdateSiteRedactionByID(corpName, siteName string, id string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRedactionBody{}, err + return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), string(b)) if err != nil { return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) } - // log.Printf("%#v", string(resp)) return getResponseSiteRedactionBody(resp) - // if err != nil { - // return ResponseSiteRedactionBodyList{}, err - // } - // return ResponseSiteRedactionBodyList{ - // Data: []ResponseSiteRedactionBody{singleResp}, - // }, nil } //GetSiteRedactionByID get a site redaction by id @@ -2046,31 +2046,26 @@ func (sc Client) GetSiteRedactionByID(corpName, siteName, id string) (ResponseSi return ResponseSiteRedactionBody{}, err } return getResponseSiteRedactionBody(resp) - // if err != nil { - // return ResponseSiteRedactionBodyList{}, err - // } - // fmt.Printf("%#v", string(resp)) - // return ResponseSiteRedactionBodyList{ - // Data: []ResponseSiteRedactionBody{singleResp}, - // }, nil - // return ResponseSiteRedactionBodyList{}, nil } // DeleteSiteRedactionByID deletes a redaction and returns an error -func (sc Client) DeleteSiteRedactionByID(corpName string, siteName string, id string) error { +func (sc Client) DeleteSiteRedactionByID(corpName, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") - return err + if err != nil { + return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + } + return nil } // ListSiteRedactions Lists the Sites Redactions -func (sc *Client) ListSiteRedactions(corpName string, siteName string) (ResponseSiteRedactionBodyList, error) { +func (sc *Client) ListSiteRedactions(corpName, siteName string) (ResponseSiteRedactionBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), "") if err != nil { return ResponseSiteRedactionBodyList{}, err } - var responseRulesList ResponseSiteRulesListData + var responseRulesList ResponseSiteRuleListData err = json.Unmarshal(resp, &responseRulesList) if err != nil { return ResponseSiteRedactionBodyList{}, err @@ -2079,37 +2074,122 @@ func (sc *Client) ListSiteRedactions(corpName string, siteName string) (Response return getResponseSiteRedactionListBody(resp) } -// GetSiteListByID get site list by ID -// func (sc Client) GetSiteListByID(corpName string, siteName string, id string) (ResponseSiteListBody, error) { -// resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") -// if err != nil { -// return ResponseSiteListBody{}, err -// } -// return getResponseSiteListBody(resp) -// } - -// func getResponseSiteRulesBody(response []byte) (ResponseSiteRulesBody, error) { -// var responseSiteRules ResponseSiteRulesBody -// err := json.Unmarshal(response, &responseSiteRules) -// if err != nil { -// return ResponseSiteRulesBody{}, err -// } -// return responseSiteRules, nil -// } - -// // ListSiteRules Lists the Site Rules -// func (sc *Client) ListSiteLists(corpName string, siteName string) ([]ResponseSiteRulesBody, error) { -// resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") - -// if err != nil { -// return []ResponseSiteRulesBody{}, err -// } - -// var responseRulesList ResponseSiteRulesListData -// err = json.Unmarshal(resp, &responseRulesList) -// if err != nil { -// return []ResponseSiteRulesBody{}, err -// } - -// return responseRulesList.Data, nil -// } +//CreateCorpRuleBody contains the rule of a Corp +type CreateCorpRuleBody struct { + SiteNames []string `json:"siteNames,omitempty"` //Sites with the rule available. Rules with a global corpScope will return '[]'. + Type string `json:"type,omitempty,omitempty"` //(group, single) + CorpScope string `json:"corpScope,omitempty"` //Whether the rule is applied to all sites or to specific sites. (global, specificSites) + Enabled bool `json:"enabled,omitempty"` + GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Signal string `json:"signal,omitempty"` //The signal id of the signal being excluded + Reason string `json:"reason,omitempty"` //Description of the rule + Expiration string `json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string + Conditions []Condition `json:"conditions,omitempty"` + Actions []Action `json:"actions,omitempty"` +} + +// ResponseCorpRuleBody contains the response from creating the rule +type ResponseCorpRuleBody struct { + *CreateCorpRuleBody + ID string `json:"id"` + CreatedBy string `json:"createdby"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` +} + +// CreateCorpRule creates a rule and returns the response +func (sc *Client) CreateCorpRule(corpName string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/rules", corpName), string(b)) + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseCorpRuleBody(resp) +} + +// UpdateCorpRuleByID updates a rule and returns a response +func (sc Client) UpdateCorpRuleByID(corpName, id string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + } + resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), string(b)) + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseCorpRuleBody(resp) +} + +// DeleteCorpRuleByID deletes a rule and returns an error +func (sc Client) DeleteCorpRuleByID(corpName, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") + if err != nil { + return fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName) + } + return nil +} + +//GetCorpRuleByID get a site rule by id +func (sc Client) GetCorpRuleByID(corpName, id string) (ResponseCorpRuleBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s could not get %s in %s", err.Error(), id, corpName) + } + return getResponseCorpRuleBody(resp) +} + +func getResponseCorpRuleBody(response []byte) (ResponseCorpRuleBody, error) { + var responseCorpRule ResponseCorpRuleBody + err := json.Unmarshal(response, &responseCorpRule) + if err != nil { + return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), response) + } + return responseCorpRule, nil +} + +//CreateCorpList corp list +func (sc Client) CreateCorpList(corpName string, body CreateListBody) (ResponseListBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/lists", corpName), string(b)) + if err != nil { + return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseListBody(resp) +} + +// UpdateCorpListByID updates a corp list +func (sc Client) UpdateCorpListByID(corpName string, id string, body UpdateListBody) (ResponseListBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + } + resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), string(b)) + if err != nil { + return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + } + return getResponseListBody(resp) +} + +// DeleteCorpListByID deletes a rule and returns an error +func (sc Client) DeleteCorpListByID(corpName string, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), "") + if err != nil { + return fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName) + } + return nil +} + +// GetCorpListByID get corp list by ID +func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), "") + if err != nil { + return ResponseListBody{}, err + } + return getResponseListBody(resp) +} diff --git a/api_test.go b/api_test.go index 7c8617b..c4c7398 100644 --- a/api_test.go +++ b/api_test.go @@ -4,7 +4,6 @@ import ( "encoding/json" "log" "os" - "reflect" "testing" "github.com/stretchr/testify/assert" @@ -130,9 +129,9 @@ func TestCreateCustomSiteAlert(t *testing.T) { // assert.Equal(t, alert.ID, alertdel.ID) } -func TestCreateSiteRules(t *testing.T) { +func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { - siteRulesBody := CreateSiteRulesBody{ + createSiteRulesBody := CreateSiteRuleBody{ Type: "signal", GroupOperator: "all", Enabled: true, @@ -168,61 +167,18 @@ func TestCreateSiteRules(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" - rules, err := sc.CreateSiteRules(corp, site, siteRulesBody) + createResp, err := sc.CreateSiteRule(corp, site, createSiteRulesBody) if err != nil { t.Fatal(err) } - assert.Equal(t, siteRulesBody, *rules.CreateSiteRulesBody) - err = sc.DeleteSiteRule(corp, site, rules.ID) - if err != nil { - t.Fatal(err) - } -} -func TestUpdateSiteRules(t *testing.T) { + assert.Equal(t, createSiteRulesBody, *createResp.CreateSiteRuleBody) - siteRulesBody := CreateSiteRulesBody{ - Type: "signal", - GroupOperator: "all", - Enabled: true, - Reason: "Example site rule", - Signal: "SQLI", - Expiration: "", - Conditions: []Condition{ - Condition{ - Type: "single", - Field: "ip", - Operator: "equals", - Value: "1.2.3.4", - }, - Condition{ - Type: "group", - GroupOperator: "any", - Conditions: []Condition{ - Condition{ - Type: "single", - Field: "ip", - Operator: "equals", - Value: "5.6.7.8", - }, - }, - }, - }, - Actions: []Action{ - Action{ - Type: "excludeSignal", - }, - }, - } - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-tescorp" - site := "splunk-test" - rule, err := sc.CreateSiteRules(corp, site, siteRulesBody) + readResp, err := sc.GetSiteRuleByID(corp, site, createResp.ID) if err != nil { t.Fatal(err) } - assert.Equal(t, siteRulesBody, *rule.CreateSiteRulesBody) - - siteUpdatedBody := CreateSiteRulesBody{ + assert.Equal(t, createSiteRulesBody, *readResp.CreateSiteRuleBody) + updateSiteRuleBody := CreateSiteRuleBody{ Type: "signal", GroupOperator: "all", Enabled: true, @@ -255,9 +211,9 @@ func TestUpdateSiteRules(t *testing.T) { }, }, } - updatedRule, err := sc.UpdateSiteRule(corp, site, *&rule.ID, siteUpdatedBody) - assert.Equal(t, siteUpdatedBody, *updatedRule.CreateSiteRulesBody) - err = sc.DeleteSiteRule(corp, site, rule.ID) + updateResp, err := sc.UpdateSiteRuleByID(corp, site, createResp.ID, updateSiteRuleBody) + assert.Equal(t, updateSiteRuleBody, *updateResp.CreateSiteRuleBody) + err = sc.DeleteSiteRuleByID(corp, site, createResp.ID) if err != nil { t.Fatal(err) } @@ -307,7 +263,7 @@ func TestUnMarshalListData(t *testing.T) { ] }`) - var responseRulesList ResponseSiteRulesListData + var responseRulesList ResponseSiteRuleListData err := json.Unmarshal(resp, &responseRulesList) if err != nil { t.Fatal(err) @@ -328,7 +284,7 @@ func TestDeleteAllSiteRules(t *testing.T) { } // assert.Equal(t, 0, len(respList)) for _, rule := range respList { - sc.DeleteSiteRule(corp, site, rule.ID) + sc.DeleteSiteRuleByID(corp, site, rule.ID) } respList, err = sc.ListSiteRules(corp, site) if err != nil { @@ -338,7 +294,7 @@ func TestDeleteAllSiteRules(t *testing.T) { } func TestGetSiteRuleById(t *testing.T) { - siteRulesBody := CreateSiteRulesBody{ + siteRulesBody := CreateSiteRuleBody{ Type: "signal", GroupOperator: "all", Enabled: true, @@ -374,105 +330,60 @@ func TestGetSiteRuleById(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" - rule, err := sc.CreateSiteRules(corp, site, siteRulesBody) + rule, err := sc.CreateSiteRule(corp, site, siteRulesBody) if err != nil { t.Fatal(err) } - assert.Equal(t, siteRulesBody, *rule.CreateSiteRulesBody) + assert.Equal(t, siteRulesBody, *rule.CreateSiteRuleBody) - readRule, err := sc.GetSiteRuleById(corp, site, *&rule.ID) + readRule, err := sc.GetSiteRuleByID(corp, site, *&rule.ID) if err != nil { t.Fatal(err) } - assert.Equal(t, siteRulesBody, *readRule.CreateSiteRulesBody) + assert.Equal(t, siteRulesBody, *readRule.CreateSiteRuleBody) - err = sc.DeleteSiteRule(corp, site, rule.ID) + err = sc.DeleteSiteRuleByID(corp, site, rule.ID) if err != nil { t.Fatal(err) } } -func TestSigSciAPI(t *testing.T) { - t.SkipNow() - testCases := map[string]map[string]func(t *testing.T){ - "Site": { - "createdelete": TestCreateDeleteSite, - }, - "Rule": { - "list": TestListSiteRules, - "createdelete": TestCreateSiteRules, - "createreaddelete": TestGetSiteRuleById, - "createupdatedelete": TestUpdateSiteRules, - "delete": TestDeleteAllSiteRules, - }, - } - for group, m := range testCases { - m := m - t.Run(group, func(t *testing.T) { - for name, tc := range m { - tc := tc - t.Run(name, func(t *testing.T) { - tc(t) - }) - } - }) - } -} - func TestCreateReadUpdateDeleteSiteList(t *testing.T) { - testCases := []struct { - createFunc func(string, string, CreateSiteListBody) (ResponseSiteListBody, error) - deleteFunc func(string, string, string) error - createBody interface{} - createBodyType string - }{ - { - NewTokenClient(testcreds.email, testcreds.token).CreateSiteList, //this is method I think these works for functions - NewTokenClient(testcreds.email, testcreds.token).DeleteSiteListByID, - CreateSiteListBody{ - Name: "My new List", - Type: "ip", - Description: "Some IPs we are putting in a list", - Entries: []string{ - "4.5.6.7", - "2.3.4.5", - "1.2.3.4", - }, - }, - "CreateSiteListBody", - }, - } sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" - - // createresp, err := sc.CreateSiteList(corp, site, siteListBody) - mytype := reflect.TypeOf(testCases[0].createBody) - // myval := reflect.ValueOf(testCases[0].createBody) - - // t.Logf("%v, %v", mytype, myval) - assert.Equal(t, mytype, reflect.TypeOf(CreateSiteListBody{})) - createresp, err := testCases[0].createFunc(corp, site, testCases[0].createBody.(CreateSiteListBody)) + createSiteListBody := CreateListBody{ + Name: "My new list", + Type: "ip", + Description: "Some IPs we are putting in a list", + Entries: []string{ + "4.5.6.7", + "2.3.4.5", + "1.2.3.4", + }, + } + createresp, err := sc.CreateSiteList(corp, site, createSiteListBody) if err != nil { t.Fatal(err) } - assert.Equal(t, testCases[0].createBody.(CreateSiteListBody), *createresp.CreateSiteListBody) + assert.Equal(t, createSiteListBody, *createresp.CreateListBody) + readresp, err := sc.GetSiteListByID(corp, site, createresp.ID) - assert.Equal(t, testCases[0].createBody.(CreateSiteListBody), *readresp.CreateSiteListBody) + assert.Equal(t, createSiteListBody, *readresp.CreateListBody) - updateSiteListBody := UpdateSiteListBody{ + updateSiteListBody := UpdateListBody{ Description: "Some IPs we are updating in the list", Entries: Entries{ Additions: []string{"3.4.5.6"}, Deletions: []string{"4.5.6.7"}, }, } - updatedresp, err := sc.UpdateSiteListByID(corp, site, readresp.ID, updateSiteListBody) + updateresp, err := sc.UpdateSiteListByID(corp, site, readresp.ID, updateSiteListBody) if err != nil { t.Fatal(err) } - assert.NotEqual(t, testCases[0].createBody.(CreateSiteListBody), *updatedresp.CreateSiteListBody) + assert.NotEqual(t, createSiteListBody, *updateresp.CreateListBody) err = sc.DeleteSiteListByID(corp, site, readresp.ID) if err != nil { t.Fatal(err) @@ -506,7 +417,7 @@ func TestCreateMultipleRedactions(t *testing.T) { createSiteRedactionBody3 := CreateSiteRedactionBody{ Field: "cookie", - RedactionType: 1, + RedactionType: 0, } createresp3, err := sc.CreateSiteRedaction(corp, site, createSiteRedactionBody3) if err != nil { @@ -550,9 +461,9 @@ func TestCreatListUpdateDeleteRedaction(t *testing.T) { readresp, err := sc.GetSiteRedactionByID(corp, site, createresp.ID) assert.Equal(t, createSiteRedactionBody, *readresp.CreateSiteRedactionBody) - updateSiteRedactionBody := UpdateSiteRedactionBody{ + updateSiteRedactionBody := CreateSiteRedactionBody{ Field: "cookie", - RedactionType: 1, + RedactionType: 0, } updatedresp, err := sc.UpdateSiteRedactionByID(corp, site, createresp.ID, updateSiteRedactionBody) if err != nil { @@ -615,3 +526,140 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { t.Fatal(err) } } +func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { + createCorpRuleBody := CreateCorpRuleBody{ + SiteNames: []string{"splunk-test"}, + Type: "signal", + GroupOperator: "all", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "1.2.3.4", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "5.6.7.8", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + Enabled: true, + Reason: "test", + Signal: "SQLI", + Expiration: "", + CorpScope: "specificSites", + } + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + createResp, err := sc.CreateCorpRule(corp, createCorpRuleBody) + if err != nil { + t.Fatal(err) + } + // t.Logf("%#v", createResp.CreateCorpRuleBody) + assert.Equal(t, createCorpRuleBody, *createResp.CreateCorpRuleBody) + + readResp, err := sc.GetCorpRuleByID(corp, createResp.ID) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, readResp, createResp) + updateCorpRuleBody := CreateCorpRuleBody{ + SiteNames: []string{"splunk-test"}, + Type: "signal", + GroupOperator: "all", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "5.6.7.8", + }, + Condition{ + Type: "group", + GroupOperator: "any", + Conditions: []Condition{ + Condition{ + Type: "single", + Field: "ip", + Operator: "equals", + Value: "6.7.8.9", + }, + }, + }, + }, + Actions: []Action{ + Action{ + Type: "excludeSignal", + }, + }, + Enabled: true, + Reason: "test", + Signal: "SQLI", + Expiration: "", + CorpScope: "specificSites", + } + updateResp, err := sc.UpdateCorpRuleByID(corp, createResp.ID, updateCorpRuleBody) + assert.Equal(t, updateCorpRuleBody, *updateResp.CreateCorpRuleBody) + + if err != nil { + t.Fatal(err) + } + err = sc.DeleteCorpRuleByID(corp, createResp.ID) + + if err != nil { + t.Fatal(err) + } +} + +func TestCreateReadUpdateDeleteCorpList(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + createCorpListBody := CreateListBody{ + Name: "My new list", + Type: "ip", + Description: "Some IPs we are putting in a list", + Entries: []string{ + "4.5.6.7", + "2.3.4.5", + "1.2.3.4", + }, + } + createresp, err := sc.CreateCorpList(corp, createCorpListBody) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createCorpListBody, *createresp.CreateListBody) + + readresp, err := sc.GetCorpListByID(corp, createresp.ID) + assert.Equal(t, createCorpListBody, *readresp.CreateListBody) + + updateCorpListBody := UpdateListBody{ + Description: "Some IPs we are updating in the list", + Entries: Entries{ + Additions: []string{"3.4.5.6"}, + Deletions: []string{"4.5.6.7"}, + }, + } + updateresp, err := sc.UpdateCorpListByID(corp, readresp.ID, updateCorpListBody) + if err != nil { + t.Fatal(err) + } + assert.NotEqual(t, createCorpListBody, *updateresp.CreateListBody) + err = sc.DeleteCorpListByID(corp, readresp.ID) + if err != nil { + t.Fatal(err) + } +} diff --git a/go.mod b/go.mod index cbcd89b..6b279d5 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,6 @@ module github.com/signalsciences/go-sigsci go 1.12 -require github.com/stretchr/testify v1.5.1 +require ( + github.com/stretchr/testify v1.5.1 +) From 05397a0dd860321a0baf41586c6e3489842c1df0 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Fri, 17 Apr 2020 17:57:41 -0700 Subject: [PATCH 08/17] add function and line number to errors being logged --- api.go | 76 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/api.go b/api.go index 3dfa377..54fc27c 100644 --- a/api.go +++ b/api.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "net/http" "net/url" + "runtime" "strings" "time" ) @@ -609,12 +610,12 @@ func (sc Client) GetCustomAlert(corpName, siteName, id string) (CustomAlert, err func (sc Client) UpdateCustomAlert(corpName, siteName, id string, body CustomAlertBody) (CustomAlert, error) { b, err := json.Marshal(body) if err != nil { - return CustomAlert{}, fmt.Errorf("%s with input %#v", err.Error(), string(b)) + return CustomAlert{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), string(b))) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), string(b)) if err != nil { - return CustomAlert{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return CustomAlert{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } var c CustomAlert @@ -1738,18 +1739,18 @@ type CreateSiteBody struct { func (sc Client) CreateSite(corpName string, body CreateSiteBody) (Site, error) { b, err := json.Marshal(body) if err != nil { - return Site{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return Site{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites", corpName), string(b)) if err != nil { - return Site{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return Site{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } var site Site err = json.Unmarshal(resp, &site) if err != nil { - return Site{}, fmt.Errorf("%s with input %v", err.Error(), resp) + return Site{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), resp)) } return site, nil } @@ -1759,7 +1760,7 @@ func (sc Client) DeleteSite(corpName, siteName string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s", corpName, siteName), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s ", err.Error(), corpName, siteName) + return logError(1, fmt.Errorf("%s could not delete %s in %s ", err.Error(), corpName, siteName)) } return nil } @@ -1810,11 +1811,11 @@ type ResponseSiteRuleListData struct { func (sc *Client) CreateSiteRule(corpName, siteName string, body CreateSiteRuleBody) (ResponseSiteRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), string(b)) if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseSiteRuleBody(resp) } @@ -1823,11 +1824,11 @@ func (sc *Client) CreateSiteRule(corpName, siteName string, body CreateSiteRuleB func (sc Client) UpdateSiteRuleByID(corpName, siteName, id string, body CreateSiteRuleBody) (ResponseSiteRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseSiteRuleBody(resp) } @@ -1836,7 +1837,7 @@ func (sc Client) UpdateSiteRuleByID(corpName, siteName, id string, body CreateSi func (sc Client) DeleteSiteRuleByID(corpName, siteName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + return logError(1, fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName)) } return nil } @@ -1845,7 +1846,7 @@ func (sc Client) DeleteSiteRuleByID(corpName, siteName, id string) error { func (sc Client) GetSiteRuleByID(corpName, siteName, id string) (ResponseSiteRuleBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules/%s", corpName, siteName, id), "") if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s could not get %s in %s in %s", err.Error(), id, siteName, corpName) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s could not get %s in %s in %s", err.Error(), id, siteName, corpName)) } return getResponseSiteRuleBody(resp) } @@ -1854,7 +1855,7 @@ func getResponseSiteRuleBody(response []byte) (ResponseSiteRuleBody, error) { var responseSiteRules ResponseSiteRuleBody err := json.Unmarshal(response, &responseSiteRules) if err != nil { - return ResponseSiteRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), response) + return ResponseSiteRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), response)) } return responseSiteRules, nil } @@ -1916,11 +1917,11 @@ type ResponseListListData struct { func (sc Client) CreateSiteList(corpName, siteName string, body CreateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/lists", corpName, siteName), string(b)) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseListBody(resp) } @@ -1938,11 +1939,11 @@ func getResponseListBody(response []byte) (ResponseListBody, error) { func (sc Client) UpdateSiteListByID(corpName, siteName string, id string, body UpdateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseListBody(resp) } @@ -1951,7 +1952,7 @@ func (sc Client) UpdateSiteListByID(corpName, siteName string, id string, body U func (sc Client) DeleteSiteListByID(corpName, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/lists/%s", corpName, siteName, id), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + return logError(1, fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName)) } return nil } @@ -1993,11 +1994,11 @@ type ResponseSiteRedactionBodyList struct { func (sc Client) CreateSiteRedaction(corpName, siteName string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseSiteRedactionBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), string(b)) if err != nil { - return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRedactionBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } redactionsData, err := getResponseSiteRedactionListBody(resp) @@ -2030,11 +2031,11 @@ func getResponseSiteRedactionBody(response []byte) (ResponseSiteRedactionBody, e func (sc Client) UpdateSiteRedactionByID(corpName, siteName string, id string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseSiteRedactionBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), string(b)) if err != nil { - return ResponseSiteRedactionBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseSiteRedactionBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseSiteRedactionBody(resp) } @@ -2052,7 +2053,7 @@ func (sc Client) GetSiteRedactionByID(corpName, siteName, id string) (ResponseSi func (sc Client) DeleteSiteRedactionByID(corpName, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName) + return logError(1, fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName)) } return nil } @@ -2101,11 +2102,11 @@ type ResponseCorpRuleBody struct { func (sc *Client) CreateCorpRule(corpName string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/rules", corpName), string(b)) if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseCorpRuleBody(resp) } @@ -2114,11 +2115,11 @@ func (sc *Client) CreateCorpRule(corpName string, body CreateCorpRuleBody) (Resp func (sc Client) UpdateCorpRuleByID(corpName, id string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), string(b)) if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseCorpRuleBody(resp) } @@ -2127,7 +2128,7 @@ func (sc Client) UpdateCorpRuleByID(corpName, id string, body CreateCorpRuleBody func (sc Client) DeleteCorpRuleByID(corpName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName) + return logError(1, fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName)) } return nil } @@ -2136,7 +2137,7 @@ func (sc Client) DeleteCorpRuleByID(corpName, id string) error { func (sc Client) GetCorpRuleByID(corpName, id string) (ResponseCorpRuleBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s could not get %s in %s", err.Error(), id, corpName) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s could not get %s in %s", err.Error(), id, corpName)) } return getResponseCorpRuleBody(resp) } @@ -2145,7 +2146,7 @@ func getResponseCorpRuleBody(response []byte) (ResponseCorpRuleBody, error) { var responseCorpRule ResponseCorpRuleBody err := json.Unmarshal(response, &responseCorpRule) if err != nil { - return ResponseCorpRuleBody{}, fmt.Errorf("%s with input %v", err.Error(), response) + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), response)) } return responseCorpRule, nil } @@ -2154,11 +2155,11 @@ func getResponseCorpRuleBody(response []byte) (ResponseCorpRuleBody, error) { func (sc Client) CreateCorpList(corpName string, body CreateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/lists", corpName), string(b)) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseListBody(resp) } @@ -2167,11 +2168,11 @@ func (sc Client) CreateCorpList(corpName string, body CreateListBody) (ResponseL func (sc Client) UpdateCorpListByID(corpName string, id string, body UpdateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %#v", err.Error(), body) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), string(b)) if err != nil { - return ResponseListBody{}, fmt.Errorf("%s with input %v", err.Error(), string(b)) + return ResponseListBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } return getResponseListBody(resp) } @@ -2180,7 +2181,7 @@ func (sc Client) UpdateCorpListByID(corpName string, id string, body UpdateListB func (sc Client) DeleteCorpListByID(corpName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), "") if err != nil { - return fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName) + return logError(1, fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName)) } return nil } @@ -2193,3 +2194,8 @@ func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, } return getResponseListBody(resp) } +func logError(skip int, err error) error { + pc, _, line, _ := runtime.Caller(skip) + fn := runtime.FuncForPC(pc).Name() + return fmt.Errorf("[ERROR] %s:%d\t%s", fn, line, err.Error()) +} From d3727f7be27d05fe54aaf3b38b1c64662073c2e6 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Wed, 22 Apr 2020 17:10:10 -0700 Subject: [PATCH 09/17] Add GetAll for site and corp rules and lists; site redactions. --- api.go | 84 +++++++++++++++++++++++++-------- api_test.go | 132 +++++++++++++++++++++------------------------------- 2 files changed, 119 insertions(+), 97 deletions(-) diff --git a/api.go b/api.go index 54fc27c..465bdaf 100644 --- a/api.go +++ b/api.go @@ -1801,8 +1801,8 @@ type ResponseSiteRuleBody struct { Updated time.Time `json:"updated"` //Last updated RFC3339 date time } -// ResponseSiteRuleListData contains the returned rules -type ResponseSiteRuleListData struct { +// ResponseSiteRuleBodyList contains the returned rules +type ResponseSiteRuleBodyList struct { TotalCount int `json:"totalCount"` Data []ResponseSiteRuleBody `json:"data"` } @@ -1860,21 +1860,21 @@ func getResponseSiteRuleBody(response []byte) (ResponseSiteRuleBody, error) { return responseSiteRules, nil } -// ListSiteRules Lists the Site Rules -func (sc *Client) ListSiteRules(corpName, siteName string) ([]ResponseSiteRuleBody, error) { +// GetAllSiteRules Lists the Site Rules +func (sc *Client) GetAllSiteRules(corpName, siteName string) (ResponseSiteRuleBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") if err != nil { - return []ResponseSiteRuleBody{}, err + return ResponseSiteRuleBodyList{}, err } - var responseRulesList ResponseSiteRuleListData + var responseRulesList ResponseSiteRuleBodyList err = json.Unmarshal(resp, &responseRulesList) if err != nil { - return []ResponseSiteRuleBody{}, err + return ResponseSiteRuleBodyList{}, err } - return responseRulesList.Data, nil + return responseRulesList, nil } // CreateListBody Create List Request @@ -1883,7 +1883,6 @@ type CreateListBody struct { Type string `json:"type,omitempty"` //List types (string, ip, country, wildcard) Description string `json:"description,omitempty"` //Optional list description Entries []string `json:"entries,omitempty"` //List entries - // *UpdateSiteListBody } // UpdateListBody update list @@ -1907,10 +1906,10 @@ type ResponseListBody struct { Updated time.Time `json:"updated"` //Last updated RFC3339 date time } -//ResponseListListData contains the returned list -type ResponseListListData struct { - TotalCount int `json:"totalCount"` - Data []ResponseListBody `json:"data"` //Site List data +//ResponseListBodyList contains the returned list +type ResponseListBodyList struct { + // TotalCount int `json:"totalCount"` + Data []ResponseListBody `json:"data"` //Site List data } //CreateSiteList Create a site list @@ -1966,6 +1965,20 @@ func (sc Client) GetSiteListByID(corpName, siteName string, id string) (Response return getResponseListBody(resp) } +//GetAllSiteLists get all site lists +func (sc Client) GetAllSiteLists(corpName, siteName string) (ResponseListBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists", corpName, siteName), "") + if err != nil { + return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + } + var responseListBodyList ResponseListBodyList + err = json.Unmarshal(resp, &responseListBodyList) + if err != nil { + return ResponseListBodyList{}, err + } + return responseListBodyList, nil +} + // CreateSiteRedactionBody Create redaction Request type CreateSiteRedactionBody struct { Field string `json:"field,omitempty"` //Field name @@ -2058,15 +2071,15 @@ func (sc Client) DeleteSiteRedactionByID(corpName, siteName string, id string) e return nil } -// ListSiteRedactions Lists the Sites Redactions -func (sc *Client) ListSiteRedactions(corpName, siteName string) (ResponseSiteRedactionBodyList, error) { +// GetAllSiteRedactions Lists the Sites Redactions +func (sc *Client) GetAllSiteRedactions(corpName, siteName string) (ResponseSiteRedactionBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), "") if err != nil { return ResponseSiteRedactionBodyList{}, err } - var responseRulesList ResponseSiteRuleListData + var responseRulesList ResponseSiteRuleBodyList err = json.Unmarshal(resp, &responseRulesList) if err != nil { return ResponseSiteRedactionBodyList{}, err @@ -2093,9 +2106,15 @@ type CreateCorpRuleBody struct { type ResponseCorpRuleBody struct { *CreateCorpRuleBody ID string `json:"id"` - CreatedBy string `json:"createdby"` - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` + CreatedBy string `json:"createdby"` //Email address of the user that created the item + Created time.Time `json:"created"` //Created RFC3339 date time + Updated time.Time `json:"updated"` //Last updated RFC3339 date time +} + +//ResponseCorpRuleBodyList list +type ResponseCorpRuleBodyList struct { + TotalCount int `json:"totalCount"` + Data []ResponseCorpRuleBody `json:"data"` //ResponseCorpRuleBody } // CreateCorpRule creates a rule and returns the response @@ -2142,6 +2161,19 @@ func (sc Client) GetCorpRuleByID(corpName, id string) (ResponseCorpRuleBody, err return getResponseCorpRuleBody(resp) } +//GetAllCorpRules get all corp rules +func (sc Client) GetAllCorpRules(corpName string) (ResponseCorpRuleBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/rules", corpName), "") + if err != nil { + return ResponseCorpRuleBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + } + var responseRuleBodyList ResponseCorpRuleBodyList + err = json.Unmarshal(resp, &responseRuleBodyList) + if err != nil { + return ResponseCorpRuleBodyList{}, err + } + return responseRuleBodyList, nil +} func getResponseCorpRuleBody(response []byte) (ResponseCorpRuleBody, error) { var responseCorpRule ResponseCorpRuleBody err := json.Unmarshal(response, &responseCorpRule) @@ -2194,6 +2226,20 @@ func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, } return getResponseListBody(resp) } + +//GetAllCorpLists get all corp lists +func (sc Client) GetAllCorpLists(corpName string) (ResponseListBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists", corpName), "") + if err != nil { + return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + } + var responseListBodyList ResponseListBodyList + err = json.Unmarshal(resp, &responseListBodyList) + if err != nil { + return ResponseListBodyList{}, err + } + return responseListBodyList, nil +} func logError(skip int, err error) error { pc, _, line, _ := runtime.Caller(skip) fn := runtime.FuncForPC(pc).Name() diff --git a/api_test.go b/api_test.go index c4c7398..cd80e01 100644 --- a/api_test.go +++ b/api_test.go @@ -212,17 +212,20 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { }, } updateResp, err := sc.UpdateSiteRuleByID(corp, site, createResp.ID, updateSiteRuleBody) + if err != nil { + t.Fatal(err) + } assert.Equal(t, updateSiteRuleBody, *updateResp.CreateSiteRuleBody) - err = sc.DeleteSiteRuleByID(corp, site, createResp.ID) + + readall, err := sc.GetAllSiteRules(corp, site) if err != nil { t.Fatal(err) } -} -func TestListSiteRules(t *testing.T) { - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-tescorp" - site := "splunk-test" - _, err := sc.ListSiteRules(corp, site) + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, 1, readall.TotalCount) + assert.Equal(t, updateSiteRuleBody, *readall.Data[0].CreateSiteRuleBody) + + err = sc.DeleteSiteRuleByID(corp, site, createResp.ID) if err != nil { t.Fatal(err) } @@ -263,7 +266,7 @@ func TestUnMarshalListData(t *testing.T) { ] }`) - var responseRulesList ResponseSiteRuleListData + var responseRulesList ResponseSiteRuleBodyList err := json.Unmarshal(resp, &responseRulesList) if err != nil { t.Fatal(err) @@ -274,79 +277,23 @@ func TestUnMarshalListData(t *testing.T) { } func TestDeleteAllSiteRules(t *testing.T) { - // t.SkipNow() + t.SkipNow() sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" - respList, err := sc.ListSiteRules(corp, site) + respList, err := sc.GetAllSiteRules(corp, site) if err != nil { t.Fatal(err) } // assert.Equal(t, 0, len(respList)) - for _, rule := range respList { + for _, rule := range respList.Data { sc.DeleteSiteRuleByID(corp, site, rule.ID) } - respList, err = sc.ListSiteRules(corp, site) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, 0, len(respList)) -} - -func TestGetSiteRuleById(t *testing.T) { - siteRulesBody := CreateSiteRuleBody{ - Type: "signal", - GroupOperator: "all", - Enabled: true, - Reason: "Example site rule", - Signal: "SQLI", - Expiration: "", - Conditions: []Condition{ - Condition{ - Type: "single", - Field: "ip", - Operator: "equals", - Value: "1.2.3.4", - }, - Condition{ - Type: "group", - GroupOperator: "any", - Conditions: []Condition{ - Condition{ - Type: "single", - Field: "ip", - Operator: "equals", - Value: "5.6.7.8", - }, - }, - }, - }, - Actions: []Action{ - Action{ - Type: "excludeSignal", - }, - }, - } - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-tescorp" - site := "splunk-test" - rule, err := sc.CreateSiteRule(corp, site, siteRulesBody) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, siteRulesBody, *rule.CreateSiteRuleBody) - - readRule, err := sc.GetSiteRuleByID(corp, site, *&rule.ID) - - if err != nil { - t.Fatal(err) - } - assert.Equal(t, siteRulesBody, *readRule.CreateSiteRuleBody) - - err = sc.DeleteSiteRuleByID(corp, site, rule.ID) + respList, err = sc.GetAllSiteRules(corp, site) if err != nil { t.Fatal(err) } + assert.Equal(t, 0, len(respList.Data)) } func TestCreateReadUpdateDeleteSiteList(t *testing.T) { @@ -384,6 +331,20 @@ func TestCreateReadUpdateDeleteSiteList(t *testing.T) { t.Fatal(err) } assert.NotEqual(t, createSiteListBody, *updateresp.CreateListBody) + updatedSiteListBody := CreateListBody{ + Name: "My new list", + Type: "ip", + Description: "Some IPs we are updating in the list", + Entries: []string{ + "2.3.4.5", + "1.2.3.4", + "3.4.5.6", + }, + } + assert.Equal(t, updatedSiteListBody, *updateresp.CreateListBody) + readall, err := sc.GetAllSiteLists(corp, site) + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, updatedSiteListBody, *readall.Data[0].CreateListBody) err = sc.DeleteSiteListByID(corp, site, readresp.ID) if err != nil { t.Fatal(err) @@ -455,9 +416,6 @@ func TestCreatListUpdateDeleteRedaction(t *testing.T) { assert.Equal(t, createSiteRedactionBody, *createresp.CreateSiteRedactionBody) - listresp, err := sc.ListSiteRedactions(corp, site) - assert.Equal(t, 1, len(listresp.Data)) - readresp, err := sc.GetSiteRedactionByID(corp, site, createresp.ID) assert.Equal(t, createSiteRedactionBody, *readresp.CreateSiteRedactionBody) @@ -469,11 +427,12 @@ func TestCreatListUpdateDeleteRedaction(t *testing.T) { if err != nil { t.Fatal(err) } - assert.NotEqual(t, createSiteRedactionBody, *updatedresp.CreateSiteRedactionBody) - assert.Equal(t, updateSiteRedactionBody.Field, *&updatedresp.CreateSiteRedactionBody.Field) - assert.Equal(t, updateSiteRedactionBody.RedactionType, *&updatedresp.CreateSiteRedactionBody.RedactionType) - + assert.Equal(t, updateSiteRedactionBody, *updatedresp.CreateSiteRedactionBody) + readall, err := sc.GetAllSiteRedactions(corp, site) + assert.Equal(t, 1, len(readall.Data)) + // assert.Equal(t, 1, readall.TotalCount) + assert.Equal(t, updateSiteRedactionBody, *readall.Data[0].CreateSiteRedactionBody) err = sc.DeleteSiteRedactionByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) @@ -612,11 +571,14 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { CorpScope: "specificSites", } updateResp, err := sc.UpdateCorpRuleByID(corp, createResp.ID, updateCorpRuleBody) - assert.Equal(t, updateCorpRuleBody, *updateResp.CreateCorpRuleBody) - if err != nil { t.Fatal(err) } + assert.Equal(t, updateCorpRuleBody, *updateResp.CreateCorpRuleBody) + readall, err := sc.GetAllCorpRules(corp) + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, 1, readall.TotalCount) + assert.Equal(t, updateCorpRuleBody, *readall.Data[0].CreateCorpRuleBody) err = sc.DeleteCorpRuleByID(corp, createResp.ID) if err != nil { @@ -658,6 +620,20 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { t.Fatal(err) } assert.NotEqual(t, createCorpListBody, *updateresp.CreateListBody) + updatedCorpListBody := CreateListBody{ + Name: "My new list", + Type: "ip", + Description: "Some IPs we are updating in the list", + Entries: []string{ + "2.3.4.5", + "1.2.3.4", + "3.4.5.6", + }, + } + assert.Equal(t, updatedCorpListBody, *updateresp.CreateListBody) + readall, err := sc.GetAllCorpLists(corp) + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, updatedCorpListBody, *readall.Data[0].CreateListBody) err = sc.DeleteCorpListByID(corp, readresp.ID) if err != nil { t.Fatal(err) From 5631df1a04391140e11ef4b705d567cefea9438e Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Mon, 27 Apr 2020 17:35:50 -0700 Subject: [PATCH 10/17] embed the the value not the pointer --- api.go | 8 ++++---- api_test.go | 50 +++++++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/api.go b/api.go index 465bdaf..c2181d5 100644 --- a/api.go +++ b/api.go @@ -1794,7 +1794,7 @@ type CreateSiteRuleBody struct { // ResponseSiteRuleBody contains the response from creating the rule type ResponseSiteRuleBody struct { - *CreateSiteRuleBody + CreateSiteRuleBody ID string `json:"id"` //internal ID CreatedBy string `json:"createdby"` //Email address of the user that created the item Created time.Time `json:"created"` //Created RFC3339 date time @@ -1899,7 +1899,7 @@ type Entries struct { // ResponseListBody contains the response from creating the list type ResponseListBody struct { - *CreateListBody + CreateListBody ID string `json:"id"` //internal ID CreatedBy string `json:"createdby"` //Email address of the user that created the item Created time.Time `json:"created"` //Created RFC3339 date time @@ -1990,7 +1990,7 @@ type CreateSiteRedactionBody struct { // ResponseSiteRedactionBody redaction response type ResponseSiteRedactionBody struct { - *CreateSiteRedactionBody + CreateSiteRedactionBody ID string `json:"id"` //internal ID CreatedBy string `json:"createdby"` //Email address of the user that created the item Created time.Time `json:"created"` //Created RFC3339 date time @@ -2104,7 +2104,7 @@ type CreateCorpRuleBody struct { // ResponseCorpRuleBody contains the response from creating the rule type ResponseCorpRuleBody struct { - *CreateCorpRuleBody + CreateCorpRuleBody ID string `json:"id"` CreatedBy string `json:"createdby"` //Email address of the user that created the item Created time.Time `json:"created"` //Created RFC3339 date time diff --git a/api_test.go b/api_test.go index cd80e01..0f777e4 100644 --- a/api_test.go +++ b/api_test.go @@ -171,13 +171,13 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteRulesBody, *createResp.CreateSiteRuleBody) + assert.Equal(t, createSiteRulesBody, createResp.CreateSiteRuleBody) readResp, err := sc.GetSiteRuleByID(corp, site, createResp.ID) if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteRulesBody, *readResp.CreateSiteRuleBody) + assert.Equal(t, createSiteRulesBody, readResp.CreateSiteRuleBody) updateSiteRuleBody := CreateSiteRuleBody{ Type: "signal", GroupOperator: "all", @@ -215,7 +215,7 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, updateSiteRuleBody, *updateResp.CreateSiteRuleBody) + assert.Equal(t, updateSiteRuleBody, updateResp.CreateSiteRuleBody) readall, err := sc.GetAllSiteRules(corp, site) if err != nil { @@ -223,7 +223,7 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { } assert.Equal(t, 1, len(readall.Data)) assert.Equal(t, 1, readall.TotalCount) - assert.Equal(t, updateSiteRuleBody, *readall.Data[0].CreateSiteRuleBody) + assert.Equal(t, updateSiteRuleBody, readall.Data[0].CreateSiteRuleBody) err = sc.DeleteSiteRuleByID(corp, site, createResp.ID) if err != nil { @@ -314,10 +314,10 @@ func TestCreateReadUpdateDeleteSiteList(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteListBody, *createresp.CreateListBody) + assert.Equal(t, createSiteListBody, createresp.CreateListBody) readresp, err := sc.GetSiteListByID(corp, site, createresp.ID) - assert.Equal(t, createSiteListBody, *readresp.CreateListBody) + assert.Equal(t, createSiteListBody, readresp.CreateListBody) updateSiteListBody := UpdateListBody{ Description: "Some IPs we are updating in the list", @@ -330,7 +330,7 @@ func TestCreateReadUpdateDeleteSiteList(t *testing.T) { if err != nil { t.Fatal(err) } - assert.NotEqual(t, createSiteListBody, *updateresp.CreateListBody) + assert.NotEqual(t, createSiteListBody, updateresp.CreateListBody) updatedSiteListBody := CreateListBody{ Name: "My new list", Type: "ip", @@ -341,10 +341,10 @@ func TestCreateReadUpdateDeleteSiteList(t *testing.T) { "3.4.5.6", }, } - assert.Equal(t, updatedSiteListBody, *updateresp.CreateListBody) + assert.Equal(t, updatedSiteListBody, updateresp.CreateListBody) readall, err := sc.GetAllSiteLists(corp, site) assert.Equal(t, 1, len(readall.Data)) - assert.Equal(t, updatedSiteListBody, *readall.Data[0].CreateListBody) + assert.Equal(t, updatedSiteListBody, readall.Data[0].CreateListBody) err = sc.DeleteSiteListByID(corp, site, readresp.ID) if err != nil { t.Fatal(err) @@ -364,7 +364,7 @@ func TestCreateMultipleRedactions(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteRedactionBody, *createresp.CreateSiteRedactionBody) + assert.Equal(t, createSiteRedactionBody, createresp.CreateSiteRedactionBody) createSiteRedactionBody2 := CreateSiteRedactionBody{ Field: "cookie", @@ -374,7 +374,7 @@ func TestCreateMultipleRedactions(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteRedactionBody2, *createresp2.CreateSiteRedactionBody) + assert.Equal(t, createSiteRedactionBody2, createresp2.CreateSiteRedactionBody) createSiteRedactionBody3 := CreateSiteRedactionBody{ Field: "cookie", @@ -384,7 +384,7 @@ func TestCreateMultipleRedactions(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createSiteRedactionBody3, *createresp3.CreateSiteRedactionBody) + assert.Equal(t, createSiteRedactionBody3, createresp3.CreateSiteRedactionBody) err = sc.DeleteSiteRedactionByID(corp, site, createresp.ID) if err != nil { @@ -414,10 +414,10 @@ func TestCreatListUpdateDeleteRedaction(t *testing.T) { t.Fatal(err) } - assert.Equal(t, createSiteRedactionBody, *createresp.CreateSiteRedactionBody) + assert.Equal(t, createSiteRedactionBody, createresp.CreateSiteRedactionBody) readresp, err := sc.GetSiteRedactionByID(corp, site, createresp.ID) - assert.Equal(t, createSiteRedactionBody, *readresp.CreateSiteRedactionBody) + assert.Equal(t, createSiteRedactionBody, readresp.CreateSiteRedactionBody) updateSiteRedactionBody := CreateSiteRedactionBody{ Field: "cookie", @@ -427,12 +427,12 @@ func TestCreatListUpdateDeleteRedaction(t *testing.T) { if err != nil { t.Fatal(err) } - assert.NotEqual(t, createSiteRedactionBody, *updatedresp.CreateSiteRedactionBody) - assert.Equal(t, updateSiteRedactionBody, *updatedresp.CreateSiteRedactionBody) + assert.NotEqual(t, createSiteRedactionBody, updatedresp.CreateSiteRedactionBody) + assert.Equal(t, updateSiteRedactionBody, updatedresp.CreateSiteRedactionBody) readall, err := sc.GetAllSiteRedactions(corp, site) assert.Equal(t, 1, len(readall.Data)) // assert.Equal(t, 1, readall.TotalCount) - assert.Equal(t, updateSiteRedactionBody, *readall.Data[0].CreateSiteRedactionBody) + assert.Equal(t, updateSiteRedactionBody, readall.Data[0].CreateSiteRedactionBody) err = sc.DeleteSiteRedactionByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) @@ -528,7 +528,7 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { t.Fatal(err) } // t.Logf("%#v", createResp.CreateCorpRuleBody) - assert.Equal(t, createCorpRuleBody, *createResp.CreateCorpRuleBody) + assert.Equal(t, createCorpRuleBody, createResp.CreateCorpRuleBody) readResp, err := sc.GetCorpRuleByID(corp, createResp.ID) if err != nil { @@ -574,11 +574,11 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, updateCorpRuleBody, *updateResp.CreateCorpRuleBody) + assert.Equal(t, updateCorpRuleBody, updateResp.CreateCorpRuleBody) readall, err := sc.GetAllCorpRules(corp) assert.Equal(t, 1, len(readall.Data)) assert.Equal(t, 1, readall.TotalCount) - assert.Equal(t, updateCorpRuleBody, *readall.Data[0].CreateCorpRuleBody) + assert.Equal(t, updateCorpRuleBody, readall.Data[0].CreateCorpRuleBody) err = sc.DeleteCorpRuleByID(corp, createResp.ID) if err != nil { @@ -603,10 +603,10 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, createCorpListBody, *createresp.CreateListBody) + assert.Equal(t, createCorpListBody, createresp.CreateListBody) readresp, err := sc.GetCorpListByID(corp, createresp.ID) - assert.Equal(t, createCorpListBody, *readresp.CreateListBody) + assert.Equal(t, createCorpListBody, readresp.CreateListBody) updateCorpListBody := UpdateListBody{ Description: "Some IPs we are updating in the list", @@ -619,7 +619,7 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { if err != nil { t.Fatal(err) } - assert.NotEqual(t, createCorpListBody, *updateresp.CreateListBody) + assert.NotEqual(t, createCorpListBody, updateresp.CreateListBody) updatedCorpListBody := CreateListBody{ Name: "My new list", Type: "ip", @@ -630,10 +630,10 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { "3.4.5.6", }, } - assert.Equal(t, updatedCorpListBody, *updateresp.CreateListBody) + assert.Equal(t, updatedCorpListBody, updateresp.CreateListBody) readall, err := sc.GetAllCorpLists(corp) assert.Equal(t, 1, len(readall.Data)) - assert.Equal(t, updatedCorpListBody, *readall.Data[0].CreateListBody) + assert.Equal(t, updatedCorpListBody, readall.Data[0].CreateListBody) err = sc.DeleteCorpListByID(corp, readresp.ID) if err != nil { t.Fatal(err) From e26dc450f843a4728c6867e51d793f5ee329341f Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Wed, 6 May 2020 17:15:44 -0700 Subject: [PATCH 11/17] skip the site crud test --- api_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api_test.go b/api_test.go index 0f777e4..25bd116 100644 --- a/api_test.go +++ b/api_test.go @@ -61,6 +61,7 @@ func TestGoUserTokenClient(t *testing.T) { } } func TestCreateDeleteSite(t *testing.T) { + t.Skip() sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-testcorp" From 47a4a2f91adbcc5bbd1decafe27763de9a66a570 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Tue, 12 May 2020 16:21:48 -0700 Subject: [PATCH 12/17] modify alerts to follow the other endpoints that were created embedding and method naming convention adds site and corp signals --- api.go | 332 ++++++++++++++++++++++++++++++++++++++-------------- api_test.go | 180 +++++++++++++++++++--------- 2 files changed, 366 insertions(+), 146 deletions(-) diff --git a/api.go b/api.go index c2181d5..668f194 100644 --- a/api.go +++ b/api.go @@ -529,106 +529,106 @@ func (sc *Client) UpdateSite(corpName, siteName string, body UpdateSiteBody) (Si return site, nil } -// CustomAlert contains the data for a custom alert -type CustomAlert struct { - *CustomAlertBody +// CreateCustomAlertBody is the body for creating a custom alert. +type CreateCustomAlertBody struct { + TagName string `json:"tagName"` + LongName string `json:"longName"` + Interval int `json:"interval"` + Threshold int `json:"threshold"` + Enabled bool `json:"enabled"` + Action string `json:"action"` +} + +//ResponseCustomAlertBody contains the data for a custom alert +type ResponseCustomAlertBody struct { + CreateCustomAlertBody ID string Created time.Time CreatedBy string Updated time.Time } -// customAlertsResponse is the response for the alerts endpoint -type customAlertsResponse struct { - Data []CustomAlert +// ResponseCustomAlertsBodyList is the response for the alerts endpoint +type ResponseCustomAlertsBodyList struct { + Data []ResponseCustomAlertBody } -// ListCustomAlerts lists custom alerts for a given corp and site. -func (sc Client) ListCustomAlerts(corpName, siteName string) ([]CustomAlert, error) { +// GetAllCustomSiteAlerts lists custom alerts for a given corp and site. +func (sc Client) GetAllCustomSiteAlerts(corpName, siteName string) (ResponseCustomAlertsBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), "") if err != nil { - return []CustomAlert{}, err + return ResponseCustomAlertsBodyList{}, err } - var car customAlertsResponse + var car ResponseCustomAlertsBodyList err = json.Unmarshal(resp, &car) if err != nil { - return []CustomAlert{}, err + return ResponseCustomAlertsBodyList{}, err } - return car.Data, nil -} - -// CustomAlertBody is the body for creating a custom alert. -type CustomAlertBody struct { - TagName string `json:"tagName"` - LongName string `json:"longName"` - Interval int `json:"interval"` - Threshold int `json:"threshold"` - Enabled bool `json:"enabled"` - Action string `json:"action"` + return car, nil } -// CreateCustomAlert creates a custom alert. -func (sc Client) CreateCustomAlert(corpName, siteName string, body CustomAlertBody) (CustomAlert, error) { +// CreateCustomSiteAlert creates a custom alert. +func (sc Client) CreateCustomSiteAlert(corpName, siteName string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { b, err := json.Marshal(body) if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), string(b)) if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } - var c CustomAlert + var c ResponseCustomAlertBody err = json.Unmarshal(resp, &c) if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } return c, nil } -// GetCustomAlert gets a custom alert by ID -func (sc Client) GetCustomAlert(corpName, siteName, id string) (CustomAlert, error) { +// GetCustomSiteAlertByID gets a custom alert by ID +func (sc Client) GetCustomSiteAlertByID(corpName, siteName, id string) (ResponseCustomAlertBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } - var ca CustomAlert + var ca ResponseCustomAlertBody err = json.Unmarshal(resp, &ca) if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } return ca, nil } -// UpdateCustomAlert updates a custom alert by id. -func (sc Client) UpdateCustomAlert(corpName, siteName, id string, body CustomAlertBody) (CustomAlert, error) { +// UpdateCustomSiteAlertByID updates a custom alert by id. +func (sc Client) UpdateCustomSiteAlertByID(corpName, siteName, id string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { b, err := json.Marshal(body) if err != nil { - return CustomAlert{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), string(b))) + return ResponseCustomAlertBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), string(b))) } resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), string(b)) if err != nil { - return CustomAlert{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + return ResponseCustomAlertBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) } - var c CustomAlert + var c ResponseCustomAlertBody err = json.Unmarshal(resp, &c) if err != nil { - return CustomAlert{}, err + return ResponseCustomAlertBody{}, err } return c, err } -// DeleteCustomAlert deletes a custom alert. -func (sc Client) DeleteCustomAlert(corpName, siteName, id string) error { +// DeleteCustomSiteAlertByID deletes a custom alert. +func (sc Client) DeleteCustomSiteAlertByID(corpName, siteName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") return err @@ -2040,6 +2040,15 @@ func getResponseSiteRedactionBody(response []byte) (ResponseSiteRedactionBody, e return responseBody, nil } +//GetSiteRedactionByID get a site redaction by id +func (sc Client) GetSiteRedactionByID(corpName, siteName, id string) (ResponseSiteRedactionBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") + if err != nil { + return ResponseSiteRedactionBody{}, err + } + return getResponseSiteRedactionBody(resp) +} + // UpdateSiteRedactionByID updates a site redaction and returns a response func (sc Client) UpdateSiteRedactionByID(corpName, siteName string, id string, body CreateSiteRedactionBody) (ResponseSiteRedactionBody, error) { b, err := json.Marshal(body) @@ -2053,15 +2062,6 @@ func (sc Client) UpdateSiteRedactionByID(corpName, siteName string, id string, b return getResponseSiteRedactionBody(resp) } -//GetSiteRedactionByID get a site redaction by id -func (sc Client) GetSiteRedactionByID(corpName, siteName, id string) (ResponseSiteRedactionBody, error) { - resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") - if err != nil { - return ResponseSiteRedactionBody{}, err - } - return getResponseSiteRedactionBody(resp) -} - // DeleteSiteRedactionByID deletes a redaction and returns an error func (sc Client) DeleteSiteRedactionByID(corpName, siteName string, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions/%s", corpName, siteName, id), "") @@ -2130,28 +2130,6 @@ func (sc *Client) CreateCorpRule(corpName string, body CreateCorpRuleBody) (Resp return getResponseCorpRuleBody(resp) } -// UpdateCorpRuleByID updates a rule and returns a response -func (sc Client) UpdateCorpRuleByID(corpName, id string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { - b, err := json.Marshal(body) - if err != nil { - return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) - } - resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), string(b)) - if err != nil { - return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) - } - return getResponseCorpRuleBody(resp) -} - -// DeleteCorpRuleByID deletes a rule and returns an error -func (sc Client) DeleteCorpRuleByID(corpName, id string) error { - _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") - if err != nil { - return logError(1, fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName)) - } - return nil -} - //GetCorpRuleByID get a site rule by id func (sc Client) GetCorpRuleByID(corpName, id string) (ResponseCorpRuleBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") @@ -2174,6 +2152,29 @@ func (sc Client) GetAllCorpRules(corpName string) (ResponseCorpRuleBodyList, err } return responseRuleBodyList, nil } + +// UpdateCorpRuleByID updates a rule and returns a response +func (sc Client) UpdateCorpRuleByID(corpName, id string, body CreateCorpRuleBody) (ResponseCorpRuleBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) + } + resp, err := sc.doRequest("PUT", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), string(b)) + if err != nil { + return ResponseCorpRuleBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + } + return getResponseCorpRuleBody(resp) +} + +// DeleteCorpRuleByID deletes a rule and returns an error +func (sc Client) DeleteCorpRuleByID(corpName, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/rules/%s", corpName, id), "") + if err != nil { + return logError(1, fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName)) + } + return nil +} + func getResponseCorpRuleBody(response []byte) (ResponseCorpRuleBody, error) { var responseCorpRule ResponseCorpRuleBody err := json.Unmarshal(response, &responseCorpRule) @@ -2196,6 +2197,29 @@ func (sc Client) CreateCorpList(corpName string, body CreateListBody) (ResponseL return getResponseListBody(resp) } +// GetCorpListByID get corp list by ID +func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), "") + if err != nil { + return ResponseListBody{}, err + } + return getResponseListBody(resp) +} + +//GetAllCorpLists get all corp lists +func (sc Client) GetAllCorpLists(corpName string) (ResponseListBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists", corpName), "") + if err != nil { + return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + } + var responseListBodyList ResponseListBodyList + err = json.Unmarshal(resp, &responseListBodyList) + if err != nil { + return ResponseListBodyList{}, err + } + return responseListBodyList, nil +} + // UpdateCorpListByID updates a corp list func (sc Client) UpdateCorpListByID(corpName string, id string, body UpdateListBody) (ResponseListBody, error) { b, err := json.Marshal(body) @@ -2218,30 +2242,160 @@ func (sc Client) DeleteCorpListByID(corpName string, id string) error { return nil } -// GetCorpListByID get corp list by ID -func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, error) { - resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists/%s", corpName, id), "") +func logError(skip int, err error) error { + pc, _, line, _ := runtime.Caller(skip) + fn := runtime.FuncForPC(pc).Name() + return fmt.Errorf("[ERROR] %s:%d\t%s", fn, line, err.Error()) +} + +//CreateSignalTagBody create a signal tag +type CreateSignalTagBody struct { + ShortName string `json:"shortName,omitempty"` //The display name of the signal tag + Description string `json:"description,omitempty"` //Optional signal tag description +} + +//UpdateSignalTagBody update a signal tag +type UpdateSignalTagBody struct { + Description string `json:"description,omitempty"` //Optional signal tag description +} + +//ResponseSignalTagBody response singnal tag +type ResponseSignalTagBody struct { + CreateSignalTagBody + TagName string `json:"tagName",omitempty"` //The identifier for the signal tag + LongName string `json:"longName",omitempty"` //The display name of the signal tag - deprecated + Configurable bool `json:"configurable",omitempty"` + Informational bool `json:"informational",omitempty"` + NeedsResponse bool `json:"needsResponse",omitempty"` + CreatedBy string `json:"createdBy",omitempty"` //Email address of the user that created the resource + Created time.Time `json:"created",omitempty"` //Created RFC3339 date time +} + +//ResponseSingnalTagBodyList response list +type ResponseSingnalTagBodyList struct { + Data []ResponseSignalTagBody `json:"data"` //ResponseSignalTagBody +} + +//CreateCorpSignalTag create signal tag +func (sc Client) CreateCorpSignalTag(corpName string, body CreateSignalTagBody) (ResponseSignalTagBody, error) { + b, err := json.Marshal(body) if err != nil { - return ResponseListBody{}, err + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) } - return getResponseListBody(resp) + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/tags", corpName), string(b)) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + } + return getResponseSignalTagBody(resp) } -//GetAllCorpLists get all corp lists -func (sc Client) GetAllCorpLists(corpName string) (ResponseListBodyList, error) { - resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists", corpName), "") +//GetCorpSignalTagByID get corp signal by id +func (sc Client) GetCorpSignalTagByID(corpName string, id string) (ResponseSignalTagBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/tags/%s", corpName, id), "") if err != nil { - return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseSignalTagBody{}, err } - var responseListBodyList ResponseListBodyList - err = json.Unmarshal(resp, &responseListBodyList) + return getResponseSignalTagBody(resp) +} + +//GetAllCorpSignalTags get all corp signals +func (sc Client) GetAllCorpSignalTags(corpName string) (ResponseSingnalTagBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/tags", corpName), "") if err != nil { - return ResponseListBodyList{}, err + return ResponseSingnalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) } - return responseListBodyList, nil + var responseSignalTagBodyList ResponseSingnalTagBodyList + err = json.Unmarshal(resp, &responseSignalTagBodyList) + if err != nil { + return ResponseSingnalTagBodyList{}, err + } + return responseSignalTagBodyList, nil } -func logError(skip int, err error) error { - pc, _, line, _ := runtime.Caller(skip) - fn := runtime.FuncForPC(pc).Name() - return fmt.Errorf("[ERROR] %s:%d\t%s", fn, line, err.Error()) + +//UpdateCorpSignalTagByID update corp signal +func (sc Client) UpdateCorpSignalTagByID(corpName string, id string, body UpdateSignalTagBody) (ResponseSignalTagBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) + } + resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/tags/%s", corpName, id), string(b)) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + } + return getResponseSignalTagBody(resp) +} + +//DeleteCorpSignalTagByID delete signal tag by id +func (sc Client) DeleteCorpSignalTagByID(corpName string, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/tags/%s", corpName, id), "") + if err != nil { + return logError(1, fmt.Errorf("%s could not delete %s in %s", err.Error(), id, corpName)) + } + return nil +} +func getResponseSignalTagBody(response []byte) (ResponseSignalTagBody, error) { + var responseBody ResponseSignalTagBody + err := json.Unmarshal(response, &responseBody) + if err != nil { + return ResponseSignalTagBody{}, err + } + return responseBody, nil +} + +//CreateSiteSignalTag create signal tag +func (sc Client) CreateSiteSignalTag(corpName, siteName string, body CreateSignalTagBody) (ResponseSignalTagBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) + } + resp, err := sc.doRequest("POST", fmt.Sprintf("/v0/corps/%s/sites/%s/tags", corpName, siteName), string(b)) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + } + return getResponseSignalTagBody(resp) +} + +//GetSiteSignalTagByID get site signal by id +func (sc Client) GetSiteSignalTagByID(corpName, siteName, id string) (ResponseSignalTagBody, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/tags/%s", corpName, siteName, id), "") + if err != nil { + return ResponseSignalTagBody{}, err + } + return getResponseSignalTagBody(resp) +} + +//GetAllSiteSignalTags get all site signals +func (sc Client) GetAllSiteSignalTags(corpName, siteName string) (ResponseSingnalTagBodyList, error) { + resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/tags", corpName, siteName), "") + if err != nil { + return ResponseSingnalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + } + var responseSignalTagBodyList ResponseSingnalTagBodyList + err = json.Unmarshal(resp, &responseSignalTagBodyList) + if err != nil { + return ResponseSingnalTagBodyList{}, err + } + return responseSignalTagBodyList, nil +} + +//UpdateSiteSignalTagByID update site signal +func (sc Client) UpdateSiteSignalTagByID(corpName, siteName, id string, body UpdateSignalTagBody) (ResponseSignalTagBody, error) { + b, err := json.Marshal(body) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), body)) + } + resp, err := sc.doRequest("PATCH", fmt.Sprintf("/v0/corps/%s/sites/%s/tags/%s", corpName, siteName, id), string(b)) + if err != nil { + return ResponseSignalTagBody{}, logError(1, fmt.Errorf("%s with input %v", err.Error(), string(b))) + } + return getResponseSignalTagBody(resp) +} + +//DeleteSiteSignalTagByID delete signal tag by id +func (sc Client) DeleteSiteSignalTagByID(corpName, siteName, id string) error { + _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/tags/%s", corpName, siteName, id), "") + if err != nil { + return logError(1, fmt.Errorf("%s could not delete %s in %s in %s", err.Error(), id, corpName, siteName)) + } + return nil } diff --git a/api_test.go b/api_test.go index 25bd116..e8bcfb5 100644 --- a/api_test.go +++ b/api_test.go @@ -83,52 +83,6 @@ func TestCreateDeleteSite(t *testing.T) { t.Logf("%#v", err) } } -func TestGetAlerts(t *testing.T) { - t.Skip() - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-tescorp" - site := "splunk-test" - alert, err := sc.GetCustomAlert(corp, site, "5e828777a981ef01c7107035") - if err != nil { - t.Fatal(err) - } - t.Logf("%+v", alert) -} -func TestCreateCustomSiteAlert(t *testing.T) { - sc := NewTokenClient(testcreds.email, testcreds.token) - corp := "splunk-tescorp" - site := "splunk-test" - customAlertBody := CustomAlertBody{ - TagName: "CMDEXE", - LongName: "Janitha Long Name", - Action: "flagged", - Enabled: true, - Interval: 1, - Threshold: 1, - } - alert, err := sc.CreateCustomAlert(corp, site, customAlertBody) //changed the method to POST - if err != nil { - t.Fatal(err) - } - assert.Equal(t, true, alert.Enabled) - customAlertBody = CustomAlertBody{ - TagName: "CMDEXE", - LongName: "Janitha Long Name", - Action: "flagged", - Enabled: false, - Interval: 1, - Threshold: 1, - } - alertup, err := sc.UpdateCustomAlert(corp, site, alert.ID, customAlertBody) - assert.Equal(t, false, alertup.Enabled) - assert.Equal(t, alert.ID, alertup.ID) - err = sc.DeleteCustomAlert(corp, site, alert.ID) - _, err = sc.GetCustomAlert(corp, site, alert.ID) - if err == nil { //expect a failure because the ID does not exist - t.Fatal(err) - } - // assert.Equal(t, alert.ID, alertdel.ID) -} func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { @@ -445,7 +399,7 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { corp := "splunk-tescorp" site := "splunk-test" - createCustomAlert := CustomAlertBody{ + createCustomAlert := CreateCustomAlertBody{ TagName: "SQLI", LongName: "Example Alert", Interval: 1, @@ -453,19 +407,19 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { Enabled: true, Action: "flagged", } - createresp, err := sc.CreateCustomAlert(corp, site, createCustomAlert) + createresp, err := sc.CreateCustomSiteAlert(corp, site, createCustomAlert) // t.Logf("%#v", createresp.Data) if err != nil { t.Fatal(err) } - assert.Equal(t, createCustomAlert, *createresp.CustomAlertBody) - readresp, err := sc.GetCustomAlert(corp, site, createresp.ID) + assert.Equal(t, createCustomAlert, createresp.CreateCustomAlertBody) + readresp, err := sc.GetCustomSiteAlertByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) } - assert.Equal(t, createCustomAlert, *readresp.CustomAlertBody) + assert.Equal(t, createCustomAlert, readresp.CreateCustomAlertBody) - updateCustomAlert := CustomAlertBody{ + updateCustomAlert := CreateCustomAlertBody{ TagName: "SQLI", LongName: "Example Alert Updated", Interval: 10, @@ -473,18 +427,25 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { Enabled: true, Action: "flagged", } - updateresp, err := sc.UpdateCustomAlert(corp, site, readresp.ID, updateCustomAlert) + updateresp, err := sc.UpdateCustomSiteAlertByID(corp, site, readresp.ID, updateCustomAlert) if err != nil { t.Fatal(err) } // t.Logf("%#v", updateresp) - assert.NotEqual(t, createCustomAlert, *updateresp.CustomAlertBody) - assert.Equal(t, updateCustomAlert, *updateresp.CustomAlertBody) - - err = sc.DeleteCustomAlert(corp, site, createresp.ID) + assert.NotEqual(t, createCustomAlert, updateresp.CreateCustomAlertBody) + assert.Equal(t, updateCustomAlert, updateresp.CreateCustomAlertBody) + allalerts, err := sc.GetAllCustomSiteAlerts(corp, site) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 1, len(allalerts.Data)) + assert.Equal(t, updateCustomAlert, allalerts.Data[0].CreateCustomAlertBody) + // for _, createresp := range allalerts.Data { + err = sc.DeleteCustomSiteAlertByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) } + // } } func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { createCorpRuleBody := CreateCorpRuleBody{ @@ -577,6 +538,9 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { } assert.Equal(t, updateCorpRuleBody, updateResp.CreateCorpRuleBody) readall, err := sc.GetAllCorpRules(corp) + if err != nil { + t.Fatal(err) + } assert.Equal(t, 1, len(readall.Data)) assert.Equal(t, 1, readall.TotalCount) assert.Equal(t, updateCorpRuleBody, readall.Data[0].CreateCorpRuleBody) @@ -607,6 +571,9 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { assert.Equal(t, createCorpListBody, createresp.CreateListBody) readresp, err := sc.GetCorpListByID(corp, createresp.ID) + if err != nil { + t.Fatal(err) + } assert.Equal(t, createCorpListBody, readresp.CreateListBody) updateCorpListBody := UpdateListBody{ @@ -633,6 +600,9 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { } assert.Equal(t, updatedCorpListBody, updateresp.CreateListBody) readall, err := sc.GetAllCorpLists(corp) + if err != nil { + t.Fatal(err) + } assert.Equal(t, 1, len(readall.Data)) assert.Equal(t, updatedCorpListBody, readall.Data[0].CreateListBody) err = sc.DeleteCorpListByID(corp, readresp.ID) @@ -640,3 +610,99 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { t.Fatal(err) } } + +func TestCreateReadUpdateDeleteCorpTag(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + createSignalTagBody := CreateSignalTagBody{ + ShortName: "example-signal-tag", + Description: "An example of a custom signal tag", + } + createresp, err := sc.CreateCorpSignalTag(corp, createSignalTagBody) + if err != nil { + t.Fatal(err) + } + readresp, err := sc.GetCorpSignalTagByID(corp, createresp.TagName) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createSignalTagBody, readresp.CreateSignalTagBody) + updateSignalTagBody := UpdateSignalTagBody{ + Description: "An example of a custom signal tag - UPDATE", + } + updateresp, err := sc.UpdateCorpSignalTagByID(corp, createresp.TagName, updateSignalTagBody) + if err != nil { + t.Fatal(err) + } + updatedSignalTagBody := CreateSignalTagBody{ + ShortName: "example-signal-tag", + Description: "An example of a custom signal tag - UPDATE", + } + assert.Equal(t, updatedSignalTagBody, updateresp.CreateSignalTagBody) + readall, err := sc.GetAllCorpSignalTags(corp) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, updatedSignalTagBody, readall.Data[0].CreateSignalTagBody) + err = sc.DeleteCorpSignalTagByID(corp, readresp.TagName) + if err != nil { + t.Fatal(err) + } +} + +func TestCreateReadUpdateDeleteSignalTag(t *testing.T) { + sc := NewTokenClient(testcreds.email, testcreds.token) + corp := "splunk-tescorp" + site := "splunk-test" + createSignalTagBody := CreateSignalTagBody{ + ShortName: "example-signal-tag", + Description: "An example of a custom signal tag", + } + createresp, err := sc.CreateSiteSignalTag(corp, site, createSignalTagBody) + if err != nil { + t.Fatal(err) + } + readresp, err := sc.GetSiteSignalTagByID(corp, site, createresp.TagName) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, createSignalTagBody, readresp.CreateSignalTagBody) + updateSignalTagBody := UpdateSignalTagBody{ + Description: "An example of a custom signal tag - UPDATE", + } + updateresp, err := sc.UpdateSiteSignalTagByID(corp, site, createresp.TagName, updateSignalTagBody) + if err != nil { + t.Fatal(err) + } + updatedSignalTagBody := CreateSignalTagBody{ + ShortName: "example-signal-tag", + Description: "An example of a custom signal tag - UPDATE", + } + assert.Equal(t, updatedSignalTagBody, updateresp.CreateSignalTagBody) + readall, err := sc.GetAllSiteSignalTags(corp, site) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 1, len(readall.Data)) + assert.Equal(t, updatedSignalTagBody, readall.Data[0].CreateSignalTagBody) + err = sc.DeleteSiteSignalTagByID(corp, site, readresp.TagName) + if err != nil { + t.Fatal(err) + } +} + +// var ( +// buf bytes.Buffer +// logger = log.New(&buf, "INFO: ", log.Lshortfile) + +// infof = func(info string) { +// logger.Output(2, info) +// } +// ) + +// func TestLog(t *testing.T) { +// infof("Hello world") + +// fmt.Print(&buf) +// } From 5c6f084df34139be2791bbdf02828a6b276e05a6 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Wed, 13 May 2020 10:44:53 -0700 Subject: [PATCH 13/17] change customsitealert to sitecustomalert --- api.go | 30 +++++++++++++++--------------- api_test.go | 8 ++++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/api.go b/api.go index 668f194..bddcc9d 100644 --- a/api.go +++ b/api.go @@ -569,8 +569,8 @@ func (sc Client) GetAllCustomSiteAlerts(corpName, siteName string) (ResponseCust return car, nil } -// CreateCustomSiteAlert creates a custom alert. -func (sc Client) CreateCustomSiteAlert(corpName, siteName string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { +// CreateSiteCustomAlert creates a custom alert. +func (sc Client) CreateSiteCustomAlert(corpName, siteName string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { b, err := json.Marshal(body) if err != nil { return ResponseCustomAlertBody{}, err @@ -590,8 +590,8 @@ func (sc Client) CreateCustomSiteAlert(corpName, siteName string, body CreateCus return c, nil } -// GetCustomSiteAlertByID gets a custom alert by ID -func (sc Client) GetCustomSiteAlertByID(corpName, siteName, id string) (ResponseCustomAlertBody, error) { +// GetSiteCustomAlertByID gets a custom alert by ID +func (sc Client) GetSiteCustomAlertByID(corpName, siteName, id string) (ResponseCustomAlertBody, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") if err != nil { return ResponseCustomAlertBody{}, err @@ -606,8 +606,8 @@ func (sc Client) GetCustomSiteAlertByID(corpName, siteName, id string) (Response return ca, nil } -// UpdateCustomSiteAlertByID updates a custom alert by id. -func (sc Client) UpdateCustomSiteAlertByID(corpName, siteName, id string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { +// UpdateSiteCustomAlertByID updates a custom alert by id. +func (sc Client) UpdateSiteCustomAlertByID(corpName, siteName, id string, body CreateCustomAlertBody) (ResponseCustomAlertBody, error) { b, err := json.Marshal(body) if err != nil { return ResponseCustomAlertBody{}, logError(1, fmt.Errorf("%s with input %#v", err.Error(), string(b))) @@ -627,8 +627,8 @@ func (sc Client) UpdateCustomSiteAlertByID(corpName, siteName, id string, body C return c, err } -// DeleteCustomSiteAlertByID deletes a custom alert. -func (sc Client) DeleteCustomSiteAlertByID(corpName, siteName, id string) error { +// DeleteSiteCustomAlertByID deletes a custom alert. +func (sc Client) DeleteSiteCustomAlertByID(corpName, siteName, id string) error { _, err := sc.doRequest("DELETE", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts/%s", corpName, siteName, id), "") return err @@ -2262,13 +2262,13 @@ type UpdateSignalTagBody struct { //ResponseSignalTagBody response singnal tag type ResponseSignalTagBody struct { CreateSignalTagBody - TagName string `json:"tagName",omitempty"` //The identifier for the signal tag - LongName string `json:"longName",omitempty"` //The display name of the signal tag - deprecated - Configurable bool `json:"configurable",omitempty"` - Informational bool `json:"informational",omitempty"` - NeedsResponse bool `json:"needsResponse",omitempty"` - CreatedBy string `json:"createdBy",omitempty"` //Email address of the user that created the resource - Created time.Time `json:"created",omitempty"` //Created RFC3339 date time + TagName string `json:"tagName,omitempty"` //The identifier for the signal tag + LongName string `json:"longName,omitempty"` //The display name of the signal tag - deprecated + Configurable bool `json:"configurable,omitempty"` + Informational bool `json:"informational,omitempty"` + NeedsResponse bool `json:"needsResponse,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` //Email address of the user that created the resource + Created time.Time `json:"created,omitempty"` //Created RFC3339 date time } //ResponseSingnalTagBodyList response list diff --git a/api_test.go b/api_test.go index e8bcfb5..25ef2df 100644 --- a/api_test.go +++ b/api_test.go @@ -407,13 +407,13 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { Enabled: true, Action: "flagged", } - createresp, err := sc.CreateCustomSiteAlert(corp, site, createCustomAlert) + createresp, err := sc.CreateSiteCustomAlert(corp, site, createCustomAlert) // t.Logf("%#v", createresp.Data) if err != nil { t.Fatal(err) } assert.Equal(t, createCustomAlert, createresp.CreateCustomAlertBody) - readresp, err := sc.GetCustomSiteAlertByID(corp, site, createresp.ID) + readresp, err := sc.GetSiteCustomAlertByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) } @@ -427,7 +427,7 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { Enabled: true, Action: "flagged", } - updateresp, err := sc.UpdateCustomSiteAlertByID(corp, site, readresp.ID, updateCustomAlert) + updateresp, err := sc.UpdateSiteCustomAlertByID(corp, site, readresp.ID, updateCustomAlert) if err != nil { t.Fatal(err) } @@ -441,7 +441,7 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { assert.Equal(t, 1, len(allalerts.Data)) assert.Equal(t, updateCustomAlert, allalerts.Data[0].CreateCustomAlertBody) // for _, createresp := range allalerts.Data { - err = sc.DeleteCustomSiteAlertByID(corp, site, createresp.ID) + err = sc.DeleteSiteCustomAlertByID(corp, site, createresp.ID) if err != nil { t.Fatal(err) } From b898a21915704c39ed631406626c073af5792c56 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Wed, 13 May 2020 11:53:17 -0700 Subject: [PATCH 14/17] update custom alert api --- api.go | 25 ++++++++++++++----------- api_test.go | 26 ++++++++++++++------------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/api.go b/api.go index bddcc9d..ebe10e7 100644 --- a/api.go +++ b/api.go @@ -531,21 +531,25 @@ func (sc *Client) UpdateSite(corpName, siteName string, body UpdateSiteBody) (Si // CreateCustomAlertBody is the body for creating a custom alert. type CreateCustomAlertBody struct { - TagName string `json:"tagName"` - LongName string `json:"longName"` - Interval int `json:"interval"` - Threshold int `json:"threshold"` - Enabled bool `json:"enabled"` - Action string `json:"action"` + TagName string `json:"tagName,omitempty"` //The name of the tag whose occurrences the alert is watching. Must match an existing tag + LongName string `json:"longName,omitempty"` //A human readable description of the alert. Must be between 3 and 25 characters. + Interval int `json:"interval"` //The number of minutes of past traffic to examine. Must be 1, 10 or 60. + Threshold int `json:"threshold"` //The number of occurrences of the tag in the interval needed to trigger the alert. + BlockDurationSeconds int `json:"blockDurationSeconds"` //The number of seconds this alert is active. + Enabled bool `json:"enabled"` //A flag to toggle this alert. + Action string `json:"action,omitempty"` //A flag that describes what happens when the alert is triggered. 'info' creates an incident in the dashboard. 'flagged' creates an incident and blocks traffic for 24 hours. } //ResponseCustomAlertBody contains the data for a custom alert type ResponseCustomAlertBody struct { CreateCustomAlertBody - ID string - Created time.Time - CreatedBy string - Updated time.Time + ID string `json:"id,omitempty"` //Site-specific unique ID of the alert + Type string `json:"type,omitempty"` //Type of alert (siteAlert, template, rateLimit, siteMetric) + SkipNotifications bool `json:"skipNotifications"` //A flag to disable external notifications - slack, webhooks, emails, etc. + FieldName string `json:"fieldName,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` //The email of the user that created the alert + Created time.Time `json:"created,omitempty"` //Created RFC3339 date time + Operator string } // ResponseCustomAlertsBodyList is the response for the alerts endpoint @@ -586,7 +590,6 @@ func (sc Client) CreateSiteCustomAlert(corpName, siteName string, body CreateCus if err != nil { return ResponseCustomAlertBody{}, err } - return c, nil } diff --git a/api_test.go b/api_test.go index 25ef2df..aa43e8e 100644 --- a/api_test.go +++ b/api_test.go @@ -400,12 +400,13 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { site := "splunk-test" createCustomAlert := CreateCustomAlertBody{ - TagName: "SQLI", - LongName: "Example Alert", - Interval: 1, - Threshold: 10, - Enabled: true, - Action: "flagged", + TagName: "SQLI", + LongName: "Example Alert", + BlockDurationSeconds: 1, + Interval: 1, + Threshold: 10, + Enabled: true, + Action: "flagged", } createresp, err := sc.CreateSiteCustomAlert(corp, site, createCustomAlert) // t.Logf("%#v", createresp.Data) @@ -420,12 +421,13 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { assert.Equal(t, createCustomAlert, readresp.CreateCustomAlertBody) updateCustomAlert := CreateCustomAlertBody{ - TagName: "SQLI", - LongName: "Example Alert Updated", - Interval: 10, - Threshold: 10, - Enabled: true, - Action: "flagged", + TagName: "SQLI", + LongName: "Example Alert Updated", + BlockDurationSeconds: 1, + Interval: 10, + Threshold: 10, + Enabled: true, + Action: "flagged", } updateresp, err := sc.UpdateSiteCustomAlertByID(corp, site, readresp.ID, updateCustomAlert) if err != nil { From 1bd8709349e4401d6ed824043905b7e620077c61 Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Thu, 21 May 2020 17:28:55 -0700 Subject: [PATCH 15/17] clean up remove redundant type fix spelling error ResponseSingal GetAllCustomSiteAlerts to GetAllSiteCustomAlerts Add Tests check the response for signal shortname and lists to conversion lowercase and hyphenated no special characters --- api.go | 24 +++++++------- api_test.go | 95 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 48 deletions(-) diff --git a/api.go b/api.go index ebe10e7..63410f9 100644 --- a/api.go +++ b/api.go @@ -557,8 +557,8 @@ type ResponseCustomAlertsBodyList struct { Data []ResponseCustomAlertBody } -// GetAllCustomSiteAlerts lists custom alerts for a given corp and site. -func (sc Client) GetAllCustomSiteAlerts(corpName, siteName string) (ResponseCustomAlertsBodyList, error) { +// GetAllSiteCustomAlerts lists custom alerts for a given corp and site. +func (sc Client) GetAllSiteCustomAlerts(corpName, siteName string) (ResponseCustomAlertsBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), "") if err != nil { return ResponseCustomAlertsBodyList{}, err @@ -2274,8 +2274,8 @@ type ResponseSignalTagBody struct { Created time.Time `json:"created,omitempty"` //Created RFC3339 date time } -//ResponseSingnalTagBodyList response list -type ResponseSingnalTagBodyList struct { +//ResponseSignalTagBodyList response list +type ResponseSignalTagBodyList struct { Data []ResponseSignalTagBody `json:"data"` //ResponseSignalTagBody } @@ -2302,15 +2302,15 @@ func (sc Client) GetCorpSignalTagByID(corpName string, id string) (ResponseSigna } //GetAllCorpSignalTags get all corp signals -func (sc Client) GetAllCorpSignalTags(corpName string) (ResponseSingnalTagBodyList, error) { +func (sc Client) GetAllCorpSignalTags(corpName string) (ResponseSignalTagBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/tags", corpName), "") if err != nil { - return ResponseSingnalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) } - var responseSignalTagBodyList ResponseSingnalTagBodyList + var responseSignalTagBodyList ResponseSignalTagBodyList err = json.Unmarshal(resp, &responseSignalTagBodyList) if err != nil { - return ResponseSingnalTagBodyList{}, err + return ResponseSignalTagBodyList{}, err } return responseSignalTagBodyList, nil } @@ -2368,15 +2368,15 @@ func (sc Client) GetSiteSignalTagByID(corpName, siteName, id string) (ResponseSi } //GetAllSiteSignalTags get all site signals -func (sc Client) GetAllSiteSignalTags(corpName, siteName string) (ResponseSingnalTagBodyList, error) { +func (sc Client) GetAllSiteSignalTags(corpName, siteName string) (ResponseSignalTagBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/tags", corpName, siteName), "") if err != nil { - return ResponseSingnalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) } - var responseSignalTagBodyList ResponseSingnalTagBodyList + var responseSignalTagBodyList ResponseSignalTagBodyList err = json.Unmarshal(resp, &responseSignalTagBodyList) if err != nil { - return ResponseSingnalTagBodyList{}, err + return ResponseSignalTagBodyList{}, err } return responseSignalTagBodyList, nil } diff --git a/api_test.go b/api_test.go index aa43e8e..8de6f1c 100644 --- a/api_test.go +++ b/api_test.go @@ -5,6 +5,7 @@ import ( "log" "os" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -94,17 +95,17 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { Signal: "SQLI", Expiration: "", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", Value: "1.2.3.4", }, - Condition{ + { Type: "group", GroupOperator: "any", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", @@ -141,17 +142,17 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { Signal: "SQLI", Expiration: "", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", Value: "1.2.3.4", }, - Condition{ + { Type: "group", GroupOperator: "any", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", @@ -161,7 +162,7 @@ func TestCreateReadUpdateDeleteSiteRules(t *testing.T) { }, }, Actions: []Action{ - Action{ + { Type: "excludeSignal", }, }, @@ -354,7 +355,7 @@ func TestCreateMultipleRedactions(t *testing.T) { t.Fatal(err) } } -func TestCreatListUpdateDeleteRedaction(t *testing.T) { +func TestCreateListUpdateDeleteRedaction(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" site := "splunk-test" @@ -436,7 +437,7 @@ func TestSiteCreateReadUpdateDeleteAlerts(t *testing.T) { // t.Logf("%#v", updateresp) assert.NotEqual(t, createCustomAlert, updateresp.CreateCustomAlertBody) assert.Equal(t, updateCustomAlert, updateresp.CreateCustomAlertBody) - allalerts, err := sc.GetAllCustomSiteAlerts(corp, site) + allalerts, err := sc.GetAllSiteCustomAlerts(corp, site) if err != nil { t.Fatal(err) } @@ -455,17 +456,17 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { Type: "signal", GroupOperator: "all", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", Value: "1.2.3.4", }, - Condition{ + { Type: "group", GroupOperator: "any", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", @@ -475,7 +476,7 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { }, }, Actions: []Action{ - Action{ + { Type: "excludeSignal", }, }, @@ -504,17 +505,17 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { Type: "signal", GroupOperator: "all", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", Value: "5.6.7.8", }, - Condition{ + { Type: "group", GroupOperator: "any", Conditions: []Condition{ - Condition{ + { Type: "single", Field: "ip", Operator: "equals", @@ -524,7 +525,7 @@ func TestCreateReadUpdateDeleteCorpRule(t *testing.T) { }, }, Actions: []Action{ - Action{ + { Type: "excludeSignal", }, }, @@ -557,7 +558,7 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" createCorpListBody := CreateListBody{ - Name: "My new list", + Name: "My new List", Type: "ip", Description: "Some IPs we are putting in a list", Entries: []string{ @@ -571,6 +572,26 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { t.Fatal(err) } assert.Equal(t, createCorpListBody, createresp.CreateListBody) + expectedCreateResponse := ResponseListBody{ + CreateListBody: CreateListBody{ + Name: "My new List", + Type: "ip", + Description: "Some IPs we are putting in a list", + Entries: []string{ + "4.5.6.7", + "2.3.4.5", + "1.2.3.4", + }, + }, + ID: "corp.my-new-list", + CreatedBy: "", + Created: time.Time{}, //wall: 0x0, ext: 63725163294, loc: (*time.Location)(nil)}, + Updated: time.Time{}, //wall: 0x0, ext: 63725163294, loc: (*time.Location)(nil)}, + } + createresp.Created = time.Time{} + createresp.Updated = time.Time{} + createresp.CreatedBy = "" + assert.Equal(t, expectedCreateResponse, createresp) readresp, err := sc.GetCorpListByID(corp, createresp.ID) if err != nil { @@ -591,7 +612,7 @@ func TestCreateReadUpdateDeleteCorpList(t *testing.T) { } assert.NotEqual(t, createCorpListBody, updateresp.CreateListBody) updatedCorpListBody := CreateListBody{ - Name: "My new list", + Name: "My new List", Type: "ip", Description: "Some IPs we are updating in the list", Entries: []string{ @@ -617,13 +638,30 @@ func TestCreateReadUpdateDeleteCorpTag(t *testing.T) { sc := NewTokenClient(testcreds.email, testcreds.token) corp := "splunk-tescorp" createSignalTagBody := CreateSignalTagBody{ - ShortName: "example-signal-tag", + ShortName: "Example Signal Tag 1", Description: "An example of a custom signal tag", } createresp, err := sc.CreateCorpSignalTag(corp, createSignalTagBody) if err != nil { t.Fatal(err) } + assert.Equal(t, createSignalTagBody, createresp.CreateSignalTagBody) + expectedCreateResponse := ResponseSignalTagBody{ + CreateSignalTagBody: CreateSignalTagBody{ + ShortName: "Example Signal Tag 1", + Description: "An example of a custom signal tag", + }, + TagName: "corp.example-signal-tag-1", + LongName: "Example Signal Tag 1", + Configurable: false, + Informational: false, + NeedsResponse: false, + CreatedBy: "", + Created: time.Time{}, + } + createresp.Created = time.Time{} + createresp.CreatedBy = "" + assert.Equal(t, expectedCreateResponse, createresp) readresp, err := sc.GetCorpSignalTagByID(corp, createresp.TagName) if err != nil { t.Fatal(err) @@ -637,7 +675,7 @@ func TestCreateReadUpdateDeleteCorpTag(t *testing.T) { t.Fatal(err) } updatedSignalTagBody := CreateSignalTagBody{ - ShortName: "example-signal-tag", + ShortName: "Example Signal Tag 1", Description: "An example of a custom signal tag - UPDATE", } assert.Equal(t, updatedSignalTagBody, updateresp.CreateSignalTagBody) @@ -693,18 +731,3 @@ func TestCreateReadUpdateDeleteSignalTag(t *testing.T) { t.Fatal(err) } } - -// var ( -// buf bytes.Buffer -// logger = log.New(&buf, "INFO: ", log.Lshortfile) - -// infof = func(info string) { -// logger.Output(2, info) -// } -// ) - -// func TestLog(t *testing.T) { -// infof("Hello world") - -// fmt.Print(&buf) -// } From 0ad807649d5423936a9120fef6160930156fa53e Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Tue, 26 May 2020 16:40:36 -0700 Subject: [PATCH 16/17] add error message for get all that includes corp and site --- api.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api.go b/api.go index 63410f9..d029ec6 100644 --- a/api.go +++ b/api.go @@ -561,7 +561,7 @@ type ResponseCustomAlertsBodyList struct { func (sc Client) GetAllSiteCustomAlerts(corpName, siteName string) (ResponseCustomAlertsBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/alerts", corpName, siteName), "") if err != nil { - return ResponseCustomAlertsBodyList{}, err + return ResponseCustomAlertsBodyList{}, logError(1, fmt.Errorf("%s with %s %s ", err.Error(), corpName, siteName)) } var car ResponseCustomAlertsBodyList @@ -1868,7 +1868,7 @@ func (sc *Client) GetAllSiteRules(corpName, siteName string) (ResponseSiteRuleBo resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/rules", corpName, siteName), "") if err != nil { - return ResponseSiteRuleBodyList{}, err + return ResponseSiteRuleBodyList{}, logError(1, fmt.Errorf("%s with %s %s ", err.Error(), corpName, siteName)) } var responseRulesList ResponseSiteRuleBodyList @@ -1972,7 +1972,7 @@ func (sc Client) GetSiteListByID(corpName, siteName string, id string) (Response func (sc Client) GetAllSiteLists(corpName, siteName string) (ResponseListBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/lists", corpName, siteName), "") if err != nil { - return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseListBodyList{}, logError(1, fmt.Errorf("%s with %s %s ", err.Error(), corpName, siteName)) } var responseListBodyList ResponseListBodyList err = json.Unmarshal(resp, &responseListBodyList) @@ -2079,7 +2079,7 @@ func (sc *Client) GetAllSiteRedactions(corpName, siteName string) (ResponseSiteR resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/redactions", corpName, siteName), "") if err != nil { - return ResponseSiteRedactionBodyList{}, err + return ResponseSiteRedactionBodyList{}, logError(1, fmt.Errorf("%s with %s %s ", err.Error(), corpName, siteName)) } var responseRulesList ResponseSiteRuleBodyList @@ -2146,7 +2146,7 @@ func (sc Client) GetCorpRuleByID(corpName, id string) (ResponseCorpRuleBody, err func (sc Client) GetAllCorpRules(corpName string) (ResponseCorpRuleBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/rules", corpName), "") if err != nil { - return ResponseCorpRuleBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseCorpRuleBodyList{}, logError(1, fmt.Errorf("%s with %s", err.Error(), corpName)) } var responseRuleBodyList ResponseCorpRuleBodyList err = json.Unmarshal(resp, &responseRuleBodyList) @@ -2213,7 +2213,7 @@ func (sc Client) GetCorpListByID(corpName string, id string) (ResponseListBody, func (sc Client) GetAllCorpLists(corpName string) (ResponseListBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/lists", corpName), "") if err != nil { - return ResponseListBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseListBodyList{}, logError(1, fmt.Errorf("%s with %s", err.Error(), corpName)) } var responseListBodyList ResponseListBodyList err = json.Unmarshal(resp, &responseListBodyList) @@ -2305,7 +2305,7 @@ func (sc Client) GetCorpSignalTagByID(corpName string, id string) (ResponseSigna func (sc Client) GetAllCorpSignalTags(corpName string) (ResponseSignalTagBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/tags", corpName), "") if err != nil { - return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s with %s ", err.Error(), corpName)) } var responseSignalTagBodyList ResponseSignalTagBodyList err = json.Unmarshal(resp, &responseSignalTagBodyList) @@ -2371,7 +2371,7 @@ func (sc Client) GetSiteSignalTagByID(corpName, siteName, id string) (ResponseSi func (sc Client) GetAllSiteSignalTags(corpName, siteName string) (ResponseSignalTagBodyList, error) { resp, err := sc.doRequest("GET", fmt.Sprintf("/v0/corps/%s/sites/%s/tags", corpName, siteName), "") if err != nil { - return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s", err.Error())) + return ResponseSignalTagBodyList{}, logError(1, fmt.Errorf("%s with %s %s ", err.Error(), corpName, siteName)) } var responseSignalTagBodyList ResponseSignalTagBodyList err = json.Unmarshal(resp, &responseSignalTagBodyList) From f0d80bac2b4566f0d5e52352a392e3ffcf980f0e Mon Sep 17 00:00:00 2001 From: Janitha Jayaweera Date: Thu, 24 Sep 2020 18:21:45 -0700 Subject: [PATCH 17/17] Adds hcl tags. This allows you to generate terraform HCL using a snippet like this ```go func (l localCreateSiteRuleBody) marshalText(localName, site, dependson string) string { str := fmt.Sprintf(`resource "sigsci_site_rule" "%s" { %s site_short_name="%s" `, localName, dependson, site) f := hclwrite.NewEmptyFile() gohcl.EncodeIntoBody(&l, f.Body()) str += string(f.Bytes()) // str += marshalStructText(l) str += "}\n" return str } ``` --- Makefile | 7 ----- api.go | 88 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index a72c78b..dfc78d3 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,3 @@ lint: test -z $(gofmt -s -l .) test: go test -v -<<<<<<< HEAD -publish: test - git tag -fa v0.3.0 - git push origin --tags - -======= ->>>>>>> upstream/master diff --git a/api.go b/api.go index 51b27d3..f314430 100644 --- a/api.go +++ b/api.go @@ -573,12 +573,12 @@ func (sc *Client) ListCustomAlerts(corpName, siteName string) ([]CustomAlert, er // CustomAlertBody is the body for creating a custom alert. type CustomAlertBody struct { - TagName string `json:"tagName"` - LongName string `json:"longName"` - Interval int `json:"interval"` - Threshold int `json:"threshold"` - Enabled bool `json:"enabled"` - Action string `json:"action"` + TagName string `hcl:"tag_name" json:"tagName"` + LongName string `hcl:"long_name" json:"longName"` + Interval int `hcl:"interval" json:"interval"` + Threshold int `hcl:"threshold" json:"threshold"` + Enabled bool `hcl:"enabled" json:"enabled"` + Action string `hcl:"action" json:"action"` } // CreateCustomAlert creates a custom alert. @@ -1864,38 +1864,38 @@ func (sc *Client) DeleteSite(corpName, siteName string) error { // Condition contains rule condition type Condition struct { - Type string `json:"type,omitempty"` //(group, single) - GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) - Field string `json:"field,omitempty"` //type: single - (scheme, method, path, useragent, domain, ip, responseCode, agentname, paramname, paramvalue, country, name, valueString, valueIp, signalType) - Operator string `json:"operator,omitempty"` //type: single - (equals, doesNotEqual, contains, doesNotContain, like, notLike, exists, doesNotExist, inList, notInList) - Value string `json:"value,omitempty"` //type: single - See request fields (https://docs.signalsciences.net/using-signal-sciences/features/rules/#request-fields) - Conditions []Condition `json:"conditions,omitempty"` + Type string `hcl:"type" json:"type,omitempty"` //(group, single) + GroupOperator string `hcl:"group_operator" json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Field string `hcl:"field" json:"field,omitempty"` //type: single - (scheme, method, path, useragent, domain, ip, responseCode, agentname, paramname, paramvalue, country, name, valueString, valueIp, signalType) + Operator string `hcl:"operator" json:"operator,omitempty"` //type: single - (equals, doesNotEqual, contains, doesNotContain, like, notLike, exists, doesNotExist, inList, notInList) + Value string `hcl:"value" json:"value,omitempty"` //type: single - See request fields (https://docs.signalsciences.net/using-signal-sciences/features/rules/#request-fields) + Conditions []Condition `hcl:"conditions,block" json:"conditions,omitempty"` } // Action contains the rule action type Action struct { - Type string `json:"type,omitempty"` //(block, allow, exclude) - Signal string `json:"signal,omitempty"` + Type string `hcl:"type" json:"type,omitempty"` //(block, allow, exclude) + Signal string `hcl:"signal" json:"signal,omitempty"` } // RateLimit holds all the data that is specific to rate limit rules type RateLimit struct { - Threshold int `json:"threshold"` - Interval int `json:"interval"` // interval in minutes, 1 or 10 - Duration int `json:"duration"` // duration in seconds + Threshold int `hcl:"threshold" json:"threshold"` + Interval int `hcl:"interval" json:"interval"` // interval in minutes, 1 or 10 + Duration int `hcl:"duration" json:"duration"` // duration in seconds } //CreateSiteRuleBody contains the rule for the site type CreateSiteRuleBody struct { - Type string `json:"type,omitempty,omitempty"` //(signal, request, rateLimit) - GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) - Enabled bool `json:"enabled,omitempty"` - Reason string `json:"reason,omitempty"` //Description of the rule - Signal string `json:"signal,omitempty"` //The signal id of the signal being excluded. Null unless type==request - Expiration string `json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string - Conditions []Condition `json:"conditions,omitempty"` - Actions []Action `json:"actions,omitempty"` - RateLimit *RateLimit `json:"rateLimit,omitempty"` //Null unless type==rateLimit + Type string `hcl:"type" json:"type,omitempty,omitempty"` //(signal, request, rateLimit) + GroupOperator string `hcl:"group_operator" json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Enabled bool `hcl:"enabled" json:"enabled,omitempty"` + Reason string `hcl:"reason" json:"reason,omitempty"` //Description of the rule + Signal string `hcl:"signal" json:"signal,omitempty"` //The signal id of the signal being excluded. Null unless type==request + Expiration string `hcl:"expiration" json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string + Conditions []Condition `hcl:"conditions,block" json:"conditions,omitempty"` + Actions []Action `hcl:"actions,block" json:"actions,omitempty"` + RateLimit *RateLimit `hcl:"rate_limit,block" json:"rateLimit,omitempty"` //Null unless type==rateLimit } // ResponseSiteRuleBody contains the response from creating the rule @@ -1985,10 +1985,10 @@ func (sc *Client) GetAllSiteRules(corpName, siteName string) (ResponseSiteRuleBo // CreateListBody Create List Request type CreateListBody struct { - Name string `json:"name,omitempty"` //Descriptive list name - Type string `json:"type,omitempty"` //List types (string, ip, country, wildcard, signal) - Description string `json:"description,omitempty"` //Optional list description - Entries []string `json:"entries,omitempty"` //List entries + Name string `hcl:"name" json:"name,omitempty"` //Descriptive list name + Type string `hcl:"type" json:"type,omitempty"` //List types (string, ip, country, wildcard, signal) + Description string `hcl:"description" json:"description,omitempty"` //Optional list description + Entries []string `hcl:"entries" json:"entries,omitempty"` //List entries } // UpdateListBody update list @@ -2087,8 +2087,8 @@ func (sc *Client) GetAllSiteLists(corpName, siteName string) (ResponseListBodyLi // CreateSiteRedactionBody Create redaction Request type CreateSiteRedactionBody struct { - Field string `json:"field,omitempty"` //Field name - RedactionType int `json:"redactionType"` //Type of redaction (0: Request Parameter, 1: Request Header, 2: Response Header) + Field string `hcl:"field" json:"field,omitempty"` //Field name + RedactionType int `hcl:"redaction_type" json:"redactionType"` //Type of redaction (0: Request Parameter, 1: Request Header, 2: Response Header) } //UpdateSiteRedactionBody update site redaction @@ -2196,16 +2196,16 @@ func (sc *Client) GetAllSiteRedactions(corpName, siteName string) (ResponseSiteR //CreateCorpRuleBody contains the rule of a Corp type CreateCorpRuleBody struct { - SiteNames []string `json:"siteNames,omitempty"` //Sites with the rule available. Rules with a global corpScope will return '[]'. - Type string `json:"type,omitempty,omitempty"` //(request, signal) - CorpScope string `json:"corpScope,omitempty"` //Whether the rule is applied to all sites or to specific sites. (global, specificSites) - Enabled bool `json:"enabled,omitempty"` - GroupOperator string `json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) - Signal string `json:"signal,omitempty"` //The signal id of the signal being excluded - Reason string `json:"reason,omitempty"` //Description of the rule - Expiration string `json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string - Conditions []Condition `json:"conditions,omitempty"` - Actions []Action `json:"actions,omitempty"` + SiteNames []string `hcl:"site_short_names" json:"siteNames,omitempty"` //Sites with the rule available. Rules with a global corpScope will return '[]'. + Type string `hcl:"type" json:"type,omitempty,omitempty"` //(request, signal) + CorpScope string `hcl:"corp_scope" json:"corpScope,omitempty"` //Whether the rule is applied to all sites or to specific sites. (global, specificSites) + Enabled bool `hcl:"enabled" json:"enabled,omitempty"` + GroupOperator string `hcl:"group_operator" json:"groupOperator,omitempty"` //type: group - Conditions that must be matched when evaluating the request (all, any) + Signal string `hcl:"signal" json:"signal,omitempty"` //The signal id of the signal being excluded + Reason string `hcl:"reason" json:"reason,omitempty"` //Description of the rule + Expiration string `hcl:"expiration" json:"expiration,omitempty"` //Date the rule will automatically be disabled. If rule is always enabled, will return empty string + Conditions []Condition `hcl:"conditions,block" json:"conditions,omitempty"` + Actions []Action `hcl:"actions,block" json:"actions,omitempty"` } // ResponseCorpRuleBody contains the response from creating the rule @@ -2350,8 +2350,8 @@ func (sc *Client) DeleteCorpListByID(corpName string, id string) error { //CreateSignalTagBody create a signal tag type CreateSignalTagBody struct { - ShortName string `json:"shortName,omitempty"` //The display name of the signal tag - Description string `json:"description,omitempty"` //Optional signal tag description + ShortName string `hcl:"short_name" json:"shortName,omitempty"` //The display name of the signal tag + Description string `hcl:"description" json:"description,omitempty"` //Optional signal tag description } //UpdateSignalTagBody update a signal tag