syntax = "proto3";
package io.linkerd.proxy.inbound;
option go_package = "github.com/linkerd/linkerd2-proxy-api/go/inbound";
import "google/protobuf/duration.proto";
import "grpc_route.proto";
import "http_route.proto";
import "meta.proto";
import "net.proto";
/// An API exposed to the linkerd2-proxy to configure the inbound proxy with per-port configuration
///
/// Proxies are expected to watch policies for each known port. As policies change, proxies update
/// their behavior for newly accepted connections.
///
/// The unary `GetPort` endpoint is exposed as a convenience for clients to query policies for
/// diagnostic purposes.
service InboundServerPolicies {
/// Gets the inbound server policy for a given workload port.
rpc GetPort(PortSpec) returns (Server) {}
/// Watches the inbound server policy for a given workload port.
rpc WatchPort(PortSpec) returns (stream Server) {}
}
message PortSpec {
// Identifies a proxy workload (e.g., pod name).
string workload = 1;
// An inbound port on _workload_.
uint32 port = 2;
}
message Server {
// If set, indicates how the proxy should proxy connections on the specified
// port.
ProxyProtocol protocol = 1;
// Indicates the IP addresses on which the proxy may receive connections.
// Connections targetting other IP addresses will be dropped.
repeated io.linkerd.proxy.net.IPAddress server_ips = 2;
// Configures a proxy to allow connections from the specified clients.
//
// If unset, no connections are permitted.
repeated Authz authorizations = 3;
// Descriptive labels to be added to metrics, etc.
//
// A control plane SHOULD return the same keys in all policies. That is, we do
// NOT want to return arbitrary pod labels in this field.
map<string, string> labels = 4;
}
message ProxyProtocol {
oneof kind {
Detect detect = 1;
Opaque opaque = 2;
Tls tls = 3;
Http1 http1 = 4;
Http2 http2 = 5;
Grpc grpc = 6;
}
message Detect {
google.protobuf.Duration timeout = 1;
// If the protocol detected as HTTP, a list of HTTP routes that should be
// matched.
repeated HttpRoute http_routes = 3;
// If the protocol detected as HTTP, applicable rate limit.
HttpLocalRateLimit http_local_rate_limit = 4;
// Never implemented.
reserved 2;
}
message Http1 {
repeated HttpRoute routes = 2;
HttpLocalRateLimit local_rate_limit = 3;
// Never implemented.
reserved 1;
}
message Http2 {
repeated HttpRoute routes = 2;
HttpLocalRateLimit local_rate_limit = 3;
// Never implemented.
reserved 1;
}
message Grpc {
repeated GrpcRoute routes = 2;
// Never implemented.
reserved 1;
}
message Opaque {
// TODO: opaque TLS settings (versions, algorithms, SNI)
}
message Tls {}
}
message Authz {
// Limits this authorization to client addresses in the provided networks.
//
// Must have at least one network, otherwise the authorization must be
// ignored. An authorization matches all clients by including an explicit
// match on, i.e., `[0.0.0.0/0, 0::/0]``.
repeated Network networks = 1;
// Must be set.
Authn authentication = 2;
// Descriptive labels to be added to metrics, etc.
//
// A control plane SHOULD return the same keys in all authorizations. That is,
// we do NOT want to return arbitrary pod labels in this field.
//
// `labels` should be considered deprecated. `metadata` is preferred. However,
// controllers should continue to set `labels` for compatibility with older
// proxies.
map<string, string> labels = 3;
// If set, describes an Authorization configuration. Replaces the free-from
// `labels` field.
io.linkerd.proxy.meta.Metadata metadata = 4;
}
// Describes a network of authorized clients.
message Network {
io.linkerd.proxy.net.IPNetwork net = 1;
repeated io.linkerd.proxy.net.IPNetwork except = 2;
}
message Authn {
oneof permit {
PermitUnauthenticated unauthenticated = 1;
// If set, requires that the connection is transported over mesh TLS.
PermitMeshTLS meshTLS = 2;
}
// TODO(ver) identify authentication resources?
// io.linkerd.proxy.meta.Metadata metadata = 3;
message PermitUnauthenticated {}
message PermitMeshTLS {
oneof clients {
// Indicates that client identities are not required.
PermitUnauthenticated unauthenticated = 1;
// Indicates that mutually-authenticated connections are permitted from
// clients with matching identities.
PermitClientIdentities identities = 2;
}
message PermitClientIdentities {
// A list of literal identities.
repeated Identity identities = 1;
// A list of identity suffixes.
//
// If this contains an empty suffix, all identities are matched.
repeated IdentitySuffix suffixes = 2;
}
}
}
message Identity { string name = 1; }
// Encodes a DNS-like name suffix as sequence of parts.
//
// An empty list is equivalent to `.` (matching all names); the list `["foo",
// "bar"]` is equivalent to "foo.bar." (matching `*.foo.bar`), etc.
message IdentitySuffix { repeated string parts = 1; }
// Inbound-specific HTTP route configuration (based on the
// [Gateway API](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute)).
message HttpRoute {
io.linkerd.proxy.meta.Metadata metadata = 1;
// If empty, the host value is ignored.
repeated io.linkerd.proxy.http_route.HostMatch hosts = 2;
// Extends the list of authorizations on the `Server` with authorizations
// specific to this route.
repeated Authz authorizations = 3;
// Must have at least one rule.
repeated Rule rules = 4;
message Rule {
repeated io.linkerd.proxy.http_route.HttpRouteMatch matches = 1;
repeated Filter filters = 2;
}
message Filter {
oneof kind {
io.linkerd.proxy.http_route.HttpFailureInjector failure_injector = 1;
io.linkerd.proxy.http_route.RequestHeaderModifier request_header_modifier = 2;
io.linkerd.proxy.http_route.RequestRedirect redirect = 3;
}
}
}
// Inbound-specific gRPC route configuration.
message GrpcRoute {
io.linkerd.proxy.meta.Metadata metadata = 1;
// If empty, the host value is ignored.
repeated io.linkerd.proxy.http_route.HostMatch hosts = 2;
// The server MUST return at least one authorization, otherwise all requests
// to this route will fail with an unauthorized response.
repeated Authz authorizations = 3;
// Must have at least one rule.
repeated Rule rules = 4;
message Rule {
repeated io.linkerd.proxy.grpc_route.GrpcRouteMatch matches = 1;
repeated Filter filters = 2;
}
message Filter {
oneof kind {
io.linkerd.proxy.grpc_route.GrpcFailureInjector failure_injector = 1;
io.linkerd.proxy.http_route.RequestHeaderModifier request_header_modifier = 2;
}
}
}
message HttpLocalRateLimit {
// Describes the associated HTTPLocalRateLimitPolicy resource
io.linkerd.proxy.meta.Metadata metadata = 1;
// Overall rate-limit, which all traffic coming to this server should abide
// to. If unset no overall limit is applied.
Limit total = 2;
// Fairness for individual identities; each separate client, grouped by
// identity, will have this rate-limit.
Limit identity = 3;
// Limit overrides for traffic from a specific client.
repeated Override overrides = 4;
message Override {
Limit limit = 1;
ClientIdentities clients = 2;
message ClientIdentities {
// A list of literal identities.
repeated Identity identities = 1;
}
}
message Limit {
uint32 requestsPerSecond = 1;
}
}