Skip to content

Commit

Permalink
azuread_conditional_access_policy: enable setting of `session_control…
Browse files Browse the repository at this point in the history
…s` instead of, or in addition to, `grant_controls`
  • Loading branch information
manicminer committed Jul 25, 2023
1 parent 8f15123 commit a6489c3
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 133 deletions.
5 changes: 4 additions & 1 deletion docs/resources/conditional_access_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,11 @@ The following arguments are supported:

* `conditions` - (Required) A `conditions` block as documented below, which specifies the rules that must be met for the policy to apply.
* `display_name` - (Required) The friendly name for this Conditional Access Policy.
* `grant_controls` - (Required) A `grant_controls` block as documented below, which specifies the grant controls that must be fulfilled to pass the policy.
* `grant_controls` - (Optional) A `grant_controls` block as documented below, which specifies the grant controls that must be fulfilled to pass the policy.
* `session_controls` - (Optional) A `session_controls` block as documented below, which specifies the session controls that are enforced after sign-in.

~> Note: At least one of `grant_controls` and/or `session_controls` blocks must be specified.

* `state` - (Required) Specifies the state of the policy object. Possible values are: `enabled`, `disabled` and `enabledForReportingButNotEnforced`

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,9 @@ func conditionalAccessPolicyResource() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"included_users": {
Type: schema.TypeList,
Optional: true,
AtLeastOneOf: []string{"conditions.0.users.0.included_groups", "conditions.0.users.0.included_roles", "conditions.0.users.0.included_users"},
DiffSuppressFunc: conditionalAccessPolicyDiffSuppress,
Type: schema.TypeList,
Optional: true,
AtLeastOneOf: []string{"conditions.0.users.0.included_groups", "conditions.0.users.0.included_roles", "conditions.0.users.0.included_users"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validate.NoEmptyStrings,
Expand Down Expand Up @@ -375,9 +374,10 @@ func conditionalAccessPolicyResource() *schema.Resource {
},

"grant_controls": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Type: schema.TypeList,
Optional: true,
AtLeastOneOf: []string{"grant_controls", "session_controls"},
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"operator": {
Expand Down Expand Up @@ -426,10 +426,10 @@ func conditionalAccessPolicyResource() *schema.Resource {
},

"session_controls": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
DiffSuppressFunc: conditionalAccessPolicyDiffSuppress,
Type: schema.TypeList,
Optional: true,
AtLeastOneOf: []string{"grant_controls", "session_controls"},
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"application_enforced_restrictions_enabled": {
Expand Down Expand Up @@ -501,48 +501,21 @@ func conditionalAccessPolicyCustomizeDiff(ctx context.Context, diff *schema.Reso
return nil
}

func conditionalAccessPolicyDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
suppress := false

switch {
case k == "session_controls.#" && old == "0" && new == "1":
sessionControlsRaw := d.Get("session_controls").([]interface{})
if len(sessionControlsRaw) == 1 && sessionControlsRaw[0] != nil {
sessionControls := sessionControlsRaw[0].(map[string]interface{})
suppress = true
if v, ok := sessionControls["application_enforced_restrictions_enabled"]; ok && v.(bool) {
suppress = false
}
if v, ok := sessionControls["cloud_app_security_policy"]; ok && v.(string) != "" {
suppress = false
}
if v, ok := sessionControls["disable_resilience_defaults"]; ok && v.(bool) {
suppress = false
}
if v, ok := sessionControls["persistent_browser_mode"]; ok && v.(string) != "" {
suppress = false
}
if v, ok := sessionControls["sign_in_frequency"]; ok && v.(int) > 0 {
suppress = false
}
if v, ok := sessionControls["sign_in_frequency_period"]; ok && v.(string) != "" {
suppress = false
}
}
}

return suppress
}

func conditionalAccessPolicyResourceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*clients.Client).ConditionalAccess.PoliciesClient

properties := msgraph.ConditionalAccessPolicy{
DisplayName: utils.String(d.Get("display_name").(string)),
State: utils.String(d.Get("state").(string)),
Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})),
GrantControls: expandConditionalAccessGrantControls(d.Get("grant_controls").([]interface{})),
SessionControls: expandConditionalAccessSessionControls(d.Get("session_controls").([]interface{})),
DisplayName: utils.String(d.Get("display_name").(string)),
State: utils.String(d.Get("state").(string)),
Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})),
}

if v, ok := d.GetOk("grant_controls"); ok {
properties.GrantControls = expandConditionalAccessGrantControls(v.([]interface{}))
}

if v, ok := d.GetOk("session_controls"); ok {
properties.SessionControls = expandConditionalAccessSessionControls(v.([]interface{}))
}

policy, _, err := client.Create(ctx, properties)
Expand All @@ -563,12 +536,18 @@ func conditionalAccessPolicyResourceUpdate(ctx context.Context, d *schema.Resour
client := meta.(*clients.Client).ConditionalAccess.PoliciesClient

properties := msgraph.ConditionalAccessPolicy{
ID: utils.String(d.Id()),
DisplayName: utils.String(d.Get("display_name").(string)),
State: utils.String(d.Get("state").(string)),
Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})),
GrantControls: expandConditionalAccessGrantControls(d.Get("grant_controls").([]interface{})),
SessionControls: expandConditionalAccessSessionControls(d.Get("session_controls").([]interface{})),
ID: utils.String(d.Id()),
DisplayName: utils.String(d.Get("display_name").(string)),
State: utils.String(d.Get("state").(string)),
Conditions: expandConditionalAccessConditionSet(d.Get("conditions").([]interface{})),
}

if v, ok := d.GetOk("grant_controls"); ok {
properties.GrantControls = expandConditionalAccessGrantControls(v.([]interface{}))
}

if v, ok := d.GetOk("session_controls"); ok {
properties.SessionControls = expandConditionalAccessSessionControls(v.([]interface{}))
}

if _, err := client.Update(ctx, properties); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestAccConditionalAccessPolicy_complete(t *testing.T) {
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("id").Exists(),
check.That(data.ResourceName).Key("display_name").HasValue(fmt.Sprintf("acctest-CONPOLICY-%d", data.RandomInteger)),
check.That(data.ResourceName).Key("state").HasValue("disabled"),
check.That(data.ResourceName).Key("state").HasValue("enabledForReportingButNotEnforced"),
),
},
data.ImportStep(),
Expand Down Expand Up @@ -164,9 +164,6 @@ func TestAccConditionalAccessPolicy_includedUserActions(t *testing.T) {
}

func TestAccConditionalAccessPolicy_sessionControls(t *testing.T) {
// This is in a separate test to avoid ForceNew in the update test due to https://github.com/microsoftgraph/msgraph-metadata/issues/93
// session_controls can be added to the complete config, and this rest removed, when this issue is resolved

data := acceptance.BuildTestData(t, "azuread_conditional_access_policy", "test")
r := ConditionalAccessPolicyResource{}

Expand Down Expand Up @@ -198,26 +195,6 @@ func TestAccConditionalAccessPolicy_sessionControls(t *testing.T) {
),
},
data.ImportStep(),
{
Config: r.sessionControlsUpdate(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("id").Exists(),
check.That(data.ResourceName).Key("display_name").HasValue(fmt.Sprintf("acctest-CONPOLICY-%d", data.RandomInteger)),
check.That(data.ResourceName).Key("state").HasValue("disabled"),
),
},
data.ImportStep(),
{
Config: r.sessionControls(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("id").Exists(),
check.That(data.ResourceName).Key("display_name").HasValue(fmt.Sprintf("acctest-CONPOLICY-%d", data.RandomInteger)),
check.That(data.ResourceName).Key("state").HasValue("disabled"),
),
},
data.ImportStep(),
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -367,7 +344,7 @@ func (ConditionalAccessPolicyResource) complete(data acceptance.TestData) string
return fmt.Sprintf(`
resource "azuread_conditional_access_policy" "test" {
display_name = "acctest-CONPOLICY-%[1]d"
state = "disabled"
state = "enabledForReportingButNotEnforced"
conditions {
client_app_types = ["all"]
Expand All @@ -376,7 +353,7 @@ resource "azuread_conditional_access_policy" "test" {
applications {
included_applications = ["All"]
excluded_applications = ["00000004-0000-0ff1-ce00-000000000000"]
excluded_applications = []
}
locations {
Expand All @@ -385,8 +362,8 @@ resource "azuread_conditional_access_policy" "test" {
}
platforms {
included_platforms = ["android"]
excluded_platforms = ["iOS"]
included_platforms = ["all"]
excluded_platforms = ["android", "iOS"]
}
users {
Expand All @@ -399,6 +376,15 @@ resource "azuread_conditional_access_policy" "test" {
operator = "OR"
built_in_controls = ["mfa"]
}
session_controls {
application_enforced_restrictions_enabled = true
disable_resilience_defaults = false
cloud_app_security_policy = "blockDownloads"
persistent_browser_mode = "always"
sign_in_frequency = 2
sign_in_frequency_period = "days"
}
}
`, data.RandomInteger)
}
Expand Down Expand Up @@ -549,11 +535,6 @@ resource "azuread_conditional_access_policy" "test" {
}
}
grant_controls {
operator = "OR"
built_in_controls = ["block"]
}
session_controls {
application_enforced_restrictions_enabled = true
disable_resilience_defaults = true
Expand All @@ -566,50 +547,6 @@ resource "azuread_conditional_access_policy" "test" {
`, data.RandomInteger)
}

func (ConditionalAccessPolicyResource) sessionControlsUpdate(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azuread_conditional_access_policy" "test" {
display_name = "acctest-CONPOLICY-%[1]d"
state = "disabled"
conditions {
client_app_types = ["browser"]
applications {
included_applications = ["All"]
}
locations {
included_locations = ["All"]
}
platforms {
included_platforms = ["all"]
}
users {
included_users = ["All"]
excluded_users = ["GuestsOrExternalUsers"]
}
}
grant_controls {
operator = "OR"
built_in_controls = ["block"]
}
session_controls {
application_enforced_restrictions_enabled = true
disable_resilience_defaults = false
cloud_app_security_policy = "blockDownloads"
persistent_browser_mode = "always"
sign_in_frequency = 2
sign_in_frequency_period = "days"
}
}
`, data.RandomInteger)
}

func (ConditionalAccessPolicyResource) sessionControlsDisabled(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azuread_conditional_access_policy" "test" {
Expand Down

0 comments on commit a6489c3

Please sign in to comment.