Skip to content

Commit

Permalink
Add odfe role and roles mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
tdegiacinto authored and phillbaker committed May 4, 2020
1 parent 6e8a88f commit 13e1cc9
Show file tree
Hide file tree
Showing 9 changed files with 939 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ script:
- |
if [ -n "$ES_OPENDISTRO_IMAGE" ]; then
wget -q --waitretry=1 --retry-connrefused --tries=60 --timeout 60 -O - 127.0.0.1:9220
curl -X POST -H 'Content-type: application/json' -d '{"name":"_warmup","type":"slack","slack":{"url": "http://www.example.com"}}' 127.0.0.1:9220/_opendistro/_alerting/destinations
curl -X POST -H 'Content-type: application/json' -d '{"name":"_warmup","type":"slack","slack":{"url": "http://www.example.com"}}' http://admin:admin@127.0.0.1:9220/_opendistro/_alerting/destinations
fi
# enforce formatting
- FILES_TO_FMT=$(gofmt -l .); [ -z "$FILES_TO_FMT" ] || (echo "$FILES_TO_FMT"; exit $?)
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,11 @@ services:
- bootstrap.memory_lock=true
- discovery.type=single-node
- path.repo=/tmp
- opendistro_security.disabled=true
- opendistro_security.ssl.http.enabled=false
- http.port=9220
- network.publish_host=127.0.0.1
- logger.org.elasticsearch=warn
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
- ELASTIC_PASSWORD=elastic
ulimits:
nproc: 65536
nofile:
Expand Down
2 changes: 2 additions & 0 deletions es/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ func Provider() terraform.ResourceProvider {
"elasticsearch_watch": resourceElasticsearchDeprecatedWatch(),
"elasticsearch_opendistro_ism_policy": resourceElasticsearchOpenDistroISMPolicy(),
"elasticsearch_opendistro_ism_policy_mapping": resourceElasticsearchOpenDistroISMPolicyMapping(),
"elasticsearch_opendistro_roles_mapping": resourceElasticsearchOpenDistroRolesMapping(),
"elasticsearch_opendistro_role": resourceElasticsearchOpenDistroRole(),
"elasticsearch_xpack_role": resourceElasticsearchXpackRole(),
"elasticsearch_xpack_role_mapping": resourceElasticsearchXpackRoleMapping(),
"elasticsearch_xpack_user": resourceElasticsearchXpackUser(),
Expand Down
2 changes: 1 addition & 1 deletion es/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func init() {

opendistroOriginalConfigureFunc := testAccOpendistroProvider.ConfigureFunc
testAccOpendistroProvider.ConfigureFunc = func(d *schema.ResourceData) (interface{}, error) {
err := d.Set("url", "http://elastic:elastic@127.0.0.1:9220")
err := d.Set("url", "http://admin:admin@127.0.0.1:9220")
if err != nil {
return nil, err
}
Expand Down
303 changes: 303 additions & 0 deletions es/resource_elasticsearch_opendistro_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
package es

import (
"context"
"encoding/json"
"errors"
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/olivere/elastic/uritemplates"

elastic7 "github.com/olivere/elastic/v7"
)

func resourceElasticsearchOpenDistroRole() *schema.Resource {
return &schema.Resource{
Create: resourceElasticsearchOpenDistroRoleCreate,
Read: resourceElasticsearchOpenDistroRoleRead,
Update: resourceElasticsearchOpenDistroRoleUpdate,
Delete: resourceElasticsearchOpenDistroRoleDelete,
Schema: map[string]*schema.Schema{
"role_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"cluster_permissions": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"index_permissions": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"index_patterns": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"fls": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"masked_fields": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"allowed_actions": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
"tenant_permissions": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"tenant_patterns": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"allowed_actions": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
}
}

func resourceElasticsearchOpenDistroRoleCreate(d *schema.ResourceData, m interface{}) error {
_, err := resourceElasticsearchPutOpenDistroRole(d, m)

if err != nil {
return err
}

name := d.Get("role_name").(string)
d.SetId(name)
return resourceElasticsearchOpenDistroRoleRead(d, m)
}

func resourceElasticsearchOpenDistroRoleRead(d *schema.ResourceData, m interface{}) error {
res, err := resourceElasticsearchGetOpenDistroRole(d.Id(), m)

if err != nil {
if elastic7.IsNotFound(err) {
log.Printf("[WARN] OpenDistroRole (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
return err
}

d.Set("tenant_permissions", res.TenantPermissions)
d.Set("cluster_permissions", res.ClusterPermissions)
d.Set("index_permissions", res.IndexPermissions)
d.Set("description", res.Description)

return nil
}

func resourceElasticsearchOpenDistroRoleUpdate(d *schema.ResourceData, m interface{}) error {
if _, err := resourceElasticsearchPutOpenDistroRole(d, m); err != nil {
return err
}

return resourceElasticsearchOpenDistroRoleRead(d, m)
}

func resourceElasticsearchOpenDistroRoleDelete(d *schema.ResourceData, m interface{}) error {
var err error

path, err := uritemplates.Expand("/_opendistro/_security/api/roles/{name}", map[string]string{
"name": d.Get("role_name").(string),
})
if err != nil {
return fmt.Errorf("error building URL path for role: %+v", err)
}

switch m.(type) {
case *elastic7.Client:
client := m.(*elastic7.Client)
_, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{
Method: "DELETE",
Path: path,
})
default:
err = errors.New("role resource not implemented prior to Elastic v7")
}

return err
}

func resourceElasticsearchGetOpenDistroRole(roleID string, m interface{}) (RoleBody, error) {
var err error
role := new(RoleBody)

path, err := uritemplates.Expand("/_opendistro/_security/api/roles/{name}", map[string]string{
"name": roleID,
})

if err != nil {
return *role, fmt.Errorf("error building URL path for role: %+v", err)
}

var body json.RawMessage
switch m.(type) {
case *elastic7.Client:
client := m.(*elastic7.Client)
var res *elastic7.Response
res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{
Method: "GET",
Path: path,
})
body = res.Body
default:
err = errors.New("role resource not implemented prior to Elastic v7")
}

if err != nil {
return *role, err
}
var roleDefinition map[string]RoleBody

if err := json.Unmarshal(body, &roleDefinition); err != nil {
return *role, fmt.Errorf("error unmarshalling role body: %+v: %+v", err, body)
}

*role = roleDefinition[roleID]

return *role, err
}

func resourceElasticsearchPutOpenDistroRole(d *schema.ResourceData, m interface{}) (*RoleResponse, error) {
response := new(RoleResponse)

indexPermissions, err := expandIndexPermissionsSet(d.Get("index_permissions").(*schema.Set).List())
if err != nil {
fmt.Print("Error in index get : ", err)
}
var indexPermissionsBody []IndexPermissions
for _, idx := range indexPermissions {
putIdx := IndexPermissions{
IndexPatterns: idx.IndexPatterns,
Fls: idx.Fls,
MaskedFields: idx.MaskedFields,
AllowedActions: idx.AllowedActions,
}
indexPermissionsBody = append(indexPermissionsBody, putIdx)
}

tenantPermissions, err := expandTenantPermissionsSet(d.Get("tenant_permissions").(*schema.Set).List())
if err != nil {
fmt.Print("Error in tenant get : ", err)
}
var tenantPermissionsBody []TenantPermissions
for _, tenant := range tenantPermissions {
putTeanant := TenantPermissions{
TenantPatterns: tenant.TenantPatterns,
AllowedActions: tenant.AllowedActions,
}
tenantPermissionsBody = append(tenantPermissionsBody, putTeanant)
}

rolesDefinition := RoleBody{
ClusterPermissions: expandStringList(d.Get("cluster_permissions").(*schema.Set).List()),
IndexPermissions: indexPermissionsBody,
TenantPermissions: tenantPermissionsBody,
Description: d.Get("description").(string),
}

roleJSON, err := json.Marshal(rolesDefinition)
if err != nil {
return response, fmt.Errorf("Body Error : %s", roleJSON)
}

path, err := uritemplates.Expand("/_opendistro/_security/api/roles/{name}", map[string]string{
"name": d.Get("role_name").(string),
})
if err != nil {
return response, fmt.Errorf("error building URL path for role: %+v", err)
}

var body json.RawMessage
switch m.(type) {
case *elastic7.Client:
client := m.(*elastic7.Client)
var res *elastic7.Response
res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{
Method: "PUT",
Path: path,
Body: string(roleJSON),
})
body = res.Body
default:
err = errors.New("role resource not implemented prior to Elastic v7")
}

if err != nil {
return response, fmt.Errorf("error creating role mapping: %+v: %+v", err, body)
}

if err := json.Unmarshal(body, response); err != nil {
return response, fmt.Errorf("error unmarshalling role body: %+v: %+v", err, body)
}

return response, nil
}

type RoleResponse struct {
Message string `json:"message"`
Status string `json:"status"`
}

type RoleBody struct {
Description string `json:"description"`
ClusterPermissions []string `json:"cluster_permissions"`
IndexPermissions []IndexPermissions `json:"index_permissions"`
TenantPermissions []TenantPermissions `json:"tenant_permissions"`
}

type IndexPermissions struct {
IndexPatterns []string `json:"index_patterns"`
Fls []string `json:"fls"`
MaskedFields []string `json:"masked_fields"`
AllowedActions []string `json:"allowed_actions"`
}

type TenantPermissions struct {
TenantPatterns []string `json:"tenant_patterns"`
AllowedActions []string `json:"allowed_actions"`
}
Loading

0 comments on commit 13e1cc9

Please sign in to comment.