Skip to content
Merged
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
6 changes: 3 additions & 3 deletions docs/resources/elasticsearch_security_system_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ resource "elasticstack_elasticsearch_security_system_user" "kibana_system" {

### Optional

- `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))
- `enabled` (Boolean) Specifies whether the user is enabled. The default value is true.
- `password` (String, Sensitive) The users password. Passwords must be at least 6 characters long.
- `password_hash` (String, Sensitive) A hash of the users password. This must be produced using the same hashing algorithm as has been configured for password storage (see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html#hashing-settings).
- `password` (String, Sensitive) The user's password. Passwords must be at least 6 characters long.
- `password_hash` (String, Sensitive) A hash of the user's password. This must be produced using the same hashing algorithm as has been configured for password storage (see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html#hashing-settings).

### Read-Only

Expand Down
60 changes: 44 additions & 16 deletions internal/clients/elasticsearch/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,60 +89,88 @@ func DeleteUser(ctx context.Context, apiClient *clients.ApiClient, username stri
return diags
}

func EnableUser(ctx context.Context, apiClient *clients.ApiClient, username string) diag.Diagnostics {
var diags diag.Diagnostics
func EnableUser(ctx context.Context, apiClient *clients.ApiClient, username string) fwdiag.Diagnostics {
var diags fwdiag.Diagnostics
esClient, err := apiClient.GetESClient()
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to get Elasticsearch client",
err.Error(),
)
return diags
}
res, err := esClient.Security.EnableUser(username, esClient.Security.EnableUser.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to enable system user",
err.Error(),
)
return diags
}
defer res.Body.Close()
if diags := utils.CheckError(res, "Unable to enable system user"); diags.HasError() {
if diags := utils.CheckErrorFromFW(res, "Unable to enable system user"); diags.HasError() {
return diags
}
return diags
}

func DisableUser(ctx context.Context, apiClient *clients.ApiClient, username string) diag.Diagnostics {
var diags diag.Diagnostics
func DisableUser(ctx context.Context, apiClient *clients.ApiClient, username string) fwdiag.Diagnostics {
var diags fwdiag.Diagnostics
esClient, err := apiClient.GetESClient()
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to get Elasticsearch client",
err.Error(),
)
return diags
}
res, err := esClient.Security.DisableUser(username, esClient.Security.DisableUser.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to disable system user",
err.Error(),
)
return diags
}
defer res.Body.Close()
if diags := utils.CheckError(res, "Unable to disable system user"); diags.HasError() {
if diags := utils.CheckErrorFromFW(res, "Unable to disable system user"); diags.HasError() {
return diags
}
return diags
}

func ChangeUserPassword(ctx context.Context, apiClient *clients.ApiClient, username string, userPassword *models.UserPassword) diag.Diagnostics {
var diags diag.Diagnostics
func ChangeUserPassword(ctx context.Context, apiClient *clients.ApiClient, username string, userPassword *models.UserPassword) fwdiag.Diagnostics {
var diags fwdiag.Diagnostics
userPasswordBytes, err := json.Marshal(userPassword)
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to marshal user password",
err.Error(),
)
return diags
}
esClient, err := apiClient.GetESClient()
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to get Elasticsearch client",
err.Error(),
)
return diags
}
res, err := esClient.Security.ChangePassword(
bytes.NewReader(userPasswordBytes),
esClient.Security.ChangePassword.WithUsername(username),
esClient.Security.ChangePassword.WithContext(ctx),
)
if err != nil {
return diag.FromErr(err)
diags.AddError(
"Unable to change user password",
err.Error(),
)
return diags
}
defer res.Body.Close()
if diags := utils.CheckError(res, "Unable to change user's password"); diags.HasError() {
if diags := utils.CheckErrorFromFW(res, "Unable to change user's password"); diags.HasError() {
return diags
}
return diags
Expand Down
161 changes: 0 additions & 161 deletions internal/elasticsearch/security/system_user.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package security_test
package system_user_test

import (
"regexp"
Expand Down Expand Up @@ -44,6 +44,37 @@ func TestAccResourceSecuritySystemUserNotFound(t *testing.T) {
})
}

func TestAccResourceSecuritySystemUserFromSDK(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Steps: []resource.TestStep{
{
// Create the system user with the last provider version where the system user resource was built on the SDK
ExternalProviders: map[string]resource.ExternalProvider{
"elasticstack": {
Source: "elastic/elasticstack",
VersionConstraint: "0.11.15",
},
},
ProtoV6ProviderFactories: acctest.Providers,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need it if we rely on ExternalProviders?

Config: testAccResourceSecuritySystemUserCreate,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_system_user.remote_monitoring_user", "username", "remote_monitoring_user"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_system_user.remote_monitoring_user", "enabled", "true"),
),
},
{
ProtoV6ProviderFactories: acctest.Providers,
Config: testAccResourceSecuritySystemUserCreate,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_system_user.remote_monitoring_user", "username", "remote_monitoring_user"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_system_user.remote_monitoring_user", "enabled", "true"),
),
},
},
})
}

const testAccResourceSecuritySystemUserCreate = `
provider "elasticstack" {
elasticsearch {}
Expand All @@ -53,7 +84,8 @@ resource "elasticstack_elasticsearch_security_system_user" "remote_monitoring_us
username = "remote_monitoring_user"
password = "new_password"
}
`
`

const testAccResourceSecuritySystemUserUpdate = `
provider "elasticstack" {
elasticsearch {}
Expand Down
15 changes: 15 additions & 0 deletions internal/elasticsearch/security/system_user/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package system_user

import (
"context"

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

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

import (
"context"
"fmt"

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

func (r *systemUserResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data SystemUserData
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
}
tflog.Warn(ctx, fmt.Sprintf(`System user '%s' is not deletable, just removing from state`, compId.ResourceId))
}
14 changes: 14 additions & 0 deletions internal/elasticsearch/security/system_user/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package system_user

import (
"github.com/hashicorp/terraform-plugin-framework/types"
)

type SystemUserData struct {
Id types.String `tfsdk:"id"`
ElasticsearchConnection types.List `tfsdk:"elasticsearch_connection"`
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
PasswordHash types.String `tfsdk:"password_hash"`
Enabled types.Bool `tfsdk:"enabled"`
}
Loading
Loading