Skip to content

Commit

Permalink
AUTH-6145 support multi-valued + service token authentication for SCI…
Browse files Browse the repository at this point in the history
…M provisioning to access applications
  • Loading branch information
khiller-cf committed Dec 10, 2024
1 parent d066e50 commit b141938
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 212 deletions.
3 changes: 3 additions & 0 deletions .changelog/4743.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/access_application: support multi-valued + Access service token authentication for SCIM provisioning to Access applications
```
192 changes: 38 additions & 154 deletions internal/sdkv2provider/resource_cloudflare_access_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,10 @@ func TestAccCloudflareAccessApplication_WithSCIMConfigInvalidMappingSchema(t *te
})
}

func TestAccCloudflareAccessApplication_WithSCIMConfigHttpBasicMissingRequired(t *testing.T) {
func TestAccCloudflareAccessApplication_WithSCIMConfigOAuthBearerToken(t *testing.T) {
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_zero_trust_access_application.%s", rnd)
idpName := fmt.Sprintf("cloudflare_zero_trust_access_identity_provider.%s", rnd)

resource.Test(t, resource.TestCase{
PreCheck: func() {
Expand All @@ -266,14 +268,34 @@ func TestAccCloudflareAccessApplication_WithSCIMConfigHttpBasicMissingRequired(t
CheckDestroy: testAccCheckCloudflareAccessApplicationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAccessApplicationSCIMConfigHttpBasicMissingRequired(rnd, accountID, domain),
ExpectError: regexp.MustCompile(`.*all of\s*` + "`scim_config.0.authentication.0.password,scim_config.0.authentication.0.user`" + `\s*must be specified.*`),
Config: testAccCloudflareAccessApplicationSCIMConfigValidOAuthBearerToken(rnd, accountID, domain),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, consts.AccountIDSchemaKey, accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "domain", fmt.Sprintf("%s.%s", rnd, domain)),
resource.TestCheckResourceAttr(name, "type", "self_hosted"),
resource.TestCheckResourceAttr(name, "session_duration", "24h"),
resource.TestCheckResourceAttr(name, "scim_config.#", "1"),
resource.TestCheckResourceAttr(name, "scim_config.0.enabled", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.remote_uri", "scim.com"),
resource.TestCheckResourceAttrPair(name, "scim_config.0.idp_uid", idpName, "id"),
resource.TestCheckResourceAttr(name, "scim_config.0.deactivate_on_delete", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.authentication.0.scheme", "oauthbearertoken"),
resource.TestCheckResourceAttrSet(name, "scim_config.0.authentication.0.token"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.schema", "urn:ietf:params:scim:schemas:core:2.0:User"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.enabled", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.filter", "title pr or userType eq \"Intern\""),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.transform_jsonata", "$merge([$, {'userName': $substringBefore($.userName, '@') & '+test@' & $substringAfter($.userName, '@')}])"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.operations.0.create", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.operations.0.update", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.operations.0.delete", "true"),
),
},
},
})
}

func TestAccCloudflareAccessApplication_WithSCIMConfigOAuthBearerToken(t *testing.T) {
func TestAccCloudflareAccessApplication_WithSCIMConfigMultiAuth(t *testing.T) {
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_zero_trust_access_application.%s", rnd)
idpName := fmt.Sprintf("cloudflare_zero_trust_access_identity_provider.%s", rnd)
Expand All @@ -286,7 +308,7 @@ func TestAccCloudflareAccessApplication_WithSCIMConfigOAuthBearerToken(t *testin
CheckDestroy: testAccCheckCloudflareAccessApplicationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAccessApplicationSCIMConfigValidOAuthBearerToken(rnd, accountID, domain),
Config: testAccCloudflareAccessApplicationSCIMConfigValidMulti(rnd, accountID, domain),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, consts.AccountIDSchemaKey, accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
Expand All @@ -300,6 +322,9 @@ func TestAccCloudflareAccessApplication_WithSCIMConfigOAuthBearerToken(t *testin
resource.TestCheckResourceAttr(name, "scim_config.0.deactivate_on_delete", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.authentication.0.scheme", "oauthbearertoken"),
resource.TestCheckResourceAttrSet(name, "scim_config.0.authentication.0.token"),
resource.TestCheckResourceAttr(name, "scim_config.0.authentication.1.scheme", "access_service_token"),
resource.TestCheckResourceAttr(name, "scim_config.0.authentication.1.client_id", "1234"),
resource.TestCheckResourceAttrSet(name, "scim_config.0.authentication.1.client_secret"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.schema", "urn:ietf:params:scim:schemas:core:2.0:User"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.enabled", "true"),
resource.TestCheckResourceAttr(name, "scim_config.0.mappings.0.filter", "title pr or userType eq \"Intern\""),
Expand Down Expand Up @@ -358,42 +383,6 @@ func TestAccCloudflareAccessApplication_WithSCIMConfigOAuth2(t *testing.T) {
})
}

func TestAccCloudflareAccessApplication_WithSCIMConfigOAuth2MissingRequired(t *testing.T) {
rnd := generateRandomResourceName()

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckCloudflareAccessApplicationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAccessApplicationSCIMConfigOAuth2MissingRequired(rnd, accountID, domain),
ExpectError: regexp.MustCompile(`.*all of\s*` + "`scim_config.0.authentication.0.authorization_url,scim_config.0.authentication.0.client_id,scim_config.0.authentication.0.client_secret,scim_config.0.authentication.0.token_url`" + `\s*must be specified.*`),
},
},
})
}

func TestAccCloudflareAccessApplication_WithSCIMConfigAuthenticationInvalid(t *testing.T) {
rnd := generateRandomResourceName()

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckCloudflareAccessApplicationDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAccessApplicationSCIMConfigAuthenticationInvalid(rnd, accountID, domain),
ExpectError: regexp.MustCompile(`Error: Conflicting configuration arguments`),
},
},
})
}

func TestAccCloudflareAccessApplication_WithCORS(t *testing.T) {
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_zero_trust_access_application.%s", rnd)
Expand Down Expand Up @@ -1983,7 +1972,7 @@ resource "cloudflare_zero_trust_access_application" "%[1]s" {
`, rnd, accountID, domain)
}

func testAccCloudflareAccessApplicationSCIMConfigValidOAuth2(rnd, accountID, domain string) string {
func testAccCloudflareAccessApplicationSCIMConfigValidMulti(rnd, accountID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_zero_trust_access_identity_provider" "%[1]s" {
account_id = "%[2]s"
Expand Down Expand Up @@ -2015,66 +2004,13 @@ resource "cloudflare_zero_trust_access_application" "%[1]s" {
idp_uid = cloudflare_zero_trust_access_identity_provider.%[1]s.id
deactivate_on_delete = true
authentication {
scheme = "oauth2"
client_id = "beepboop"
client_secret = "bop"
authorization_url = "https://www.authorization.com"
token_url = "https://www.token.com"
scopes = ["read"]
}
mappings {
schema = "urn:ietf:params:scim:schemas:core:2.0:User"
enabled = true
filter = "title pr or userType eq \"Intern\""
transform_jsonata = "$merge([$, {'userName': $substringBefore($.userName, '@') & '+test@' & $substringAfter($.userName, '@')}])"
operations {
create = true
update = true
delete = true
}
}
}
}
`, rnd, accountID, domain)
}

func testAccCloudflareAccessApplicationSCIMConfigOAuth2MissingRequired(rnd, accountID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_zero_trust_access_identity_provider" "%[1]s" {
account_id = "%[2]s"
name = "%[1]s"
type = "azureAD"
config {
client_id = "test"
client_secret = "test"
directory_id = "directory"
support_groups = true
}
scim_config {
enabled = true
group_member_deprovision = true
seat_deprovision = true
user_deprovision = true
scheme = "oauthbearertoken"
token = "beepboop"
}
}
resource "cloudflare_zero_trust_access_application" "%[1]s" {
account_id = "%[2]s"
name = "%[1]s"
type = "self_hosted"
session_duration = "24h"
domain = "%[1]s.%[3]s"
scim_config {
enabled = true
remote_uri = "scim.com"
idp_uid = cloudflare_zero_trust_access_identity_provider.%[1]s.id
deactivate_on_delete = true
authentication {
scheme = "oauth2"
client_id = "beepboop"
client_secret = "bop"
authorization_url = "https://www.authorization.com"
scopes = ["read"]
scheme = "access_service_token"
client_id = "1234"
client_secret = "5678"
}
mappings {
schema = "urn:ietf:params:scim:schemas:core:2.0:User"
Expand All @@ -2086,13 +2022,14 @@ resource "cloudflare_zero_trust_access_application" "%[1]s" {
update = true
delete = true
}
strictness = "strict"
}
}
}
`, rnd, accountID, domain)
}

func testAccCloudflareAccessApplicationSCIMConfigAuthenticationInvalid(rnd, accountID, domain string) string {
func testAccCloudflareAccessApplicationSCIMConfigValidOAuth2(rnd, accountID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_zero_trust_access_identity_provider" "%[1]s" {
account_id = "%[2]s"
Expand Down Expand Up @@ -2129,9 +2066,6 @@ resource "cloudflare_zero_trust_access_application" "%[1]s" {
client_secret = "bop"
authorization_url = "https://www.authorization.com"
token_url = "https://www.token.com"
token = "1234"
user = "user"
password = "ahhh"
scopes = ["read"]
}
mappings {
Expand All @@ -2150,56 +2084,6 @@ resource "cloudflare_zero_trust_access_application" "%[1]s" {
`, rnd, accountID, domain)
}

func testAccCloudflareAccessApplicationSCIMConfigHttpBasicMissingRequired(rnd, accountID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_zero_trust_access_identity_provider" "%[1]s" {
account_id = "%[2]s"
name = "%[1]s"
type = "azureAD"
config {
client_id = "test"
client_secret = "test"
directory_id = "directory"
support_groups = true
}
scim_config {
enabled = true
group_member_deprovision = true
seat_deprovision = true
user_deprovision = true
}
}
resource "cloudflare_zero_trust_access_application" "%[1]s" {
account_id = "%[2]s"
name = "%[1]s"
type = "self_hosted"
session_duration = "24h"
domain = "%[1]s.%[3]s"
scim_config {
enabled = true
remote_uri = "scim.com"
idp_uid = cloudflare_zero_trust_access_identity_provider.%[1]s.id
deactivate_on_delete = true
authentication {
scheme = "httpbasic"
user = "test"
}
mappings {
schema = "urn:ietf:params:scim:schemas:core:2.0:User"
enabled = true
filter = "title pr or userType eq \"Intern\""
transform_jsonata = "$merge([$, {'userName': $substringBefore($.userName, '@') & '+test@' & $substringAfter($.userName, '@')}])"
operations {
create = true
update = true
delete = true
}
}
}
}`, rnd, accountID, domain)
}

func testAccCloudflareAccessApplicationSCIMConfigInvalidMappingSchema(rnd, accountID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_zero_trust_access_identity_provider" "%[1]s" {
Expand Down
Loading

0 comments on commit b141938

Please sign in to comment.