internal/elasticsearch/security/role_mapping.go (179 lines of code) (raw):

package security import ( "context" "encoding/json" "fmt" "github.com/elastic/terraform-provider-elasticstack/internal/clients" "github.com/elastic/terraform-provider-elasticstack/internal/clients/elasticsearch" "github.com/elastic/terraform-provider-elasticstack/internal/models" "github.com/elastic/terraform-provider-elasticstack/internal/utils" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func ResourceRoleMapping() *schema.Resource { roleMappingSchema := map[string]*schema.Schema{ "id": { Description: "Internal identifier of the resource", Type: schema.TypeString, Computed: true, }, "name": { Type: schema.TypeString, Required: true, Description: "The distinct name that identifies the role mapping, used solely as an identifier.", ForceNew: true, }, "enabled": { Type: schema.TypeBool, Optional: true, Default: true, Description: "Mappings that have `enabled` set to `false` are ignored when role mapping is performed.", }, "rules": { Type: schema.TypeString, Required: true, DiffSuppressFunc: utils.DiffJsonSuppress, Description: "The rules that determine which users should be matched by the mapping. A rule is a logical condition that is expressed by using a JSON DSL.", }, "roles": { Type: schema.TypeSet, Elem: &schema.Schema{ Type: schema.TypeString, }, Description: "A list of role names that are granted to the users that match the role mapping rules.", Optional: true, ConflictsWith: []string{"role_templates"}, ExactlyOneOf: []string{"roles", "role_templates"}, }, "role_templates": { Type: schema.TypeString, DiffSuppressFunc: utils.DiffJsonSuppress, Description: "A list of mustache templates that will be evaluated to determine the roles names that should granted to the users that match the role mapping rules.", Optional: true, ConflictsWith: []string{"roles"}, ExactlyOneOf: []string{"roles", "role_templates"}, }, "metadata": { Type: schema.TypeString, Optional: true, Default: "{}", DiffSuppressFunc: utils.DiffJsonSuppress, Description: "Additional metadata that helps define which roles are assigned to each user. Keys beginning with `_` are reserved for system usage.", }, } utils.AddConnectionSchema(roleMappingSchema) return &schema.Resource{ Description: "Manage role mappings. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role-mapping.html", CreateContext: resourceSecurityRoleMappingPut, UpdateContext: resourceSecurityRoleMappingPut, ReadContext: resourceSecurityRoleMappingRead, DeleteContext: resourceSecurityRoleMappingDelete, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, Schema: roleMappingSchema, } } func resourceSecurityRoleMappingPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } roleMappingName := d.Get("name").(string) id, diags := client.ID(ctx, roleMappingName) if diags.HasError() { return diags } var rules map[string]interface{} if err := json.Unmarshal([]byte(d.Get("rules").(string)), &rules); err != nil { return diag.FromErr(err) } var roleTemplates []map[string]interface{} if t, ok := d.GetOk("role_templates"); ok && t.(string) != "" { if err := json.Unmarshal([]byte(t.(string)), &roleTemplates); err != nil { return diag.FromErr(err) } } roleMapping := models.RoleMapping{ Name: roleMappingName, Enabled: d.Get("enabled").(bool), Roles: utils.ExpandStringSet(d.Get("roles").(*schema.Set)), RoleTemplates: roleTemplates, Rules: rules, Metadata: json.RawMessage(d.Get("metadata").(string)), } if diags := elasticsearch.PutRoleMapping(ctx, client, &roleMapping); diags.HasError() { return diags } d.SetId(id.String()) return resourceSecurityRoleMappingRead(ctx, d, meta) } func resourceSecurityRoleMappingRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } resourceID, diags := clients.ResourceIDFromStr(d.Id()) if diags.HasError() { return diags } roleMapping, diags := elasticsearch.GetRoleMapping(ctx, client, resourceID) if roleMapping == nil && diags == nil { tflog.Warn(ctx, fmt.Sprintf(`Role mapping "%s" not found, removing from state`, resourceID)) d.SetId("") return diags } if diags.HasError() { return diags } rules, err := json.Marshal(roleMapping.Rules) if err != nil { return diag.FromErr(err) } metadata, err := json.Marshal(roleMapping.Metadata) if err != nil { return diag.FromErr(err) } if err := d.Set("name", roleMapping.Name); err != nil { return diag.FromErr(err) } if len(roleMapping.Roles) > 0 { if err := d.Set("roles", roleMapping.Roles); err != nil { return diag.FromErr(err) } } if len(roleMapping.RoleTemplates) > 0 { roleTemplates, err := json.Marshal(roleMapping.RoleTemplates) if err != nil { return diag.FromErr(err) } if err := d.Set("role_templates", string(roleTemplates)); err != nil { return diag.FromErr(err) } } if err := d.Set("enabled", roleMapping.Enabled); err != nil { return diag.FromErr(err) } if err := d.Set("rules", string(rules)); err != nil { return diag.FromErr(err) } if err := d.Set("metadata", string(metadata)); err != nil { return diag.FromErr(err) } return nil } func resourceSecurityRoleMappingDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } resourceID, diags := clients.ResourceIDFromStr(d.Id()) if diags.HasError() { return diags } if diags := elasticsearch.DeleteRoleMapping(ctx, client, resourceID); diags.HasError() { return diags } return nil }