Combination of AuthorizationPolicy behaviors for subpaths

Hi :slight_smile:
I’m trying to create a combination of AuthorizationPolicies but I can’t get it to work, posting here hoping för help.
I’m deploying a Prometheus, Alertmanager and Grafana stack using Helm to a cluster with Istio. I also have a custom authorization provider installed and configured.

I have created virtual services for Prometheus, Alertmanager and Grafana and traffic routing works well. Next I created an AuthorizationPolicy with CUSTOM action to provide authorization through my custom provider (OAuth2Proxy), this too works.

Now I realize that Grafana dashboards has stopped working, because the request to prometheus (I suppose) requires a manual login step, so I exclude these paths in the AuthorizationPolicy and create a specific ALLOW policy for request using this ServiceAccount and a DENY for all requests without the same SA. But dashboards still does not load (error 500 in Grafana). I’ve tried a number of different solutions but every time I get Grafana to work it turns out that the query URL is open to the world, not OK.

Basically my requirements are:

  • SSO on all paths
  • Grafana can reach /api/v1/query* on Prometheus
  • SSO on /api/v1/query* for other requests

It seems that since CUSTOM policies are in alpha I cannot use notPrincipal, which would have been handy.

This is the code right now:

---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: prometheus
  namespace: monitoring
  labels:
    app: monitoring-kube-prometheus-prometheus
    app.kubernetes.io/instance: monitoring-kube-prometheus-prometheus
    app.kubernetes.io/name: monitoring-kube-prometheus-prometheus
spec:
  gateways:
    - istio-ingress/default-gateway
  hosts:
    - prometheus.istio...
  http:
    - route:
        - destination:
            host: monitoring-kube-prometheus-prometheus
            port:
              number: 9090
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: prometheus-custom-sso
  namespace: monitoring
spec:
  action: CUSTOM
  selector:
    matchLabels: 
      app.kubernetes.io/name: prometheus
  provider:
    name: oauth2-proxy
  rules:
  # Bypass SSO rule for Grafana dashboards
  - to:
    - operation:
        notPaths: ["/api/v1/query*"]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: prometheus-allow-grafana
  namespace: monitoring
spec:
  action: ALLOW
  selector:
    matchLabels: 
      app.kubernetes.io/name: prometheus
  rules:
  # Allow Grafana to query without SSO
  - from:
    - source:
        principals: [
          "cluster.local/ns/monitoring/sa/monitoring-kube-prometheus-stack-grafana"
          ] 
  - to:
    - operation:
        paths: ["/api/v1/query*"]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: prometheus-deny
  namespace: monitoring
spec:
  action: DENY
  selector:
    matchLabels: 
      app.kubernetes.io/name: prometheus
  rules:
  # Deny anyone else to query
  - from:
    - source:
        notPrincipals: [
          "cluster.local/ns/monitoring/sa/monitoring-kube-prometheus-stack-grafana"
          ] 
  - to:
    - operation:
        paths: ["/api/v1/query*"]

I’ll just post the solution here. After som investigation I found that:

  • The ALLOW policy must overlap the CUSTOM policy, so that both allow the request. The allow policy can be broader than the custom one to allow internal traffic without SSO.
  • If there is at least one ALLOW then the inverted DENY becomes redundant. If there is an allow policy everything else gets denied.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: prometheus
  namespace: monitoring
  labels:
    app: monitoring-kube-prometheus-prometheus
    app.kubernetes.io/instance: monitoring-kube-prometheus-prometheus
    app.kubernetes.io/name: monitoring-kube-prometheus-prometheus
spec:
  gateways:
    - istio-ingress/default-gateway
  hosts:
    - prometheus.istio...
  http:
    - route:
        - destination:
            host: monitoring-kube-prometheus-prometheus
            port:
              number: 9090
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: prometheus-custom-sso
  namespace: monitoring
spec:
  action: CUSTOM
  selector:
    matchLabels: 
      app.kubernetes.io/name: prometheus
  provider:
    name: oauth2-proxy-developer
  rules:
  - to:
    - operation:
        hosts: [
          "prometheus.istio..."
        ]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: prometheus-allow
  namespace: monitoring
spec:
  action: ALLOW
  selector:
    matchLabels: 
      app.kubernetes.io/name: prometheus
  rules:
  - to:
    - operation:
        hosts: [
          "prometheus.istio..."
        ]
  - from:
    - source:
        principals: [
          "cluster.local/ns/monitoring/sa/monitoring-kube-prometheus-stack-grafana",
          "cluster.local/ns/monitoring/sa/monitoring-kube-prometheus-operator"
        ] 
    to:
    - operation:
        paths: ["/api/*"]