private bool GetAuthorizationLevelAsync_CalledWithSingleThreadedContext_DoesNotDeadlock(ISecretManager secretManager) { var resetEvent = new ManualResetEvent(false); var thread = new Thread(() => { HttpRequestMessage request = new HttpRequestMessage(); request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, TestFunctionKeyValue1); var context = new SingleThreadedSynchronizationContext(true); SynchronizationContext.SetSynchronizationContext(context); AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, secretManager, functionName: "TestFunction") .ContinueWith(t => { context.Stop(); resetEvent.Set(); }); context.Run(); }); thread.IsBackground = true; thread.Start(); bool eventSignaled = resetEvent.WaitOne(TimeSpan.FromSeconds(5)); thread.Abort(); return(eventSignaled); }
public void GetAuthorizationLevel_InvalidKeyQueryParam_ReturnsAnonymous() { Uri uri = new Uri(string.Format("http://functions/api/foo?key={0}", "invalid")); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object); Assert.Equal(AuthorizationLevel.Anonymous, level); }
public void GetAuthorizationLevel_InvalidKeyHeader_ReturnsAnonymous() { HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, "invalid"); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object); Assert.Equal(AuthorizationLevel.Anonymous, level); }
public void GetAuthorizationLevel_ValidCodeQueryParam_MasterKey_ReturnsAdmin() { Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", testMasterKeyValue)); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object); Assert.Equal(AuthorizationLevel.Admin, level); }
public void GetAuthorizationLevel_ValidKeyHeader_MasterKey_ReturnsAdmin() { HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, testMasterKeyValue); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object); Assert.Equal(AuthorizationLevel.Admin, level); }
public async Task GetAuthorizationLevel_ValidCodeQueryParam_SystemKey_ReturnsSystem() { Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", TestSystemKeyValue1)); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); AuthorizationLevel level = await AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.System, level); }
public async Task GetAuthorizationLevel_InvalidCodeQueryParam_ReturnsAnonymous() { Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", "invalid")); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); AuthorizationLevel level = await AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.Anonymous, level); }
public async Task GetAuthorizationLevel_ValidCodeQueryParam_MasterKey_ReturnsAdmin() { Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", TestMasterKeyValue)); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); var result = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.Admin, result.AuthorizationLevel); }
public static void SkipAuthorization_AllowAnonymous_ClassLevel_ReturnsTrue() { var actionContext = CreateActionContext(typeof(AnonymousTestController).GetMethod("Get")); Assert.True(AuthorizationLevelAttribute.SkipAuthorization(actionContext)); actionContext = CreateActionContext(typeof(AnonymousTestController).GetMethod("GetAnonymous")); Assert.True(AuthorizationLevelAttribute.SkipAuthorization(actionContext)); }
public static async Task <AuthorizationLevel> DetermineAuthorizationLevelAsync(HttpRequestMessage request, FunctionDescriptor function, IDependencyResolver resolver) { var secretManager = resolver.GetService <ISecretManager>(); var authorizationLevel = await AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, secretManager, functionName : function.Name); request.SetAuthorizationLevel(authorizationLevel); return(authorizationLevel); }
public void OnAuthorization_AnonymousLevel_Succeeds() { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Anonymous); _actionContext.ControllerContext.Request = new HttpRequestMessage(); attribute.OnAuthorization(_actionContext); Assert.Null(_actionContext.Response); }
public async Task GetAuthorizationLevel_InvalidKeyHeader_ReturnsAnonymous() { HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, "invalid"); var result = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.Anonymous, result.AuthorizationLevel); }
public async Task GetAuthorizationLevel_ValidKeyHeader_MasterKey_ReturnsAdmin() { HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, TestMasterKeyValue); var result = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.Admin, result.AuthorizationLevel); }
public async Task OnAuthorization_AnonymousLevel_Succeeds() { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Anonymous); _actionContext.ControllerContext.Request = new HttpRequestMessage(); await attribute.OnAuthorizationAsync(_actionContext, CancellationToken.None); Assert.Null(_actionContext.Response); }
public async Task GetAuthorizationLevel_ValidCodeQueryParam_WithNamedKeyRequirement_ReturnsExpectedLevel(string keyName, string keyValue, AuthorizationLevel expectedLevel, string functionName = null) { Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", keyValue)); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); Func <IDictionary <string, string>, string, bool> evaluator = (secrets, value) => SystemAuthorizationLevelAttribute.EvaluateKeyMatch(secrets, value, keyName); AuthorizationLevel level = await AuthorizationLevelAttribute.GetAuthorizationLevelAsync(request, MockSecretManager.Object, evaluator, functionName : functionName); Assert.Equal(expectedLevel, level); }
public void OnAuthorization_AdminLevel_ValidHeader_Succeeds() { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Admin); HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, "abc123"); _actionContext.ControllerContext.Request = request; attribute.OnAuthorization(_actionContext); Assert.Null(_actionContext.Response); }
public static async Task <AuthorizationLevel> DetermineAuthorizationLevelAsync(HttpRequestMessage request, FunctionDescriptor function, IDependencyResolver resolver) { var secretManager = resolver.GetService <ISecretManager>(); var authorizationResult = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, secretManager, functionName : function.Name); var authorizationLevel = authorizationResult.AuthorizationLevel; request.SetAuthorizationLevel(authorizationLevel); request.SetProperty(ScriptConstants.AzureFunctionsHttpRequestKeyNameKey, authorizationResult.KeyName); return(authorizationLevel); }
public async Task OnAuthorization_AdminLevel_ValidHeader_Succeeds() { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Admin); HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, "abc123"); _actionContext.ControllerContext.Request = request; await attribute.OnAuthorizationAsync(_actionContext, CancellationToken.None); Assert.Null(_actionContext.Response); }
public void GetAuthorizationLevel_ValidCodeQueryParam_FunctionKey_ReturnsFunction(string hostFunctionKeyValue, string functionKeyValue) { // first try host level function key Uri uri = new Uri(string.Format("http://functions/api/foo?code={0}", hostFunctionKeyValue)); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object, functionName: "TestFunction"); Assert.Equal(AuthorizationLevel.Function, level); uri = new Uri(string.Format("http://functions/api/foo?code={0}", functionKeyValue)); request = new HttpRequestMessage(HttpMethod.Get, uri); level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object, functionName: "TestFunction"); Assert.Equal(AuthorizationLevel.Function, level); }
public void GetAuthorizationLevel_ValidKeyHeader_FunctionKey_ReturnsFunction(string hostFunctionKeyValue, string functionKeyValue) { // first verify the host level function key works HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, hostFunctionKeyValue); AuthorizationLevel level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object); Assert.Equal(AuthorizationLevel.Function, level); // test function specific key request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, functionKeyValue); level = AuthorizationLevelAttribute.GetAuthorizationLevel(request, _mockSecretManager.Object, functionName: "TestFunction"); Assert.Equal(AuthorizationLevel.Function, level); }
public void OnAuthorization_AdminLevel_NoMasterKeySet_ReturnsUnauthorized() { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Admin); _hostSecrets.MasterKey = null; HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, testMasterKeyValue); _actionContext.ControllerContext.Request = request; attribute.OnAuthorization(_actionContext); HttpResponseMessage response = _actionContext.Response; Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); }
public async Task OnAuthorization_WithNamedKeyHeader_Succeeds() { var attribute = new AuthorizationLevelAttribute(AuthorizationLevel.System, TestSystemKeyName1); HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, TestSystemKeyValue1); var actionContext = CreateActionContext(typeof(TestController).GetMethod(nameof(TestController.Get)), HttpConfig); actionContext.ControllerContext.Request = request; await attribute.OnAuthorizationAsync(actionContext, CancellationToken.None); Assert.Null(actionContext.Response); }
public void OnAuthorization_AdminLevel_InvalidHeader_ReturnsUnauthorized(string headerValue) { AuthorizationLevelAttribute attribute = new AuthorizationLevelAttribute(AuthorizationLevel.Admin); HttpRequestMessage request = new HttpRequestMessage(); if (headerValue != null) { request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, headerValue); } _actionContext.ControllerContext.Request = request; attribute.OnAuthorization(_actionContext); HttpResponseMessage response = _actionContext.Response; Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); }
public async Task GetAuthorizationLevel_ValidKeyHeader_FunctionKey_ReturnsFunction(string hostFunctionKeyValue, string functionKeyValue) { // first verify the host level function key works HttpRequestMessage request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, hostFunctionKeyValue); var result = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, MockSecretManager.Object); Assert.Equal(AuthorizationLevel.Function, result.AuthorizationLevel); // test function specific key request = new HttpRequestMessage(); request.Headers.Add(AuthorizationLevelAttribute.FunctionsKeyHeaderName, functionKeyValue); result = await AuthorizationLevelAttribute.GetAuthorizationResultAsync(request, MockSecretManager.Object, functionName : "TestFunction"); Assert.Equal(AuthorizationLevel.Function, result.AuthorizationLevel); }
public override async Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { HttpRequestMessage request = controllerContext.Request; // First see if the request maps to an HTTP function FunctionDescriptor function = _scriptHostManager.GetHttpFunctionOrNull(request.RequestUri); if (function == null) { return(new HttpResponseMessage(HttpStatusCode.NotFound)); } // Authorize the request SecretManager secretManager = (SecretManager)controllerContext.Configuration.DependencyResolver.GetService(typeof(SecretManager)); HttpBindingMetadata httpFunctionMetadata = (HttpBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger); bool isWebHook = !string.IsNullOrEmpty(httpFunctionMetadata.WebHookType); if (!isWebHook && !AuthorizationLevelAttribute.IsAuthorized(request, httpFunctionMetadata.AuthLevel, secretManager, functionName: function.Name)) { return(new HttpResponseMessage(HttpStatusCode.Unauthorized)); } HttpResponseMessage response = null; if (isWebHook) { // This is a WebHook request so define a delegate for the user function. // The WebHook Receiver pipeline will first validate the request fully // then invoke this callback. Func <HttpRequestMessage, Task <HttpResponseMessage> > invokeFunction = async(req) => { return(await _scriptHostManager.HandleRequestAsync(function, req, cancellationToken)); }; response = await _webHookReceiverManager.HandleRequestAsync(function, request, invokeFunction); } else { // Not a WebHook request so dispatch directly response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken); } return(response); }
public void HasAuthorizationLevelAttribute() { AuthorizationLevelAttribute attribute = typeof(AdminController).GetCustomAttribute <AuthorizationLevelAttribute>(); Assert.Equal(AuthorizationLevel.Admin, attribute.Level); }
public override async Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { HttpRequestMessage request = controllerContext.Request; // First see if the request maps to an HTTP function FunctionDescriptor function = _scriptHostManager.GetHttpFunctionOrNull(request.RequestUri); if (function == null) { return(new HttpResponseMessage(HttpStatusCode.NotFound)); } // Determine the authorization level of the request SecretManager secretManager = controllerContext.Configuration.DependencyResolver.GetService <SecretManager>(); AuthorizationLevel authorizationLevel = AuthorizationLevelAttribute.GetAuthorizationLevel(request, secretManager, functionName: function.Name); if (function.Metadata.IsExcluded || (function.Metadata.IsDisabled && authorizationLevel != AuthorizationLevel.Admin)) { // disabled functions are not publically addressable w/o Admin level auth, // and excluded functions are also ignored here (though the check above will // already exclude them) return(new HttpResponseMessage(HttpStatusCode.NotFound)); } // Dispatch the request HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => string.Compare("HttpTrigger", p.Type, StringComparison.OrdinalIgnoreCase) == 0); bool isWebHook = !string.IsNullOrEmpty(httpFunctionMetadata.WebHookType); HttpResponseMessage response = null; if (isWebHook) { if (authorizationLevel == AuthorizationLevel.Admin) { // Admin level requests bypass the WebHook auth pipeline response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken); } else { // This is a WebHook request so define a delegate for the user function. // The WebHook Receiver pipeline will first validate the request fully // then invoke this callback. Func <HttpRequestMessage, Task <HttpResponseMessage> > invokeFunction = async(req) => { // Reset the content stream before passing the request down to the function Stream stream = await req.Content.ReadAsStreamAsync(); stream.Seek(0, SeekOrigin.Begin); return(await _scriptHostManager.HandleRequestAsync(function, req, cancellationToken)); }; response = await _webHookReceiverManager.HandleRequestAsync(function, request, invokeFunction); } } else { // Authorize if (authorizationLevel < httpFunctionMetadata.AuthLevel) { return(new HttpResponseMessage(HttpStatusCode.Unauthorized)); } // Validate the HttpMethod // Note that for WebHook requests, WebHook receiver does its own validation if (httpFunctionMetadata.Methods != null && !httpFunctionMetadata.Methods.Contains(request.Method)) { return(new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)); } // Not a WebHook request so dispatch directly response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken); } return(response); }
public static void SkipAuthorization_AllowAnonymousNotSpecified_ReturnsFalse() { var actionContext = CreateActionContext(typeof(TestController).GetMethod("Get")); Assert.False(AuthorizationLevelAttribute.SkipAuthorization(actionContext)); }