-
Notifications
You must be signed in to change notification settings - Fork 467
[HealthChecks] Add HealthChecks endpoint, register telemetry publisher #11341
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
base: dev
Are you sure you want to change the base?
Changes from all commits
dc88a63
02dbe40
5ac3a6a
e51ca54
201c711
127ffd6
4b45648
df335d1
33c6dc6
99095cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||
// Copyright (c) .NET Foundation. All rights reserved. | ||||||||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||||||||
|
||||||||
using System; | ||||||||
using System.Threading.Tasks; | ||||||||
using Microsoft.AspNetCore.Authentication; | ||||||||
using Microsoft.AspNetCore.Authorization; | ||||||||
using Microsoft.AspNetCore.Authorization.Policy; | ||||||||
using Microsoft.AspNetCore.Http; | ||||||||
using Microsoft.Azure.WebJobs.Script.WebHost.Security.Authorization.Policies; | ||||||||
|
||||||||
namespace Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.HealthChecks | ||||||||
{ | ||||||||
public sealed class HealthCheckAuthMiddleware( | ||||||||
RequestDelegate next, IPolicyEvaluator policy, IAuthorizationPolicyProvider provider) | ||||||||
{ | ||||||||
private readonly RequestDelegate _next = next ?? throw new ArgumentNullException(nameof(next)); | ||||||||
private readonly IPolicyEvaluator _policy = policy ?? throw new ArgumentNullException(nameof(policy)); | ||||||||
private readonly IAuthorizationPolicyProvider _provider = provider ?? throw new ArgumentNullException(nameof(provider)); | ||||||||
|
||||||||
public async Task InvokeAsync(HttpContext context) | ||||||||
{ | ||||||||
ArgumentNullException.ThrowIfNull(context); | ||||||||
|
||||||||
AuthorizationPolicy policy = await _provider.GetPolicyAsync(PolicyNames.AdminAuthLevel) | ||||||||
.ConfigureAwait(false); | ||||||||
|
||||||||
AuthenticateResult authentication = await _policy.AuthenticateAsync(policy, context) | ||||||||
.ConfigureAwait(false); | ||||||||
|
||||||||
if (!authentication.Succeeded) | ||||||||
{ | ||||||||
context.Response.StatusCode = StatusCodes.Status401Unauthorized; | ||||||||
return; | ||||||||
} | ||||||||
|
||||||||
PolicyAuthorizationResult authorization = await _policy.AuthorizeAsync( | ||||||||
policy, authentication, context, null).ConfigureAwait(false); | ||||||||
|
||||||||
if (!authorization.Succeeded) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. super nit: new lines (same for lines 30-31)
Suggested change
|
||||||||
{ | ||||||||
context.Response.StatusCode = StatusCodes.Status403Forbidden; | ||||||||
return; | ||||||||
} | ||||||||
|
||||||||
await _next(context); | ||||||||
} | ||||||||
} | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,10 +50,12 @@ public void AddScriptHostHealthCheck_ThrowsOnNullBuilder() | |
} | ||
|
||
[Fact] | ||
public void AddWebJobsScriptHealthChecks_RegistersBothHealthChecks() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have any tests that verify the new http routes E2E, e.g. similar to the host API tests we have in SamplesEndToEndTests_CSharp There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added some tests there. |
||
public void AddWebJobsScriptHealthChecks_RegistersExpectedServices() | ||
{ | ||
// arrange | ||
ServiceCollection services = new(); | ||
Mock<IHealthChecksBuilder> builder = new(MockBehavior.Strict); | ||
builder.Setup(b => b.Services).Returns(services); | ||
builder.Setup(b => b.Add(It.IsAny<HealthCheckRegistration>())).Returns(builder.Object); | ||
|
||
// act | ||
|
@@ -67,7 +69,10 @@ public void AddWebJobsScriptHealthChecks_RegistersBothHealthChecks() | |
builder.Verify(b => b.Add(IsRegistration<ScriptHostHealthCheck>( | ||
HealthCheckNames.ScriptHostLifeCycle, HealthCheckTags.Readiness)), | ||
Times.Once); | ||
builder.Verify(b => b.Services, Times.AtLeastOnce); | ||
builder.VerifyNoOtherCalls(); | ||
|
||
VerifyPublishers(services, null, HealthCheckTags.Liveness, HealthCheckTags.Readiness); | ||
} | ||
|
||
[Fact] | ||
|
@@ -216,17 +221,7 @@ public void AddTelemetryPublisher_RegistersExpected(string[] tags, string[] expe | |
builder.AddTelemetryPublisher(tags); | ||
|
||
// assert | ||
services.Where(x => x.ServiceType == typeof(IHealthCheckPublisher)).Should().HaveCount(expected.Length) | ||
.And.AllSatisfy(x => x.Lifetime.Should().Be(ServiceLifetime.Singleton)); | ||
|
||
ServiceProvider provider = services.BuildServiceProvider(); | ||
IEnumerable<IHealthCheckPublisher> publishers = provider.GetServices<IHealthCheckPublisher>(); | ||
|
||
publishers.Should().HaveCount(expected.Length); | ||
foreach (string tag in expected) | ||
{ | ||
publishers.Should().ContainSingle(p => VerifyPublisher(p, tag)); | ||
} | ||
VerifyPublishers(services, expected); | ||
} | ||
|
||
private static HealthCheckRegistration IsRegistration<T>(string name, string tag) | ||
|
@@ -248,6 +243,21 @@ static bool IsType(HealthCheckRegistration registration) | |
}); | ||
} | ||
|
||
private static void VerifyPublishers(IServiceCollection services, params string[] tags) | ||
{ | ||
services.Where(x => x.ServiceType == typeof(IHealthCheckPublisher)).Should().HaveCount(tags.Length) | ||
.And.AllSatisfy(x => x.Lifetime.Should().Be(ServiceLifetime.Singleton)); | ||
|
||
ServiceProvider provider = services.BuildServiceProvider(); | ||
IEnumerable<IHealthCheckPublisher> publishers = provider.GetServices<IHealthCheckPublisher>(); | ||
|
||
publishers.Should().HaveCount(tags.Length); | ||
foreach (string tag in tags) | ||
{ | ||
publishers.Should().ContainSingle(p => VerifyPublisher(p, tag)); | ||
} | ||
} | ||
|
||
private static bool VerifyPublisher(IHealthCheckPublisher publisher, string tag) | ||
{ | ||
return publisher is TelemetryHealthCheckPublisher telemetryPublisher | ||
|
Uh oh!
There was an error while loading. Please reload this page.