private void AddMethod(Effect effect, HttpVerb verb, string resource) { if (verb == null) { throw new AuthPolicyBuilderException($"{nameof(verb)} cannot be null"); } if (resource == null) { throw new AuthPolicyBuilderException($"{nameof(resource)} cannot be null"); } if (!_pathRegex.IsMatch(resource)) { throw new AuthPolicyBuilderException($"{nameof(resource)} is invalid: {resource}. Path should match {_pathRegex}"); } var cleanedResource = resource.First() == '/' ? resource.Substring(1) : resource; var arn = new ApiGatewayArn { Verb = verb.ToString(), Resource = cleanedResource, }; switch (effect) { case Effect.Deny: _denyMethodArns.Add(arn); return; case Effect.Allow: _allowMethodArns.Add(arn); return; } }
public static ApiGatewayArn Parse(string value) { try { var result = new ApiGatewayArn(); string[] arnSplit = value.Split(':'); result.Partition = arnSplit[1]; result.Service = arnSplit[2]; result.Region = arnSplit[3]; result.AwsAccountId = arnSplit[4]; string[] pathSplit = arnSplit[5].Split('/'); result.RestApiId = pathSplit[0]; result.Stage = pathSplit[1]; result.Verb = pathSplit[2]; if (pathSplit.Length > 3) { result.Resource = string.Join("/", pathSplit.Skip(3)); } return(result); } catch (Exception) { throw new ApiGatewayArnException($"Invalid method arn: '{value}'"); } }
public static bool TryParse(string value, out ApiGatewayArn methodArn) { try { methodArn = Parse(value); return(true); } catch { methodArn = null; return(false); } }
public void ValidateRequest(Request request, out ApiGatewayArn apiGatewayArn) { _logger.LogTrace("Validating request"); apiGatewayArn = null; var validationMessages = new List <string>(); if (request == null) { validationMessages.Add("Request is required."); } else { if (request.Type == null) { validationMessages.Add("Expected 'type' to have been provided."); } else if (request.Type.ToUpperInvariant() != "TOKEN") { validationMessages.Add("Expected 'type' to have value 'TOKEN'."); } if (string.IsNullOrWhiteSpace(request.AuthorizationToken)) { validationMessages.Add("Expected 'authorizationToken' to have been provided."); } else if (!new Regex("^Bearer .*$").IsMatch(request.AuthorizationToken)) { validationMessages.Add("Expected 'authorizationToken' to match '^Bearer .*$'."); } if (string.IsNullOrWhiteSpace(request.MethodArn)) { validationMessages.Add("Expected 'methodArn' to have been provided."); } else if (!ApiGatewayArn.TryParse(request.MethodArn, out apiGatewayArn)) { validationMessages.Add($"Could not parse 'methodArn': '{request.MethodArn}'."); } } if (validationMessages.Count > 0) { _logger.LogError("Request validation failed", new { validationMessages }); throw new RequestValidationException(); } _logger.LogTrace("Successfully validated request"); }
public Response Build(ApiGatewayArn apiGatewayArn, string principalId = null) { PopulateMethods(apiGatewayArn); var statements = GetStatements(); return(new Response { PrincipalID = principalId, PolicyDocument = new APIGatewayCustomAuthorizerPolicy { Version = _policyVersion, Statement = statements, } }); }
public Response Authorize(Request request) { ApiGatewayArn apiGatewayArn = null; string principalId = null; try { _logger.LogDebug("Authorizing"); _requestValidationService.ValidateRequest(request, out apiGatewayArn); TokenValidationParameters jwtConfig = _tokenConfigService.GetJwtConfig(); string token = request.AuthorizationToken?.Replace("Bearer ", ""); ClaimsPrincipal user = _tokenValidationService.ValidateToken(token, jwtConfig); principalId = _claimsPrincipalService.GetPrincipalId(user); // this uses the all-or-nothing auth strategy by default: _policyBuilder.AllowAllMethods(); // however, you could allow/deny specific methods/resources based off the user's claims, for example: // Claim role = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role); // HttpVerb verb = role?.Value == "admin" ? HttpVerb.All : HttpVerb.Get; // _policyBuilder.AllowMethod(verb, "config"); _logger.LogDebug("Authorization succeeded", new { principalId }); } catch (BaseException ex) { _logger.LogDebug(ex.Message, new { ex.InnerException }); _logger.LogDebug("Authorization failed", new { }); // you may choose to throw an unauthorized exception here instead of returning a "deny all" policy // throw new UnauthorizedException(); _policyBuilder.DenyAllMethods(); } Response response = _policyBuilder.Build(apiGatewayArn, principalId); // you can add key-value pairs that can be accessed in API Gateway via $context.authorizer.<key> // response.Context.Add("key", "value"); return(response); }
private void PopulateMethods(ApiGatewayArn apiGatewayArn) { populate(_allowMethodArns); populate(_denyMethodArns); void populate(List <ApiGatewayArn> methodArns) { foreach (var arn in methodArns) { arn.Partition = apiGatewayArn.Partition; arn.Service = apiGatewayArn.Service.DefaultTo("*"); arn.Region = apiGatewayArn.Region.DefaultTo("*"); arn.AwsAccountId = apiGatewayArn.AwsAccountId; arn.RestApiId = apiGatewayArn.RestApiId.DefaultTo("*"); arn.Stage = apiGatewayArn.Stage.DefaultTo("*"); } } }