-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RBAC: resource for RBAC role assignments (#647)
* role assignment resource * clean up * remove possibility to do global assignments for now * remove possibility to do global assignments for now * Fix variable reference * Append `.vscode` and `vendor` to `.gitignore` * Fix typo * tests attempt 1 * set id correctly * add tests * change id * Update grafana/resource_role_assignment.go Co-authored-by: Julien Duchesne <[email protected]> * Update grafana/resource_role_assignment.go Co-authored-by: Vardan Torosyan <[email protected]> * fix IDs * update API client dependency * Generate docs * Read after update * try to update api client dependency * improve the test * attempt to refactor annotation test * uncomment Co-authored-by: linoman <[email protected]> Co-authored-by: Julien Duchesne <[email protected]> Co-authored-by: Vardan Torosyan <[email protected]>
- Loading branch information
1 parent
42573f3
commit f487ec3
Showing
9 changed files
with
301 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "grafana_role_assignment Resource - terraform-provider-grafana" | ||
subcategory: "Grafana Enteprise" | ||
description: |- | ||
Note: This resource is available only with Grafana Enterprise 9.2+. | ||
* Official documentation https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/ | ||
* HTTP API https://grafana.com/docs/grafana/latest/developers/http_api/access_control/ | ||
--- | ||
|
||
# grafana_role_assignment (Resource) | ||
|
||
**Note:** This resource is available only with Grafana Enterprise 9.2+. | ||
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/) | ||
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/) | ||
|
||
|
||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `role_uid` (String) Grafana RBAC role UID. | ||
|
||
### Optional | ||
|
||
- `service_accounts` (Set of Number) IDs of service accounts that the role should be assigned to. | ||
- `teams` (Set of Number) IDs of teams that the role should be assigned to. | ||
- `users` (Set of Number) IDs of users that the role should be assigned to. | ||
|
||
### Read-Only | ||
|
||
- `id` (String) The ID of this resource. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package grafana | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
gapi "github.com/grafana/grafana-api-golang-client" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func ResourceRoleAssignment() *schema.Resource { | ||
return &schema.Resource{ | ||
Description: ` | ||
**Note:** This resource is available only with Grafana Enterprise 9.2+. | ||
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/) | ||
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/) | ||
`, | ||
CreateContext: UpdateRoleAssignments, | ||
UpdateContext: UpdateRoleAssignments, | ||
ReadContext: ReadRoleAssignments, | ||
DeleteContext: UpdateRoleAssignments, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: schema.ImportStatePassthroughContext, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"role_uid": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "Grafana RBAC role UID.", | ||
}, | ||
"users": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
ForceNew: false, | ||
Description: "IDs of users that the role should be assigned to.", | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeInt, | ||
}, | ||
}, | ||
"teams": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
ForceNew: false, | ||
Description: "IDs of teams that the role should be assigned to.", | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeInt, | ||
}, | ||
}, | ||
"service_accounts": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
ForceNew: false, | ||
Description: "IDs of service accounts that the role should be assigned to.", | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeInt, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func ReadRoleAssignments(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
client := meta.(*client).gapi | ||
uid := d.Id() | ||
assignments, err := client.GetRoleAssignments(uid) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
if err := setRoleAssignments(assignments, d); err != nil { | ||
return diag.FromErr(err) | ||
} | ||
return nil | ||
} | ||
|
||
func UpdateRoleAssignments(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
if !d.IsNewResource() && !d.HasChange("users") && !d.HasChange("teams") && !d.HasChange("service_accounts") { | ||
return nil | ||
} | ||
|
||
client := meta.(*client).gapi | ||
|
||
uid := d.Get("role_uid").(string) | ||
users, err := collectRoleAssignmentsToFn(d.Get("users")) | ||
if err != nil { | ||
return diag.Errorf("invalid user IDs specified %v", err) | ||
} | ||
teams, err := collectRoleAssignmentsToFn(d.Get("teams")) | ||
if err != nil { | ||
return diag.Errorf("invalid team IDs specified %v", err) | ||
} | ||
serviceAccounts, err := collectRoleAssignmentsToFn(d.Get("service_accounts")) | ||
if err != nil { | ||
return diag.Errorf("invalid service account IDs specified %v", err) | ||
} | ||
|
||
ra := &gapi.RoleAssignments{ | ||
RoleUID: uid, | ||
Users: users, | ||
Teams: teams, | ||
ServiceAccounts: serviceAccounts, | ||
} | ||
assignments, err := client.UpdateRoleAssignments(ra) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
if err := setRoleAssignments(assignments, d); err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
return ReadRoleAssignments(ctx, d, meta) | ||
} | ||
|
||
func setRoleAssignments(assignments *gapi.RoleAssignments, d *schema.ResourceData) error { | ||
d.SetId(assignments.RoleUID) | ||
if err := d.Set("role_uid", assignments.RoleUID); err != nil { | ||
return err | ||
} | ||
if err := d.Set("users", assignments.Users); err != nil { | ||
return err | ||
} | ||
if err := d.Set("teams", assignments.Teams); err != nil { | ||
return err | ||
} | ||
if err := d.Set("service_accounts", assignments.ServiceAccounts); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func collectRoleAssignmentsToFn(r interface{}) ([]int, error) { | ||
output := make([]int, 0) | ||
for _, rID := range r.(*schema.Set).List() { | ||
id, ok := rID.(int) | ||
if !ok { | ||
return []int{}, fmt.Errorf("%s is not a valid id", rID) | ||
} | ||
output = append(output, id) | ||
} | ||
return output, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package grafana | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform" | ||
|
||
gapi "github.com/grafana/grafana-api-golang-client" | ||
) | ||
|
||
func TestRoleAssignments(t *testing.T) { | ||
CheckEnterpriseTestsEnabled(t) | ||
var roleAssignment gapi.RoleAssignments | ||
|
||
resource.Test(t, resource.TestCase{ | ||
ProviderFactories: testAccProviderFactories, | ||
CheckDestroy: testRoleAssignmentCheckDestroy(&roleAssignment), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: fmt.Sprintf(roleAssignmentConfig, roleUID), | ||
Check: resource.ComposeTestCheckFunc( | ||
testRoleAssignmentCheckExists("grafana_role_assignment.test", &roleAssignment), | ||
resource.TestCheckResourceAttr( | ||
"grafana_role_assignment.test", "role_uid", roleUID, | ||
), | ||
resource.TestCheckResourceAttr( | ||
"grafana_role_assignment.test", "users.#", "2", | ||
), | ||
resource.TestCheckResourceAttr( | ||
"grafana_role_assignment.test", "service_accounts.#", "0", | ||
), | ||
resource.TestCheckResourceAttr( | ||
"grafana_role_assignment.test", "teams.#", "1", | ||
), | ||
), | ||
}, | ||
{ | ||
Config: fmt.Sprintf(roleAssignmentConfig, roleUID), | ||
Destroy: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testRoleAssignmentCheckExists(rn string, ra *gapi.RoleAssignments) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[rn] | ||
if !ok { | ||
return fmt.Errorf("resource not found: %s", rn) | ||
} | ||
|
||
uid, ok := rs.Primary.Attributes["role_uid"] | ||
if !ok { | ||
return fmt.Errorf("resource UID not set") | ||
} | ||
|
||
client := testAccProvider.Meta().(*client).gapi | ||
role, err := client.GetRoleAssignments(uid) | ||
if err != nil { | ||
return fmt.Errorf("error getting role assignments: %s", err) | ||
} | ||
|
||
*ra = *role | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testRoleAssignmentCheckDestroy(ra *gapi.RoleAssignments) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
client := testAccProvider.Meta().(*client).gapi | ||
role, err := client.GetRoleAssignments(ra.RoleUID) | ||
if err == nil && (len(role.Users) > 0 || len(role.ServiceAccounts) > 0 || len(role.Teams) > 0) { | ||
return fmt.Errorf("role is still assigned") | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
var roleUID = "terraform_test_role" | ||
|
||
var roleAssignmentConfig = ` | ||
resource "grafana_team" "test_team" { | ||
name = "terraform_test_team" | ||
} | ||
resource "grafana_user" "test_user" { | ||
email = "[email protected]" | ||
login = "[email protected]" | ||
password = "12345" | ||
} | ||
resource "grafana_user" "test_user2" { | ||
email = "[email protected]" | ||
login = "[email protected]" | ||
password = "12345" | ||
} | ||
resource "grafana_role_assignment" "test" { | ||
role_uid = "%s" | ||
users = [grafana_user.test_user.id, grafana_user.test_user2.id] | ||
teams = [grafana_team.test_team.id] | ||
} | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters