-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Authentication not working with auth_settings_v2
because of not-omitted empty validation checks
#20820
Comments
auth_settings_v2
because of not-omited empty validation checksauth_settings_v2
because of not-omitted empty validation checks
The problem is that the app authentication is checking empty lists. Arguments that are not omitted if not empty:
|
For everyone who have this authentication issue:
Removing the lists You can use the Azure Resource Explorer to temporary fix the issue (until the next Terraform deployment): https://resources.azure.com |
It's a much BIGGER issueHey Hashicorp, I think you have a big issue with the new Azure does differentiates between not-existing configuration fields and empty values! DescriptionIn all ExampleIf there is a Terraform model defining a field like: JWTAllowedClientApps []string `tfschema:"jwt_allowed_client_applications"` Terraforms default value will be: But the AllowedClientApplications *[]string `json:"allowedClientApplications,omitempty"` That omits the field from the json, ONLY when the value of the pointer It means that all Terraform azurerm's AllowedClientApplications: pointer.To(aad.JWTAllowedClientApps), ConclusionThere is a great mismatch between Terraform's The deployed services will not working properly because of an invalid appsevice or authentication configuration that exists but is empty. Probably a lot more of services are affected! |
Created a PR in hashicorp/go-azure-helpers to add a new pointer method This could be used to replace all the problematic |
Thanks @mickare for raising this issue, I apologize for not being able to test the empty string list and the null value, can you share more details about how the empty string differs from the null when api is checking this property, did empty list mean anything for this property? |
Hi @xiaxyi, there is a HUGE difference between an "empty list" and a "missing list". Showing the problem with code is much faster. package main
import (
"encoding/json"
"fmt"
)
type Model struct {
X []int `json:"x,omitempty"`
Y *[]int `json:"y,omitempty"`
}
func main() {
var slice []int
a := Model{}
b := Model{slice, &slice}
c := Model{[]int{}, &[]int{}}
d := Model{[]int{1, 2}, &[]int{3, 4}}
fmt.Printf("a: %+v\n", a)
fmt.Printf("b: %+v\n", b)
fmt.Printf("c: %+v\n", c)
fmt.Printf("d: %+v\n", d)
a_json, _ := json.Marshal(a)
b_json, _ := json.Marshal(b)
c_json, _ := json.Marshal(c)
d_json, _ := json.Marshal(d)
fmt.Printf("a->Json: %s\n", a_json)
fmt.Printf("b->Json: %s\n", b_json)
fmt.Printf("c->Json: %s\n", c_json)
fmt.Printf("d->Json: %s\n", d_json)
} Output:
The difference between cases a,b,c show that it does matter if an empty pointer or an empty list is provided to any model that is serialized with json. Case C is the problematic one when |
Can confirm the issue when trying to configure App Service authentication with I used hours to debug the issue, but only difference I found (comparing first the manual and auto-generated app registrations, then the actual Examples of the differences in settings ( Autogenerated (auth working): {
"enabled": true,
"isAutoProvisioned": true,
"login": {
"disableWWWAuthenticate": false
},
"registration": {
"clientId": "xxxxx",
"clientSecretSettingName": "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET",
"openIdIssuer": "https://sts.windows.net/yyyyy/v2.0"
},
"validation": {
"allowedAudiences": [
"api://xxxxx"
],
"defaultAuthorizationPolicy": {
"allowedPrincipals": {}
},
"jwtClaimChecks": {}
}
} Created with Terraform (auth not working, HTTP 500 with no other details): {
"enabled": true,
"login": {
"disableWWWAuthenticate": false,
"loginParameters": []
},
"registration": {
"clientId": "xxxxx",
"clientSecretCertificateThumbprint": "",
"clientSecretSettingName": "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET",
"openIdIssuer": "https://sts.windows.net/yyyyy/v2.0"
},
"validation": {
"allowedAudiences": [
"api://xxxxx"
],
"defaultAuthorizationPolicy": {
"allowedApplications": [],
"allowedPrincipals": {
"groups": [],
"identities": []
}
},
"jwtClaimChecks": {
"allowedClientApplications": [],
"allowedGroups": []
}
}
}
auth_settings_v2 {
auth_enabled = true
require_authentication = true
unauthenticated_action = "Return401"
active_directory_v2 {
client_id = "xxxxx"
tenant_auth_endpoint = "https://sts.windows.net/yyyyy/v2.0"
client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET"
allowed_audiences = [
"api://xxxxx"
]
}
login {
token_store_enabled = true
}
} This makes the |
Thanks @mickare and @teemukj for the update, I see this issue, we do need to make the non-configured field to null, instead of initating it as an empty list... I see you are making PR to the pointer functions from sdk perspective, I'm not sure about how the reviewers' opinion about it, but I'll try seeking for solutions from the RP's perspective. |
Same issue here with data source from a
|
Same, running from Azure Pipelines (Microsoft Hosted Agent) with Service Connection, using Terraform 1.40.0 with AzureRM 3.47.0 on Ubuntu 22.04.2 LTS. Edit: I'd just use Here's some code to reproduce: # Run the script to get the environment variables of interest.
# This is a data source, so it will run at plan time.
# this bit of code says a lot, imho.
data "external" "env" {
program = ["sh", "-c", "jq -n 'env | {ARM_TENANT_ID,ARM_SUBSCRIPTION_ID,ARM_CLIENT_ID,ARM_CLIENT_SECRET}'"]
}
# Define a Resource Group for an Azure App
resource "azurerm_resource_group" "example_rg" {
name = "${var.app_name}-rg"
location = "West Europe"
}
# Define an Azure App Service Plan for Linux
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service_plan
resource "azurerm_service_plan" "example_service_plan" {
name = "${var.app_name}-serviceplan"
location = azurerm_resource_group.example_rg.location
resource_group_name = azurerm_resource_group.example_rg.name
os_type = "Linux"
sku_name = "B1"
}
# Define an Azure Web App
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/azurerm_linux_web_app
resource "azurerm_linux_web_app" "example_wa" {
name = "${var.app_name}"
resource_group_name = azurerm_resource_group.example_rg.name
location = azurerm_service_plan.example_service_plan.location
service_plan_id = azurerm_service_plan.example_service_plan.id
# Enable a System Managed Identity for the Azure Web App
identity {
type = "SystemAssigned"
}
site_config {
# iisnode
application_stack {
node_version = "16-lts"
}
}
# Configure the Azure Web app with your AAD Auth Provider (see web.config)
auth_settings_v2 {
enabled = true
allow_unauthenticated_access = false
issuer = "https://login.microsoftonline.com/${data.external.env.result["ARM_TENANT_ID"]}/v2.0"
default_provider = "AzureActiveDirectory"
client_id = data.external.env.result["ARM_CLIENT_ID"]
client_secret = data.external.env.result["ARM_CLIENT_SECRET"]
additional_login_params = ["scope=openid profile email User.Read"]
token_refresh_extension_hours = 24
token_store_enabled = true
unauthenticated_client_action = "RedirectToLoginPage"
identity_providers {
id = "AzureActiveDirectory"
configuration {
groups_claim = "groups"
allowed_groups = var.app_allowed_groups
}
}
}
}
# Output the Azure Web App URL
output "webapp_url" {
value = "https://${azurerm_linux_web_app.example_wa.default_hostname}"
} Yields
|
@ncook-hxgn |
@teemukj I am using The documentation has no examples of I digress. Given the lack of examples to work from, is there something obviously wrong that you can see in my code? I managed to get Then, given the lack of examples of Edit: Yeah it looks like my terraform is the wrong structure. So, am I correct in thinking that v3.45.0 is when I'm using VS Code, with the Microsoft Terraform Extension.. Edit 2: .It looks a bit like the Edit 3: This works, I get an app deployed. However, upon visiting the app and consenting to permissions, the redirect back to my site via the callback url fails. That's a seperate issue (I raised #20989), and definitely a regression from This code is for the next person looking for an example azurerm_linux_web_app with active_directory_v2: # Run the script to get the environment variables of interest.
# This is a data source, so it will run at plan time.
# this bit of code says a lot, imho.
data "external" "env" {
program = ["sh", "-c", "jq -n 'env | {ARM_TENANT_ID,ARM_SUBSCRIPTION_ID,ARM_CLIENT_ID,ARM_CLIENT_SECRET}'"]
}
# Define a Resource Group for an Azure App
resource "azurerm_resource_group" "example_rg" {
name = "${var.app_name}-rg"
location = "West Europe"
}
# Define an Azure App Service Plan for Linux
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service_plan
resource "azurerm_service_plan" "example_service_plan" {
name = "${var.app_name}-serviceplan"
location = azurerm_resource_group.example_rg.location
resource_group_name = azurerm_resource_group.example_rg.name
os_type = "Linux"
sku_name = "B1"
}
# Define an Azure Web App
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/azurerm_linux_web_app
resource "azurerm_linux_web_app" "example_wa" {
name = "${var.app_name}"
resource_group_name = azurerm_resource_group.example_rg.name
location = azurerm_service_plan.example_service_plan.location
service_plan_id = azurerm_service_plan.example_service_plan.id
# Enable a System Managed Identity for the Azure Web App
identity {
type = "SystemAssigned"
}
# iisnode
site_config {
application_stack {
node_version = "16-lts"
}
}
# Configure the Azure Web app with your AAD Auth Provider (see web.config)
auth_settings_v2 {
auth_enabled = true
require_authentication = true
default_provider = "AzureActiveDirectory"
unauthenticated_action = "RedirectToLoginPage"
# our default_provider:
active_directory_v2 {
tenant_auth_endpoint = "https://login.microsoftonline.com/${data.external.env.result["ARM_TENANT_ID"]}/v2.0"
client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" # should be used instead of ARM_CLIENT_SECRET
client_id = data.external.env.result["ARM_CLIENT_ID"]
allowed_groups = var.app_allowed_groups
}
# use a store for tokens (az blob storage backed)
login {
token_store_enabled = true
}
}
}
# Output the Azure Web App URL
output "webapp_url" {
value = "https://${azurerm_linux_web_app.example_wa.default_hostname}"
} |
I've hit the same issue and resorted to using azapi as a workaround until this bug is resolved. resource "azurerm_linux_web_app" "wa" {
name = var.app_name
resource_group_name = var.resource_group_name
location = var.resource_location
service_plan_id = var.asp_id
identity {
type = "SystemAssigned"
}
site_config {
}
app_settings = {
MICROSOFT_PROVIDER_AUTHENTICATION_SECRET = "${var.auth_secret}"
}
sticky_settings {
app_setting_names = [
"MICROSOFT_PROVIDER_AUTHENTICATION_SECRET"
]
}
lifecycle {
ignore_changes = [
auth_settings_v2
]
}
}
resource "azapi_update_resource" "wa_auth_v2_config" {
type = "Microsoft.Web/sites/config@2022-03-01"
resource_id = "${azurerm_linux_web_app.wa.id}/config/authsettingsV2"
body = jsonencode({
"properties" = {
"globalValidation" = ...,
"httpSettings" = ...,
"identityProviders" = ...,
"login" = ...
})
depends_on = [
azurerm_linux_web_app.wa
]
} It is not quite as nice as the azurerm way, but it works for now. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This functionality has been released in v3.49.0 of the Terraform Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you! |
I tried 3.49, and the problem might be fixed but I can't tell because it crashed. Using the following terraform code (unchanged from before really) # Run the script to get the environment variables of interest.
# This is a data source, so it will run at plan time.
data "external" "env" {
program = ["sh", "-c", "jq -n 'env | {ARM_TENANT_ID,ARM_SUBSCRIPTION_ID,ARM_CLIENT_ID,ARM_CLIENT_SECRET}'"]
}
# Define a Resource Group for an Azure App
resource "azurerm_resource_group" "example_rg" {
name = "${var.app_name}-rg"
location = "West Europe"
}
# Define an Azure App Service Plan for Linux
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service_plan
resource "azurerm_service_plan" "example_service_plan" {
name = "${var.app_name}-serviceplan"
location = azurerm_resource_group.example_rg.location
resource_group_name = azurerm_resource_group.example_rg.name
os_type = "Linux"
sku_name = "B1"
}
# Define an Azure Web App
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/azurerm_linux_web_app
resource "azurerm_linux_web_app" "example_wa" {
name = "${var.app_name}"
resource_group_name = azurerm_resource_group.example_rg.name
location = azurerm_service_plan.example_service_plan.location
service_plan_id = azurerm_service_plan.example_service_plan.id
# Enable a System Managed Identity for the Azure Web App
identity {
type = "SystemAssigned"
}
# iisnode
site_config {
application_stack {
node_version = "16-lts"
}
}
# Configure the Azure Web app with your AAD Auth Provider (see web.config)
#auth_settings {
# enabled = true
# issuer = "https://sts.windows.net/${data.external.env.result["ARM_TENANT_ID"]}"
# default_provider = "AzureActiveDirectory"
# token_refresh_extension_hours = 24
# token_store_enabled = true
# unauthenticated_client_action = "RedirectToLoginPage"
#
# active_directory {
# client_id = data.external.env.result["ARM_CLIENT_ID"]
# client_secret = data.external.env.result["ARM_CLIENT_SECRET"]
# }
#}
# Configure the Azure Web app with your AAD Auth Provider (see web.config)
auth_settings_v2 {
auth_enabled = true
require_authentication = true
default_provider = "AzureActiveDirectory"
unauthenticated_action = "RedirectToLoginPage"
# our default_provider:
active_directory_v2 {
tenant_auth_endpoint = "https://login.microsoftonline.com/${data.external.env.result["ARM_TENANT_ID"]}/v2.0"
client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" # should be used instead of ARM_CLIENT_SECRET
client_id = data.external.env.result["ARM_CLIENT_ID"]
# client_secret = data.external.env.result["ARM_CLIENT_SECRET"]
allowed_groups = var.app_allowed_groups
}
# use a store for tokens (az blob storage backed)
login {
token_store_enabled = true
}
}
}
# Output the Azure Web App URL
output "webapp_url" {
value = "https://${azurerm_linux_web_app.example_wa.default_hostname}"
} This is the output I got:
|
I have exactly the same issue. Does anyone work on this? |
Fix is already merged in #21113 and will be in next release :) |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
Is there an existing issue for this?
Community Note
Terraform Version
1.3.9
AzureRM Provider Version
3.45.0
Affected Resource(s)/Data Source(s)
azurerm_linux_web_app
Terraform Configuration Files
Debug Output/Panic Output
Expected Behaviour
Expected resource json in
authsettingsV2
.Actual Behaviour
Actual resource json in
authsettingsV2
.Steps to Reproduce
No response
Important Factoids
No response
References
#20676
The text was updated successfully, but these errors were encountered: