コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #9
0
        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));
        }
コード例 #10
0
        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);
        }
コード例 #14
0
        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);
        }
コード例 #15
0
        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);
        }
コード例 #17
0
        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);
        }
コード例 #18
0
        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);
        }
コード例 #25
0
        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);
        }
コード例 #26
0
        public void HasAuthorizationLevelAttribute()
        {
            AuthorizationLevelAttribute attribute = typeof(AdminController).GetCustomAttribute <AuthorizationLevelAttribute>();

            Assert.Equal(AuthorizationLevel.Admin, attribute.Level);
        }
コード例 #27
0
        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);
        }
コード例 #28
0
        public static void SkipAuthorization_AllowAnonymousNotSpecified_ReturnsFalse()
        {
            var actionContext = CreateActionContext(typeof(TestController).GetMethod("Get"));

            Assert.False(AuthorizationLevelAttribute.SkipAuthorization(actionContext));
        }