Skip to content

Commit 6f7f822

Browse files
committed
Adding anonymous host/ping API
1 parent da67ce8 commit 6f7f822

File tree

5 files changed

+98
-9
lines changed

5 files changed

+98
-9
lines changed

src/WebJobs.Script.WebHost/Controllers/AdminController.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ public HostStatus GetHostStatus()
103103
return status;
104104
}
105105

106+
[HttpPost]
107+
[Route("admin/host/ping")]
108+
[AllowAnonymous]
109+
public HttpResponseMessage Ping()
110+
{
111+
return new HttpResponseMessage(HttpStatusCode.OK);
112+
}
113+
106114
[HttpPost]
107115
[Route("admin/host/debug")]
108116
public HttpResponseMessage LaunchDebugger()

src/WebJobs.Script.WebHost/Filters/AuthorizationLevelAttribute.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Net.Http;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using System.Web.Http;
1112
using System.Web.Http.Controllers;
1213
using System.Web.Http.Filters;
1314

@@ -31,6 +32,11 @@ public async override Task OnAuthorizationAsync(HttpActionContext actionContext,
3132
throw new ArgumentNullException("actionContext");
3233
}
3334

35+
if (SkipAuthorization(actionContext))
36+
{
37+
return;
38+
}
39+
3440
ISecretManager secretManager = actionContext.ControllerContext.Configuration.DependencyResolver.GetService<ISecretManager>();
3541
var settings = actionContext.ControllerContext.Configuration.DependencyResolver.GetService<WebHostSettings>();
3642

@@ -99,5 +105,11 @@ internal static async Task<AuthorizationLevel> GetAuthorizationLevelAsync(HttpRe
99105

100106
return AuthorizationLevel.Anonymous;
101107
}
108+
109+
internal static bool SkipAuthorization(HttpActionContext actionContext)
110+
{
111+
return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0
112+
|| actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0;
113+
}
102114
}
103115
}

src/WebJobs.Script.WebHost/GlobalSuppressions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,4 @@
8888
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.#.ctor(Microsoft.Azure.WebJobs.Script.ScriptHostConfiguration,Microsoft.Azure.WebJobs.Script.WebHost.ISecretManagerFactory,Microsoft.Azure.WebJobs.Script.Config.ScriptSettingsManager,Microsoft.Azure.WebJobs.Script.WebHost.WebHostSettings,Microsoft.Azure.WebJobs.Script.IScriptHostFactory)")]
8989
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.MetricsEventManager.#BeginEvent(System.String,System.String)")]
9090
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemMetricEvent.#DebugValue")]
91+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Controllers.AdminController.#Ping()")]

test/WebJobs.Script.Tests.Integration/SamplesEndToEndTests.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
using System.Net.Http.Headers;
1111
using System.Reflection;
1212
using System.Text;
13-
using System.Threading;
1413
using System.Threading.Tasks;
1514
using System.Web.Http;
16-
using System.Web.Http.Hosting;
1715
using System.Xml.Linq;
1816
using Microsoft.Azure.WebJobs.Host;
1917
using Microsoft.Azure.WebJobs.Script.Config;
@@ -22,15 +20,13 @@
2220
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
2321
using Microsoft.ServiceBus;
2422
using Microsoft.ServiceBus.Messaging;
25-
using Microsoft.WebJobs.Script.Tests;
2623
using Microsoft.WindowsAzure.Storage;
2724
using Microsoft.WindowsAzure.Storage.Blob;
2825
using Microsoft.WindowsAzure.Storage.Queue;
2926
using Microsoft.WindowsAzure.Storage.Table;
3027
using Newtonsoft.Json;
3128
using Newtonsoft.Json.Linq;
3229
using Xunit;
33-
using static Microsoft.Azure.WebJobs.Script.Tests.FunctionGeneratorTests;
3430

3531
namespace Microsoft.Azure.WebJobs.Script.Tests
3632
{
@@ -910,6 +906,15 @@ public async Task ServiceBusTopicTrigger_ManualInvoke_Succeeds()
910906
Assert.Equal(value, result.Trim());
911907
}
912908

909+
[Fact]
910+
public async Task HostPing_Succeeds()
911+
{
912+
string uri = "admin/host/ping";
913+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
914+
HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
915+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
916+
}
917+
913918
[Fact]
914919
public async Task HostStatus_Succeeds()
915920
{

test/WebJobs.Script.Tests/Filters/AuthorizationLevelAttributeTests.cs

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Net;
77
using System.Net.Http;
8+
using System.Reflection;
89
using System.Threading;
910
using System.Threading.Tasks;
1011
using System.Web.Http;
@@ -35,11 +36,9 @@ public class AuthorizationLevelAttributeTests
3536

3637
public AuthorizationLevelAttributeTests()
3738
{
38-
_actionContext = new HttpActionContext();
39-
HttpControllerContext controllerContext = new HttpControllerContext();
40-
_actionContext.ControllerContext = controllerContext;
41-
HttpConfiguration httpConfig = new HttpConfiguration();
42-
controllerContext.Configuration = httpConfig;
39+
var httpConfig = new HttpConfiguration();
40+
_actionContext = CreateActionContext(typeof(TestController).GetMethod("Get"), httpConfig);
41+
4342
Mock<IDependencyResolver> mockDependencyResolver = new Mock<IDependencyResolver>(MockBehavior.Strict);
4443
httpConfig.DependencyResolver = mockDependencyResolver.Object;
4544
_mockSecretManager = new Mock<ISecretManager>(MockBehavior.Strict);
@@ -301,5 +300,69 @@ public async Task GetAuthorizationLevel_InvalidCodeQueryParam_ReturnsAnonymous()
301300

302301
Assert.Equal(AuthorizationLevel.Anonymous, level);
303302
}
303+
304+
[Fact]
305+
public static void SkipAuthorization_AllowAnonymous_MethodLevel_ReturnsTrue()
306+
{
307+
var actionContext = CreateActionContext(typeof(TestController).GetMethod("GetAnonymous"));
308+
Assert.True(AuthorizationLevelAttribute.SkipAuthorization(actionContext));
309+
}
310+
311+
[Fact]
312+
public static void SkipAuthorization_AllowAnonymous_ClassLevel_ReturnsTrue()
313+
{
314+
var actionContext = CreateActionContext(typeof(AnonymousTestController).GetMethod("Get"));
315+
Assert.True(AuthorizationLevelAttribute.SkipAuthorization(actionContext));
316+
317+
actionContext = CreateActionContext(typeof(AnonymousTestController).GetMethod("GetAnonymous"));
318+
Assert.True(AuthorizationLevelAttribute.SkipAuthorization(actionContext));
319+
}
320+
321+
[Fact]
322+
public static void SkipAuthorization_AllowAnonymousNotSpecified_ReturnsFalse()
323+
{
324+
var actionContext = CreateActionContext(typeof(TestController).GetMethod("Get"));
325+
Assert.False(AuthorizationLevelAttribute.SkipAuthorization(actionContext));
326+
}
327+
328+
private static HttpActionContext CreateActionContext(MethodInfo action, HttpConfiguration config = null)
329+
{
330+
config = config ?? new HttpConfiguration();
331+
var actionContext = new HttpActionContext();
332+
var controllerDescriptor = new HttpControllerDescriptor(config, action.ReflectedType.Name, action.ReflectedType);
333+
var controllerContext = new HttpControllerContext();
334+
controllerContext.ControllerDescriptor = controllerDescriptor;
335+
actionContext.ControllerContext = controllerContext;
336+
var actionDescriptor = new ReflectedHttpActionDescriptor(controllerDescriptor, action);
337+
actionContext.ActionDescriptor = actionDescriptor;
338+
controllerContext.Configuration = config;
339+
340+
return actionContext;
341+
}
342+
343+
public class TestController : ApiController
344+
{
345+
public void Get()
346+
{
347+
}
348+
349+
[AllowAnonymous]
350+
public void GetAnonymous()
351+
{
352+
}
353+
}
354+
355+
[AllowAnonymous]
356+
public class AnonymousTestController : ApiController
357+
{
358+
public void Get()
359+
{
360+
}
361+
362+
[AllowAnonymous]
363+
public void GetAnonymous()
364+
{
365+
}
366+
}
304367
}
305368
}

0 commit comments

Comments
 (0)