예제 #1
0
        public void TryParse_WhenArnIsValid()
        {
            var expected = ApiGatewayArn.Parse(_methodArn);

            Assert.True(ApiGatewayArn.TryParse(_methodArn, out var actual));
            Assert.Equal(expected.ToString(), actual.ToString());
        }
예제 #2
0
        public static AuthPolicyBuilder Validade(string token,
                                                 string method,
                                                 ILambdaLogger logger)
        {
            try
            {
                var methodArn  = ApiGatewayArn.Parse(method);
                var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage);

                var policyBuilder = new AuthPolicyBuilder("", methodArn.AwsAccountId, apiOptions);

                var isValid = token.Equals("7793B690-9EC7-4240-A152-1D3046693CB3");

                if (isValid)
                {
                    policyBuilder.AllowMethod(new HttpVerb(methodArn.Verb), methodArn.Resource);
                }
                else
                {
                    policyBuilder.DenyMethod(new HttpVerb(methodArn.Verb), methodArn.Resource);
                }

                return(policyBuilder);
            }
            catch (Exception e)
            {
                logger.LogLine($"Error {e.Message} at {e.StackTrace}");

                return(default);
예제 #3
0
        public AuthPolicy FunctionHandler(TokenAuthorizerContext input, ILambdaContext context)
        {
            try
            {
                IdentityModelEventSource.ShowPII = true;

                context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}");
                context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}");
                var result      = Validator.Validate(input.AuthorizationToken, ProjectId);
                var principalId = result.IsValid ? result.Token.Payload.Sub : null;
                context.Logger.LogLine($"Is sub={principalId} valid: {result.IsValid}");
                var methodArn     = ApiGatewayArn.Parse(input.MethodArn);
                var apiOptions    = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage);
                var policyBuilder = new AuthPolicyBuilder(principalId, methodArn.AwsAccountId, apiOptions);
                if (principalId != null)
                {
                    policyBuilder.AllowAllMethods();
                }
                else
                {
                    policyBuilder.AllowMethod(HttpVerb.Post, "/api/scrape/scrape");
                }

                var authResponse = policyBuilder.Build();
                return(authResponse);
            }
            catch (Exception ex)
            {
                context.Logger.LogLine($"Exception caught: {JsonConvert.SerializeObject(ex)}");
                throw ex;
            }
        }
예제 #4
0
        public void ToString_ReturnsExpectedString()
        {
            var expected = $"{_methodArn}/";

            var actual = ApiGatewayArn.Parse(_methodArn).ToString();

            Assert.Equal(expected, actual);
        }
예제 #5
0
        public void Parse_Throws_WhenArnIsInvalid()
        {
            var invalidArn = "this-is-an-invalid-arn";

            var actual = Record.Exception(() => ApiGatewayArn.Parse(invalidArn));

            Assert.NotNull(actual);
            Assert.IsAssignableFrom <Exception>(actual);
        }
예제 #6
0
        public void Build_SetsStage_WhenNoStageProvided()
        {
            var apiGatewayArn = ApiGatewayArn.Parse("arn:partition:service:region:awsAccountId:restApiId//verb");

            _testObject.AllowAllMethods();

            var actual = _testObject.Build(apiGatewayArn);

            var statement = actual.PolicyDocument.Statement.Single();

            Assert.Contains($"arn:partition:service:region:awsAccountId:restApiId/*/*/*", statement.Resource);
        }
        public void ValidateRequest_Sets_ApiGatewayArn()
        {
            var request = new Request
            {
                Type = FakeType,
                AuthorizationToken = FakeToken,
                MethodArn          = FakeMethodArn,
            };
            var expected = ApiGatewayArn.Parse(FakeMethodArn);

            _testObject.ValidateRequest(request, out var actual);

            Assert.Equal(expected.ToString(), actual.ToString());
        }
예제 #8
0
 public void Parse_Sets_Service()
 {
     Assert.Equal("service", ApiGatewayArn.Parse(_methodArn).Service);
 }
예제 #9
0
 public void Parse_Returns_ApiGatewayArn()
 {
     Assert.NotNull(ApiGatewayArn.Parse(_methodArn));
 }
        public AuthPolicy FunctionHandler(TokenAuthorizerContext input, ILambdaContext context)
        {
            try
            {
                context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}");
                context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}");

                // validate the incoming token
                // and produce the principal user identifier associated with the token

                // this could be accomplished in a number of ways:
                // 1. Call out to OAuth provider
                // 2. Decode a JWT token inline
                // 3. Lookup in a self-managed DB
                var principalId = "user|a1b2c3d4";

                // you can send a 401 Unauthorized response to the client by failing like so:
                // throw new Exception("Unauthorized");

                // if the token is valid, a policy must be generated which will allow or deny access to the client

                // if access is denied, the client will receive a 403 Access Denied response
                // if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called

                // build apiOptions for the AuthPolicy
                var methodArn  = ApiGatewayArn.Parse(input.MethodArn);
                var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage);

                // this function must generate a policy that is associated with the recognized principal user identifier.
                // depending on your use case, you might store policies in a DB, or generate them on the fly

                // keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)
                // and will apply to subsequent calls to any method/resource in the RestApi
                // made with the same token

                // the example policy below denies access to all resources in the RestApi
                var policyBuilder = new AuthPolicyBuilder(principalId, methodArn.AwsAccountId, apiOptions);
                policyBuilder.DenyAllMethods();
                // policyBuilder.AllowMethod(HttpVerb.GET, "/users/username");

                // finally, build the policy
                var authResponse = policyBuilder.Build();

                // new! -- add additional key-value pairs
                // these are made available by APIGW like so: $context.authorizer.<key>
                // additional context is cached
                authResponse.Context.Add("key", "value"); // $context.authorizer.key -> value
                authResponse.Context.Add("number", 1);
                authResponse.Context.Add("bool", true);

                return(authResponse);
            }
            catch (Exception ex)
            {
                if (ex is UnauthorizedException)
                {
                    throw;
                }

                // log the exception and return a 401
                context.Logger.LogLine(ex.ToString());
                throw new UnauthorizedException();
            }
        }
예제 #11
0
        public AuthPolicy FunctionHandler(TokenAuthorizerContext input, ILambdaContext context)
        {
            try
            {
                context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}");
                context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}");

                var tokenValidation = new TokenValidation(context);
                var principalId     = tokenValidation.GetPrincipalId(input.AuthorizationToken);

                var methodArn  = ApiGatewayArn.Parse(input.MethodArn);
                var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage);

                var policyBuilder = new AuthPolicyBuilder(principalId, methodArn.AwsAccountId, apiOptions);

                // Add your API endpoints and their corresponding HTTP verb, that does not require Group authorization
                policyBuilder.AllowMethod(HttpVerb.Get, "/shop");
                policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*");
                policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*/products");
                policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*/stock");
                policyBuilder.AllowMethod(HttpVerb.Post, "/reset");

                var groupName = tokenValidation.GroupName;

                if (groupName == null)
                {
                    context.Logger.LogLine("No group based authorization needed");
                }
                else
                {
                    // Replace the "employee" and "manager" group names below with your preferred choice
                    // Add your API endpoints and their corresponding HTTP verb, that requires Group authorization
                    if (groupName.Contains(','))
                    {
                        var groups = new List <string>(groupName.Split(','));
                        if (groups.Contains("employee") && groups.Contains("manager"))
                        {
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock");
                            policyBuilder.AllowMethod(HttpVerb.Post, "/warehouse/*/stock/*/move/*");
                        }
                        else
                        {
                            context.Logger.LogLine("Group based authorization failed");
                        }
                    }
                    else if (groupName == "employee" || groupName == "manager")
                    {
                        switch (groupName)
                        {
                        case "employee":
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock");
                            break;

                        case "manager":
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*");
                            policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock");
                            policyBuilder.AllowMethod(HttpVerb.Post, "/warehouse/*/stock/*/move/*");
                            break;
                        }
                    }
                    else
                    {
                        context.Logger.LogLine("Group based authorization failed");
                    }
                }

                var authResponse = policyBuilder.Build();
                authResponse.Context.Add("key", "value");
                authResponse.Context.Add("number", 1);
                authResponse.Context.Add("bool", true);

                return(authResponse);
            }
            catch (Exception ex)
            {
                context.Logger.LogLine(ex.ToString());
                throw new Exception("Unauthorized");
            }
        }
예제 #12
0
 public void Parse_Sets_Region()
 {
     Assert.Equal("region", ApiGatewayArn.Parse(_methodArn).Region);
 }
예제 #13
0
        public AuthPolicy Authorizer(TokenAuthorizerContext input, ILambdaContext context)
        {
            try
            {
                // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJnYXRld2F5SWQiOiJhMWZiNGRjOC0zY2Y2LTRlZTYtYmU1Zi03ZGI1ZjA3MDkxZDQiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.-WH60ifv_FTHbEkoU2TQgkHDpT9zgmQ1HzQDgqngGjA
                context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}");
                // context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}");

                // validate the incoming token
                // and produce the principal user identifier associated with the token
                string jwtSecret = "SECRET";
                string decodedJWT;
                try
                {
                    byte[] secretKey = Encoding.ASCII.GetBytes(jwtSecret);
                    decodedJWT = Jose.JWT.Decode(input.AuthorizationToken, secretKey);
                }
                catch (Exception ex)
                {
                    context.Logger.LogLine(ex.ToString());
                    throw new Exception("Bad token bro");
                }

                var pineappleJWT = System.Text.Json.JsonSerializer.Deserialize <PineappleJWTToken>(decodedJWT);

                // build apiOptions for the AuthPolicy
                var methodArn  = ApiGatewayArn.Parse(input.MethodArn);
                var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage);

                // this function must generate a policy that is associated with the recognized principal user identifier.
                // depending on your use case, you might store policies in a DB, or generate them on the fly

                // keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)
                // and will apply to subsequent calls to any method/resource in the RestApi
                // made with the same token

                // the example policy below denies access to all resources in the RestApi
                var policyBuilder = new AuthPolicyBuilder(pineappleJWT.gatewayId, methodArn.AwsAccountId, apiOptions);
                // policyBuilder.DenyAllMethods();
                policyBuilder.AllowAllMethods();
                // policyBuilder.AllowMethod(HttpVerb.GET, "/users/username");

                // finally, build the policy
                var authResponse = policyBuilder.Build();

                // new! -- add additional key-value pairs
                // these are made available by APIGW like so: $context.authorizer.<key>
                // additional context is cached
                authResponse.Context.Add("key", "value"); // $context.authorizer.key -> value
                authResponse.Context.Add("number", 1);
                authResponse.Context.Add("bool", true);

                return(authResponse);
            }
            catch (Exception ex)
            {
                if (ex is UnauthorizedException)
                {
                    throw;
                }

                // log the exception and return a 401
                context.Logger.LogLine(ex.ToString());
                throw new UnauthorizedException();
            }
        }
예제 #14
0
 public PolicyBuilderTests()
 {
     _standardArn = ApiGatewayArn.Parse(StandardArn);
     _testObject  = new PolicyBuilder();
 }
예제 #15
0
 public void Parse_Sets_AwsAccountId()
 {
     Assert.Equal("awsAccountId", ApiGatewayArn.Parse(_methodArn).AwsAccountId);
 }
예제 #16
0
 public void Parse_Sets_RestApiId()
 {
     Assert.Equal("restApiId", ApiGatewayArn.Parse(_methodArn).RestApiId);
 }
예제 #17
0
 public void Parse_Sets_Partition()
 {
     Assert.Equal("partition", ApiGatewayArn.Parse(_methodArn).Partition);
 }
예제 #18
0
 public void Parse_Sets_Stage()
 {
     Assert.Equal("stage", ApiGatewayArn.Parse(_methodArn).Stage);
 }
예제 #19
0
        public void Parse_Sets_Resource(string resource)
        {
            var methodArn = resource == null ? _methodArn : _methodArn + "/" + resource;

            Assert.Equal(resource, ApiGatewayArn.Parse(methodArn).Resource);
        }
예제 #20
0
 public void Parse_Sets_Verb()
 {
     Assert.Equal("verb", ApiGatewayArn.Parse(_methodArn).Verb);
 }