Skip to content

Commit

Permalink
authz_filter: extended ext_authz to support v2alpha api (#3162)
Browse files Browse the repository at this point in the history
This PR extends the current Ext_Authz filter to allow optional HTTP attributes being passed from the Authorization service down to client or, to the upstream services. I would like to get some feedback on the changes to the current gRPC async client and filter before moving to implementation of HTTP part of this extension and tests.

*issue: #2828

Risk Level: Medium
Testing: Manual, unit testing.
Docs Changes: envoyproxy/data-plane-api#563

Signed-off-by: Gabriel <[email protected]>
  • Loading branch information
Gabriel Sagula authored and htuch committed Jun 27, 2018
1 parent 9025369 commit 5244597
Show file tree
Hide file tree
Showing 42 changed files with 1,647 additions and 403 deletions.
10 changes: 5 additions & 5 deletions api/envoy/api/v2/core/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ api_go_proto_library(
],
)

api_go_proto_library(
name = "http_uri",
proto = ":http_uri",
)

api_proto_library(
name = "http_uri",
srcs = ["http_uri.proto"],
Expand All @@ -88,11 +93,6 @@ api_proto_library(
],
)

api_go_proto_library(
name = "http_uri",
proto = ":http_uri",
)

api_proto_library(
name = "grpc_service",
srcs = ["grpc_service.proto"],
Expand Down
52 changes: 35 additions & 17 deletions api/envoy/config/filter/http/ext_authz/v2alpha/ext_authz.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@ option go_package = "v2alpha";
import "envoy/api/v2/core/grpc_service.proto";
import "envoy/api/v2/core/http_uri.proto";

// [#protodoc-title: HTTP External Authorization ]
// The external authorization HTTP service configuration
// [#protodoc-title: External Authorization ]
// The external authorization service configuration
// :ref:`configuration overview <config_http_filters_ext_authz>`.

// [#not-implemented-hide:]
// [#comment: The HttpService is under development and will be supported soon.]
message HttpService {
// Sets the HTTP server URI which the authorization requests must be sent to.
envoy.api.v2.core.HttpUri server_uri = 1;

// Sets an optional prefix to the value of authorization request header `path`.
string path_prefix = 2;
}

// External Authorization filter calls out to an external service over the
// gRPC Authorization API defined by
// :ref:`CheckRequest <envoy_api_msg_service.auth.v2alpha.CheckRequest>`.
// A failed check will cause this filter to close the HTTP request with 403(Forbidden).
// External Authorization filter calls out to an external service over either:
//
// 1. gRPC Authorization API defined by :ref:`CheckRequest <envoy_api_msg_service.auth.v2alpha.CheckRequest>`.
// 2. Raw HTTP Authorization server by passing the request headers to the service.
//
// A failed check will cause this filter to close the HTTP request normally with 403 (Forbidden), unless
// a different status code has been indicated in the authorization response.
message ExtAuthz {

oneof services {
Expand All @@ -32,7 +25,7 @@ message ExtAuthz {
envoy.api.v2.core.GrpcService grpc_service = 1;

// The external authorization HTTP service configuration.
// [#not-implemented-hide:]
// The default timeout is set to 200ms by this filter.
HttpService http_service = 3;
}

Expand All @@ -42,3 +35,28 @@ message ExtAuthz {
// Defaults to false.
bool failure_mode_allow = 2;
}

// External Authorization filter calls out to an upstream authorization server by passing the raw HTTP
// request headers to the server. This allows the authorization service to take a decision whether the
// request is authorized or not.
//
// A successful check allows the authorization service adding or overriding headers from the original
// request before dispatching it to the upstream. This is done by including the headers in the response
// sent back from the authorization service to the filter. Note that `Status`, `Method`, `Path` and
// `Content Length` response headers are automatically removed from this response by the filter. If other
// headers need be deleted, they should be specified in `response_headers_to_remove` field.
//
// A failed check will cause this filter to close the HTTP request normally with 403 (Forbidden), unless
// a different status code has been indicated by the authorization service via response headers. The HTTP
// service also allows the authorization filter to also pass data from the response body to the downstream
// client in case of a denied request.
message HttpService {
// Sets the HTTP server URI which the authorization requests must be sent to.
envoy.api.v2.core.HttpUri server_uri = 1;

// Sets an optional prefix to the value of authorization request header `path`.
string path_prefix = 2;

// Sets a list of headers that should be not be sent *from the authorization server* to the upstream.
repeated string response_headers_to_remove = 3;
}
2 changes: 2 additions & 0 deletions api/envoy/service/auth/v2alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ api_proto_library(
has_services = 1,
deps = [
":attribute_context",
"//envoy/api/v2/core:base",
"//envoy/type:http_status",
],
)
46 changes: 36 additions & 10 deletions api/envoy/service/auth/v2alpha/external_auth.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package envoy.service.auth.v2alpha;
option go_package = "v2alpha";
option java_generic_services = true;

import "envoy/api/v2/core/base.proto";
import "envoy/type/http_status.proto";
import "envoy/service/auth/v2alpha/attribute_context.proto";

import "google/rpc/status.proto";
Expand All @@ -27,21 +29,45 @@ message CheckRequest {
AttributeContext attributes = 1;
}

// HTTP attributes for a denied response.
message DeniedHttpResponse {
// This field allows the authorization service to send a HTTP response status
// code to the downstream client other than 403 (Forbidden).
envoy.type.HttpStatus status = 1 [(validate.rules).message.required = true];

// This field allows the authorization service to send HTTP response headers
// to the the downstream client.
repeated envoy.api.v2.core.HeaderValueOption headers = 2;

// This field allows the authorization service to send a response body data
// to the the downstream client.
string body = 3;
}

// HTTP attributes for an ok response.
message OkHttpResponse {
// HTTP entity headers in addition to the original request headers. This allows the authorization
// service to append, to add or to override headers from the original request before
// dispatching it to the upstream. By setting `append` field to `true` in the `HeaderValueOption`,
// the filter will append the correspondent header value to the matched request header. Note that
// by Leaving `append` as false, the filter will either add a new header, or override an existing
// one if there is a match.
repeated envoy.api.v2.core.HeaderValueOption headers = 2;
}

// Intended for gRPC and Network Authorization servers `only`.
message CheckResponse {
// Status `OK` allows the request. Any other status indicates the request should be denied.
google.rpc.Status status = 1;

// An optional message that contains HTTP response attributes. This message is
// An message that contains HTTP response attributes. This message is
// used when the authorization service needs to send custom responses to the
// downstream client or, to modify/add request headers being dispatched to the upstream.
message HttpResponse {
// Http status code.
uint32 status_code = 1 [(validate.rules).uint32 = {gte: 100, lt: 600}];

// Http entity headers.
map<string, string> headers = 2;

// Http entity body.
string body = 3;
oneof http_response {
// Supplies http attributes for a denied response.
DeniedHttpResponse denied_response = 2;

// Supplies http attributes for an ok response.
OkHttpResponse ok_response = 3;
}
}
11 changes: 11 additions & 0 deletions api/envoy/type/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ load("//bazel:api_build_system.bzl", "api_go_proto_library", "api_proto_library"

licenses(["notice"]) # Apache 2

api_proto_library(
name = "http_status",
srcs = ["http_status.proto"],
visibility = ["//visibility:public"],
)

api_go_proto_library(
name = "http_status",
proto = ":http_status",
)

api_proto_library(
name = "percent",
srcs = ["percent.proto"],
Expand Down
83 changes: 83 additions & 0 deletions api/envoy/type/http_status.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
syntax = "proto3";

package envoy.type;

import "validate/validate.proto";

// HTTP response codes supported in Envoy.
// For more details: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
enum StatusCode {
// Empty - This code not part of the HTTP status code specification, but it is needed for proto `enum` type.
Empty = 0;

Continue = 100;

OK = 200;
Created = 201;
Accepted = 202;
NonAuthoritativeInformation = 203;
NoContent = 204;
ResetContent = 205;
PartialContent = 206;
MultiStatus = 207;
AlreadyReported = 208;
IMUsed = 226;

MultipleChoices = 300;
MovedPermanently = 301;
Found = 302;
SeeOther = 303;
NotModified = 304;
UseProxy = 305;
TemporaryRedirect = 307;
PermanentRedirect = 308;

BadRequest = 400;
Unauthorized = 401;
PaymentRequired = 402;
Forbidden = 403;
NotFound = 404;
MethodNotAllowed = 405;
NotAcceptable = 406;
ProxyAuthenticationRequired = 407;
RequestTimeout = 408;
Conflict = 409;
Gone = 410;
LengthRequired = 411;
PreconditionFailed = 412;
PayloadTooLarge = 413;
URITooLong = 414;
UnsupportedMediaType = 415;
RangeNotSatisfiable = 416;
ExpectationFailed = 417;
MisdirectedRequest = 421;
UnprocessableEntity = 422;
Locked = 423;
FailedDependency = 424;
UpgradeRequired = 426;
PreconditionRequired = 428;
TooManyRequests = 429;
RequestHeaderFieldsTooLarge = 431;

InternalServerError = 500;
NotImplemented = 501;
BadGateway = 502;
ServiceUnavailable = 503;
GatewayTimeout = 504;
HTTPVersionNotSupported = 505;
VariantAlsoNegotiates = 506;
InsufficientStorage = 507;
LoopDetected = 508;
NotExtended = 510;
NetworkAuthenticationRequired = 511;

}

// HTTP status.
message HttpStatus {
// Supplies HTTP response code.
StatusCode code = 1 [
(validate.rules).enum = {not_in: [0]},
(validate.rules).enum.defined_only = true
];
}
1 change: 1 addition & 0 deletions docs/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ PROTO_RST="
/envoy/service/accesslog/v2/als/envoy/service/accesslog/v2/als.proto.rst
/envoy/service/auth/v2alpha/external_auth/envoy/service/auth/v2alpha/attribute_context.proto.rst
/envoy/service/auth/v2alpha/external_auth/envoy/service/auth/v2alpha/external_auth.proto.rst
/envoy/type/http_status/envoy/type/http_status.proto.rst
/envoy/type/percent/envoy/type/percent.proto.rst
/envoy/type/range/envoy/type/range.proto.rst
"
Expand Down
1 change: 1 addition & 0 deletions docs/root/api-v2/types/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ Types
:glob:
:maxdepth: 2

../type/http_status.proto
../type/percent.proto
../type/range.proto
40 changes: 34 additions & 6 deletions docs/root/configuration/http_filters/ext_authz_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ External Authorization
* External authorization :ref:`architecture overview <arch_overview_ext_authz>`
* :ref:`HTTP filter v2 API reference <envoy_api_msg_config.filter.http.ext_authz.v2alpha.ExtAuthz>`

The external authorization HTTP filter calls an external gRPC service to check if the incoming
The external authorization HTTP filter calls an external gRPC or HTTP service to check if the incoming
HTTP request is authorized or not.
If the request is deemed unauthorized then the request will be denied with 403 (Forbidden) response.
If the request is deemed unauthorized then the request will be denied normally with 403 (Forbidden) response.
Note that sending additional custom metadata from the authorization service to the upstream, or to the downstream is
also possible. This is explained in more details at :ref:`HTTP filter <envoy_api_msg_config.filter.http.ext_authz.v2alpha.ExtAuthz>`.

.. tip::
It is recommended that this filter is configured first in the filter chain so that requests are
Expand All @@ -18,14 +20,14 @@ The content of the requests that are passed to an authorization service is speci

.. _config_http_filters_ext_authz_http_configuration:

The HTTP filter, using a gRPC service, can be configured as follows. You can see all the
The HTTP filter, using a gRPC/HTTP service, can be configured as follows. You can see all the
configuration options at
:ref:`HTTP filter <envoy_api_msg_config.filter.http.ext_authz.v2alpha.ExtAuthz>`.

Example
-------
Configuration Examples
-----------------------------

A sample filter configuration could be:
A sample filter configuration for a gRPC authorization server:

.. code-block:: yaml
Expand All @@ -36,13 +38,39 @@ A sample filter configuration could be:
envoy_grpc:
cluster_name: ext-authz
.. code-block:: yaml
clusters:
- name: ext-authz
type: static
http2_protocol_options: {}
hosts:
- socket_address: { address: 127.0.0.1, port_value: 10003 }
A sample filter configuration for a raw HTTP authorization server:

.. code-block:: yaml
http_filters:
- name: envoy.ext_authz
config:
http_service:
server_uri:
uri: 127.0.0.1:10003
cluster: ext-authz
timeout: 0.25s
failure_mode_allow: false
.. code-block:: yaml
clusters:
- name: ext-authz
connect_timeout: 0.25s
type: logical_dns
lb_policy: round_robin
hosts:
- socket_address: { address: 127.0.0.1, port_value: 10003 }
Statistics
----------
The HTTP filter outputs statistics in the *cluster.<route target cluster>.ext_authz.* namespace.
Expand Down
6 changes: 4 additions & 2 deletions docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ Version history
to close tcp_proxy upstream connections when health checks fail.
* cluster: added :ref:`option <envoy_api_field_Cluster.drain_connections_on_host_removal>` to drain
connections from hosts after they are removed from service discovery, regardless of health status.
* cluster: fixed bug preventing the deletion of all endpoints in a priority.
* debug: added symbolized stack traces (where supported).
* cluster: fixed bug preventing the deletion of all endpoints in a priority
* debug: added symbolized stack traces (where supported)
* ext-authz filter: added support to raw HTTP authorization.
* ext-authz filter: added support to gRPC responses to carry HTTP attributes.
* grpc: support added for the full set of :ref:`Google gRPC call credentials
<envoy_api_msg_core.GrpcService.GoogleGrpc.CallCredentials>`.
* gzip filter: added :ref:`stats <gzip-statistics>` to the filter.
Expand Down
5 changes: 5 additions & 0 deletions include/envoy/http/header_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,5 +498,10 @@ class HeaderMap {

typedef std::unique_ptr<HeaderMap> HeaderMapPtr;

/**
* Convenient container type for storing Http::LowerCaseString and std::string key/value pairs.
*/
typedef std::vector<std::pair<LowerCaseString, std::string>> HeaderVector;

} // namespace Http
} // namespace Envoy
1 change: 1 addition & 0 deletions source/common/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ envoy_cc_library(
"//include/envoy/stats:stats_interface",
"//source/common/common:enum_to_int",
"//source/common/common:utility_lib",
"@envoy_api//envoy/type:http_status_cc",
],
)

Expand Down
Loading

0 comments on commit 5244597

Please sign in to comment.