Skip to content

Inbound policy can't be applied to metrics port (4191) when using native sidecar containers #14103

@alpeb

Description

@alpeb

What is the issue?

Prometheus isn't able to scrape metrics on proxies injected as native sidecar containers in workloads with a restrictive inbound policy.

How can it be reproduced?

  • Install linkerd with proxy.nativeSidecar: true
  • Install linkerd viz
  • Install emojivoto
  • Set up authorization for the web workload:
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
  annotations:
  name: admin
  namespace: emojivoto
spec:
  accessPolicy: deny
  podSelector:
    matchLabels:
      app: web-svc
  port: linkerd-admin
  proxyProtocol: HTTP/1
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
  namespace: emojivoto
  name: web-http-sa
spec:
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: admin
  requiredAuthenticationRefs:
    - name: prometheus
      kind: MeshTLSAuthentication
      group: policy.linkerd.io
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
  namespace: emojivoto
  name: prometheus
spec:
  identities:
  - "prometheus.linkerd-viz.serviceaccount.identity.linkerd.cluster.local"

linkerd diagnostics policy po/web-xxx 4191 doesn't detect that policy:

labels:
  group: ""
  kind: default
  name: deny
protocol:
  Kind:
    Detect:
      http_routes:
      - metadata:
          Kind:
            Default: default
        rules:
        - matches:
          - path:
              Kind:
                Prefix: /
      - authorizations:
        - authentication:
            Permit:
              Unauthenticated: {}
          labels:
            group: ""
            kind: default
            name: probe
          metadata:
            Kind:
              Default: probe
          networks:
          - net:
              ip:
                Ip:
                  Ipv4: 0
          - net:
              ip:
                Ip:
                  Ipv6: {}
        metadata:
          Kind:
            Default: probe
        rules:
        - matches:
          - method:
              Type:
                Registered: 0
            path:
              Kind:
                Exact: /live
          - method:
              Type:
                Registered: 0
            path:
              Kind:
                Exact: /ready
      timeout:
        seconds: 10

Updating the linkerd config such that proxy.nativeSidecar: false results in the policy being detected:

authorizations:
- authentication:
    Permit:
      MeshTLS:
        Clients:
          Identities:
            identities:
            - name: prometheus.linkerd-viz.serviceaccount.identity.linkerd.cluster.local
  labels:
    group: policy.linkerd.io
    kind: authorizationpolicy
    name: web-http-sa
  metadata:
    Kind:
      Resource:
        group: policy.linkerd.io
        kind: authorizationpolicy
        name: web-http-sa
  networks:
  - net:
      ip:
        Ip:
          Ipv4: 0
  - net:
      ip:
        Ip:
          Ipv6: {}
labels:
  group: policy.linkerd.io
  kind: server
  name: admin
protocol:
  Kind:
    Http1:
      routes:
      - metadata:
          Kind:
            Default: default
        rules:
        - matches:
          - path:
              Kind:
                Prefix: /
      - authorizations:
        - authentication:
            Permit:
              Unauthenticated: {}
          labels:
            group: ""
            kind: default
            name: probe
          metadata:
            Kind:
              Default: probe
          networks:
          - net:
              ip:
                Ip:
                  Ipv4: 0
          - net:
              ip:
                Ip:
                  Ipv6: {}
        metadata:
          Kind:
            Default: probe
        rules:
        - matches:
          - method:
              Type:
                Registered: 0
            path:
              Kind:
                Exact: /live
          - method:
              Type:
                Registered: 0
            path:
              Kind:
                Exact: /ready

Logs, error output, etc

No relevant logs in this case.

output of linkerd check -o short

Check is fine.

Environment

  • k8s >= 1.29
  • Linkerd >= 2.15 (when native sidecars where introduced)

Possible solution

When the policy controller indexes a pod, we use this function to retrieve its ports, but we iterate only through containers and ignore initContainers:

/// Gets the set of named ports with `protocol: TCP` from a pod spec.
pub(crate) fn pod_tcp_ports_by_name(spec: &k8s::PodSpec) -> HashMap<String, PortSet> {
let mut ports = HashMap::<String, PortSet>::default();
for (port, name) in spec
.containers
.iter()
.flat_map(|c| c.ports.iter().flatten())
.filter_map(named_tcp_port)
{
ports.entry(name.to_string()).or_default().insert(port);
}
ports
}
/// Gets the set of named ports withn `protocol: TCP` from an external workload
/// spec.
///
/// Since an external workload has only one set of ports, each name is
/// guaranteed to be unique.

Additional context

No response

Would you like to work on fixing this bug?

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions