linkerd2-proxy-api 0.18.0

Linkerd Proxy API gRPC bindings and utilities
Documentation
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;
  }
}