Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New resource & data source 'azurerm_azuread_group' #1839

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type ArmClient struct {
roleDefinitionsClient authorization.RoleDefinitionsClient
applicationsClient graphrbac.ApplicationsClient
servicePrincipalsClient graphrbac.ServicePrincipalsClient
groupsClient graphrbac.GroupsClient

// Autoscale Settings
autoscaleSettingsClient insights.AutoscaleSettingsClient
Expand Down Expand Up @@ -509,6 +510,13 @@ func (c *ArmClient) registerAuthentication(endpoint, graphEndpoint, subscription
servicePrincipalsClient.Sender = sender
servicePrincipalsClient.SkipResourceProviderRegistration = c.skipProviderRegistration
c.servicePrincipalsClient = servicePrincipalsClient

groupsClient := graphrbac.NewGroupsClientWithBaseURI(graphEndpoint, tenantId)
setUserAgent(&groupsClient.Client)
groupsClient.Authorizer = graphAuth
groupsClient.Sender = sender
groupsClient.SkipResourceProviderRegistration = c.skipProviderRegistration
c.groupsClient = groupsClient
}

func (c *ArmClient) registerCDNClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) {
Expand Down
97 changes: 97 additions & 0 deletions azurerm/data_source_azuread_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package azurerm

import (
"fmt"
"log"
"strings"

"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
tiwood marked this conversation as resolved.
Show resolved Hide resolved
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmAzureADGroup() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmAzureADGroupRead,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"object_id"},
},

"object_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"name"},
ValidateFunc: validate.UUID,
},
tiwood marked this conversation as resolved.
Show resolved Hide resolved
},
}
}

func dataSourceArmAzureADGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).groupsClient
ctx := meta.(*ArmClient).StopContext

var adgroup graphrbac.ADGroup
var groupObj *graphrbac.ADGroup

if oId, ok := d.GetOk("object_id"); ok {
// use the object_id to find the Azure AD group

objectId := oId.(string)
resp, err := client.Get(ctx, objectId)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error: AzureAD Group with ID %q was not found", objectId)
}

return fmt.Errorf("Error making Read request on AzureAD Group with ID %q: %+v", objectId, err)
}

adgroup = resp

} else {

// use the name to find the Azure AD group
name := d.Get("name").(string)
filter := fmt.Sprintf("displayName eq '%s'", name)
log.Printf("[DEBUG] [data_source_azuread_group] Using filter %q", filter)

resp, err := client.ListComplete(ctx, filter)
if err != nil {
return fmt.Errorf("Error listing Azure AD groups: %+v", err)
}

for _, v := range *resp.Response().Value {
if v.DisplayName != nil {
if strings.EqualFold(*v.DisplayName, name) {
log.Printf("[DEBUG] [data_source_azuread_group] %q (API result) matches %q (given value). The group has the objectId: %q", *v.DisplayName, name, *v.ObjectID)
groupObj = &v
break
} else {
log.Printf("[DEBUG] [data_source_azuread_group] %q (API result) does not match %q (given value)", *v.DisplayName, name)
}
}
}
if groupObj == nil {
return fmt.Errorf("Couldn't locate a Azure AD group with a name of %q", name)
}

adgroup = *groupObj
}

d.SetId(*adgroup.ObjectID)
d.Set("object_id", adgroup.ObjectID)
d.Set("name", adgroup.DisplayName)

return nil
}
79 changes: 79 additions & 0 deletions azurerm/data_source_azuread_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package azurerm

import (
"fmt"
"testing"

"github.com/google/uuid"
"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataSourceAzureRMAzureADGroup_byObjectId(t *testing.T) {
dataSourceName := "data.azurerm_azuread_group.test"
id := uuid.New().String()
config := testAccDataSourceAzureRMAzureADGroup_objectId(id)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMActiveDirectoryGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMActiveDirectoryGroup(id),
},
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMActiveDirectoryGroupExists(dataSourceName),
resource.TestCheckResourceAttr(dataSourceName, "name", fmt.Sprintf("acctest%s", id)),
),
},
},
})
}

func TestAccDataSourceAzureRMAzureADGroup_byName(t *testing.T) {
dataSourceName := "data.azurerm_azuread_group.test"
id := uuid.New().String()
config := testAccDataSourceAzureRMAzureADGroup_name(id)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMActiveDirectoryGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMActiveDirectoryGroup(id),
},
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMActiveDirectoryGroupExists(dataSourceName),
resource.TestCheckResourceAttr(dataSourceName, "name", fmt.Sprintf("acctest%s", id)),
),
},
},
})
}

func testAccDataSourceAzureRMAzureADGroup_objectId(id string) string {
template := testAccAzureRMActiveDirectoryGroup(id)
return fmt.Sprintf(`
%s

data "azurerm_azuread_group" "test" {
object_id = "${azurerm_azuread_group.test.id}"
}
`, template)
}

func testAccDataSourceAzureRMAzureADGroup_name(id string) string {
template := testAccAzureRMActiveDirectoryGroup(id)
return fmt.Sprintf(`
%s

data "azurerm_azuread_group" "test" {
name = "${azurerm_azuread_group.test.name}"
}
`, template)
}
2 changes: 2 additions & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func Provider() terraform.ResourceProvider {

DataSourcesMap: map[string]*schema.Resource{
"azurerm_azuread_application": dataSourceArmAzureADApplication(),
"azurerm_azuread_group": dataSourceArmAzureADGroup(),
tiwood marked this conversation as resolved.
Show resolved Hide resolved
"azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(),
"azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(),
"azurerm_app_service": dataSourceArmAppService(),
Expand Down Expand Up @@ -124,6 +125,7 @@ func Provider() terraform.ResourceProvider {

ResourcesMap: map[string]*schema.Resource{
"azurerm_azuread_application": resourceArmActiveDirectoryApplication(),
"azurerm_azuread_group": resourceArmActiveDirectoryGroup(),
"azurerm_azuread_service_principal": resourceArmActiveDirectoryServicePrincipal(),
"azurerm_azuread_service_principal_password": resourceArmActiveDirectoryServicePrincipalPassword(),
"azurerm_application_gateway": resourceArmApplicationGateway(),
Expand Down
87 changes: 87 additions & 0 deletions azurerm/resource_arm_azuread_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package azurerm

import (
"fmt"
"log"

"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmActiveDirectoryGroup() *schema.Resource {
return &schema.Resource{
Create: resourceArmActiveDirectoryGroupCreate,
Read: resourceArmActiveDirectoryGroupRead,
Delete: resourceArmActiveDirectoryGroupDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.NoZeroValues,
},
tiwood marked this conversation as resolved.
Show resolved Hide resolved
},
}
}

func resourceArmActiveDirectoryGroupCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).groupsClient
ctx := meta.(*ArmClient).StopContext

name := d.Get("name").(string)

properties := graphrbac.GroupCreateParameters{
DisplayName: &name,
MailEnabled: utils.Bool(false),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we expose these three properties in the schema instead of silently defaulting them?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could do that, but at the moment the Graph API only supports the creation of security enabled groups (MailEnabled: false, SecurityEnabled: true). See here.

So what is the protocol here, adding these to the schema as computed and default to them for now, or keep it as is?

MailNickname: &name,
SecurityEnabled: utils.Bool(true),
}

group, err := client.Create(ctx, properties)
if err != nil {
return err
}

d.SetId(*group.ObjectID)

return resourceArmActiveDirectoryGroupRead(d, meta)
}

func resourceArmActiveDirectoryGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).groupsClient
ctx := meta.(*ArmClient).StopContext

resp, err := client.Get(ctx, d.Id())
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] [resource_arm_azuread_group] Azure AD group with id %q was not found - removing from state", d.Id())
d.SetId("")
return nil
}

return fmt.Errorf("Error retrieving Azure AD Group with ID %q: %+v", d.Id(), err)
}

d.Set("name", resp.DisplayName)

return nil
}

func resourceArmActiveDirectoryGroupDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).groupsClient
ctx := meta.(*ArmClient).StopContext

if resp, err := client.Delete(ctx, d.Id()); err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("Error Deleting Azure AD Group with ID %q: %+v", d.Id(), err)
}
}

return nil
}
Loading