diff --git a/internal/services/conditionalaccess/client/client.go b/internal/services/conditionalaccess/client/client.go index fa29ce21ea..f69bb673b1 100644 --- a/internal/services/conditionalaccess/client/client.go +++ b/internal/services/conditionalaccess/client/client.go @@ -4,24 +4,39 @@ package client import ( + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccessnamedlocation" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccesspolicy" "github.com/hashicorp/terraform-provider-azuread/internal/common" - "github.com/manicminer/hamilton/msgraph" ) +// CAUTION! +// The Conditional Access API has compatibility issues between API versions. If you create a policy using the Beta API, +// or even if you update an existing policy using the Beta API that was originally created with the Stable API, that +// policy will be irrevocably mutated and can no longer be updated, or even _read_ using the Stable API. +// For this reason, we are bound to using the Stable API here, as to use the Beta API, even to update a single property +// for a Conditional Access Policy, will break that policy for users. The only way to go back to the Stable API after +// breaking a policy in this way, is to delete and recreate it, which is wholly undesirable for a critical security resource. + type Client struct { - NamedLocationsClient *msgraph.NamedLocationsClient - PoliciesClient *msgraph.ConditionalAccessPoliciesClient + PolicyClient *conditionalaccesspolicy.ConditionalAccessPolicyClient + NamedLocationClient *conditionalaccessnamedlocation.ConditionalAccessNamedLocationClient } -func NewClient(o *common.ClientOptions) *Client { - namedLocationsClient := msgraph.NewNamedLocationsClient() - o.ConfigureClient(&namedLocationsClient.BaseClient) +func NewClient(o *common.ClientOptions) (*Client, error) { + policyClient, err := conditionalaccesspolicy.NewConditionalAccessPolicyClientWithBaseURI(o.Environment.MicrosoftGraph) + if err != nil { + return nil, err + } + o.Configure(policyClient.Client) - policiesClient := msgraph.NewConditionalAccessPoliciesClient() - o.ConfigureClient(&policiesClient.BaseClient) + namedLocationClient, err := conditionalaccessnamedlocation.NewConditionalAccessNamedLocationClientWithBaseURI(o.Environment.MicrosoftGraph) + if err != nil { + return nil, err + } + o.Configure(namedLocationClient.Client) return &Client{ - NamedLocationsClient: namedLocationsClient, - PoliciesClient: policiesClient, - } + PolicyClient: policyClient, + NamedLocationClient: namedLocationClient, + }, nil } diff --git a/internal/services/conditionalaccess/conditional_access_policy_resource.go b/internal/services/conditionalaccess/conditional_access_policy_resource.go index 3f6e90e3a5..22129ab0fb 100644 --- a/internal/services/conditionalaccess/conditional_access_policy_resource.go +++ b/internal/services/conditionalaccess/conditional_access_policy_resource.go @@ -8,18 +8,18 @@ import ( "errors" "fmt" "log" - "net/http" "time" "github.com/hashicorp/go-azure-helpers/lang/pointer" - "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccesspolicy" "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-provider-azuread/internal/clients" - "github.com/hashicorp/terraform-provider-azuread/internal/helpers" - "github.com/hashicorp/terraform-provider-azuread/internal/tf" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/validation" - "github.com/manicminer/hamilton/msgraph" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/consistency" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/validation" ) func conditionalAccessPolicyResource() *pluginsdk.Resource { @@ -47,19 +47,15 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "display_name": { - Type: pluginsdk.TypeString, - Required: true, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "state": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessPolicyStateDisabled, - msgraph.ConditionalAccessPolicyStateEnabled, - msgraph.ConditionalAccessPolicyStateEnabledForReportingButNotEnforced, - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessPolicyState(), false), }, "conditions": { @@ -79,8 +75,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, ExactlyOneOf: []string{"conditions.0.applications.0.included_applications", "conditions.0.applications.0.included_user_actions"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -88,8 +84,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -98,8 +94,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, ExactlyOneOf: []string{"conditions.0.applications.0.included_applications", "conditions.0.applications.0.included_user_actions"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -116,8 +112,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -125,8 +121,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -144,8 +140,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, AtLeastOneOf: []string{"conditions.0.users.0.included_groups", "conditions.0.users.0.included_roles", "conditions.0.users.0.included_users", "conditions.0.users.0.included_guests_or_external_users"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -153,8 +149,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -163,8 +159,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, AtLeastOneOf: []string{"conditions.0.users.0.included_groups", "conditions.0.users.0.included_roles", "conditions.0.users.0.included_users", "conditions.0.users.0.included_guests_or_external_users"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -172,8 +168,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -182,8 +178,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, AtLeastOneOf: []string{"conditions.0.users.0.included_groups", "conditions.0.users.0.included_roles", "conditions.0.users.0.included_users", "conditions.0.users.0.included_guests_or_external_users"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -191,8 +187,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -206,17 +202,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Required: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessGuestOrExternalUserTypeNone, - msgraph.ConditionalAccessGuestOrExternalUserTypeInternalGuest, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bCollaborationGuest, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bCollaborationMember, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bDirectConnectUser, - msgraph.ConditionalAccessGuestOrExternalUserTypeOtherExternalUser, - msgraph.ConditionalAccessGuestOrExternalUserTypeServiceProvider, - msgraph.ConditionalAccessGuestOrExternalUserTypeUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessGuestOrExternalUserTypes(), false), }, }, "external_tenants": { @@ -225,20 +212,16 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "membership_kind": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessExternalTenantsMembershipKindAll, - msgraph.ConditionalAccessExternalTenantsMembershipKindEnumerated, - msgraph.ConditionalAccessExternalTenantsMembershipKindUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessExternalTenantsMembershipKind(), false), }, "members": { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -257,17 +240,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Required: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessGuestOrExternalUserTypeNone, - msgraph.ConditionalAccessGuestOrExternalUserTypeInternalGuest, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bCollaborationGuest, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bCollaborationMember, - msgraph.ConditionalAccessGuestOrExternalUserTypeB2bDirectConnectUser, - msgraph.ConditionalAccessGuestOrExternalUserTypeOtherExternalUser, - msgraph.ConditionalAccessGuestOrExternalUserTypeServiceProvider, - msgraph.ConditionalAccessGuestOrExternalUserTypeUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessGuestOrExternalUserTypes(), false), }, }, "external_tenants": { @@ -276,20 +250,16 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "membership_kind": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessExternalTenantsMembershipKindAll, - msgraph.ConditionalAccessExternalTenantsMembershipKindEnumerated, - msgraph.ConditionalAccessExternalTenantsMembershipKindUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessExternalTenantsMembershipKind(), false), }, "members": { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -306,15 +276,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Required: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessClientAppTypeAll, - msgraph.ConditionalAccessClientAppTypeBrowser, - msgraph.ConditionalAccessClientAppTypeEasSupported, - msgraph.ConditionalAccessClientAppTypeExchangeActiveSync, - msgraph.ConditionalAccessClientAppTypeMobileAppsAndDesktopClients, - msgraph.ConditionalAccessClientAppTypeOther, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessClientApp(), false), }, }, @@ -331,18 +294,15 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "mode": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessFilterModeExclude, - msgraph.ConditionalAccessFilterModeInclude, - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForFilterMode(), false), }, "rule": { - Type: pluginsdk.TypeString, - Required: true, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -361,8 +321,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Required: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -370,8 +330,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -388,17 +348,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Required: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessDevicePlatformAll, - msgraph.ConditionalAccessDevicePlatformAndroid, - msgraph.ConditionalAccessDevicePlatformIos, - msgraph.ConditionalAccessDevicePlatformLinux, - msgraph.ConditionalAccessDevicePlatformMacOs, - msgraph.ConditionalAccessDevicePlatformUnknownFutureValue, - msgraph.ConditionalAccessDevicePlatformWindows, - msgraph.ConditionalAccessDevicePlatformWindowsPhone, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessDevicePlatform(), false), }, }, @@ -406,17 +357,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessDevicePlatformAll, - msgraph.ConditionalAccessDevicePlatformAndroid, - msgraph.ConditionalAccessDevicePlatformIos, - msgraph.ConditionalAccessDevicePlatformLinux, - msgraph.ConditionalAccessDevicePlatformMacOs, - msgraph.ConditionalAccessDevicePlatformUnknownFutureValue, - msgraph.ConditionalAccessDevicePlatformWindows, - msgraph.ConditionalAccessDevicePlatformWindowsPhone, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessDevicePlatform(), false), }, }, }, @@ -427,14 +369,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessRiskLevelHigh, - msgraph.ConditionalAccessRiskLevelLow, - msgraph.ConditionalAccessRiskLevelMedium, - msgraph.ConditionalAccessRiskLevelNone, - msgraph.ConditionalAccessRiskLevelUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForRiskLevel(), false), }, }, @@ -442,15 +378,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessRiskLevelHidden, - msgraph.ConditionalAccessRiskLevelHigh, - msgraph.ConditionalAccessRiskLevelLow, - msgraph.ConditionalAccessRiskLevelMedium, - msgraph.ConditionalAccessRiskLevelNone, - msgraph.ConditionalAccessRiskLevelUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForRiskLevel(), false), }, }, @@ -458,15 +387,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessRiskLevelHidden, - msgraph.ConditionalAccessRiskLevelHigh, - msgraph.ConditionalAccessRiskLevelLow, - msgraph.ConditionalAccessRiskLevelMedium, - msgraph.ConditionalAccessRiskLevelNone, - msgraph.ConditionalAccessRiskLevelUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForRiskLevel(), false), }, }, }, @@ -491,17 +413,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, AtLeastOneOf: []string{"grant_controls.0.built_in_controls", "grant_controls.0.authentication_strength_policy_id", "grant_controls.0.terms_of_use"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessGrantControlApprovedApplication, - msgraph.ConditionalAccessGrantControlBlock, - msgraph.ConditionalAccessGrantControlCompliantApplication, - msgraph.ConditionalAccessGrantControlCompliantDevice, - msgraph.ConditionalAccessGrantControlDomainJoinedDevice, - msgraph.ConditionalAccessGrantControlMfa, - msgraph.ConditionalAccessGrantControlPasswordChange, - msgraph.ConditionalAccessGrantControlUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForConditionalAccessGrantControl(), false), }, }, @@ -516,8 +429,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -526,8 +439,8 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { Optional: true, AtLeastOneOf: []string{"grant_controls.0.built_in_controls", "grant_controls.0.authentication_strength_policy_id", "grant_controls.0.terms_of_use"}, Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -535,10 +448,11 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { }, "session_controls": { - Type: pluginsdk.TypeList, - Optional: true, - AtLeastOneOf: []string{"grant_controls", "session_controls"}, - MaxItems: 1, + Type: pluginsdk.TypeList, + Optional: true, + AtLeastOneOf: []string{"grant_controls", "session_controls"}, + MaxItems: 1, + //ConfigMode: pluginsdk.SchemaConfigModeAttr, DiffSuppressFunc: conditionalAccessPolicyDiffSuppress, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ @@ -548,14 +462,9 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { }, "cloud_app_security_policy": { - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessCloudAppSecuritySessionControlTypeBlockDownloads, - msgraph.ConditionalAccessCloudAppSecuritySessionControlTypeMcasConfigured, - msgraph.ConditionalAccessCloudAppSecuritySessionControlTypeMonitorOnly, - msgraph.ConditionalAccessCloudAppSecuritySessionControlTypeUnknownFutureValue, - }, false), + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForCloudAppSecuritySessionControlType(), false), }, "disable_resilience_defaults": { @@ -564,12 +473,9 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { }, "persistent_browser_mode": { - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.PersistentBrowserSessionModeAlways, - msgraph.PersistentBrowserSessionModeNever, - }, false), + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForPersistentBrowserSessionMode(), false), }, "sign_in_frequency": { @@ -580,33 +486,24 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { }, "sign_in_frequency_authentication_type": { - Type: pluginsdk.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessAuthenticationTypePrimaryAndSecondaryAuthentication, - msgraph.ConditionalAccessAuthenticationTypeSecondaryAuthentication, - }, false), + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForSignInFrequencyAuthenticationType(), false), }, "sign_in_frequency_interval": { - Type: pluginsdk.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessFrequencyIntervalTimeBased, - msgraph.ConditionalAccessFrequencyIntervalEveryTime, - }, false), + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForSignInFrequencyInterval(), false), }, "sign_in_frequency_period": { Type: pluginsdk.TypeString, Optional: true, RequiredWith: []string{"session_controls.0.sign_in_frequency"}, - ValidateFunc: validation.StringInSlice([]string{ - msgraph.ConditionalAccessFrequencyTypeDays, - msgraph.ConditionalAccessFrequencyTypeHours, - }, false), + ValidateFunc: validation.StringInSlice(stable.PossibleValuesForSigninFrequencyType(), false), }, }, }, @@ -618,13 +515,13 @@ func conditionalAccessPolicyResource() *pluginsdk.Resource { func conditionalAccessPolicyCustomizeDiff(_ context.Context, diff *pluginsdk.ResourceDiff, _ interface{}) error { // The API does not like sessionControls being set with ineffectual properties, so this additional validation complements // AtLeastOneOf: []string{"grant_controls", "session_controls"} by helping to ensure that either `grant_controls` or a - // useful `session_controls` block has been set in the configuration. + // _useful_ `session_controls` block has been set in the configuration. var sessionControlsSetButIneffective bool if diff.Get("session_controls.#").(int) == 1 && !diff.Get("session_controls.0.application_enforced_restrictions_enabled").(bool) && diff.Get("session_controls.0.cloud_app_security_policy").(string) == "" && !diff.Get("session_controls.0.disable_resilience_defaults").(bool) && diff.Get("session_controls.0.persistent_browser_mode").(string) == "" && diff.Get("session_controls.0.sign_in_frequency").(int) == 0 && - diff.Get("session_controls.0.sign_in_frequency_authentication_type").(string) == msgraph.ConditionalAccessAuthenticationTypePrimaryAndSecondaryAuthentication && - diff.Get("session_controls.0.sign_in_frequency_interval").(string) == msgraph.ConditionalAccessFrequencyIntervalTimeBased { + diff.Get("session_controls.0.sign_in_frequency_authentication_type").(string) == string(stable.SignInFrequencyAuthenticationType_PrimaryAndSecondaryAuthentication) && + diff.Get("session_controls.0.sign_in_frequency_interval").(string) == string(stable.SignInFrequencyInterval_TimeBased) { sessionControlsSetButIneffective = true } if diff.Get("grant_controls.#").(int) == 0 && sessionControlsSetButIneffective { @@ -677,11 +574,11 @@ func conditionalAccessPolicyDiffSuppress(k, old, new string, d *pluginsdk.Resour } func conditionalAccessPolicyResourceCreate(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.PoliciesClient + client := meta.(*clients.Client).ConditionalAccess.PolicyClient - properties := msgraph.ConditionalAccessPolicy{ + properties := stable.ConditionalAccessPolicy{ DisplayName: pointer.To(d.Get("display_name").(string)), - State: pointer.To(d.Get("state").(string)), + State: pointer.To(stable.ConditionalAccessPolicyState(d.Get("state").(string))), Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})), } @@ -693,27 +590,32 @@ func conditionalAccessPolicyResourceCreate(ctx context.Context, d *pluginsdk.Res properties.SessionControls = expandConditionalAccessSessionControls(v.([]interface{})) } - policy, _, err := client.Create(ctx, properties) + resp, err := client.CreateConditionalAccessPolicy(ctx, properties, conditionalaccesspolicy.DefaultCreateConditionalAccessPolicyOperationOptions()) if err != nil { return tf.ErrorDiagF(err, "Could not create conditional access policy") } - if policy.ID == nil || *policy.ID == "" { + policy := resp.Model + if policy == nil { + return tf.ErrorDiagF(errors.New("model was nil"), "Could not create conditional access policy") + } + + if policy.Id == nil || *policy.Id == "" { return tf.ErrorDiagF(errors.New("Bad API response"), "Object ID returned for conditional access policy is nil/empty") } - d.SetId(*policy.ID) + d.SetId(*policy.Id) return conditionalAccessPolicyResourceRead(ctx, d, meta) } func conditionalAccessPolicyResourceUpdate(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.PoliciesClient + client := meta.(*clients.Client).ConditionalAccess.PolicyClient + id := stable.NewIdentityConditionalAccessPolicyID(d.Id()) - properties := msgraph.ConditionalAccessPolicy{ - ID: pointer.To(d.Id()), + properties := stable.ConditionalAccessPolicy{ DisplayName: pointer.To(d.Get("display_name").(string)), - State: pointer.To(d.Get("state").(string)), + State: pointer.To(stable.ConditionalAccessPolicyState(d.Get("state").(string))), Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})), } @@ -725,7 +627,7 @@ func conditionalAccessPolicyResourceUpdate(ctx context.Context, d *pluginsdk.Res properties.SessionControls = expandConditionalAccessSessionControls(v.([]interface{})) } - if _, err := client.Update(ctx, properties); err != nil { + if _, err := client.UpdateConditionalAccessPolicy(ctx, id, properties, conditionalaccesspolicy.DefaultUpdateConditionalAccessPolicyOperationOptions()); err != nil { return tf.ErrorDiagF(err, "Could not update conditional access policy with ID: %q", d.Id()) } @@ -740,19 +642,19 @@ func conditionalAccessPolicyResourceUpdate(ctx context.Context, d *pluginsdk.Res MinTimeout: 5 * time.Second, ContinuousTargetOccurence: 5, Refresh: func() (interface{}, string, error) { - client.BaseClient.DisableRetries = true - policy, _, err := client.Get(ctx, d.Id(), odata.Query{}) + resp, err := client.GetConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultGetConditionalAccessPolicyOperationOptions()) if err != nil { return nil, "Error", err } + policy := resp.Model if policy == nil { return "stub", "Pending", nil } if policy.DisplayName == nil || *policy.DisplayName != d.Get("display_name").(string) { return "stub", "Pending", nil } - if policy.State == nil || *policy.State != d.Get("state").(string) { + if policy.State == nil || *policy.State != stable.ConditionalAccessPolicyState(d.Get("state").(string)) { return "stub", "Pending", nil } @@ -767,21 +669,27 @@ func conditionalAccessPolicyResourceUpdate(ctx context.Context, d *pluginsdk.Res } func conditionalAccessPolicyResourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.PoliciesClient + client := meta.(*clients.Client).ConditionalAccess.PolicyClient + id := stable.NewIdentityConditionalAccessPolicyID(d.Id()) - policy, status, err := client.Get(ctx, d.Id(), odata.Query{}) + resp, err := client.GetConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultGetConditionalAccessPolicyOperationOptions()) if err != nil { - if status == http.StatusNotFound { - log.Printf("[DEBUG] Conditional Access Policy with Object ID %q was not found - removing from state", d.Id()) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s not found - removing from state", id) d.SetId("") return nil } - return tf.ErrorDiagPathF(err, "id", "Retrieving Conditional Access Policy with object ID %q", d.Id()) + return tf.ErrorDiagPathF(err, "id", "retrieving %s", id) } - tf.Set(d, "display_name", policy.DisplayName) - tf.Set(d, "state", policy.State) + policy := resp.Model + if policy == nil { + return tf.ErrorDiagF(errors.New("model was nil"), "retrieving %s", id) + } + + tf.Set(d, "display_name", pointer.From(policy.DisplayName)) + tf.Set(d, "state", pointer.From(policy.State)) tf.Set(d, "conditions", flattenConditionalAccessConditionSet(policy.Conditions)) tf.Set(d, "grant_controls", flattenConditionalAccessGrantControls(policy.GrantControls)) tf.Set(d, "session_controls", flattenConditionalAccessSessionControls(policy.SessionControls)) @@ -790,36 +698,33 @@ func conditionalAccessPolicyResourceRead(ctx context.Context, d *pluginsdk.Resou } func conditionalAccessPolicyResourceDelete(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.PoliciesClient - policyId := d.Id() + client := meta.(*clients.Client).ConditionalAccess.PolicyClient + id := stable.NewIdentityConditionalAccessPolicyID(d.Id()) - _, status, err := client.Get(ctx, policyId, odata.Query{}) + resp, err := client.GetConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultGetConditionalAccessPolicyOperationOptions()) if err != nil { - if status == http.StatusNotFound { - log.Printf("[DEBUG] Conditional Access Policy with ID %q already deleted", policyId) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s already deleted", id) return nil } - return tf.ErrorDiagPathF(err, "id", "Retrieving conditional access policy with ID %q", policyId) + return tf.ErrorDiagPathF(err, "id", "retrieving %s", id) } - status, err = client.Delete(ctx, policyId) - if err != nil { - return tf.ErrorDiagPathF(err, "id", "Deleting conditional access policy with ID %q, got status %d", policyId, status) + if _, err = client.DeleteConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultDeleteConditionalAccessPolicyOperationOptions()); err != nil { + return tf.ErrorDiagPathF(err, "id", "Deleting %s", id) } - if err := helpers.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) { - defer func() { client.BaseClient.DisableRetries = false }() - client.BaseClient.DisableRetries = true - if _, status, err := client.Get(ctx, policyId, odata.Query{}); err != nil { - if status == http.StatusNotFound { + if err := consistency.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) { + if resp, err := client.GetConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultGetConditionalAccessPolicyOperationOptions()); err != nil { + if response.WasNotFound(resp.HttpResponse) { return pointer.To(false), nil } return nil, err } return pointer.To(true), nil }); err != nil { - return tf.ErrorDiagF(err, "Waiting for deletion of conditional access policy with ID %q", policyId) + return tf.ErrorDiagF(err, "Waiting for deletion of %s", id) } return nil diff --git a/internal/services/conditionalaccess/conditional_access_policy_resource_test.go b/internal/services/conditionalaccess/conditional_access_policy_resource_test.go index 15f9bf2cc2..787da4e283 100644 --- a/internal/services/conditionalaccess/conditional_access_policy_resource_test.go +++ b/internal/services/conditionalaccess/conditional_access_policy_resource_test.go @@ -6,15 +6,16 @@ package conditionalaccess_test import ( "context" "fmt" - "net/http" "testing" "github.com/hashicorp/go-azure-helpers/lang/pointer" - "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccesspolicy" "github.com/hashicorp/terraform-provider-azuread/internal/acceptance" "github.com/hashicorp/terraform-provider-azuread/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azuread/internal/clients" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk" ) type ConditionalAccessPolicyResource struct{} @@ -332,23 +333,17 @@ func TestAccConditionalAccessPolicy_guestsOrExternalUsers(t *testing.T) { } func (r ConditionalAccessPolicyResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - clients.ConditionalAccess.PoliciesClient.BaseClient.DisableRetries = true - defer func() { - clients.ConditionalAccess.PoliciesClient.BaseClient.DisableRetries = false - }() + id := stable.NewIdentityConditionalAccessPolicyID(state.ID) - var id *string - - app, status, err := clients.ConditionalAccess.PoliciesClient.Get(ctx, state.ID, odata.Query{}) + resp, err := clients.ConditionalAccess.PolicyClient.GetConditionalAccessPolicy(ctx, id, conditionalaccesspolicy.DefaultGetConditionalAccessPolicyOperationOptions()) if err != nil { - if status == http.StatusNotFound { - return nil, fmt.Errorf("Conditional Access Policy with ID %q does not exist", state.ID) + if response.WasNotFound(resp.HttpResponse) { + return pointer.To(false), nil } - return nil, fmt.Errorf("failed to retrieve Conditional Access Policy with ID %q: %+v", state.ID, err) + return nil, fmt.Errorf("failed to retrieve %s: %v", id, err) } - id = app.ID - return pointer.To(id != nil && *id == state.ID), nil + return pointer.To(true), nil } func (ConditionalAccessPolicyResource) basic(data acceptance.TestData) string { @@ -511,6 +506,8 @@ resource "azuread_conditional_access_policy" "test" { cloud_app_security_policy = "monitorOnly" persistent_browser_mode = "never" sign_in_frequency = 10 + sign_in_frequency_authentication_type = "primaryAndSecondaryAuthentication" + sign_in_frequency_interval = "timeBased" sign_in_frequency_period = "hours" } } @@ -550,10 +547,6 @@ resource "azuread_conditional_access_policy" "test" { operator = "OR" built_in_controls = ["block"] } - - session_controls { - application_enforced_restrictions_enabled = false - } } `, data.RandomInteger) } diff --git a/internal/services/conditionalaccess/conditionalaccess.go b/internal/services/conditionalaccess/conditionalaccess.go index ba082f509c..2b3adcf0fb 100644 --- a/internal/services/conditionalaccess/conditionalaccess.go +++ b/internal/services/conditionalaccess/conditionalaccess.go @@ -4,37 +4,56 @@ package conditionalaccess import ( + "strings" + "github.com/hashicorp/go-azure-helpers/lang/pointer" - "github.com/hashicorp/terraform-provider-azuread/internal/tf" - "github.com/manicminer/hamilton/msgraph" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/sdk/nullable" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf" ) -func flattenConditionalAccessConditionSet(in *msgraph.ConditionalAccessConditionSet) []interface{} { +func flattenConditionalAccessConditionSet(in *stable.ConditionalAccessConditionSet) []interface{} { if in == nil { return []interface{}{} } + clientAppTypes := make([]string, 0) + for _, v := range in.ClientAppTypes { + clientAppTypes = append(clientAppTypes, string(v)) + } + + servicePrincipalRiskLevels := make([]string, 0) + for _, v := range pointer.From(in.ServicePrincipalRiskLevels) { + servicePrincipalRiskLevels = append(servicePrincipalRiskLevels, string(v)) + } + + signInRiskLevels := make([]string, 0) + for _, v := range in.SignInRiskLevels { + signInRiskLevels = append(signInRiskLevels, string(v)) + } + + userRiskLevels := make([]string, 0) + for _, v := range in.UserRiskLevels { + userRiskLevels = append(userRiskLevels, string(v)) + } + return []interface{}{ map[string]interface{}{ "applications": flattenConditionalAccessApplications(in.Applications), "client_applications": flattenConditionalAccessClientApplications(in.ClientApplications), "users": flattenConditionalAccessUsers(in.Users), - "client_app_types": tf.FlattenStringSlicePtr(in.ClientAppTypes), + "client_app_types": clientAppTypes, "devices": flattenConditionalAccessDevices(in.Devices), "locations": flattenConditionalAccessLocations(in.Locations), "platforms": flattenConditionalAccessPlatforms(in.Platforms), - "service_principal_risk_levels": tf.FlattenStringSlicePtr(in.ServicePrincipalRiskLevels), - "sign_in_risk_levels": tf.FlattenStringSlicePtr(in.SignInRiskLevels), - "user_risk_levels": tf.FlattenStringSlicePtr(in.UserRiskLevels), + "service_principal_risk_levels": servicePrincipalRiskLevels, + "sign_in_risk_levels": signInRiskLevels, + "user_risk_levels": userRiskLevels, }, } } -func flattenConditionalAccessApplications(in *msgraph.ConditionalAccessApplications) []interface{} { - if in == nil { - return []interface{}{} - } - +func flattenConditionalAccessApplications(in stable.ConditionalAccessApplications) []interface{} { return []interface{}{ map[string]interface{}{ "included_applications": tf.FlattenStringSlicePtr(in.IncludeApplications), @@ -44,7 +63,7 @@ func flattenConditionalAccessApplications(in *msgraph.ConditionalAccessApplicati } } -func flattenConditionalAccessClientApplications(in *msgraph.ConditionalAccessClientApplications) []interface{} { +func flattenConditionalAccessClientApplications(in *stable.ConditionalAccessClientApplications) []interface{} { if in == nil { return []interface{}{} } @@ -57,7 +76,7 @@ func flattenConditionalAccessClientApplications(in *msgraph.ConditionalAccessCli } } -func flattenConditionalAccessUsers(in *msgraph.ConditionalAccessUsers) []interface{} { +func flattenConditionalAccessUsers(in *stable.ConditionalAccessUsers) []interface{} { if in == nil { return []interface{}{} } @@ -76,7 +95,7 @@ func flattenConditionalAccessUsers(in *msgraph.ConditionalAccessUsers) []interfa } } -func flattenConditionalAccessDevices(in *msgraph.ConditionalAccessDevices) []interface{} { +func flattenConditionalAccessDevices(in *stable.ConditionalAccessDevices) []interface{} { if in == nil { return []interface{}{} } @@ -88,7 +107,7 @@ func flattenConditionalAccessDevices(in *msgraph.ConditionalAccessDevices) []int } } -func flattenConditionalAccessLocations(in *msgraph.ConditionalAccessLocations) []interface{} { +func flattenConditionalAccessLocations(in *stable.ConditionalAccessLocations) []interface{} { if in == nil { return []interface{}{} } @@ -101,33 +120,48 @@ func flattenConditionalAccessLocations(in *msgraph.ConditionalAccessLocations) [ } } -func flattenConditionalAccessPlatforms(in *msgraph.ConditionalAccessPlatforms) []interface{} { +func flattenConditionalAccessPlatforms(in *stable.ConditionalAccessPlatforms) []interface{} { if in == nil { return []interface{}{} } + includePlatforms := make([]string, 0) + for _, v := range pointer.From(in.IncludePlatforms) { + includePlatforms = append(includePlatforms, string(v)) + } + + excludePlatforms := make([]string, 0) + for _, v := range pointer.From(in.ExcludePlatforms) { + excludePlatforms = append(excludePlatforms, string(v)) + } + return []interface{}{ map[string]interface{}{ - "included_platforms": tf.FlattenStringSlicePtr(in.IncludePlatforms), - "excluded_platforms": tf.FlattenStringSlicePtr(in.ExcludePlatforms), + "included_platforms": includePlatforms, + "excluded_platforms": excludePlatforms, }, } } -func flattenConditionalAccessGrantControls(in *msgraph.ConditionalAccessGrantControls) []interface{} { +func flattenConditionalAccessGrantControls(in *stable.ConditionalAccessGrantControls) []interface{} { if in == nil { return []interface{}{} } var authenticationStrengthPolicyId string if in.AuthenticationStrength != nil { - authenticationStrengthPolicyId = pointer.From(in.AuthenticationStrength.ID) + authenticationStrengthPolicyId = pointer.From(in.AuthenticationStrength.Id) + } + + builtInControls := make([]string, 0) + for _, v := range pointer.From(in.BuiltInControls) { + builtInControls = append(builtInControls, string(v)) } return []interface{}{ map[string]interface{}{ - "operator": in.Operator, - "built_in_controls": tf.FlattenStringSlicePtr(in.BuiltInControls), + "operator": in.Operator.GetOrZero(), + "built_in_controls": builtInControls, "authentication_strength_policy_id": authenticationStrengthPolicyId, "custom_authentication_factors": tf.FlattenStringSlicePtr(in.CustomAuthenticationFactors), "terms_of_use": tf.FlattenStringSlicePtr(in.TermsOfUse), @@ -135,24 +169,24 @@ func flattenConditionalAccessGrantControls(in *msgraph.ConditionalAccessGrantCon } } -func flattenConditionalAccessSessionControls(in *msgraph.ConditionalAccessSessionControls) []interface{} { +func flattenConditionalAccessSessionControls(in *stable.ConditionalAccessSessionControls) []interface{} { if in == nil { return []interface{}{} } applicationEnforceRestrictions := false if in.ApplicationEnforcedRestrictions != nil { - applicationEnforceRestrictions = pointer.From(in.ApplicationEnforcedRestrictions.IsEnabled) + applicationEnforceRestrictions = in.ApplicationEnforcedRestrictions.IsEnabled.GetOrZero() } cloudAppSecurity := "" if in.CloudAppSecurity != nil { - cloudAppSecurity = pointer.From(in.CloudAppSecurity.CloudAppSecurityType) + cloudAppSecurity = string(pointer.From(in.CloudAppSecurity.CloudAppSecurityType)) } disableResilienceDefaults := false if in.DisableResilienceDefaults != nil { - disableResilienceDefaults = *in.DisableResilienceDefaults + disableResilienceDefaults = in.DisableResilienceDefaults.GetOrZero() } signInFrequency := 0 @@ -160,18 +194,18 @@ func flattenConditionalAccessSessionControls(in *msgraph.ConditionalAccessSessio signInFrequencyInterval := "" signInFrequencyPeriod := "" if in.SignInFrequency != nil { - if in.SignInFrequency.Value != nil && in.SignInFrequency.Type != nil { - signInFrequency = int(*in.SignInFrequency.Value) - signInFrequencyPeriod = *in.SignInFrequency.Type + if !in.SignInFrequency.Value.IsNull() && in.SignInFrequency.Type != nil { + signInFrequency = int(in.SignInFrequency.Value.GetOrZero()) + signInFrequencyPeriod = string(*in.SignInFrequency.Type) } - signInFrequencyAuthenticationType = pointer.From(in.SignInFrequency.AuthenticationType) - signInFrequencyInterval = pointer.From(in.SignInFrequency.FrequencyInterval) + signInFrequencyAuthenticationType = string(pointer.From(in.SignInFrequency.AuthenticationType)) + signInFrequencyInterval = string(pointer.From(in.SignInFrequency.FrequencyInterval)) } persistentBrowserMode := "" if in.PersistentBrowser != nil { - persistentBrowserMode = pointer.From(in.PersistentBrowser.Mode) + persistentBrowserMode = string(pointer.From(in.PersistentBrowser.Mode)) } return []interface{}{ @@ -188,7 +222,7 @@ func flattenConditionalAccessSessionControls(in *msgraph.ConditionalAccessSessio } } -func flattenConditionalAccessDeviceFilter(in *msgraph.ConditionalAccessFilter) []interface{} { +func flattenConditionalAccessDeviceFilter(in *stable.ConditionalAccessFilter) []interface{} { if in == nil { return []interface{}{} } @@ -201,33 +235,40 @@ func flattenConditionalAccessDeviceFilter(in *msgraph.ConditionalAccessFilter) [ } } -func flattenGuestsOrExternalUsers(in *msgraph.ConditionalAccessGuestsOrExternalUsers) []interface{} { +func flattenGuestsOrExternalUsers(in *stable.ConditionalAccessGuestsOrExternalUsers) []interface{} { if in == nil { return []interface{}{} } + guestOrExternalUserTypes := make([]string, 0) + for _, v := range strings.Split(string(pointer.From(in.GuestOrExternalUserTypes)), ",") { + guestOrExternalUserTypes = append(guestOrExternalUserTypes, strings.TrimSpace(v)) + } + return []interface{}{ map[string]interface{}{ - "guest_or_external_user_types": tf.FlattenStringSlicePtr(in.GuestOrExternalUserTypes), + "guest_or_external_user_types": guestOrExternalUserTypes, "external_tenants": flattenExternalTenants(in.ExternalTenants), }, } } -func flattenExternalTenants(in *msgraph.ConditionalAccessExternalTenants) []interface{} { +func flattenExternalTenants(in stable.ConditionalAccessExternalTenants) []interface{} { if in == nil { return []interface{}{} } + externalTenants := in.ConditionalAccessExternalTenants() + return []interface{}{ map[string]interface{}{ - "membership_kind": in.MembershipKind, - "members": tf.FlattenStringSlicePtr(in.Members), + "membership_kind": externalTenants.MembershipKind, + "members": tf.FlattenStringSlicePtr(externalTenants.Members), }, } } -func flattenCountryNamedLocation(in *msgraph.CountryNamedLocation) []interface{} { +func flattenCountryNamedLocation(in *stable.CountryNamedLocation) []interface{} { if in == nil { return []interface{}{} } @@ -239,13 +280,13 @@ func flattenCountryNamedLocation(in *msgraph.CountryNamedLocation) []interface{} return []interface{}{ map[string]interface{}{ - "countries_and_regions": tf.FlattenStringSlicePtr(in.CountriesAndRegions), + "countries_and_regions": tf.FlattenStringSlice(in.CountriesAndRegions), "include_unknown_countries_and_regions": includeUnknown, }, } } -func flattenIPNamedLocation(in *msgraph.IPNamedLocation) []interface{} { +func flattenIPNamedLocation(in *stable.IPNamedLocation) []interface{} { if in == nil { return []interface{}{} } @@ -263,60 +304,83 @@ func flattenIPNamedLocation(in *msgraph.IPNamedLocation) []interface{} { } } -func flattenIPNamedLocationIPRange(in *[]msgraph.IPNamedLocationIPRange) []interface{} { - if in == nil || len(*in) == 0 { +func flattenIPNamedLocationIPRange(in []stable.IPRange) []interface{} { + if len(in) == 0 { return []interface{}{} } result := make([]string, 0) - for _, cidr := range *in { - if cidr.CIDRAddress != nil { - result = append(result, *cidr.CIDRAddress) + for _, i := range in { + switch model := i.(type) { + case stable.IPv4CIDRRange: + if model.CIDRAddress != nil { + result = append(result, *model.CIDRAddress) + } + case stable.IPv6CIDRRange: + if model.CIDRAddress != nil { + result = append(result, *model.CIDRAddress) + } } } return tf.FlattenStringSlice(result) } -func expandConditionalAccessConditionSet(in []interface{}) *msgraph.ConditionalAccessConditionSet { +func expandConditionalAccessConditionSet(in []interface{}) *stable.ConditionalAccessConditionSet { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessConditionSet{} + result := stable.ConditionalAccessConditionSet{} config := in[0].(map[string]interface{}) applications := config["applications"].([]interface{}) - users := config["users"].([]interface{}) - clientAppTypes := config["client_app_types"].([]interface{}) + clientApplications := config["client_applications"].([]interface{}) devices := config["devices"].([]interface{}) locations := config["locations"].([]interface{}) platforms := config["platforms"].([]interface{}) - servicePrincipalRiskLevels := config["service_principal_risk_levels"].([]interface{}) - signInRiskLevels := config["sign_in_risk_levels"].([]interface{}) - userRiskLevels := config["user_risk_levels"].([]interface{}) - clientApplications := config["client_applications"].([]interface{}) + users := config["users"].([]interface{}) + + clientAppTypes := make([]stable.ConditionalAccessClientApp, 0) + for _, elem := range config["client_app_types"].([]interface{}) { + clientAppTypes = append(clientAppTypes, stable.ConditionalAccessClientApp(elem.(string))) + } + + servicePrincipalRiskLevels := make([]stable.RiskLevel, 0) + for _, elem := range config["service_principal_risk_levels"].([]interface{}) { + servicePrincipalRiskLevels = append(servicePrincipalRiskLevels, stable.RiskLevel(elem.(string))) + } + + signInRiskLevels := make([]stable.RiskLevel, 0) + for _, elem := range config["sign_in_risk_levels"].([]interface{}) { + signInRiskLevels = append(signInRiskLevels, stable.RiskLevel(elem.(string))) + } + + userRiskLevels := make([]stable.RiskLevel, 0) + for _, elem := range config["user_risk_levels"].([]interface{}) { + userRiskLevels = append(userRiskLevels, stable.RiskLevel(elem.(string))) + } result.Applications = expandConditionalAccessApplications(applications) - result.Users = expandConditionalAccessUsers(users) - result.ClientAppTypes = tf.ExpandStringSlicePtr(clientAppTypes) + result.ClientAppTypes = clientAppTypes + result.ClientApplications = expandConditionalAccessClientApplications(clientApplications) result.Devices = expandConditionalAccessDevices(devices) result.Locations = expandConditionalAccessLocations(locations) result.Platforms = expandConditionalAccessPlatforms(platforms) - result.ServicePrincipalRiskLevels = tf.ExpandStringSlicePtr(servicePrincipalRiskLevels) - result.SignInRiskLevels = tf.ExpandStringSlicePtr(signInRiskLevels) - result.UserRiskLevels = tf.ExpandStringSlicePtr(userRiskLevels) - result.ClientApplications = expandConditionalAccessClientApplications(clientApplications) + result.ServicePrincipalRiskLevels = &servicePrincipalRiskLevels + result.SignInRiskLevels = signInRiskLevels + result.UserRiskLevels = userRiskLevels + result.Users = expandConditionalAccessUsers(users) return &result } -func expandConditionalAccessClientApplications(in []interface{}) *msgraph.ConditionalAccessClientApplications { +func expandConditionalAccessClientApplications(in []interface{}) *stable.ConditionalAccessClientApplications { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessClientApplications{} + result := stable.ConditionalAccessClientApplications{} config := in[0].(map[string]interface{}) includeServicePrincipals := config["included_service_principals"].([]interface{}) @@ -328,12 +392,8 @@ func expandConditionalAccessClientApplications(in []interface{}) *msgraph.Condit return &result } -func expandConditionalAccessApplications(in []interface{}) *msgraph.ConditionalAccessApplications { - if len(in) == 0 || in[0] == nil { - return nil - } - - result := msgraph.ConditionalAccessApplications{} +func expandConditionalAccessApplications(in []interface{}) stable.ConditionalAccessApplications { + result := stable.ConditionalAccessApplications{} config := in[0].(map[string]interface{}) includeApplications := config["included_applications"].([]interface{}) @@ -344,15 +404,15 @@ func expandConditionalAccessApplications(in []interface{}) *msgraph.ConditionalA result.ExcludeApplications = tf.ExpandStringSlicePtr(excludeApplications) result.IncludeUserActions = tf.ExpandStringSlicePtr(includeUserActions) - return &result + return result } -func expandConditionalAccessUsers(in []interface{}) *msgraph.ConditionalAccessUsers { +func expandConditionalAccessUsers(in []interface{}) *stable.ConditionalAccessUsers { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessUsers{} + result := stable.ConditionalAccessUsers{} config := in[0].(map[string]interface{}) includeUsers := config["included_users"].([]interface{}) @@ -375,91 +435,92 @@ func expandConditionalAccessUsers(in []interface{}) *msgraph.ConditionalAccessUs return &result } -func expandConditionalAccessPlatforms(in []interface{}) *msgraph.ConditionalAccessPlatforms { - result := msgraph.ConditionalAccessPlatforms{} +func expandConditionalAccessDevices(in []interface{}) *stable.ConditionalAccessDevices { if len(in) == 0 || in[0] == nil { return nil } + result := stable.ConditionalAccessDevices{} config := in[0].(map[string]interface{}) - includePlatforms := config["included_platforms"].([]interface{}) - excludePlatforms := config["excluded_platforms"].([]interface{}) - - result.IncludePlatforms = tf.ExpandStringSlicePtr(includePlatforms) - result.ExcludePlatforms = tf.ExpandStringSlicePtr(excludePlatforms) + deviceFilter := config["filter"].([]interface{}) + if len(deviceFilter) > 0 { + result.DeviceFilter = expandConditionalAccessFilter(deviceFilter) + } return &result } -func expandConditionalAccessDevices(in []interface{}) *msgraph.ConditionalAccessDevices { - result := msgraph.ConditionalAccessDevices{} - +func expandConditionalAccessLocations(in []interface{}) *stable.ConditionalAccessLocations { if len(in) == 0 || in[0] == nil { - // The devices field cannot be empty on POST, and is currently totally ignored when empty on PATCH, - // so for now we'll just return nil here and revisit later. return nil } + result := stable.ConditionalAccessLocations{} config := in[0].(map[string]interface{}) - deviceFilter := config["filter"].([]interface{}) + includeLocations := config["included_locations"].([]interface{}) + excludeLocations := config["excluded_locations"].([]interface{}) - if len(deviceFilter) > 0 { - result.DeviceFilter = expandConditionalAccessFilter(deviceFilter) - } + result.IncludeLocations = tf.ExpandStringSlicePtr(includeLocations) + result.ExcludeLocations = tf.ExpandStringSlicePtr(excludeLocations) return &result } -func expandConditionalAccessLocations(in []interface{}) *msgraph.ConditionalAccessLocations { +func expandConditionalAccessPlatforms(in []interface{}) *stable.ConditionalAccessPlatforms { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessLocations{} + result := stable.ConditionalAccessPlatforms{} config := in[0].(map[string]interface{}) - includeLocations := config["included_locations"].([]interface{}) - excludeLocations := config["excluded_locations"].([]interface{}) + includePlatforms := make([]stable.ConditionalAccessDevicePlatform, 0) + for _, elem := range config["included_platforms"].([]interface{}) { + includePlatforms = append(includePlatforms, stable.ConditionalAccessDevicePlatform(elem.(string))) + } - result.IncludeLocations = tf.ExpandStringSlicePtr(includeLocations) - result.ExcludeLocations = tf.ExpandStringSlicePtr(excludeLocations) + excludePlatforms := make([]stable.ConditionalAccessDevicePlatform, 0) + for _, elem := range config["excluded_platforms"].([]interface{}) { + excludePlatforms = append(excludePlatforms, stable.ConditionalAccessDevicePlatform(elem.(string))) + } + + result.IncludePlatforms = &includePlatforms + result.ExcludePlatforms = &excludePlatforms return &result } -func expandConditionalAccessGrantControls(in []interface{}) *msgraph.ConditionalAccessGrantControls { +func expandConditionalAccessGrantControls(in []interface{}) *stable.ConditionalAccessGrantControls { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessGrantControls{} + result := stable.ConditionalAccessGrantControls{} config := in[0].(map[string]interface{}) - operator := config["operator"].(string) - authenticationStrengthId := config["authentication_strength_policy_id"].(string) - builtInControls := config["built_in_controls"].([]interface{}) - customAuthenticationFactors := config["custom_authentication_factors"].([]interface{}) - termsOfUse := config["terms_of_use"].([]interface{}) - - result.Operator = &operator - - if authenticationStrengthId != "" { - result.AuthenticationStrength = &msgraph.AuthenticationStrengthPolicy{ - ID: &authenticationStrengthId, + if id := config["authentication_strength_policy_id"].(string); id != "" { + result.AuthenticationStrength = &stable.AuthenticationStrengthPolicy{ + Id: &id, } } - result.BuiltInControls = tf.ExpandStringSlicePtr(builtInControls) - result.CustomAuthenticationFactors = tf.ExpandStringSlicePtr(customAuthenticationFactors) - result.TermsOfUse = tf.ExpandStringSlicePtr(termsOfUse) + builtInControls := make([]stable.ConditionalAccessGrantControl, 0) + for _, elem := range config["built_in_controls"].([]interface{}) { + builtInControls = append(builtInControls, stable.ConditionalAccessGrantControl(elem.(string))) + } + + result.BuiltInControls = &builtInControls + result.CustomAuthenticationFactors = tf.ExpandStringSlicePtr(config["custom_authentication_factors"].([]interface{})) + result.Operator = nullable.Value(config["operator"].(string)) + result.TermsOfUse = tf.ExpandStringSlicePtr(config["terms_of_use"].([]interface{})) return &result } -func expandConditionalAccessSessionControls(in []interface{}) *msgraph.ConditionalAccessSessionControls { - result := msgraph.ConditionalAccessSessionControls{} +func expandConditionalAccessSessionControls(in []interface{}) *stable.ConditionalAccessSessionControls { + result := stable.ConditionalAccessSessionControls{} if len(in) == 0 || in[0] == nil { return &result @@ -467,56 +528,56 @@ func expandConditionalAccessSessionControls(in []interface{}) *msgraph.Condition config := in[0].(map[string]interface{}) - result.ApplicationEnforcedRestrictions = &msgraph.ApplicationEnforcedRestrictionsSessionControl{ - IsEnabled: pointer.To(config["application_enforced_restrictions_enabled"].(bool)), + result.ApplicationEnforcedRestrictions = &stable.ApplicationEnforcedRestrictionsSessionControl{ + IsEnabled: nullable.Value(config["application_enforced_restrictions_enabled"].(bool)), } - if cloudAppSecurity := config["cloud_app_security_policy"].(string); cloudAppSecurity != "" { - result.CloudAppSecurity = &msgraph.CloudAppSecurityControl{ - IsEnabled: pointer.To(true), - CloudAppSecurityType: pointer.To(cloudAppSecurity), + if cloudAppSecurity := config["cloud_app_security_policy"]; cloudAppSecurity.(string) != "" { + result.CloudAppSecurity = &stable.CloudAppSecuritySessionControl{ + IsEnabled: nullable.Value(true), + CloudAppSecurityType: pointer.To(stable.CloudAppSecuritySessionControlType(cloudAppSecurity.(string))), } } DisableResilienceDefaults := config["disable_resilience_defaults"] - result.DisableResilienceDefaults = pointer.To(DisableResilienceDefaults.(bool)) + result.DisableResilienceDefaults = nullable.Value(DisableResilienceDefaults.(bool)) - if persistentBrowserMode := config["persistent_browser_mode"].(string); persistentBrowserMode != "" { - result.PersistentBrowser = &msgraph.PersistentBrowserSessionControl{ - IsEnabled: pointer.To(true), - Mode: pointer.To(persistentBrowserMode), + if persistentBrowserMode := config["persistent_browser_mode"]; persistentBrowserMode.(string) != "" { + result.PersistentBrowser = &stable.PersistentBrowserSessionControl{ + IsEnabled: nullable.Value(true), + Mode: pointer.To(stable.PersistentBrowserSessionMode(persistentBrowserMode.(string))), } } - signInFrequency := msgraph.SignInFrequencySessionControl{} + signInFrequency := stable.SignInFrequencySessionControl{} if frequencyValue := config["sign_in_frequency"].(int); frequencyValue > 0 { - signInFrequency.IsEnabled = pointer.To(true) - signInFrequency.Type = pointer.To(config["sign_in_frequency_period"].(string)) - signInFrequency.Value = pointer.To(int32(frequencyValue)) + signInFrequency.IsEnabled = nullable.Value(true) + signInFrequency.Type = pointer.To(stable.SigninFrequencyType(config["sign_in_frequency_period"].(string))) + signInFrequency.Value = nullable.Value(int64(frequencyValue)) // AuthenticationType and FrequencyInterval must be set to default values here - signInFrequency.AuthenticationType = pointer.To(msgraph.ConditionalAccessAuthenticationTypePrimaryAndSecondaryAuthentication) - signInFrequency.FrequencyInterval = pointer.To(msgraph.ConditionalAccessFrequencyIntervalTimeBased) + signInFrequency.AuthenticationType = pointer.To(stable.SignInFrequencyAuthenticationType_PrimaryAndSecondaryAuthentication) + signInFrequency.FrequencyInterval = pointer.To(stable.SignInFrequencyInterval_TimeBased) } if authenticationType, ok := config["sign_in_frequency_authentication_type"]; ok && authenticationType.(string) != "" { - signInFrequency.AuthenticationType = pointer.To(authenticationType.(string)) + signInFrequency.AuthenticationType = pointer.To(stable.SignInFrequencyAuthenticationType(authenticationType.(string))) } if interval, ok := config["sign_in_frequency_interval"]; ok && interval.(string) != "" { - signInFrequency.FrequencyInterval = pointer.To(interval.(string)) + signInFrequency.FrequencyInterval = pointer.To(stable.SignInFrequencyInterval(interval.(string))) } // API returns 400 error if signInFrequency is set with all default/zero values - if (signInFrequency.IsEnabled != nil && *signInFrequency.IsEnabled) || - (signInFrequency.FrequencyInterval != nil && *signInFrequency.FrequencyInterval != msgraph.ConditionalAccessFrequencyIntervalTimeBased) || - (signInFrequency.AuthenticationType != nil && *signInFrequency.AuthenticationType != msgraph.ConditionalAccessAuthenticationTypePrimaryAndSecondaryAuthentication) { + if (signInFrequency.IsEnabled.GetOrZero()) || + (signInFrequency.FrequencyInterval != nil && *signInFrequency.FrequencyInterval != stable.SignInFrequencyInterval_TimeBased) || + (signInFrequency.AuthenticationType != nil && *signInFrequency.AuthenticationType != stable.SignInFrequencyAuthenticationType_PrimaryAndSecondaryAuthentication) { result.SignInFrequency = &signInFrequency } // API does not accept ineffectual and sessionControls object, and it will not remove any existing sessionControls unless the entire object is set to null - if (result.ApplicationEnforcedRestrictions == nil || !pointer.From(result.ApplicationEnforcedRestrictions.IsEnabled)) && - result.CloudAppSecurity == nil && !pointer.From(result.DisableResilienceDefaults) && + if (result.ApplicationEnforcedRestrictions == nil || !result.ApplicationEnforcedRestrictions.IsEnabled.GetOrZero()) && + result.CloudAppSecurity == nil && !result.DisableResilienceDefaults.GetOrZero() && result.PersistentBrowser == nil && result.SignInFrequency == nil { return nil } @@ -524,8 +585,8 @@ func expandConditionalAccessSessionControls(in []interface{}) *msgraph.Condition return &result } -func expandConditionalAccessFilter(in []interface{}) *msgraph.ConditionalAccessFilter { - result := msgraph.ConditionalAccessFilter{} +func expandConditionalAccessFilter(in []interface{}) *stable.ConditionalAccessFilter { + result := stable.ConditionalAccessFilter{} if len(in) == 0 || in[0] == nil { return &result @@ -533,44 +594,46 @@ func expandConditionalAccessFilter(in []interface{}) *msgraph.ConditionalAccessF config := in[0].(map[string]interface{}) - result.Mode = pointer.To(config["mode"].(string)) + result.Mode = pointer.To(stable.FilterMode(config["mode"].(string))) result.Rule = pointer.To(config["rule"].(string)) return &result } -func expandGuestsOrExternalUsers(in []interface{}) *msgraph.ConditionalAccessGuestsOrExternalUsers { +func expandGuestsOrExternalUsers(in []interface{}) *stable.ConditionalAccessGuestsOrExternalUsers { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessGuestsOrExternalUsers{} - config := in[0].(map[string]interface{}) + result := stable.ConditionalAccessGuestsOrExternalUsers{} - types := config["guest_or_external_user_types"].([]interface{}) + var guestOrExternalUserTypes *stable.ConditionalAccessGuestOrExternalUserTypes + if len(config["guest_or_external_user_types"].([]interface{})) > 0 { + values := strings.Join(tf.ExpandStringSlice(config["guest_or_external_user_types"].([]interface{})), ",") + guestOrExternalUserTypes = pointer.To(stable.ConditionalAccessGuestOrExternalUserTypes(values)) + } - result.GuestOrExternalUserTypes = tf.ExpandStringSlicePtr(types) + result.GuestOrExternalUserTypes = guestOrExternalUserTypes result.ExternalTenants = expandExternalTenants(config["external_tenants"].([]interface{})) return &result } -func expandExternalTenants(in []interface{}) *msgraph.ConditionalAccessExternalTenants { +func expandExternalTenants(in []interface{}) stable.ConditionalAccessExternalTenants { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.ConditionalAccessExternalTenants{} + result := stable.BaseConditionalAccessExternalTenantsImpl{} config := in[0].(map[string]interface{}) members := config["members"].([]interface{}) - result.MembershipKind = pointer.To(config["membership_kind"].(string)) + result.MembershipKind = pointer.To(stable.ConditionalAccessExternalTenantsMembershipKind(config["membership_kind"].(string))) - // only membership_kind enumerated is allowed to have members field set - // so we omit setting an empty array when no members configured + // only membership_kind enumerated is allowed to have members field set, so we omit setting an empty array when no members configured if len(members) > 0 { result.Members = tf.ExpandStringSlicePtr(members) } @@ -578,29 +641,29 @@ func expandExternalTenants(in []interface{}) *msgraph.ConditionalAccessExternalT return &result } -func expandCountryNamedLocation(in []interface{}) *msgraph.CountryNamedLocation { +func expandCountryNamedLocation(in []interface{}) *stable.CountryNamedLocation { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.CountryNamedLocation{} + result := stable.CountryNamedLocation{} config := in[0].(map[string]interface{}) countriesAndRegions := config["countries_and_regions"].([]interface{}) includeUnknown := config["include_unknown_countries_and_regions"] - result.CountriesAndRegions = tf.ExpandStringSlicePtr(countriesAndRegions) + result.CountriesAndRegions = tf.ExpandStringSlice(countriesAndRegions) result.IncludeUnknownCountriesAndRegions = pointer.To(includeUnknown.(bool)) return &result } -func expandIPNamedLocation(in []interface{}) *msgraph.IPNamedLocation { +func expandIPNamedLocation(in []interface{}) *stable.IPNamedLocation { if len(in) == 0 || in[0] == nil { return nil } - result := msgraph.IPNamedLocation{} + result := stable.IPNamedLocation{} config := in[0].(map[string]interface{}) ipRanges := config["ip_ranges"].([]interface{}) @@ -612,17 +675,13 @@ func expandIPNamedLocation(in []interface{}) *msgraph.IPNamedLocation { return &result } -func expandIPNamedLocationIPRange(in []interface{}) *[]msgraph.IPNamedLocationIPRange { - if len(in) == 0 { - return nil - } - - result := make([]msgraph.IPNamedLocationIPRange, 0) +func expandIPNamedLocationIPRange(in []interface{}) []stable.IPRange { + result := make([]stable.IPRange, 0) for _, cidr := range in { - result = append(result, msgraph.IPNamedLocationIPRange{ + result = append(result, stable.IPv4CIDRRange{ CIDRAddress: pointer.To(cidr.(string)), }) } - return &result + return result } diff --git a/internal/services/conditionalaccess/named_location_data_source.go b/internal/services/conditionalaccess/named_location_data_source.go index d723d7a21e..b3697235e7 100644 --- a/internal/services/conditionalaccess/named_location_data_source.go +++ b/internal/services/conditionalaccess/named_location_data_source.go @@ -7,15 +7,17 @@ import ( "context" "errors" "fmt" - "net/http" "time" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccessnamedlocation" "github.com/hashicorp/go-azure-sdk/sdk/odata" "github.com/hashicorp/terraform-provider-azuread/internal/clients" - "github.com/hashicorp/terraform-provider-azuread/internal/tf" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/validation" - "github.com/manicminer/hamilton/msgraph" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/validation" ) func namedLocationDataSource() *pluginsdk.Resource { @@ -28,9 +30,9 @@ func namedLocationDataSource() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "display_name": { - Type: pluginsdk.TypeString, - Required: true, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "ip": { @@ -79,44 +81,56 @@ func namedLocationDataSource() *pluginsdk.Resource { } func namedLocationDataSourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.NamedLocationsClient + client := meta.(*clients.Client).ConditionalAccess.NamedLocationClient displayName := d.Get("display_name").(string) - query := odata.Query{Filter: fmt.Sprintf("displayName eq '%s'", displayName)} - result, status, err := client.List(ctx, query) + options := conditionalaccessnamedlocation.ListConditionalAccessNamedLocationsOperationOptions{ + Filter: pointer.To(fmt.Sprintf("displayName eq '%s'", odata.EscapeSingleQuote(displayName))), + } + resp, err := client.ListConditionalAccessNamedLocations(ctx, options) if err != nil { - if status == http.StatusNotFound { + if response.WasNotFound(resp.HttpResponse) { return tf.ErrorDiagPathF(nil, "display_name", "Named Location with display name %q was not found", displayName) } } - if result == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "Result is nil") + + namedLocations := resp.Model + if namedLocations == nil { + return tf.ErrorDiagF(errors.New("model was nil"), "Bad API Response") } - if len(*result) == 0 { + if len(*namedLocations) == 0 { return tf.ErrorDiagPathF(nil, "display_name", "No Named Location was found with display name %q", displayName) } - if len(*result) > 1 { + if len(*namedLocations) > 1 { return tf.ErrorDiagPathF(nil, "display_name", "More than one Named Location was found with display name %q", displayName) } - location := (*result)[0] + item := (*namedLocations)[0] - if ipnl, ok := location.(msgraph.IPNamedLocation); ok { - if ipnl.ID == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "ID is nil for returned IP Named Location") - } - d.SetId(*ipnl.ID) - tf.Set(d, "display_name", ipnl.DisplayName) - tf.Set(d, "ip", flattenIPNamedLocation(&ipnl)) + if item == nil { + return tf.ErrorDiagF(errors.New("NamedLocation was nil"), "Bad API Response") } - if cnl, ok := location.(msgraph.CountryNamedLocation); ok { - if cnl.ID == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "ID is nil for returned Country Named Location") + switch namedLocation := item.(type) { + case stable.IPNamedLocation: + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("ID is nil for returned IP Named Location"), "Bad API response") } - d.SetId(*cnl.ID) - tf.Set(d, "display_name", cnl.DisplayName) - tf.Set(d, "country", flattenCountryNamedLocation(&cnl)) + + d.SetId(*namedLocation.Id) + + tf.Set(d, "display_name", pointer.From(namedLocation.DisplayName)) + tf.Set(d, "ip", flattenIPNamedLocation(&namedLocation)) + + case stable.CountryNamedLocation: + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("ID is nil for returned Country Named Location"), "Bad API response") + } + + d.SetId(*namedLocation.Id) + + tf.Set(d, "display_name", pointer.From(namedLocation.DisplayName)) + tf.Set(d, "country", flattenCountryNamedLocation(&namedLocation)) } return nil diff --git a/internal/services/conditionalaccess/named_location_resource.go b/internal/services/conditionalaccess/named_location_resource.go index 1bedf73ba7..1ecfacbcdc 100644 --- a/internal/services/conditionalaccess/named_location_resource.go +++ b/internal/services/conditionalaccess/named_location_resource.go @@ -8,19 +8,19 @@ import ( "errors" "fmt" "log" - "net/http" "reflect" "time" "github.com/hashicorp/go-azure-helpers/lang/pointer" - "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccessnamedlocation" "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-provider-azuread/internal/clients" - "github.com/hashicorp/terraform-provider-azuread/internal/helpers" - "github.com/hashicorp/terraform-provider-azuread/internal/tf" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azuread/internal/tf/validation" - "github.com/manicminer/hamilton/msgraph" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/consistency" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/validation" ) func namedLocationResource() *pluginsdk.Resource { @@ -46,9 +46,9 @@ func namedLocationResource() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "display_name": { - Type: pluginsdk.TypeString, - Required: true, - ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "ip": { @@ -105,40 +105,56 @@ func namedLocationResource() *pluginsdk.Resource { } func namedLocationResourceCreate(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.NamedLocationsClient - - displayName := d.Get("display_name").(string) - - base := msgraph.BaseNamedLocation{ - DisplayName: pointer.To(displayName), - } + client := meta.(*clients.Client).ConditionalAccess.NamedLocationClient if v, ok := d.GetOk("ip"); ok { properties := expandIPNamedLocation(v.([]interface{})) - properties.BaseNamedLocation = &base + properties.DisplayName = pointer.To(d.Get("display_name").(string)) - ipLocation, _, err := client.CreateIP(ctx, *properties) + resp, err := client.CreateConditionalAccessNamedLocation(ctx, *properties, conditionalaccessnamedlocation.DefaultCreateConditionalAccessNamedLocationOperationOptions()) if err != nil { return tf.ErrorDiagF(err, "Could not create named location") } - if ipLocation.ID == nil || *ipLocation.ID == "" { - return tf.ErrorDiagF(errors.New("Bad API response"), "Object ID returned for named location is nil/empty") + + if resp.Model == nil { + return tf.ErrorDiagF(errors.New("returned model was nil"), "Bad API Response") } - d.SetId(*ipLocation.ID) - } else if v, ok := d.GetOk("country"); ok { + namedLocation, ok := resp.Model.(stable.IPNamedLocation) + if !ok { + return tf.ErrorDiagF(errors.New("returned model was not an IPNamedLocation"), "Bad API response") + } + + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("nil/empty object ID returned for named location"), "Bad API response") + } + + d.SetId(*namedLocation.Id) + + } else if v, ok = d.GetOk("country"); ok { properties := expandCountryNamedLocation(v.([]interface{})) - properties.BaseNamedLocation = &base + properties.DisplayName = pointer.To(d.Get("display_name").(string)) - countryLocation, _, err := client.CreateCountry(ctx, *properties) + resp, err := client.CreateConditionalAccessNamedLocation(ctx, *properties, conditionalaccessnamedlocation.DefaultCreateConditionalAccessNamedLocationOperationOptions()) if err != nil { return tf.ErrorDiagF(err, "Could not create named location") } - if countryLocation.ID == nil || *countryLocation.ID == "" { - return tf.ErrorDiagF(errors.New("Bad API response"), "Object ID returned for named location is nil/empty") + + if resp.Model == nil { + return tf.ErrorDiagF(errors.New("returned model was nil"), "Bad API Response") + } + + namedLocation, ok := resp.Model.(stable.CountryNamedLocation) + if !ok { + return tf.ErrorDiagF(errors.New("returned model was not a CountryNamedLocation"), "Bad API response") + } + + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("nil/empty object ID returned for named location"), "Bad API response") } - d.SetId(*countryLocation.ID) + d.SetId(*namedLocation.Id) + } else { return tf.ErrorDiagF(errors.New("one of `ip` or `country` must be specified"), "Unable to determine named location type") } @@ -147,187 +163,184 @@ func namedLocationResourceCreate(ctx context.Context, d *pluginsdk.ResourceData, } func namedLocationResourceUpdate(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.NamedLocationsClient - - base := msgraph.BaseNamedLocation{ - ID: pointer.To(d.Id()), - } - - if d.HasChange("display_name") { - displayName := d.Get("display_name").(string) - base.DisplayName = &displayName - } - - var updateRefreshFunc pluginsdk.StateRefreshFunc //nolint:staticcheck + client := meta.(*clients.Client).ConditionalAccess.NamedLocationClient + id := stable.NewIdentityConditionalAccessNamedLocationID(d.Id()) if v, ok := d.GetOk("ip"); ok { properties := expandIPNamedLocation(v.([]interface{})) - properties.BaseNamedLocation = &base - if _, err := client.UpdateIP(ctx, *properties); err != nil { - return tf.ErrorDiagF(err, "Could not update named location with ID %q: %+v", d.Id(), err) + if d.HasChange("display_name") { + properties.DisplayName = pointer.To(d.Get("display_name").(string)) } - updateRefreshFunc = func() (interface{}, string, error) { - result, _, err := client.GetIP(ctx, d.Id(), odata.Query{}) + if _, err := client.UpdateConditionalAccessNamedLocation(ctx, id, *properties, conditionalaccessnamedlocation.DefaultUpdateConditionalAccessNamedLocationOperationOptions()); err != nil { + return tf.ErrorDiagF(err, "Updating %s", id) + } + + if err := consistency.WaitForUpdate(ctx, func(ctx context.Context) (*bool, error) { + resp, err := client.GetConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultGetConditionalAccessNamedLocationOperationOptions()) if err != nil { - return nil, "Error", err + return nil, err + } + + if resp.Model == nil { + return nil, errors.New("returned model was nil") } - if locationRaw := flattenIPNamedLocation(result); len(locationRaw) > 0 { + namedLocation, ok := resp.Model.(stable.IPNamedLocation) + if !ok { + return nil, errors.New("returned model was not an IPNamedLocation") + } + + if locationRaw := flattenIPNamedLocation(&namedLocation); len(locationRaw) > 0 { location := locationRaw[0].(map[string]interface{}) ip := v.([]interface{})[0].(map[string]interface{}) + if !reflect.DeepEqual(location["ip_ranges"], ip["ip_ranges"]) { - return "stub", "Pending", nil + return pointer.To(false), nil } + if location["trusted"].(bool) != ip["trusted"].(bool) { - return "stub", "Pending", nil + return pointer.To(false), nil } } - return "stub", "Updated", nil + return pointer.To(true), nil + }); err != nil { + return tf.ErrorDiagF(err, "waiting for update of %s", id) } - } - if v, ok := d.GetOk("country"); ok { + } else if v, ok := d.GetOk("country"); ok { properties := expandCountryNamedLocation(v.([]interface{})) - properties.BaseNamedLocation = &base - if _, err := client.UpdateCountry(ctx, *properties); err != nil { - return tf.ErrorDiagF(err, "Could not update named location with ID %q: %+v", d.Id(), err) + if d.HasChange("display_name") { + properties.DisplayName = pointer.To(d.Get("display_name").(string)) + } + + if _, err := client.UpdateConditionalAccessNamedLocation(ctx, id, *properties, conditionalaccessnamedlocation.DefaultUpdateConditionalAccessNamedLocationOperationOptions()); err != nil { + return tf.ErrorDiagF(err, "Updating %s", id) } - updateRefreshFunc = func() (interface{}, string, error) { - result, _, err := client.GetCountry(ctx, d.Id(), odata.Query{}) + if err := consistency.WaitForUpdate(ctx, func(ctx context.Context) (*bool, error) { + resp, err := client.GetConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultGetConditionalAccessNamedLocationOperationOptions()) if err != nil { - return nil, "Error", err + return nil, err } - if locationRaw := flattenCountryNamedLocation(result); len(locationRaw) > 0 { + if resp.Model == nil { + return nil, errors.New("returned model was nil") + } + + namedLocation, ok := resp.Model.(stable.CountryNamedLocation) + if !ok { + return nil, errors.New("returned model was not a CountryNamedLocation") + } + + if locationRaw := flattenCountryNamedLocation(&namedLocation); len(locationRaw) > 0 { location := locationRaw[0].(map[string]interface{}) ip := v.([]interface{})[0].(map[string]interface{}) + if !reflect.DeepEqual(location["countries_and_regions"], ip["countries_and_regions"]) { - return "stub", "Pending", nil + return pointer.To(false), nil } + if location["include_unknown_countries_and_regions"].(bool) != ip["include_unknown_countries_and_regions"].(bool) { - return "stub", "Pending", nil + return pointer.To(false), nil } } - return "stub", "Updated", nil + return pointer.To(true), nil + }); err != nil { + return tf.ErrorDiagF(err, "waiting for update of %s", id) } } - log.Printf("[DEBUG] Waiting for named location %q to be updated", d.Id()) - timeout, _ := ctx.Deadline() - stateConf := &pluginsdk.StateChangeConf{ //nolint:staticcheck - Pending: []string{"Pending"}, - Target: []string{"Updated"}, - Timeout: time.Until(timeout), - MinTimeout: 5 * time.Second, - ContinuousTargetOccurence: 5, - Refresh: updateRefreshFunc, - } - if _, err := stateConf.WaitForStateContext(ctx); err != nil { - return tf.ErrorDiagF(err, "waiting for update of named location with ID %q", d.Id()) - } - return namedLocationResourceRead(ctx, d, meta) } func namedLocationResourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.NamedLocationsClient + client := meta.(*clients.Client).ConditionalAccess.NamedLocationClient + id := stable.NewIdentityConditionalAccessNamedLocationID(d.Id()) - result, status, err := client.Get(ctx, d.Id(), odata.Query{}) + resp, err := client.GetConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultGetConditionalAccessNamedLocationOperationOptions()) if err != nil { - if status == http.StatusNotFound { - log.Printf("[DEBUG] Named Location with Object ID %q was not found - removing from state", d.Id()) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s was not found - removing from state", id) d.SetId("") return nil } } - if result == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "Result is nil") - } - location := *result + if resp.Model == nil { + return tf.ErrorDiagF(errors.New("returned model was nil"), "Bad API Response") + } - if ipnl, ok := location.(msgraph.IPNamedLocation); ok { - if ipnl.ID == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "ID is nil for returned IP Named Location") + switch namedLocation := resp.Model.(type) { + case stable.IPNamedLocation: + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("ID is nil for returned IP Named Location"), "Bad API response") } - d.SetId(*ipnl.ID) - tf.Set(d, "display_name", ipnl.DisplayName) - tf.Set(d, "ip", flattenIPNamedLocation(&ipnl)) - } - if cnl, ok := location.(msgraph.CountryNamedLocation); ok { - if cnl.ID == nil { - return tf.ErrorDiagF(errors.New("Bad API response"), "ID is nil for returned Country Named Location") + d.SetId(*namedLocation.Id) + + tf.Set(d, "display_name", pointer.From(namedLocation.DisplayName)) + tf.Set(d, "ip", flattenIPNamedLocation(&namedLocation)) + + case stable.CountryNamedLocation: + if namedLocation.Id == nil { + return tf.ErrorDiagF(errors.New("ID is nil for returned Country Named Location"), "Bad API response") } - d.SetId(*cnl.ID) - tf.Set(d, "display_name", cnl.DisplayName) - tf.Set(d, "country", flattenCountryNamedLocation(&cnl)) + + d.SetId(*namedLocation.Id) + + tf.Set(d, "display_name", pointer.From(namedLocation.DisplayName)) + tf.Set(d, "country", flattenCountryNamedLocation(&namedLocation)) } return nil } func namedLocationResourceDelete(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) pluginsdk.Diagnostics { - client := meta.(*clients.Client).ConditionalAccess.NamedLocationsClient - namedLocationId := d.Id() + client := meta.(*clients.Client).ConditionalAccess.NamedLocationClient + id := stable.NewIdentityConditionalAccessNamedLocationID(d.Id()) - if _, ok := d.GetOk("ip"); ok { - resp, status, err := client.GetIP(ctx, namedLocationId, odata.Query{}) - if err != nil { - if status == http.StatusNotFound { - log.Printf("[DEBUG] Named Location with ID %q already deleted", namedLocationId) - return nil - } - - return tf.ErrorDiagPathF(err, "id", "Retrieving named location with ID %q", namedLocationId) - } - if resp != nil && resp.IsTrusted != nil && *resp.IsTrusted { - properties := msgraph.IPNamedLocation{ - BaseNamedLocation: &msgraph.BaseNamedLocation{ - ID: &namedLocationId, - }, - IsTrusted: pointer.To(false), - } - if _, err := client.UpdateIP(ctx, properties); err != nil { - return tf.ErrorDiagF(err, "Updating named location with ID %q", namedLocationId) - } - } - } + if v, ok := d.GetOk("ip"); ok { + properties := expandIPNamedLocation(v.([]interface{})) + properties.IsTrusted = pointer.To(false) - if _, ok := d.GetOk("country"); ok { - if _, status, err := client.GetCountry(ctx, namedLocationId, odata.Query{}); err != nil { - if status == http.StatusNotFound { - log.Printf("[DEBUG] Named Location with ID %q already deleted", namedLocationId) + if resp, err := client.UpdateConditionalAccessNamedLocation(ctx, id, properties, conditionalaccessnamedlocation.DefaultUpdateConditionalAccessNamedLocationOperationOptions()); err != nil { + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s already deleted", id) return nil } - return tf.ErrorDiagPathF(err, "id", "Retrieving named location with ID %q", namedLocationId) + return tf.ErrorDiagF(err, "updating %s prior to deletion", id) } } - status, err := client.Delete(ctx, namedLocationId) + resp, err := client.DeleteConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultDeleteConditionalAccessNamedLocationOperationOptions()) if err != nil { - return tf.ErrorDiagPathF(err, "id", "Deleting named location with ID %q, got status %d", namedLocationId, status) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s already deleted", id) + return nil + } + + return tf.ErrorDiagF(err, "deleting %s", id) } - if err := helpers.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) { - defer func() { client.BaseClient.DisableRetries = false }() - client.BaseClient.DisableRetries = true - if _, status, err := client.Get(ctx, namedLocationId, odata.Query{}); err != nil { - if status == http.StatusNotFound { + if err = consistency.WaitForDeletion(ctx, func(ctx context.Context) (*bool, error) { + resp, err := client.GetConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultGetConditionalAccessNamedLocationOperationOptions()) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { return pointer.To(false), nil } + return nil, err } + return pointer.To(true), nil }); err != nil { - return tf.ErrorDiagF(err, "waiting for deletion of named location with ID %q", namedLocationId) + return tf.ErrorDiagF(err, "waiting for deletion of %s", id) } return nil diff --git a/internal/services/conditionalaccess/named_location_resource_test.go b/internal/services/conditionalaccess/named_location_resource_test.go index e728245189..b7f490b4c1 100644 --- a/internal/services/conditionalaccess/named_location_resource_test.go +++ b/internal/services/conditionalaccess/named_location_resource_test.go @@ -6,16 +6,16 @@ package conditionalaccess_test import ( "context" "fmt" - "net/http" "testing" "github.com/hashicorp/go-azure-helpers/lang/pointer" - "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/common-types/stable" + "github.com/hashicorp/go-azure-sdk/microsoft-graph/identity/stable/conditionalaccessnamedlocation" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-azuread/internal/acceptance" "github.com/hashicorp/terraform-provider-azuread/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azuread/internal/clients" - "github.com/manicminer/hamilton/msgraph" ) type NamedLocationResource struct{} @@ -139,22 +139,18 @@ func TestAccNamedLocation_updateCountry(t *testing.T) { } func (r NamedLocationResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { - namedLocation, status, err := clients.ConditionalAccess.NamedLocationsClient.Get(ctx, state.ID, odata.Query{}) + client := clients.ConditionalAccess.NamedLocationClient + id := stable.NewIdentityConditionalAccessNamedLocationID(state.ID) + + resp, err := client.GetConditionalAccessNamedLocation(ctx, id, conditionalaccessnamedlocation.DefaultGetConditionalAccessNamedLocationOperationOptions()) if err != nil { - if status == http.StatusNotFound { - return nil, fmt.Errorf("Named Location with object ID %q does not exist", state.ID) + if response.WasNotFound(resp.HttpResponse) { + return pointer.To(false), nil } return nil, fmt.Errorf("failed to retrieve Named Location with object ID %q: %+v", state.ID, err) } - ipnl, ok1 := (*namedLocation).(msgraph.IPNamedLocation) - cnl, ok2 := (*namedLocation).(msgraph.CountryNamedLocation) - if ok1 { - return pointer.To(ipnl.ID != nil && *ipnl.ID == state.ID), nil - } - if ok2 { - return pointer.To(cnl.ID != nil && *cnl.ID == state.ID), nil - } - return nil, fmt.Errorf("Unable to match object ID %q to a known type", state.ID) + + return pointer.To(true), nil } func (NamedLocationResource) basicIP(data acceptance.TestData) string { diff --git a/internal/services/conditionalaccess/registration.go b/internal/services/conditionalaccess/registration.go index 71e6babaa0..69166174a9 100644 --- a/internal/services/conditionalaccess/registration.go +++ b/internal/services/conditionalaccess/registration.go @@ -4,7 +4,7 @@ package conditionalaccess import ( - "github.com/hashicorp/terraform-provider-azuread/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azuread/internal/helpers/tf/pluginsdk" ) type Registration struct{}