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 'azuread_user' #18

Merged
merged 21 commits into from
Feb 10, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions azuread/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type ArmClient struct {
domainsClient graphrbac.DomainsClient
groupsClient graphrbac.GroupsClient
servicePrincipalsClient graphrbac.ServicePrincipalsClient
usersClient graphrbac.UsersClient
}

// getArmClient is a helper method which returns a fully instantiated *ArmClient based on the auth Config's current settings.
Expand Down Expand Up @@ -83,6 +84,9 @@ func (c *ArmClient) registerGraphRBACClients(endpoint, tenantID string, authoriz

c.servicePrincipalsClient = graphrbac.NewServicePrincipalsClientWithBaseURI(endpoint, tenantID)
configureClient(&c.servicePrincipalsClient.Client, authorizer)

c.usersClient = graphrbac.NewUsersClientWithBaseURI(endpoint, tenantID)
configureClient(&c.usersClient.Client, authorizer)
}

func configureClient(client *autorest.Client, auth autorest.Authorizer) {
Expand Down
79 changes: 79 additions & 0 deletions azuread/data_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package azuread

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-azuread/azuread/helpers/ar"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
)

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

Schema: map[string]*schema.Schema{
"user_principal_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
},

"account_enabled": {
Type: schema.TypeBool,
Computed: true,
},

"display_name": {
Type: schema.TypeString,
Computed: true,
},

"mail": {
Type: schema.TypeString,
Computed: true,
},

"mail_nickname": {
Type: schema.TypeString,
Computed: true,
},
},
tiwood marked this conversation as resolved.
Show resolved Hide resolved
}
}

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

var user graphrbac.User

queryString := d.Get("user_principal_name").(string)

log.Printf("[DEBUG] Using Get with the following query string: %q", queryString)
user, err := client.Get(ctx, queryString)
if err != nil {
if ar.ResponseWasNotFound(user.Response) {
return fmt.Errorf("Error: No AzureAD User found with the following query string: %q", queryString)
}
return fmt.Errorf("Error making Read request on AzureAD User the following query string: %q: %+v", queryString, err)
}

if user.ObjectID == nil {
return fmt.Errorf("User objectId is nil")
}

d.SetId(*user.ObjectID)
tiwood marked this conversation as resolved.
Show resolved Hide resolved
d.Set("user_principal_name", user.UserPrincipalName)
d.Set("account_enabled", user.AccountEnabled)
d.Set("display_name", user.DisplayName)
d.Set("mail", user.Mail)
d.Set("mail_nickname", user.MailNickname)

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

import (
"fmt"
"math/rand"
"strconv"
"testing"

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

func TestAccDataSourceAzureADUser_byUserPrincipalName(t *testing.T) {
dataSourceName := "data.azuread_user.test"
id := strconv.Itoa(rand.Intn(9999))
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 change this to:

Suggested change
id := strconv.Itoa(rand.Intn(9999))
id := acctest.RandString(7)

password := id + "p@$$wR2"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAzureADUserDataSource_byUserPrincipalName(id, password),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dataSourceName, "user_principal_name"),
resource.TestCheckResourceAttrSet(dataSourceName, "account_enabled"),
resource.TestCheckResourceAttrSet(dataSourceName, "display_name"),
resource.TestCheckResourceAttrSet(dataSourceName, "mail_nickname"),
),
},
},
})
}

func testAccAzureADUserDataSource_byUserPrincipalName(id, password string) string {
template := testAccADUser_basic(id, password)
return fmt.Sprintf(`

%s

data "azuread_user" "test" {
user_principal_name = "${azuread_user.test.user_principal_name}"
}
`, template)
}
16 changes: 16 additions & 0 deletions azuread/helpers/validate/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package validate

import (
"fmt"
"regexp"
"strings"
)

Expand All @@ -18,3 +19,18 @@ func NoEmptyStrings(i interface{}, k string) ([]string, []error) {

return nil, nil
}

// StringIsEmailAddress validates that the given string is a valid email address ([email protected])
func StringIsEmailAddress(i interface{}, k string) ([]string, []error) {
tiwood marked this conversation as resolved.
Show resolved Hide resolved
v, ok := i.(string)
if !ok {
return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
}

regExIsEmailAddress := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
if !regExIsEmailAddress.MatchString(v) {
return nil, []error{fmt.Errorf("%q must be in email address format", k)}
}

return nil, nil
}
34 changes: 34 additions & 0 deletions azuread/helpers/validate/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,37 @@ func TestNoEmptyStrings(t *testing.T) {
})
}
}

func TestStringIsEmailAddress(t *testing.T) {
cases := []struct {
Value string
TestName string
ErrCount int
}{
{
Value: "[email protected]",
TestName: "Valid_EmailAddress",
ErrCount: 0,
},
{
Value: "john.doehashicorp.com",
TestName: "Invalid_EmailAddress_NoAtChar",
ErrCount: 1,
},
{
Value: "john/doe@ha$hicorp.com",
TestName: "Invalid_EmailAddress_InvalidChars",
ErrCount: 1,
},
}

for _, tc := range cases {
t.Run(tc.TestName, func(t *testing.T) {
_, errors := StringIsEmailAddress(tc.Value, tc.TestName)

if len(errors) != tc.ErrCount {
t.Fatalf("Expected StringIsEmailAddress to have %d not %d errors for %q", tc.ErrCount, len(errors), tc.TestName)
}
})
}
}
2 changes: 2 additions & 0 deletions azuread/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ func Provider() terraform.ResourceProvider {
"azuread_domains": dataDomains(),
"azuread_group": dataGroup(),
"azuread_service_principal": dataServicePrincipal(),
"azuread_user": dataSourceUser(),
},

ResourcesMap: map[string]*schema.Resource{
"azuread_application": resourceApplication(),
"azuread_group": resourceGroup(),
"azuread_service_principal": resourceServicePrincipal(),
"azuread_service_principal_password": resourceServicePrincipalPassword(),
"azuread_user": resourceUser(),
},
}

Expand Down
Loading