Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Add support for `unenrollment_timeout` in `elasticstack_fleet_agent_policy` ([#1169](https://github.com/elastic/terraform-provider-elasticstack/issues/1169))
- Handle default value for `allow_restricted_indices` in `elasticstack_elasticsearch_security_api_key` ([#1315](https://github.com/elastic/terraform-provider-elasticstack/pull/1315))
- Fixed `nil` reference in kibana synthetics API client in case of response errors ([#1320](https://github.com/elastic/terraform-provider-elasticstack/pull/1320))
- Migrate `elasticstack_elasticsearch_security_role` resource to Terraform Plugin Framework ([#1330](https://github.com/elastic/terraform-provider-elasticstack/pull/1330))

## [0.11.17] - 2025-07-21

Expand Down
12 changes: 6 additions & 6 deletions docs/resources/elasticsearch_security_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
page_title: "elasticstack_elasticsearch_security_role Resource - terraform-provider-elasticstack"
subcategory: "Security"
description: |-
Adds and updates roles in the native realm. See the security API put role documentation https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role.html for more details.
Adds and updates roles in the native realm. See the role API documentation https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role.html for more details.
---

# elasticstack_elasticsearch_security_role (Resource)

Adds and updates roles in the native realm. See the [security API put role documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role.html) for more details.
Adds and updates roles in the native realm. See the [role API documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role.html) for more details.

## Example Usage

Expand Down Expand Up @@ -58,7 +58,7 @@ output "role" {
- `applications` (Block Set) A list of application privilege entries. (see [below for nested schema](#nestedblock--applications))
- `cluster` (Set of String) A list of cluster privileges. These privileges define the cluster level actions that users with this role are able to execute.
- `description` (String) The description of the role.
- `elasticsearch_connection` (Block List, Max: 1, Deprecated) Elasticsearch connection configuration block. This property will be removed in a future provider version. Configure the Elasticsearch connection via the provider configuration instead. (see [below for nested schema](#nestedblock--elasticsearch_connection))
- `elasticsearch_connection` (Block List, Deprecated) Elasticsearch connection configuration block. (see [below for nested schema](#nestedblock--elasticsearch_connection))
- `global` (String) An object defining global privileges.
- `indices` (Block Set) A list of indices permissions entries. (see [below for nested schema](#nestedblock--indices))
- `metadata` (String) Optional meta-data.
Expand Down Expand Up @@ -111,10 +111,10 @@ Required:
Optional:

- `allow_restricted_indices` (Boolean) Include matching restricted indices in names parameter. Usage is strongly discouraged as it can grant unrestricted operations on critical data, make the entire system unstable or leak sensitive information.
- `field_security` (Block List, Max: 1) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedblock--indices--field_security))
- `field_security` (Attributes List) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedatt--indices--field_security))
- `query` (String) A search query that defines the documents the owners of the role have read access to.

<a id="nestedblock--indices--field_security"></a>
<a id="nestedatt--indices--field_security"></a>
### Nested Schema for `indices.field_security`

Optional:
Expand All @@ -135,7 +135,7 @@ Required:

Optional:

- `field_security` (Block List, Max: 1) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedblock--remote_indices--field_security))
- `field_security` (Block List) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedblock--remote_indices--field_security))
- `query` (String) A search query that defines the documents the owners of the role have read access to.

<a id="nestedblock--remote_indices--field_security"></a>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package security_test
package role_test

import (
"fmt"
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/elasticsearch/security"
"github.com/elastic/terraform-provider-elasticstack/internal/elasticsearch/security/role"
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
Expand Down Expand Up @@ -46,11 +46,10 @@ func TestAccResourceSecurityRole(t *testing.T) {
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "run_as.#"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "global"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "applications.#"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices"),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(security.MinSupportedRemoteIndicesVersion),
SkipFunc: versionutils.CheckIfVersionIsUnsupported(role.MinSupportedRemoteIndicesVersion),
Config: testAccResourceSecurityRoleRemoteIndicesCreate(roleNameRemoteIndices),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleNameRemoteIndices),
Expand All @@ -65,7 +64,7 @@ func TestAccResourceSecurityRole(t *testing.T) {
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(security.MinSupportedRemoteIndicesVersion),
SkipFunc: versionutils.CheckIfVersionIsUnsupported(role.MinSupportedRemoteIndicesVersion),
Config: testAccResourceSecurityRoleRemoteIndicesUpdate(roleNameRemoteIndices),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleNameRemoteIndices),
Expand All @@ -75,21 +74,20 @@ func TestAccResourceSecurityRole(t *testing.T) {
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "run_as.#"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "global"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "applications.#"),
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "remote_indices.*.clusters.*", "test-cluster2"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "remote_indices.*.names.*", "sample2"),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(security.MinSupportedDescriptionVersion),
SkipFunc: versionutils.CheckIfVersionIsUnsupported(role.MinSupportedDescriptionVersion),
Config: testAccResourceSecurityRoleDescriptionCreate(roleNameDescription),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleNameDescription),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "description", "test description"),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(security.MinSupportedDescriptionVersion),
SkipFunc: versionutils.CheckIfVersionIsUnsupported(role.MinSupportedDescriptionVersion),
Config: testAccResourceSecurityRoleDescriptionUpdate(roleNameDescription),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleNameDescription),
Expand All @@ -100,6 +98,45 @@ func TestAccResourceSecurityRole(t *testing.T) {
})
}

func TestAccResourceSecurityRoleFromSDK(t *testing.T) {
roleName := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Steps: []resource.TestStep{
{
// Create the role with the last provider version where the role resource was built on the SDK
ExternalProviders: map[string]resource.ExternalProvider{
"elasticstack": {
Source: "elastic/elasticstack",
VersionConstraint: "0.11.17",
},
},
Config: testAccResourceSecurityRoleCreate(roleName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices", "true"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "indices.*.names.*", "index1"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "indices.*.names.*", "index2"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "cluster.*", "all"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "run_as.*", "other_user"),
),
},
{
ProtoV6ProviderFactories: acctest.Providers,
Config: testAccResourceSecurityRoleCreate(roleName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "name", roleName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices", "true"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "indices.*.names.*", "index1"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "indices.*.names.*", "index2"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "cluster.*", "all"),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "run_as.*", "other_user"),
),
},
},
})
}

func testAccResourceSecurityRoleCreate(roleName string) string {
return fmt.Sprintf(`
provider "elasticstack" {
Expand Down
12 changes: 12 additions & 0 deletions internal/elasticsearch/security/role/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package role

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/resource"
)

func (r *roleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
diags := r.update(ctx, req.Plan, &resp.State)
resp.Diagnostics.Append(diags...)
}
33 changes: 33 additions & 0 deletions internal/elasticsearch/security/role/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package role

import (
"context"

"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/clients/elasticsearch"
"github.com/elastic/terraform-provider-elasticstack/internal/diagutil"
"github.com/hashicorp/terraform-plugin-framework/resource"
)

func (r *roleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data RoleData
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

compId, diags := clients.CompositeIdFromStrFw(data.Id.ValueString())
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

client, diags := clients.MaybeNewApiClientFromFrameworkResource(ctx, data.ElasticsearchConnection, r.client)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

sdkDiags := elasticsearch.DeleteRole(ctx, client, compId.ResourceId)
resp.Diagnostics.Append(diagutil.FrameworkDiagsFromSDK(sdkDiags)...)
}
Loading
Loading