Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
55 changes: 55 additions & 0 deletions docs/resources/kibana_prebuilt_rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "elasticstack_kibana_prebuilt_rule Resource - elasticstack"
subcategory: ""
description: |-
Manages Elastic prebuilt detection rules. This resource installs and updates Elastic prebuilt rules and timelines, and optionally enables/disables rules based on specified tags. See https://www.elastic.co/guide/en/security/current/prebuilt-rules.html
---

# elasticstack_kibana_prebuilt_rule (Resource)

Manages Elastic prebuilt detection rules. This resource installs and updates Elastic prebuilt rules and timelines, and optionally enables/disables rules based on specified tags. See https://www.elastic.co/guide/en/security/current/prebuilt-rules.html

## Example Usage

```terraform
provider "elasticstack" {
kibana {}
}

resource "elasticstack_kibana_prebuilt_rule" "enable" {
tags = ["OS: Linux", "OS: Windows"]
}

resource "elasticstack_kibana_prebuilt_rule" "install_no_enable" {
tags = []
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `space_id` (String) An identifier for the space. If space_id is not provided, the default space is used.
- `tags` (List of String) A list of tag names to filter prebuilt rules for enabling/disabling. Use ['all'] to enable all prebuilt rules, or an empty list to install but not enable any rules.

### Read-Only

- `id` (String) The ID of this resource.
- `rules_installed` (Number) Number of prebuilt rules that are installed.
- `rules_not_installed` (Number) Number of prebuilt rules that are not installed.
- `rules_not_updated` (Number) Number of prebuilt rules that have updates available.
- `timelines_installed` (Number) Number of prebuilt timelines that are installed.
- `timelines_not_installed` (Number) Number of prebuilt timelines that are not installed.
- `timelines_not_updated` (Number) Number of prebuilt timelines that have updates available.

## Import

Import is supported using the following syntax:

The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:

```shell
terraform import elasticstack_kibana_prebuilt_rule.enable "default"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import elasticstack_kibana_prebuilt_rule.enable "default"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resource doesn't implement an import handler, so this command will fail.

IMO I'm not sure import actually makes sense for this resource though, it's quite difficult for us to know that all rules matching a given tag set have been enabled. I don't think there's a real impact to just running create again if the rules have been installed and the expected rules are already enabled?

11 changes: 11 additions & 0 deletions examples/resources/elasticstack_kibana_prebuilt_rule/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
provider "elasticstack" {
kibana {}
}

resource "elasticstack_kibana_prebuilt_rule" "enable" {
tags = ["OS: Linux", "OS: Windows"]
}

resource "elasticstack_kibana_prebuilt_rule" "install_no_enable" {
tags = []
}
78 changes: 78 additions & 0 deletions internal/kibana/prebuilt_rules/acc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package prebuilt_rules_test

import (
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

var minVersionPrebuiltRules = version.Must(version.NewVersion("8.0.0"))

func TestAccResourcePrebuiltRules(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.Providers,
Steps: []resource.TestStep{
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionPrebuiltRules),
Config: testAccPrebuiltRuleConfigBasic(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_kibana_prebuilt_rule.test", "space_id", "default"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "rules_installed"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "rules_not_installed"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "rules_not_updated"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "timelines_installed"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "timelines_not_installed"),
resource.TestCheckResourceAttrSet("elasticstack_kibana_prebuilt_rule.test", "timelines_not_updated"),
),
},
},
})
}

func TestAccResourcePrebuiltRule_withTags(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.Providers,
CheckDestroy: testAccPrebuiltRuleDestroy,
Steps: []resource.TestStep{
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionPrebuiltRules),
Config: testAccPrebuiltRuleConfigWithTags(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_kibana_prebuilt_rule.test", "space_id", "default"),
resource.TestCheckResourceAttr("elasticstack_kibana_prebuilt_rule.test", "tags.#", "2"),
resource.TestCheckResourceAttr("elasticstack_kibana_prebuilt_rule.test", "tags.0", "OS: Linux"),
resource.TestCheckResourceAttr("elasticstack_kibana_prebuilt_rule.test", "tags.1", "OS: Windows"),
),
},
},
})
}

func testAccPrebuiltRuleDestroy(s *terraform.State) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a no-op we can just omit it entirely from the test definition.

// For prebuilt rules, there's nothing to destroy
// The rules remain in Kibana as they are managed by Elastic
return nil
}

func testAccPrebuiltRuleConfigBasic() string {
return `
resource "elasticstack_kibana_prebuilt_rule" "test" {
space_id = "default"
}
`
}

func testAccPrebuiltRuleConfigWithTags() string {
return `
resource "elasticstack_kibana_prebuilt_rule" "test" {
space_id = "default"
tags = ["OS: Linux", "OS: Windows"]
}
`
}
75 changes: 75 additions & 0 deletions internal/kibana/prebuilt_rules/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package prebuilt_rules

import (
"context"

"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-framework/resource"
)

func (r *PrebuiltRuleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var model prebuiltRuleModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
}

serverVersion, sdkDiags := r.client.ServerVersion(ctx)
resp.Diagnostics.Append(utils.FrameworkDiagsFromSDK(sdkDiags)...)
if resp.Diagnostics.HasError() {
return
}

minVersion := version.Must(version.NewVersion("8.0.0"))
if serverVersion.LessThan(minVersion) {
resp.Diagnostics.AddError("Unsupported server version", "Prebuilt rules are not supported until Elastic Stack v8.0.0. Upgrade the target server to use this resource")
return
}

client, err := r.client.GetKibanaOapiClient()
if err != nil {
resp.Diagnostics.AddError(err.Error(), "")
return
}

spaceID := model.SpaceID.ValueString()

// Install/update prebuilt rules and timelines
resp.Diagnostics.Append(installPrebuiltRules(ctx, client, spaceID)...)
if resp.Diagnostics.HasError() {
return
}

// Enable/disable rules based on tags if specified
tags, tagDiags := model.getTags(ctx)
resp.Diagnostics.Append(tagDiags...)
if resp.Diagnostics.HasError() {
return
}

if len(tags) > 0 {
resp.Diagnostics.Append(manageRulesByTags(ctx, client, spaceID, tags)...)
if resp.Diagnostics.HasError() {
return
}
}

// Set the resource ID to the space ID
model.ID = model.SpaceID

// Read the current status to populate computed attributes
status, statusDiags := getPrebuiltRulesStatus(ctx, client, spaceID)
resp.Diagnostics.Append(statusDiags...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(model.populateFromStatus(ctx, status)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, model)...)
}
54 changes: 54 additions & 0 deletions internal/kibana/prebuilt_rules/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package prebuilt_rules

import (
"context"

"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-framework/resource"
)

func (r *PrebuiltRuleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var model prebuiltRuleModel

resp.Diagnostics.Append(req.State.Get(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
}

serverVersion, sdkDiags := r.client.ServerVersion(ctx)
resp.Diagnostics.Append(utils.FrameworkDiagsFromSDK(sdkDiags)...)
if resp.Diagnostics.HasError() {
return
}

minVersion := version.Must(version.NewVersion("8.0.0"))
if serverVersion.LessThan(minVersion) {
resp.Diagnostics.AddError("Unsupported server version", "Prebuilt rules are not supported until Elastic Stack v8.0.0. Upgrade the target server to use this resource")
return
}

client, err := r.client.GetKibanaOapiClient()
if err != nil {
resp.Diagnostics.AddError(err.Error(), "")
return
}

spaceID := model.SpaceID.ValueString()

// Disable rules that were managed by this resource
tags, tagDiags := model.getTags(ctx)
resp.Diagnostics.Append(tagDiags...)
if resp.Diagnostics.HasError() {
return
}

if len(tags) > 0 {
resp.Diagnostics.Append(performBulkActionByTags(ctx, client, spaceID, "disable", tags)...)
if resp.Diagnostics.HasError() {
return
}
}

// The Terraform state will be removed automatically
}
Loading