Azure App Insights 中的异常过多(已恢复)
Posted
技术标签:
【中文标题】Azure App Insights 中的异常过多(已恢复)【英文标题】:Too many (recovered) exceptions in Azure App Insights 【发布时间】:2021-10-26 08:11:06 【问题描述】:我有一个问题:Application Insights 收到太多误报,并且正在发送有关异常情况的邮件,经过调查,这些异常情况不会对我们的应用程序造成任何问题
总结,TL;DR
这是一个 X->Y 问题。问题 Y 是 AAI 正在记录大量服务器异常,请参阅详细说明,并向我们发送警报。问题 X 是 JWT 身份验证中间件抛出关于不匹配密钥的异常,但正在恢复所有这些异常,并切换到不同的 OIDC 提供程序。结果调用成功。
我可以做些什么来修复这些异常或将这些异常列入白名单?
问题 2:异常何时记录到 AAI?仅当它们未处理或记录器决定处理时?
上下文
我们的应用程序通过经过身份验证的 webhook 从 Twilio Sendgrid 接收电子邮件数据。它还允许我们的 B2C 租户用户访问应用程序并浏览数据/统计信息。
B2C 不允许客户端凭据流动,并且 Sendgrid 不支持范围。 最终我们最终使用了两个 OIDC 提供程序:用于交互用户的 Azure AD B2C,以及内存中的 OpenIddict 向我们验证 Sendgrid 服务。
一些代码
public void ConfigureServices(IServiceCollection services)
services.AddLogging(
configuration => configuration
.AddApplicationInsights()
.SetMinimumLevel(LogLevel.Trace)
.AddConsole()
);
services.ConfigureOpenIddictAuthentication();
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration)
//.EnableTokenAcquisitionToCallDownstreamApi()
//.AddInMemoryTokenCaches()
;
services.AddAuthorization(authorization => authorization
.AddPolicy("AzureSendgridPolicy", policy => policy
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme,
OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)
)
);
public static IServiceCollection ConfigureOpenIddictAuthentication(this IServiceCollection services)
services.AddDbContext<OpenIddictDbContext>(ef => ef
// Configure the context to use an in-memory store.
// This prevents multiple cluster instances from deployment
.UseInMemoryDatabase(nameof(OpenIddictDbContext))
// Register the entity sets needed by OpenIddict.
.UseOpenIddict()
)
.AddOpenIddict(options =>
options.AddServer(server => server
.DisableAccessTokenEncryption() //Just for development
//Development: no time to waste on certificate management today
.AddEphemeralEncryptionKey()
.AddEphemeralSigningKey()
.RegisterClaims(OpenIddictConstants.Claims.Role)
.RegisterScopes(OpenIddictConstants.Scopes.Roles)
.SetTokenEndpointUris("/api/v1/Auth/token")
.SetAuthorizationEndpointUris("/api/v1/Auth/authorize")
.AllowClientCredentialsFlow() //Only one supported by Sendgrid
.UseAspNetCore()
.EnableTokenEndpointPassthrough())
.AddCore(core => core.UseEntityFrameworkCore(ef => ef.UseDbContext<OpenIddictDbContext>()))
.AddValidation(validation => validation
.UseLocalServer(_ => )
.UseAspNetCore(_ => )
)
)
.AddHostedService<OpenIddictHostedService>()
.AddAuthentication()
;
return services;
Azure 应用程序洞察
在AAI上,我发现最常抛出的异常是SecurityTokenUnableToValidateException
它被抛出很多次,比真正的401
s 要多得多。由于开发环境中的临时密钥,每次重新启动应用程序时,OpenIddict 都会重新生成 JWK。
但仔细观察一些痕迹,我发现这不是错误
这是我的发现:
服务器返回 204 作为涉及的数据库,100% 向数据库写入数据(401 不涉及 EF 的数据库访问) 异常分析发现异常中指定的JWK异常分析
查看抛出的异常,这是来自 AAI 的描述性文本
IDX10516: Signature validation failed. Unable to match key:
kid: 'RMHQYNQ4TV9KUHI2EI-INM-XYSOF_1RETVYMWQGE'.
Exceptions caught:
''.
token: '"alg":"RS256","kid":"RMHQYNQ4TV9KUHI2EI-INM-XYSOF_1RETVYMWQGE","typ":"at+jwt"."sub":"SendgridWebhook","name":"Sendgrid Webhook API","oi_prst":"SendgridWebhook","client_id":"SendgridWebhook","oi_tkn_id":"8d0d5f94-2094-4a21-b84d-304d1d99e3fb","exp":1629910230,"iss":"https://****.azurewebsites.net/","iat":1629906630'. Valid Lifetime: 'True'. Valid Issuer: 'False'
堆栈跟踪
Microsoft.IdentityModel.Tokens.SecurityTokenUnableToValidateException:
at Microsoft.IdentityModel.Tokens.InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt (Microsoft.IdentityModel.Tokens, Version=6.10.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature (System.IdentityModel.Tokens.Jwt, Version=6.10.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken (System.IdentityModel.Tokens.Jwt, Version=6.10.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler+<HandleAuthenticateAsync>d__6.MoveNext (Microsoft.AspNetCore.Authentication.JwtBearer, Version=5.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
我确定会发生以下情况
-
应用收到 JWT
由于注册了多个 OIDC 提供程序,运行时会同时获取 B2C 和自身应用程序的 JWK
根据 B2C 密钥验证 JWT,失败
已根据自身密钥验证 JWT,成功
已授予访问权限
我相信在框架中的某个地方,代码结构良好,如下所示。由于要尝试多个提供程序,因此只有当所有提供程序都失败时才会引发异常。否则,简单的 for 循环将作为对异常的恢复
object principal = null;
Exception toThrow = null;
for (IAuthenticationProvider provider: GetProviders)
try
principal = provider.Authenticate(jwt);
catch(SomeKindOfJwtException ex)
toThrow = ex;
if (principal == null) //and perhaps the exception is not null
throw toThrow;
看看那个 JWK RMHQYNQ4TV9KUHI2EI-INM-XYSOF_1RETVYMWQGE
,我可以通过浏览器导航 https://***.azurewebsites.net/.well-known/jwks
轻松找到它
"keys": [
"kid": "RMHQYNQ4TV9KUHI2EI-INM-XYSOF_1RETVYMWQGE",
"use": "sig",
"kty": "RSA",
"alg": "RS256",
"e": "AQAB",
"n": "rMhqYnq4tv9kuHi2Ei-Inm-xysof_1retVymwqGeQ4hnlCRgrMAODGD4qxybhnpufuitEQRckCb4P49O_qafSQ0ocgRRIIuQJc-vLhLJHGp681_9cZT-jGxHnGw5Jdr0NZxH8RwV6cXcmpRN6f2WupujyhLLNwuu8aaTrucHA3JXshib9ad9R96OacT1r6X77HHXdSzURLRWH-f2JFwpBjOvVfJPxW4dzPY0BT7CzP3lxVvGiNXOp4-E8kVz1jER2EP5wO0Ho2qjlIbGUvGF1ui7GxLItldDs-PkZOGGvsO7yS7aeQHSiMTJt7EO-w-ffCJYv-ZColAiHO9jNL0NmQ"
]
我也做得太多,偷看微软的资源。 Here 应该是抛出异常的地方,可能 here 应该是记录异常的地方
【问题讨论】:
【参考方案1】:我可以做些什么来修复这些异常或将这些异常列入白名单?
添加telemetry filter。根据异常遥测,您可以决定放弃遥测。
问题 2:异常何时记录到 AAI?仅当它们未处理或记录器决定处理时?
当未处理时,或当指示这样做时。例如,当使用 ILogger
记录异常时,在使用 AAI ILogger (see docs) 时也会将其记录到 AAI 中
【讨论】:
从我链接的微软代码来看,JWTHandler 将失败的尝试记录到记录器,记录器配置为记录到 AAI。我将尝试过滤遥测数据,并希望在答案上打一个绿色复选标记 不认为您可以发布一个示例过滤器来实现这一点?我有完全相同的场景,我怀疑过滤器是减少 AAI 噪声的唯一方法。谢谢!以上是关于Azure App Insights 中的异常过多(已恢复)的主要内容,如果未能解决你的问题,请参考以下文章
text Azure App Insights Kubernetes日志
从 Azure Application Insights 连续导出的 ParsedStack 异常的流分析查询
用于 Python 应用程序的 Azure Application Insights 日志记录 - 显式设置异常属性
如何使用 Pyspark 提取 Azure Application Insights 事件?