Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent trailing slash for identifierUris when no path #928

Merged
merged 3 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/services/applications/application_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ func applicationResourceCustomizeDiff(ctx context.Context, diff *schema.Resource
}
// urn scheme not supported with personal account sign-ins
for _, v := range identifierUris {
if diags := validate.IsUriFunc([]string{"http", "https", "api", "ms-appx"}, false, false)(v, cty.Path{}); diags.HasError() {
if diags := validate.IsUriFunc([]string{"http", "https", "api", "ms-appx"}, false, false, false)(v, cty.Path{}); diags.HasError() {
return fmt.Errorf("`identifier_uris` is invalid. The URN scheme is not supported when `sign_in_audience` is %q or %q",
msgraph.SignInAudienceAzureADandPersonalMicrosoftAccount, msgraph.SignInAudiencePersonalMicrosoftAccount)
}
Expand Down
21 changes: 15 additions & 6 deletions internal/validate/uri.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import (
)

func IsAppUri(i interface{}, path cty.Path) diag.Diagnostics {
return IsUriFunc([]string{"http", "https", "api", "ms-appx"}, true, false)(i, path)
return IsUriFunc([]string{"http", "https", "api", "ms-appx"}, true, false, false)(i, path)
}

func IsHttpOrHttpsUrl(i interface{}, path cty.Path) diag.Diagnostics {
return IsUriFunc([]string{"http", "https"}, false, false)(i, path)
return IsUriFunc([]string{"http", "https"}, false, true, false)(i, path)
}

func IsHttpsUrl(i interface{}, path cty.Path) diag.Diagnostics {
return IsUriFunc([]string{"https"}, false, false)(i, path)
return IsUriFunc([]string{"https"}, false, true, false)(i, path)
}

func IsLogoutUrl(i interface{}, path cty.Path) (ret diag.Diagnostics) {
ret = IsUriFunc([]string{"http", "https"}, false, false)(i, path)
ret = IsUriFunc([]string{"http", "https"}, false, true, false)(i, path)
if len(ret) > 0 {
return
}
Expand All @@ -47,7 +47,7 @@ func IsRedirectUriFunc(urnAllowed bool, publicClient bool) schema.SchemaValidate
allowedSchemes = []string{"http", "https", "ms-appx-web"}
}

ret = IsUriFunc(allowedSchemes, urnAllowed, true)(i, path)
ret = IsUriFunc(allowedSchemes, urnAllowed, true, true)(i, path)
if len(ret) > 0 {
return
}
Expand All @@ -64,7 +64,7 @@ func IsRedirectUriFunc(urnAllowed bool, publicClient bool) schema.SchemaValidate
}
}

func IsUriFunc(validURLSchemes []string, urnAllowed bool, forceTrailingSlash bool) schema.SchemaValidateDiagFunc {
func IsUriFunc(validURLSchemes []string, urnAllowed bool, allowTrailingSlash bool, forceTrailingSlash bool) schema.SchemaValidateDiagFunc {
return func(i interface{}, path cty.Path) (ret diag.Diagnostics) {
v, ok := i.(string)
if !ok {
Expand Down Expand Up @@ -103,6 +103,15 @@ func IsUriFunc(validURLSchemes []string, urnAllowed bool, forceTrailingSlash boo
return
}

if !allowTrailingSlash && u.Path == "/" {
ret = append(ret, diag.Diagnostic{
Severity: diag.Error,
Summary: "URI must not have a trailing slash when there is no path segment",
AttributePath: path,
})
return
}

if u.Host == "" {
ret = append(ret, diag.Diagnostic{
Severity: diag.Error,
Expand Down
58 changes: 58 additions & 0 deletions internal/validate/uri_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,61 @@ func TestIsAppURI(t *testing.T) {
})
}
}

func TestIsUriFunc(t *testing.T) {
cases := []struct {
TestName string
Url string
UrnAllowed bool
AllowTrailingSlash bool
ForceTrailingSlash bool
Errors int
Schemes []string
}{
{
TestName: "no path with trailing slash not allowed should error",
Url: "http://www.example.com/",
UrnAllowed: true,
AllowTrailingSlash: false,
ForceTrailingSlash: false,
Errors: 1,
Schemes: []string{"http"},
},
{
TestName: "no path with no trailing slash valid",
Url: "http://www.example.com",
UrnAllowed: true,
AllowTrailingSlash: false,
ForceTrailingSlash: false,
Errors: 0,
Schemes: []string{"http"},
},
{
TestName: "path with no trailing slash is valid",
Url: "http://www.example.com/path",
UrnAllowed: true,
AllowTrailingSlash: false,
ForceTrailingSlash: false,
Errors: 0,
Schemes: []string{"http"},
},
{
TestName: "uri empty should not be valid",
Url: "",
UrnAllowed: true,
AllowTrailingSlash: false,
ForceTrailingSlash: false,
Errors: 1,
Schemes: []string{"http"},
},
}

for _, tc := range cases {
t.Run(tc.TestName, func(t *testing.T) {
diags := IsUriFunc(tc.Schemes, tc.UrnAllowed, tc.AllowTrailingSlash, tc.ForceTrailingSlash)
if len(diags(tc.Url, cty.Path{})) != tc.Errors {
t.Fatalf("Expected IsUriFunc to have %d errors for %v", tc.Errors, tc.Url)
}
})
}
}