---

apiVersion: v1
kind: ConfigMap
metadata:
  name: kas-fleet-manager-envoy-config
  annotations:
    qontract.recycle: "true"
data:
  main.yaml: |
    # The administration endpoint uses a Unix socket instead of TCP in order
    # to avoid exposing it outside of the pod. Requests for metrics and
    # probes will go via an HTTP listener that only accepts requests for the
    # /metrics and /ready paths.
    admin:
      access_log_path: /dev/null
      address:
        pipe:
          path: /sockets/admin.socket

    static_resources:

      clusters:

      # This backend is used to send metrics and probes requests to the
      # administration endpoint.
      - name: admin
        connect_timeout: 1s
        type: STATIC
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: admin
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  pipe:
                    path: /sockets/admin.socket

      # This cluster is used to send requests to the backend. Note that
      # currently it uses TLS, but that doesn't make much sense in this
      # context because this communication is completely iside the pod. We
      # should change this to use plain TCP and maybe even Unix sockets.
      - name: backend
        connect_timeout: 1s
        type: STATIC
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: backend
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 127.0.0.1
                    port_value: 8000 # KAS Fleet Manager port
        transport_socket:
          name: envoy.transport_sockets.tls
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
            common_tls_context:
              validation_context:
                trusted_ca:
                  filename: /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt

      # This cluster is used to send request to the rate limiting service.
      - name: limiter
        connect_timeout: 1s
        type: STRICT_DNS
        lb_policy: ROUND_ROBIN
        http2_protocol_options: {}
        load_assignment:
          cluster_name: limiter
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: limitador.app-sre-rate-limiting.svc
                    port_value: 8081

      listeners:

      # This listener is used to accept /metrics and /ready requests.
      # Everything else will be rejected.
      - name: admin
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 9000
        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: admin
              route_config:
                name: admin
                virtual_hosts:
                - name: admin
                  domains:
                  - "*"
                  routes:
                  - name: ready
                    match:
                      path: /ready
                    route:
                      cluster: admin
                  - name: metrics
                    match:
                      path: /metrics
                    route:
                      cluster: admin
                      prefix_rewrite: /stats/prometheus
              http_filters:
              - name: envoy.filters.http.router

      # This listener is used to accept inbound API requests.
      - name: ingress
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 9001
        filter_chains:
        - transport_socket:
            name: envoy.transport_sockets.tls
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
              common_tls_context:
                tls_certificates:
                - certificate_chain:
                    filename: /secrets/tls/tls.crt
                  private_key:
                    filename: /secrets/tls/tls.key
          filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              access_log:
              - name: envoy.access_loggers.file
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                  path: /dev/stdout
              stat_prefix: ingress
              route_config:
                name: backend
                virtual_hosts:
                - name: all
                  domains:
                  - "*"
                  routes:

                  # Route kas-fleet-manager's agent-cluster related endpoints
                  # directly to the service without rate limiting
                  - name: kas-fleet-shard-operator-agent-cluster-routes
                    match:
                      prefix: /api/kafkas_mgmt/v1/agent-clusters
                    route:
                      cluster: backend

                  # Apply rate limit to all other kas-fleet-manager endpoints
                  - name: kas-fleet-manager-v1-routes
                    match:
                      prefix: /api/kafkas_mgmt/v1
                    route:
                      cluster: backend
                      rate_limits:
                      - actions:
                        - generic_key:
                            descriptor_key: path
                            descriptor_value: kas_fleet_manager_v1

                  # This is an example of how to define a rate limit for a
                  # specific path.
                  # - name: my_path
                  #   match:
                  #     path: /my_path
                  #   route:
                  #     cluster: backend
                  #     rate_limits:
                  #     - actions:
                  #       - generic_key:
                  #           descriptor_key: example_descriptor_key
                  #           descriptor_value: example_descriptor_value

                  # Everything else not matching one of the rules above goes
                  # directly to the backend, without rate limits.
                  - name: default
                    match:
                      prefix: /
                    route:
                      cluster: backend

              http_filters:

              # This is needed to enable the rate limiter:
              - name: envoy.filters.http.ratelimit
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
                  domain: development:kas_fleet_manager # This changes by environment
                  failure_mode_deny: false
                  timeout: 0.05s
                  rate_limit_service:
                    grpc_service:
                      envoy_grpc:
                        cluster_name: limiter
                    transport_api_version: V3

              # This is mandatory in order to have the HTTP routes above.
              - name: envoy.filters.http.router

              # We need this in order to generate JSON responses according to
              # our API guidelines, otherwise Envoy will generate plain text
              # responses.
              local_reply_config:
                mappers:
                - filter:
                    status_code_filter:
                      comparison:
                        op: EQ
                        value:
                          default_value: 429
                          runtime_key: none
                  body_format_override:
                    json_format:
                      kind: "Error"
                      id: "429"
                      href: "/api/kafkas_mgmt/v1/errors/429"
                      code: "KAFKAS-MGMT-429"
                      reason: "Too Many Requests"
