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 'azuread_application_password' #71

Merged
merged 18 commits into from
May 26, 2019
Merged
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
4 changes: 2 additions & 2 deletions azuread/data_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ func dataApplicationRead(d *schema.ResourceData, meta interface{}) error {
d.Set("available_to_other_tenants", app.AvailableToOtherTenants)
d.Set("oauth2_allow_implicit_flow", app.Oauth2AllowImplicitFlow)

if err := d.Set("identifier_uris", tf.FlattenStringArrayPtr(app.IdentifierUris)); err != nil {
if err := d.Set("identifier_uris", tf.FlattenStringSlicePtr(app.IdentifierUris)); err != nil {
return fmt.Errorf("Error setting `identifier_uris`: %+v", err)
}

if err := d.Set("reply_urls", tf.FlattenStringArrayPtr(app.ReplyUrls)); err != nil {
if err := d.Set("reply_urls", tf.FlattenStringSlicePtr(app.ReplyUrls)); err != nil {
return fmt.Errorf("Error setting `reply_urls`: %+v", err)
}

Expand Down
211 changes: 211 additions & 0 deletions azuread/helpers/graph/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package graph

import (
"fmt"
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
"github.com/Azure/go-autorest/autorest/date"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/p"
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
)

// valid types are `application` and `service_principal`
func PasswordResourceSchema(object_type string) map[string]*schema.Schema {
return map[string]*schema.Schema{
object_type + "_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.UUID,
},

"key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validate.UUID,
},

"value": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Sensitive: true,
ValidateFunc: validate.NoEmptyStrings,
},

"start_date": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validation.ValidateRFC3339TimeString,
},

"end_date": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"end_date_relative"},
ValidateFunc: validation.ValidateRFC3339TimeString,
},

"end_date_relative": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{"end_date"},
ValidateFunc: validate.NoEmptyStrings,
},
}
}

type PasswordCredentialId struct {
ObjectId string
KeyId string
}

func (id PasswordCredentialId) String() string {
return id.ObjectId + "/" + id.KeyId
}

func ParsePasswordCredentialId(id string) (PasswordCredentialId, error) {
parts := strings.Split(id, "/")
if len(parts) != 2 {
return PasswordCredentialId{}, fmt.Errorf("Password Credential ID should be in the format {objectId}/{keyId} - but got %q", id)
}

if _, err := uuid.ParseUUID(parts[0]); err != nil {
return PasswordCredentialId{}, fmt.Errorf("Object ID isn't a valid UUID (%q): %+v", id[0], err)
}

if _, err := uuid.ParseUUID(parts[1]); err != nil {
return PasswordCredentialId{}, fmt.Errorf("Object ID isn't a valid UUID (%q): %+v", id[1], err)
}

return PasswordCredentialId{
ObjectId: parts[0],
KeyId: parts[1],
}, nil

}

func PasswordCredentialIdFrom(objectId, keyId string) PasswordCredentialId {
return PasswordCredentialId{
ObjectId: objectId,
KeyId: keyId,
}
}

func PasswordCredentialForResource(d *schema.ResourceData) (*graphrbac.PasswordCredential, error) {
value := d.Get("value").(string)

// errors should be handled by the validation
var keyId string
if v, ok := d.GetOk("key_id"); ok {
keyId = v.(string)
} else {
kid, err := uuid.GenerateUUID()
if err != nil {
return nil, err
}

keyId = kid
}

var endDate time.Time
if v := d.Get("end_date").(string); v != "" {
endDate, _ = time.Parse(time.RFC3339, v)
} else if v := d.Get("end_date_relative").(string); v != "" {
d, err := time.ParseDuration(v)
if err != nil {
return nil, fmt.Errorf("unable to parse `end_date_relative` (%s) as a duration", v)
}
endDate = time.Now().Add(d)
} else {
return nil, fmt.Errorf("one of `end_date` or `end_date_relative` must be specified")
}

credential := graphrbac.PasswordCredential{
KeyID: p.String(keyId),
Value: p.String(value),
EndDate: &date.Time{Time: endDate},
}

if v, ok := d.GetOk("start_date"); ok {
// errors will be handled by the validation
startDate, _ := time.Parse(time.RFC3339, v.(string))
credential.StartDate = &date.Time{Time: startDate}
}

return &credential, nil
}

func PasswordCredentialResultFindByKeyId(creds graphrbac.PasswordCredentialListResult, keyId string) *graphrbac.PasswordCredential {
var cred *graphrbac.PasswordCredential

if creds.Value != nil {
for _, c := range *creds.Value {
if c.KeyID == nil {
continue
}

if *c.KeyID == keyId {
cred = &c
break
}
}
}

return cred
}

func PasswordCredentialResultAdd(existing graphrbac.PasswordCredentialListResult, cred *graphrbac.PasswordCredential, errorOnDuplicate bool) (*[]graphrbac.PasswordCredential, error) {
newCreds := make([]graphrbac.PasswordCredential, 0)

if existing.Value != nil {
if errorOnDuplicate {
for _, v := range *existing.Value {
if v.KeyID == nil {
continue
}

if *v.KeyID == *cred.KeyID {
return nil, fmt.Errorf("credential already exists found")
}
}
}

newCreds = *existing.Value
}
newCreds = append(newCreds, *cred)

return &newCreds, nil
}

func PasswordCredentialResultRemoveByKeyId(existing graphrbac.PasswordCredentialListResult, keyId string) *[]graphrbac.PasswordCredential {
newCreds := make([]graphrbac.PasswordCredential, 0)

if existing.Value != nil {
for _, v := range *existing.Value {
if v.KeyID == nil {
continue
}

if *v.KeyID == keyId {
continue
}

newCreds = append(newCreds, v)
}
}

return &newCreds
}
13 changes: 0 additions & 13 deletions azuread/helpers/guid/guid.go

This file was deleted.

5 changes: 2 additions & 3 deletions azuread/helpers/p/p.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package p //or maybe ptr?

//helper functions to convert to a pointer
package p // or maybe ptr?

// helper functions to convert to a pointer
func Bool(input bool) *bool {
return &input
}
Expand Down
4 changes: 2 additions & 2 deletions azuread/helpers/tf/marshall.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package tf

func ExpandStringArrayPtr(input []interface{}) *[]string {
func ExpandStringSlicePtr(input []interface{}) *[]string {
result := make([]string, 0)
for _, item := range input {
result = append(result, item.(string))
}
return &result
}

func FlattenStringArrayPtr(input *[]string) []interface{} {
func FlattenStringSlicePtr(input *[]string) []interface{} {
result := make([]interface{}, 0)
if input != nil {
for _, item := range *input {
Expand Down
6 changes: 3 additions & 3 deletions azuread/locks.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package azuread

// handle the case of using the same name for different kinds of resources
func azureADLockByName(name string, resourceType string) {
// handles the case of using the same name for different kinds of resources
func azureADLockByName(resourceType string, name string) {
armMutexKV.Lock(resourceType + "." + name)
}

func azureADUnlockByName(name string, resourceType string) {
func azureADUnlockByName(resourceType string, name string) {
armMutexKV.Unlock(resourceType + "." + name)
}
1 change: 1 addition & 0 deletions azuread/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func Provider() terraform.ResourceProvider {

ResourcesMap: map[string]*schema.Resource{
"azuread_application": resourceApplication(),
"azuread_application_password": resourceApplicationPassword(),
"azuread_group": resourceGroup(),
"azuread_service_principal": resourceServicePrincipal(),
"azuread_service_principal_password": resourceServicePrincipalPassword(),
Expand Down
16 changes: 9 additions & 7 deletions azuread/resource_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate"
)

const resourceApplicationName = "azuread_application"

func resourceApplication() *schema.Resource {
return &schema.Resource{
Create: resourceApplicationCreate,
Expand Down Expand Up @@ -192,8 +194,8 @@ func resourceApplicationCreate(d *schema.ResourceData, meta interface{}) error {
properties := graphrbac.ApplicationCreateParameters{
AdditionalProperties: make(map[string]interface{}),
DisplayName: &name,
IdentifierUris: tf.ExpandStringArrayPtr(identUrls.([]interface{})),
ReplyUrls: tf.ExpandStringArrayPtr(d.Get("reply_urls").(*schema.Set).List()),
IdentifierUris: tf.ExpandStringSlicePtr(identUrls.([]interface{})),
ReplyUrls: tf.ExpandStringSlicePtr(d.Get("reply_urls").(*schema.Set).List()),
AvailableToOtherTenants: p.Bool(d.Get("available_to_other_tenants").(bool)),
RequiredResourceAccess: expandADApplicationRequiredResourceAccess(d),
}
Expand Down Expand Up @@ -265,11 +267,11 @@ func resourceApplicationUpdate(d *schema.ResourceData, meta interface{}) error {
}

if d.HasChange("identifier_uris") {
properties.IdentifierUris = tf.ExpandStringArrayPtr(d.Get("identifier_uris").([]interface{}))
properties.IdentifierUris = tf.ExpandStringSlicePtr(d.Get("identifier_uris").([]interface{}))
}

if d.HasChange("reply_urls") {
properties.ReplyUrls = tf.ExpandStringArrayPtr(d.Get("reply_urls").(*schema.Set).List())
properties.ReplyUrls = tf.ExpandStringSlicePtr(d.Get("reply_urls").(*schema.Set).List())
}

if d.HasChange("available_to_other_tenants") {
Expand Down Expand Up @@ -300,7 +302,7 @@ func resourceApplicationUpdate(d *schema.ResourceData, meta interface{}) error {
switch appType := d.Get("type"); appType {
case "webapp/api":
properties.AdditionalProperties["publicClient"] = false
properties.IdentifierUris = tf.ExpandStringArrayPtr(d.Get("identifier_uris").([]interface{}))
properties.IdentifierUris = tf.ExpandStringSlicePtr(d.Get("identifier_uris").([]interface{}))
case "native":
properties.AdditionalProperties["publicClient"] = true
properties.IdentifierUris = &[]string{}
Expand Down Expand Up @@ -349,11 +351,11 @@ func resourceApplicationRead(d *schema.ResourceData, meta interface{}) error {
d.Set("type", "webapp/api")
}

if err := d.Set("identifier_uris", tf.FlattenStringArrayPtr(resp.IdentifierUris)); err != nil {
if err := d.Set("identifier_uris", tf.FlattenStringSlicePtr(resp.IdentifierUris)); err != nil {
return fmt.Errorf("Error setting `identifier_uris`: %+v", err)
}

if err := d.Set("reply_urls", tf.FlattenStringArrayPtr(resp.ReplyUrls)); err != nil {
if err := d.Set("reply_urls", tf.FlattenStringSlicePtr(resp.ReplyUrls)); err != nil {
return fmt.Errorf("Error setting `reply_urls`: %+v", err)
}

Expand Down
Loading