Skip to content

Commit

Permalink
Merge pull request #10782 from terraform-providers/r/aadds
Browse files Browse the repository at this point in the history
Active Directory Domain Services
  • Loading branch information
manicminer authored Jul 22, 2021
2 parents 515c5e0 + 5639055 commit 9c4cb52
Show file tree
Hide file tree
Showing 46 changed files with 7,172 additions and 88 deletions.
1 change: 1 addition & 0 deletions .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var services = mapOf(
"desktopvirtualization" to "Desktop Virtualization",
"devtestlabs" to "Dev Test",
"digitaltwins" to "Digital Twins",
"domainservices" to "DomainServices",
"eventgrid" to "EventGrid",
"eventhub" to "EventHub",
"firewall" to "Firewall",
Expand Down
19 changes: 19 additions & 0 deletions azurerm/helpers/validate/strings.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
package validate

import (
"encoding/base64"
"fmt"
"strings"
)

// Base64EncodedString validates that the string is base64 encoded
func Base64EncodedString(i interface{}, k string) ([]string, []error) {
v, ok := i.(string)
if !ok {
return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
}

if strings.TrimSpace(v) == "" {
return nil, []error{fmt.Errorf("%q must not be empty", k)}
}

if _, err := base64.StdEncoding.DecodeString(v); err != nil {
return nil, []error{fmt.Errorf("%q must be a valid base64 encoded string", k)}
}

return nil, nil
}

// LowerCasedString validates that the string is lower-cased
func LowerCasedString(i interface{}, k string) ([]string, []error) {
v, ok := i.(string)
Expand Down
28 changes: 28 additions & 0 deletions azurerm/helpers/validate/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@ import (
"testing"
)

func TestBase64EncodedString(t *testing.T) {
cases := []struct {
Input string
Errors int
}{
{
Input: "",
Errors: 1,
},
{
Input: "aGVsbG8td29ybGQ=",
Errors: 0,
},
{
Input: "hello-world",
Errors: 1,
},
}

for _, tc := range cases {
t.Run(tc.Input, func(t *testing.T) {
if _, errors := Base64EncodedString(tc.Input, "base64"); len(errors) != tc.Errors {
t.Fatalf("Expected Base64 string to have %d not %d errors for %q: %v", tc.Errors, len(errors), tc.Input, errors)
}
})
}
}

func TestLowerCasedStrings(t *testing.T) {
cases := []struct {
Value string
Expand Down
3 changes: 3 additions & 0 deletions azurerm/internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
devtestlabs "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs/client"
digitaltwins "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/digitaltwins/client"
dns "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/dns/client"
domainservices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices/client"
eventgrid "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventgrid/client"
eventhub "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/client"
firewall "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/firewall/client"
Expand Down Expand Up @@ -142,6 +143,7 @@ type Client struct {
DevTestLabs *devtestlabs.Client
DigitalTwins *digitaltwins.Client
Dns *dns.Client
DomainServices *domainservices.Client
EventGrid *eventgrid.Client
Eventhub *eventhub.Client
Firewall *firewall.Client
Expand Down Expand Up @@ -246,6 +248,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.DevTestLabs = devtestlabs.NewClient(o)
client.DigitalTwins = digitaltwins.NewClient(o)
client.Dns = dns.NewClient(o)
client.DomainServices = domainservices.NewClient(o)
client.EventGrid = eventgrid.NewClient(o)
client.Eventhub = eventhub.NewClient(o)
client.Firewall = firewall.NewClient(o)
Expand Down
2 changes: 2 additions & 0 deletions azurerm/internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/digitaltwins"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/dns"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventgrid"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/firewall"
Expand Down Expand Up @@ -147,6 +148,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration {
devtestlabs.Registration{},
digitaltwins.Registration{},
dns.Registration{},
domainservices.Registration{},
eventgrid.Registration{},
eventhub.Registration{},
firewall.Registration{},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
package domainservices

import (
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceActiveDirectoryDomainService() *pluginsdk.Resource {
return &pluginsdk.Resource{
Read: dataSourceActiveDirectoryDomainServiceRead,

Timeouts: &pluginsdk.ResourceTimeout{
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotWhiteSpace,
},

"resource_group_name": azure.SchemaResourceGroupNameForDataSource(),

"deployment_id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"domain_configuration_type": {
Type: pluginsdk.TypeString,
Computed: true,
},

"domain_name": {
Type: pluginsdk.TypeString,
Computed: true,
},

"filtered_sync_enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"location": azure.SchemaLocationForDataSource(),

"notifications": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"additional_recipients": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
"notify_dc_admins": {
Type: pluginsdk.TypeBool,
Computed: true,
},
"notify_global_admins": {
Type: pluginsdk.TypeBool,
Computed: true,
},
},
},
},

"replica_sets": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: dataSourceActiveDirectoryDomainServiceReplicaSetSchema(),
},
},

"secure_ldap": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"external_access_enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"certificate_expiry": {
Type: pluginsdk.TypeString,
Computed: true,
},

"certificate_thumbprint": {
Type: pluginsdk.TypeString,
Computed: true,
},

"public_certificate": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
},
},

"security": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"ntlm_v1_enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"sync_kerberos_passwords": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"sync_ntlm_passwords": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"sync_on_prem_passwords": {
Type: pluginsdk.TypeBool,
Computed: true,
},

"tls_v1_enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},
},
},
},

"sku": {
Type: pluginsdk.TypeString,
Computed: true,
},

"sync_owner": {
Type: pluginsdk.TypeString,
Computed: true,
},

"tags": tags.SchemaDataSource(),

"tenant_id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"version": {
Type: pluginsdk.TypeInt,
Computed: true,
},
},
}
}

func dataSourceActiveDirectoryDomainServiceReplicaSetSchema() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
// TODO: add health-related attributes

"domain_controller_ip_addresses": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"external_access_ip_address": {
Type: pluginsdk.TypeString,
Computed: true,
},

"id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"location": azure.SchemaLocationForDataSource(),

"service_status": {
Type: pluginsdk.TypeString,
Computed: true,
},

"subnet_id": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func dataSourceActiveDirectoryDomainServiceRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).DomainServices.DomainServicesClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

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

resp, err := client.Get(ctx, resourceGroup, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return nil
}
return err
}

if resp.ID == nil {
return fmt.Errorf("reading Domain Service: ID was returned nil")
}
d.SetId(*resp.ID)

d.Set("name", name)
d.Set("resource_group_name", resourceGroup)

if resp.Location == nil {
return fmt.Errorf("reading Domain Service %q: location was returned nil", d.Id())
}
d.Set("location", azure.NormalizeLocation(*resp.Location))

if props := resp.DomainServiceProperties; props != nil {
d.Set("deployment_id", props.DeploymentID)

domainConfigType := ""
if v := props.DomainConfigurationType; v != nil {
domainConfigType = *v
}
d.Set("domain_configuration_type", domainConfigType)

d.Set("domain_name", props.DomainName)

d.Set("filtered_sync_enabled", false)
if props.FilteredSync == aad.FilteredSyncEnabled {
d.Set("filtered_sync_enabled", true)
}

d.Set("sku", props.Sku)
d.Set("sync_owner", props.SyncOwner)
d.Set("tenant_id", props.TenantID)
d.Set("version", props.Version)

if err := d.Set("notifications", flattenDomainServiceNotifications(props.NotificationSettings)); err != nil {
return fmt.Errorf("setting `notifications`: %+v", err)
}

if err := d.Set("secure_ldap", flattenDomainServiceLdaps(d, props.LdapsSettings, true)); err != nil {
return fmt.Errorf("setting `secure_ldap`: %+v", err)
}

if err := d.Set("security", flattenDomainServiceSecurity(props.DomainSecuritySettings)); err != nil {
return fmt.Errorf("setting `security`: %+v", err)
}

replicaSets := flattenDomainServiceReplicaSets(props.ReplicaSets)
if err := d.Set("replica_sets", replicaSets); err != nil {
return fmt.Errorf("setting `replica_sets`: %+v", err)
}
}

return tags.FlattenAndSet(d, resp.Tags)
}
Loading

0 comments on commit 9c4cb52

Please sign in to comment.