Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.5.0
* New resource: `splunk_saved_event_types` for managing saved event types knowledge objects.
* Fix: saved search `action_email_include_*` fields (results_link, view_link, search, trigger, trigger_time) — removed omitempty from URL parameters so value 0 is sent to Splunk and can be set in config
* Change: saved search `action_email_include_results_link` and `action_email_include_view_link` now default to 1 to match Splunk savedsearches.conf; removed Computed so defaults apply
* Fix: HEC token list uses GET /services/data/inputs/http so tokens are found after create.

## 1.4.36
* Fix: saved search action_email_include_results_link handles 0 value
* Fix: saved search action_email_include_view_link handles 0 value
Expand Down
7 changes: 5 additions & 2 deletions client/inputs_http_event_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ func (client *Client) DeleteHttpEventCollectorObject(name, owner, app string) (*
return resp, nil
}

// services/data/inputs/http
// ReadAllHttpEventCollectorObject returns the list of HTTP Event Collector tokens.
// Per Splunk RESTREF (https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTinput#data.2Finputs.2Fhttp),
// the documented list endpoint is GET /services/data/inputs/http (global, no servicesNS).
// GET /servicesNS/-/-/data/inputs/http returns empty in some deployments (see issue #56).
func (client *Client) ReadAllHttpEventCollectorObject() (*http.Response, error) {
endpoint := client.BuildSplunkURL(nil, "servicesNS", "-", "-", "data", "inputs", "http")
endpoint := client.BuildSplunkURL(nil, "services", "data", "inputs", "http")
resp, err := client.Get(endpoint)
if err != nil {
return nil, err
Expand Down
22 changes: 22 additions & 0 deletions client/models/saved_event_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package models

type SavedEventTypesResponse struct {
Entry []SavedEventTypesEntry `json:"entry"`
Messages []ErrorMessage `json:"messages"`
}

type SavedEventTypesEntry struct {
Name string `json:"name"`
ACL ACLObject `json:"acl"`
Content SavedEventTypeObject `json:"content"`
}

type SavedEventTypeObject struct {
Name string `json:"name"`
Description string `json:"description" url:"description,omitempty"`
Disabled bool `json:"disabled,omitempty" url:"disabled,omitempty"`
Color string `json:"color,omitempty" url:"color,omitempty"`
Priority int `json:"priority,omitempty" url:"priority,omitempty"`
Search string `json:"search,omitempty" url:"search,omitempty"`
Tags []string `json:"tags,omitempty" url:"tags,omitempty"`
}
6 changes: 3 additions & 3 deletions client/models/saved_searches.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ type SavedSearchObject struct {
ActionEmailFrom string `json:"action.email.from,omitempty" url:"action.email.from,omitempty"`
ActionEmailHostname string `json:"action.email.hostname,omitempty" url:"action.email.hostname,omitempty"`
ActionEmailIncludeResultsLink int `json:"action.email.include.results_link,string,omitempty" url:"action.email.include.results_link"`
ActionEmailIncludeSearch int `json:"action.email.include.search,string,omitempty" url:"action.email.include.search,omitempty"`
ActionEmailIncludeTrigger int `json:"action.email.include.trigger,string,omitempty" url:"action.email.include.trigger,omitempty"`
ActionEmailIncludeTriggerTime int `json:"action.email.include.trigger_time,string,omitempty" url:"action.email.include.trigger_time,omitempty"`
ActionEmailIncludeSearch int `json:"action.email.include.search,string,omitempty" url:"action.email.include.search"`
ActionEmailIncludeTrigger int `json:"action.email.include.trigger,string,omitempty" url:"action.email.include.trigger"`
ActionEmailIncludeTriggerTime int `json:"action.email.include.trigger_time,string,omitempty" url:"action.email.include.trigger_time"`
ActionEmailIncludeViewLink int `json:"action.email.include.view_link,string,omitempty" url:"action.email.include.view_link"`
ActionEmailInline bool `json:"action.email.inline" url:"action.email.inline"`
ActionEmailMailserver string `json:"action.email.mailserver,omitempty" url:"action.email.mailserver,omitempty"`
Expand Down
69 changes: 69 additions & 0 deletions client/saved_event_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package client

import (
"github.com/splunk/terraform-provider-splunk/client/models"
"net/http"

"github.com/google/go-querystring/query"
)

func (client *Client) CreateSavedEventTypes(name, owner, app string, savedEventTypeObject *models.SavedEventTypeObject) error {
values, err := query.Values(savedEventTypeObject)
values.Add("name", name)
if err != nil {
return err
}

endpoint := client.BuildSplunkURL(nil, "servicesNS", owner, app, "saved", "eventtypes")
resp, err := client.Post(endpoint, values)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}

func (client *Client) ReadSavedEventTypes(name, owner, app string) (*http.Response, error) {
endpoint := client.BuildSplunkURL(nil, "servicesNS", owner, app, "saved", "eventtypes", name)
resp, err := client.Get(endpoint)
if err != nil {
return nil, err
}

return resp, nil
}

func (client *Client) UpdateSavedEventTypes(name string, owner string, app string, savedEventTypeObject *models.SavedEventTypeObject) error {
values, err := query.Values(&savedEventTypeObject)
if err != nil {
return err
}
endpoint := client.BuildSplunkURL(nil, "servicesNS", owner, app, "saved", "eventtypes", name)
resp, err := client.Post(endpoint, values)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}

func (client *Client) DeleteSavedEventTypes(name, owner, app string) (*http.Response, error) {
endpoint := client.BuildSplunkURL(nil, "servicesNS", owner, app, "saved", "eventtypes", name)
resp, err := client.Delete(endpoint)
if err != nil {
return nil, err
}

return resp, nil
}

// services/saved/eventtypes
func (client *Client) ReadAllSavedEventTypes() (*http.Response, error) {
endpoint := client.BuildSplunkURL(nil, "servicesNS", "-", "-", "saved", "eventtypes")
resp, err := client.Get(endpoint)
if err != nil {
return nil, err
}

return resp, nil
}
38 changes: 38 additions & 0 deletions docs/resources/saved_event_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Resource: splunk_saved_event_types
Create and manage saved event types (knowledge objects).

## Example Usage
```
resource "splunk_saved_event_types" "test" {
name = "test"
description = "Test New event description"
disabled = false
priority = 1
search = "index=main"
color = "et_blue"
tags = ["tag"]
acl {
owner = "admin"
sharing = "app"
app = "launcher"
}
}
```

## Argument Reference
For latest resource argument reference: https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTknowledge#saved.2Feventtypes

This resource block supports the following arguments:
* `name` - (Required) A name for the event type.
* `description` - (Optional) Human-readable description of this event type.
* `search` - (Required) Event type search string.
* `color`- (Optional) Color for this event type. The supported colors are: none, et_blue, et_green, et_magenta, et_orange, et_purple, et_red, et_sky, et_teal, et_yellow.
* `disabled` - (Optional) If True, disables the event type.
* `priority` - (Optional) Specify an integer from 1 to 10 for the value used to determine the order in which the matching event types of an event are displayed. 1 is the highest priority.
* `tags` - (Optional) [Deprecated] Use tags.conf.spec file to assign tags to groups of events with related field values.
* `acl` - (Optional) The app/user context that is the namespace for the resource

## Attribute Reference
In addition to all arguments above, This resource block exports the following arguments:

* `id` - The ID of the saved search event type
10 changes: 5 additions & 5 deletions docs/resources/saved_searches.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ This resource block supports the following arguments:
- `action_email_format` - (Optional) Valid values: (table | plain | html | raw | csv)Specify the format of text in the email. This value also applies to any attachments.
- `action_email_from` - (Optional) Email address from which the email action originates.Defaults to splunk@$LOCALHOST or whatever value is set in alert_actions.conf.
- `action_email_hostname` - (Optional) Sets the hostname used in the web link (url) sent in email actions.This value accepts two forms:hostname (for example, splunkserver, splunkserver.example.com)
- `action_email_include_results_link` - (Optional) Specify whether to include a link to the results. Defaults to 0.
- `action_email_include_search` - (Optional) Specify whether to include the search that caused an email to be sent. Defaults to 0.
- `action_email_include_trigger` - (Optional) Specify whether to show the trigger condition that caused the alert to fire. Defaults to 0.
- `action_email_include_trigger_time` - (Optional) Specify whether to show the time that the alert was fired. Defaults to 0.
- `action_email_include_view_link` - (Optional) Specify whether to show the title and a link to enable the user to edit the saved search. Defaults to 0.
- `action_email_include_results_link` - (Optional) Specify whether to include a link to the results. Defaults to 1 (true). [1|0]
- `action_email_include_search` - (Optional) Specify whether to include the search that caused an email to be sent. [1|0]
- `action_email_include_trigger` - (Optional) Specify whether to show the trigger condition that caused the alert to fire. [1|0]
- `action_email_include_trigger_time` - (Optional) Specify whether to show the time that the alert was fired. [1|0]
- `action_email_include_view_link` - (Optional) Specify whether to show the title and a link to enable the user to edit the saved search. Defaults to 1 (true). [1|0]
- `action_email_inline` - (Optional) Indicates whether the search results are contained in the body of the email.Results can be either inline or attached to an email.
- `action_email_mailserver` - (Optional) Set the address of the MTA server to be used to send the emails.Defaults to <LOCALHOST> or whatever is set in alert_actions.conf.
- `action_email_max_results` - (Optional) Sets the global maximum number of search results to send when email.action is enabled. Defaults to 100.
Expand Down
44 changes: 44 additions & 0 deletions examples/splunk/hec_token/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example: HEC token creation (no indexer acknowledgement).
# Uses SPLUNK_URL, SPLUNK_USERNAME, SPLUNK_PASSWORD. Run: terraform init && terraform apply

terraform {
required_providers {
random = {
source = "hashicorp/random"
version = ">= 3.0"
}
splunk = {
source = "splunk/splunk"
version = ">= 1.4.0"
}
}
}

provider "splunk" {}

resource "splunk_indexes" "test_index_1" {
name = "test_index_1"
max_hot_buckets = 6
max_total_data_size_mb = 1000000
}

resource "splunk_global_http_event_collector" "http" {
disabled = false
enable_ssl = true
port = 8088
}

resource "random_uuid" "no_ack" {}

resource "splunk_inputs_http_event_collector" "no_ack" {
name = "some-name"
token = random_uuid.no_ack.result
index = "test_index_1"
indexes = ["test_index_1"]
disabled = false
use_ack = 0
depends_on = [
splunk_indexes.test_index_1,
splunk_global_http_event_collector.http,
]
}
28 changes: 28 additions & 0 deletions examples/splunk/saved_event_types/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Example: saved event type (knowledge object).
# Uses SPLUNK_URL, SPLUNK_USERNAME, SPLUNK_PASSWORD. Run: terraform init && terraform apply
# See: https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTknowledge#saved.2Feventtypes

terraform {
required_providers {
splunk = {
source = "splunk/splunk"
version = ">= 1.4.0"
}
}
}

provider "splunk" {}

resource "splunk_saved_event_types" "example" {
name = "terraform-example-event-type"
search = "index=main sourcetype=access_combined"
description = "Example event type created by Terraform"
disabled = false
priority = 1
color = "et_green"
acl {
owner = "admin"
sharing = "app"
app = "search"
}
}
46 changes: 46 additions & 0 deletions examples/splunk/saved_search_email_include/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# One-off config to create a saved search with all action_email_include_* params
# for manual verification in Splunk UI. Uses SPLUNK_URL, SPLUNK_USERNAME,
# SPLUNK_PASSWORD (and SPLUNK_HOME if needed). Run: terraform init && terraform apply
# Then in Splunk: Settings → Saved searches → "Test Email Include Links Zero".
# Clean up with: terraform destroy

terraform {
required_providers {
splunk = {
source = "splunk/splunk"
version = ">= 1.4.0"
}
}
}

provider "splunk" {}

resource "splunk_saved_searches" "test" {
name = "Test Email Include Links Zero"
search = "index=main"
actions = "email"
action_email_include_results_link = 0
action_email_include_view_link = 0
action_email_include_search = 0
action_email_include_trigger = 1
action_email_include_trigger_time = 1
action_email_format = "table"
action_email_max_time = "5m"
action_email_max_results = 10
action_email_send_csv = 1
action_email_send_results = false
action_email_subject = "Splunk Alert: $name$"
action_email_to = "splunk@splunk.com"
action_email_track_alert = true
alert_track = true
dispatch_earliest_time = "rt-15m"
dispatch_latest_time = "rt-0m"
dispatch_index_earliest = "-10m"
dispatch_index_latest = "-5m"
cron_schedule = "*/5 * * * *"
acl {
owner = "admin"
sharing = "app"
app = "launcher"
}
}
1 change: 1 addition & 0 deletions splunk/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func providerResources() map[string]*schema.Resource {
"splunk_indexes": index(),
"splunk_configs_conf": configsConf(),
"splunk_data_ui_views": splunkDashboards(),
"splunk_saved_event_types": savedEventTypes(),
}
}

Expand Down
49 changes: 49 additions & 0 deletions splunk/resource_splunk_inputs_http_event_collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,23 @@ resource "splunk_inputs_http_event_collector" "new-token" {
}
`

// hecTokenListEndpointConfig creates a HEC token with no acl block (default nobody/splunk_httpinput).
const hecTokenListEndpointConfig = `
resource "splunk_global_http_event_collector" "http" {
disabled = false
enable_ssl = true
}

resource "splunk_inputs_http_event_collector" "list_endpoint_test" {
name = "test-hec-list-endpoint"
index = "main"
indexes = ["main"]
disabled = false
use_ack = 0
depends_on = ["splunk_global_http_event_collector.http"]
}
`

func TestAccSplunkHttpEventCollectorInput(t *testing.T) {
resourceName := "splunk_inputs_http_event_collector.new-token"
resource.Test(t, resource.TestCase{
Expand Down Expand Up @@ -163,6 +180,38 @@ func TestAccSplunkHttpEventCollectorInputWithToken(t *testing.T) {
})
}

// TestAccSplunkHttpEventCollectorInputListEndpoint creates a HEC token with default ACL (no acl block)
// and asserts it can be read back. After create, the provider runs Read(), which lists tokens via
// ReadAllHttpEventCollectorObject(), finds the entry by name, then reads the token with that entry’s
// owner and app. The test passes only if the list returns the token and the subsequent read succeeds.
func TestAccSplunkHttpEventCollectorInputListEndpoint(t *testing.T) {
resourceName := "splunk_inputs_http_event_collector.list_endpoint_test"
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccSplunkHttpEventCollectorInputDestroyResources,
Steps: []resource.TestStep{
{
Config: hecTokenListEndpointConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "test-hec-list-endpoint"),
resource.TestCheckResourceAttr(resourceName, "index", "main"),
resource.TestCheckResourceAttr(resourceName, "indexes.#", "1"),
resource.TestCheckResourceAttr(resourceName, "indexes.0", "main"),
resource.TestCheckResourceAttr(resourceName, "disabled", "false"),
resource.TestCheckResourceAttr(resourceName, "use_ack", "0"),
resource.TestCheckResourceAttrSet(resourceName, "token"),
resource.TestCheckResourceAttr(resourceName, "acl.#", "1"),
resource.TestCheckResourceAttr(resourceName, "acl.0.app", "splunk_httpinput"),
resource.TestCheckResourceAttr(resourceName, "acl.0.owner", "nobody"),
),
},
},
})
}

func testAccSplunkHttpEventCollectorInputDestroyResources(s *terraform.State) error {
client, err := newTestClient()
if err != nil {
Expand Down
Loading
Loading