Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ext auth service : add http/https protocol #786

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,17 @@ vars in the `net-kourier-controller` deployment:
my-auth:2222
- `KOURIER_EXTAUTHZ_FAILUREMODEALLOW*`: Allow traffic to go through if the ext
auth service is down. Accepts true/false
- `KOURIER_EXTAUTHZ_PROTOCOL`: The protocol used to query the ext auth
service. Can be one of : grpc, http, https. Defaults to grpc
- `KOURIER_EXTAUTHZ_MAXREQUESTBYTES`: Max request bytes, if not set, defaults to
8192 Bytes. More info
[Envoy Docs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html?highlight=max_request_bytes#extensions-filters-http-ext-authz-v3-buffersettings)
- `KOURIER_EXTAUTHZ_TIMEOUT`: Max time in ms to wait for the ext authz service.
Defaults to 2s.
Defaults to 2s
- `KOURIER_EXTAUTHZ_PATHPREFIX`: If `KOURIER_EXTAUTHZ_PROTOCOL` is equal to
http or https, path to query the ext auth service. Example : if set to
`/verify`, it will query `/verify/` (**notice the trailing `/`**).
If not set, it will query `/`.

`*` Required

Expand Down
115 changes: 88 additions & 27 deletions pkg/config/ext_authz.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,32 @@ type ExternalAuthzConfig struct {
HTTPFilter *hcm.HttpFilter
}

type extAuthzProtocol string

const (
extAuthzProtocolGRPC extAuthzProtocol = "grpc"
extAuthzProtocolHTTP extAuthzProtocol = "http"
extAuthzProtocolHTTPS extAuthzProtocol = "https"
)

var extAuthzProtocols = map[extAuthzProtocol]struct{}{
extAuthzProtocolGRPC: {},
extAuthzProtocolHTTP: {},
extAuthzProtocolHTTPS: {},
}

func isValidExtAuthzProtocol(protocol extAuthzProtocol) bool {
_, ok := extAuthzProtocols[protocol]
return ok
}

type config struct {
Host string
FailureModeAllow bool
MaxRequestBytes uint32 `default:"8192"`
Timeout int `default:"2000"`
MaxRequestBytes uint32 `default:"8192"`
Timeout int `default:"2000"`
Protocol extAuthzProtocol `default:"grpc"`
PathPrefix string
}

func init() {
Expand All @@ -69,6 +90,11 @@ func init() {
var env config
envconfig.MustProcess("KOURIER_EXTAUTHZ", &env)

if !isValidExtAuthzProtocol(env.Protocol) {
err := fmt.Errorf("protocol %s is invalid, must be in %+v", env.Protocol, extAuthzProtocols)
panic(err)
}

host, portStr, err := net.SplitHostPort(env.Host)
if err != nil {
panic(err)
Expand All @@ -84,21 +110,32 @@ func init() {
panic(fmt.Sprintf("port %d bigger than %d", port, unixMaxPort))
}

timeout := time.Duration(env.Timeout) * time.Millisecond

ExternalAuthz = &ExternalAuthzConfig{
Enabled: true,
Cluster: extAuthzCluster(host, uint32(port)),
HTTPFilter: externalAuthZFilter(extAuthzClusterName, timeout, env.FailureModeAllow, env.MaxRequestBytes),
Cluster: extAuthzCluster(host, uint32(port), env.Protocol),
HTTPFilter: externalAuthZFilter(&env),
}
}

func extAuthzCluster(host string, port uint32) *v3Cluster.Cluster {
const extAuthzClusterTypedExtensionProtocolOptionsHTTP = "envoy.extensions.upstreams.http.v3.HttpProtocolOptions"

func extAuthzCluster(host string, port uint32, protocol extAuthzProtocol) *v3Cluster.Cluster {
var explicitHTTPConfig *httpOptions.HttpProtocolOptions_ExplicitHttpConfig

switch protocol {
case extAuthzProtocolGRPC:
explicitHTTPConfig = &httpOptions.HttpProtocolOptions_ExplicitHttpConfig{
ProtocolConfig: &httpOptions.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{},
}
case extAuthzProtocolHTTP, extAuthzProtocolHTTPS:
explicitHTTPConfig = &httpOptions.HttpProtocolOptions_ExplicitHttpConfig{
ProtocolConfig: &httpOptions.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{},
}
}

opts, _ := anypb.New(&httpOptions.HttpProtocolOptions{
UpstreamProtocolOptions: &httpOptions.HttpProtocolOptions_ExplicitHttpConfig_{
ExplicitHttpConfig: &httpOptions.HttpProtocolOptions_ExplicitHttpConfig{
ProtocolConfig: &httpOptions.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{},
},
ExplicitHttpConfig: explicitHTTPConfig,
},
})

Expand All @@ -108,7 +145,7 @@ func extAuthzCluster(host string, port uint32) *v3Cluster.Cluster {
Type: v3Cluster.Cluster_STRICT_DNS,
},
TypedExtensionProtocolOptions: map[string]*anypb.Any{
"envoy.extensions.upstreams.http.v3.HttpProtocolOptions": opts,
extAuthzClusterTypedExtensionProtocolOptionsHTTP: opts,
},
ConnectTimeout: durationpb.New(5 * time.Second),
LoadAssignment: &endpoint.ClusterLoadAssignment{
Expand Down Expand Up @@ -137,29 +174,53 @@ func extAuthzCluster(host string, port uint32) *v3Cluster.Cluster {
}
}

func externalAuthZFilter(clusterName string, timeout time.Duration, failureModeAllow bool, maxRequestBytes uint32) *hcm.HttpFilter {
func externalAuthZFilter(conf *config) *hcm.HttpFilter {
timeout := durationpb.New(time.Duration(conf.Timeout) * time.Millisecond)

extAuthConfig := &extAuthService.ExtAuthz{
Services: &extAuthService.ExtAuthz_GrpcService{
TransportApiVersion: core.ApiVersion_V3,
FailureModeAllow: conf.FailureModeAllow,
WithRequestBody: &extAuthService.BufferSettings{
MaxRequestBytes: conf.MaxRequestBytes,
AllowPartialMessage: true,
},
ClearRouteCache: false,
}

headers := []*core.HeaderValue{{
Key: "client",
Value: "kourier",
}}

switch conf.Protocol {
case extAuthzProtocolGRPC:
extAuthConfig.Services = &extAuthService.ExtAuthz_GrpcService{
GrpcService: &core.GrpcService{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{
ClusterName: clusterName,
ClusterName: extAuthzClusterName,
},
},
Timeout: durationpb.New(timeout),
InitialMetadata: []*core.HeaderValue{{
Key: "client",
Value: "kourier",
}},
Timeout: timeout,
InitialMetadata: headers,
},
},
TransportApiVersion: core.ApiVersion_V3,
FailureModeAllow: failureModeAllow,
WithRequestBody: &extAuthService.BufferSettings{
MaxRequestBytes: maxRequestBytes,
AllowPartialMessage: true,
},
ClearRouteCache: false,
}
case extAuthzProtocolHTTP, extAuthzProtocolHTTPS:
extAuthConfig.Services = &extAuthService.ExtAuthz_HttpService{
HttpService: &extAuthService.HttpService{
ServerUri: &core.HttpUri{
Uri: fmt.Sprintf("%s://%s", conf.Protocol, conf.Host),
HttpUpstreamType: &core.HttpUri_Cluster{
Cluster: extAuthzClusterName,
},
Timeout: timeout,
},
PathPrefix: conf.PathPrefix,
AuthorizationRequest: &extAuthService.AuthorizationRequest{
HeadersToAdd: headers,
},
},
}
}

envoyConf, err := anypb.New(extAuthConfig)
Expand Down
Loading