diff --git a/docs/data-sources/directory_roles.md b/docs/data-sources/directory_roles.md new file mode 100644 index 0000000000..96539631f5 --- /dev/null +++ b/docs/data-sources/directory_roles.md @@ -0,0 +1,45 @@ +--- +subcategory: "Directory Roles" +--- + +# Resource: azuread_directory_roles + +Use this data source to access information about activated directory roles within Azure Active Directory. + +## API Permissions + +The following API permissions are required in order to use this resource. + +When authenticated with a service principal, this resource requires one of the following application roles: `RoleManagement.Read.Directory` or `Directory.Read.All` + +When authenticated with a user principal, this data source does not require any additional roles. + +## Example Usage + +```terraform +data "azuread_directory_roles" "current" {} + +output "roles" { + value = data.azuread_directory_roles.current.object_ids +} +``` + +## Argument Reference + +This data source does not have any arguments. + +## Attributes Reference + +The following attributes are exported: + +* `object_ids` - The object IDs of the roles. +* `roles` - A list of users. Each `role` object provides the attributes documented below. + +--- + +`role` object exports the following: + +* `display_name` - The display name of the directory role. +* `template_id` - The template ID of the directory role. +* `description` - The description of the directory role. +* `object_id` - The object ID of the directory role. diff --git a/internal/services/directoryroles/directory_roles_data_source.go b/internal/services/directoryroles/directory_roles_data_source.go new file mode 100644 index 0000000000..1ba5cbb7ce --- /dev/null +++ b/internal/services/directoryroles/directory_roles_data_source.go @@ -0,0 +1,109 @@ +package directoryroles + +import ( + "context" + "crypto/sha1" + "encoding/base64" + "errors" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-azuread/internal/clients" + "github.com/hashicorp/terraform-provider-azuread/internal/tf" +) + +func directoryRolesDataSource() *schema.Resource { + return &schema.Resource{ + ReadContext: directoryRolesDataSourceRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "object_ids": { + Description: "The object IDs of the roles", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "roles": { + Description: "A list of roles", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": { + Description: "The display name of the directory role", + Type: schema.TypeString, + Computed: true, + }, + + "template_id": { + Description: "The object ID of the template associated with the directory role", + Type: schema.TypeString, + Computed: true, + }, + + "description": { + Description: "The description of the directory role", + Type: schema.TypeString, + Computed: true, + }, + + "object_id": { + Description: "The object ID of the directory role", + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func directoryRolesDataSourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*clients.Client).DirectoryRoles.DirectoryRolesClient + + directoryRoles, _, err := client.List(ctx) + if err != nil { + return tf.ErrorDiagF(err, "Could not retrieve roles") + } + if directoryRoles == nil { + return tf.ErrorDiagF(errors.New("API error: nil directoryRoles were returned"), "Retrieving all directory roles") + } + + objectIds := make([]string, 0) + roleList := make([]map[string]interface{}, 0) + + for _, r := range *directoryRoles { + objectIds = append(objectIds, *r.ID()) + + role := make(map[string]interface{}) + role["description"] = r.Description + role["display_name"] = r.DisplayName + role["object_id"] = r.ID() + role["template_id"] = r.RoleTemplateId + roleList = append(roleList, role) + } + + // Generate a unique ID based on result + h := sha1.New() + if _, err := h.Write([]byte(strings.Join(objectIds, "/"))); err != nil { + return tf.ErrorDiagF(err, "Unable to compute hash for Object IDs") + } + + d.SetId("roles#" + base64.URLEncoding.EncodeToString(h.Sum(nil))) + + tf.Set(d, "roles", roleList) + tf.Set(d, "object_ids", objectIds) + + return nil +} diff --git a/internal/services/directoryroles/directory_roles_data_source_test.go b/internal/services/directoryroles/directory_roles_data_source_test.go new file mode 100644 index 0000000000..696184b990 --- /dev/null +++ b/internal/services/directoryroles/directory_roles_data_source_test.go @@ -0,0 +1,39 @@ +package directoryroles_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-azuread/internal/acceptance" + "github.com/hashicorp/terraform-provider-azuread/internal/acceptance/check" +) + +type DirectoryRolesDataSource struct{} + +func TestAccDirectoryRolesDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azuread_directory_roles", "test") + r := DirectoryRolesDataSource{} + + data.DataSourceTest(t, []resource.TestStep{ + { + Config: r.basic(), + Check: r.testCheckFunc(data), + }, + }) +} + +func (DirectoryRolesDataSource) testCheckFunc(data acceptance.TestData, additionalChecks ...resource.TestCheckFunc) resource.TestCheckFunc { + checks := []resource.TestCheckFunc{ + check.That(data.ResourceName).Key("roles.0.description").Exists(), + check.That(data.ResourceName).Key("roles.0.display_name").Exists(), + check.That(data.ResourceName).Key("roles.0.object_id").Exists(), + check.That(data.ResourceName).Key("roles.0.template_id").Exists(), + } + checks = append(checks, additionalChecks...) + return resource.ComposeTestCheckFunc(checks...) +} + +func (DirectoryRolesDataSource) basic() string { + return `data "azuread_directory_roles" "test" {}` +} diff --git a/internal/services/directoryroles/registration.go b/internal/services/directoryroles/registration.go index ed6d5e91a1..5bd2740f59 100644 --- a/internal/services/directoryroles/registration.go +++ b/internal/services/directoryroles/registration.go @@ -20,7 +20,9 @@ func (r Registration) WebsiteCategories() []string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { - return map[string]*schema.Resource{} + return map[string]*schema.Resource{ + "azuread_directory_roles": directoryRolesDataSource(), + } } // SupportedResources returns the supported Resources supported by this Service