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);
public void TryParse_WhenArnIsValid() { var expected = ApiGatewayArn.Parse(_methodArn); Assert.True(ApiGatewayArn.TryParse(_methodArn, out var actual)); Assert.Equal(expected.ToString(), actual.ToString()); }
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; } }
public void ToString_ReturnsExpectedString() { var expected = $"{_methodArn}/"; var actual = ApiGatewayArn.Parse(_methodArn).ToString(); Assert.Equal(expected, actual); }
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); }
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 Authorize_Calls_PolicyBuilder_Build() { var apiGatewayArn = new ApiGatewayArn(); var principalId = "fake-principal-id"; _requestValidatorService.Setup(x => x.ValidateRequest(It.IsAny <Request>(), out apiGatewayArn)); _claimsPrincipalService.Setup(x => x.GetPrincipalId(It.IsAny <ClaimsPrincipal>())).Returns(principalId); _testObject.Authorize(new Request()); _policyBuilder.Verify(x => x.Build(apiGatewayArn, principalId), Times.Once); }
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()); }
private void AddMethod(Effect effect, HttpVerb verb, string resource, ICollection <Condition> conditions = null) { if (verb == null) { throw new ArgumentNullException(nameof(verb)); } if (resource == null) { throw new ArgumentNullException(nameof(resource)); } if (!_pathRegex.IsMatch(resource)) { throw new Exception($"Invalid resource path: {resource}. Path should match {_pathRegex}"); } var cleanedResource = resource.First() == '/' ? resource.Substring(1) : resource; ApiGatewayArn arn = new ApiGatewayArn { RestApiId = _restApiId, Region = _region, Stage = _stage, AwsAccountId = AwsAccountId, Verb = verb.ToString(), Resource = cleanedResource }; switch (effect) { case Effect.Deny: _denyMethods.Add(new Method { ArnResource = arn.ToString(), Conditions = ConditionsToDictionary(conditions) }); return; case Effect.Allow: _allowMethods.Add(new Method { ArnResource = arn.ToString(), Conditions = ConditionsToDictionary(conditions) }); return; } }
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"); } }
public void Parse_Sets_Partition() { Assert.Equal("partition", ApiGatewayArn.Parse(_methodArn).Partition); }
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(); } }
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(); } }
public void Parse_Sets_Region() { Assert.Equal("region", ApiGatewayArn.Parse(_methodArn).Region); }
public void Parse_Sets_Service() { Assert.Equal("service", ApiGatewayArn.Parse(_methodArn).Service); }
public PolicyBuilderTests() { _standardArn = ApiGatewayArn.Parse(StandardArn); _testObject = new PolicyBuilder(); }
public void Parse_Sets_AwsAccountId() { Assert.Equal("awsAccountId", ApiGatewayArn.Parse(_methodArn).AwsAccountId); }
public void Parse_Sets_RestApiId() { Assert.Equal("restApiId", ApiGatewayArn.Parse(_methodArn).RestApiId); }
public void Parse_Returns_ApiGatewayArn() { Assert.NotNull(ApiGatewayArn.Parse(_methodArn)); }
public void Parse_Sets_Stage() { Assert.Equal("stage", ApiGatewayArn.Parse(_methodArn).Stage); }
public void Parse_Sets_Resource(string resource) { var methodArn = resource == null ? _methodArn : _methodArn + "/" + resource; Assert.Equal(resource, ApiGatewayArn.Parse(methodArn).Resource); }
public void Parse_Sets_Verb() { Assert.Equal("verb", ApiGatewayArn.Parse(_methodArn).Verb); }