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 4 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
94 changes: 94 additions & 0 deletions azurerm/data_source_azuread_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package azurerm

import (
"fmt"
"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/utils"
"log"
"strings"
)

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

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

"name": {
tiwood marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"object_id"},
},
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 @@ -80,6 +80,7 @@ func Provider() terraform.ResourceProvider {
DataSourcesMap: map[string]*schema.Resource{
"azurerm_azuread_application": dataSourceArmAzureADApplication(),
"azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(),
"azurerm_azuread_group": dataSourceArmAzureADGroup(),
tiwood marked this conversation as resolved.
Show resolved Hide resolved
"azurerm_application_security_group": dataSourceArmApplicationSecurityGroup(),
"azurerm_app_service": dataSourceArmAppService(),
"azurerm_app_service_plan": dataSourceAppServicePlan(),
Expand Down Expand Up @@ -126,6 +127,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_azuread_application": resourceArmActiveDirectoryApplication(),
"azurerm_azuread_service_principal": resourceArmActiveDirectoryServicePrincipal(),
"azurerm_azuread_service_principal_password": resourceArmActiveDirectoryServicePrincipalPassword(),
"azurerm_azuread_group": resourceArmActiveDirectoryGroup(),
tiwood marked this conversation as resolved.
Show resolved Hide resolved
"azurerm_application_gateway": resourceArmApplicationGateway(),
"azurerm_application_insights": resourceArmApplicationInsights(),
"azurerm_application_security_group": resourceArmApplicationSecurityGroup(),
Expand Down
92 changes: 92 additions & 0 deletions azurerm/resource_arm_azuread_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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/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{
"object_id": {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a reason for this property to exist? .id can be used instead and is even what your using in your tests object_id = "${azurerm_azuread_group.test.id}"

Type: schema.TypeString,
Computed: true,
},

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
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)
d.Set("object_id", group.ObjectID)
tiwood marked this conversation as resolved.
Show resolved Hide resolved

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

resp, err := client.Delete(ctx, d.Id())
if err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could be:

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