From 7b1ade829425d0431f68ef2503f937beb6a3357f Mon Sep 17 00:00:00 2001 From: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:51:29 -0700 Subject: [PATCH 1/3] Rework & Simplify Kubeflow Auth Signed-off-by: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> --- .github/workflows/kserve_m2m_test.yaml | 4 - .../notebook_controller_m2m_test.yaml | 4 - .../workflows/pipeline_run_from_notebook.yaml | 4 - .github/workflows/pipeline_test.yaml | 4 - .github/workflows/pss_test.yaml | 30 ++- README.md | 20 +- .../istio-authorization-config.yaml | 21 +- common/dex/base/params.yaml | 5 - common/dex/overlays/istio/kustomization.yaml | 3 - common/dex/overlays/istio/params.yaml | 3 - .../dex/overlays/istio/virtual-service.yaml | 6 +- common/istio-1-22/README.md | 1 - .../istio-install/base/kustomization.yaml | 1 - .../istio-install/base/x-forwarded-host.yaml | 42 ---- common/istio-cni-1-22/README.md | 1 - .../istio-install/base/kustomization.yaml | 1 - .../istio-install/base/x-forwarded-host.yaml | 42 ---- common/oauth2-proxy/base/deployment.yaml | 15 +- common/oauth2-proxy/base/kubeflow-logo.svg | 15 ++ common/oauth2-proxy/base/kustomization.yaml | 49 +++- .../base/oauth2-proxy-config.yaml | 57 ----- common/oauth2-proxy/base/oauth2_proxy.cfg | 79 +++++++ common/oauth2-proxy/base/params.yaml | 5 - .../oauth2-proxy/base/rbac.tokenreviews.yaml | 24 -- common/oauth2-proxy/base/virtualservice.yaml | 18 ++ common/oauth2-proxy/components/README.md | 21 +- .../components/cluster-jwks-proxy/README.md | 0 .../cluster-jwks-proxy.yaml | 80 +++++++ .../cluster-jwks-proxy/kustomization.yaml | 10 + .../README.md | 41 ---- ...ronjob.kubeflow-m2m-oidc-configurator.yaml | 48 ---- .../kustomization.yaml | 24 -- .../rbac.yaml | 35 --- .../script.sh | 143 ------------ ...gressgateway-oauth2-proxy.cloudflare.yaml} | 13 +- ...icy.istio-ingressgateway-oauth2-proxy.yaml | 13 +- ...ingressgateway-require-jwt.cloudflare.yaml | 33 +++ ...licy.istio-ingressgateway-require-jwt.yaml | 24 ++ .../istio-external-auth/kustomization.yaml | 9 +- .../requestauthentication.dex-jwt.yaml | 39 +++- .../components/istio-m2m/README.md | 6 - .../components/istio-m2m/kustomization.yaml | 24 -- .../components/istio-m2m/params.yaml | 3 - .../istio-m2m/requestauthentication.yaml | 40 +++- .../m2m-dex-and-eks/kustomization.yaml | 31 +++ .../m2m-dex-and-kind/kustomization.yaml | 35 +++ .../{m2m => m2m-dex-only}/kustomization.yaml | 7 +- .../m2m-self-signed/kustomization.yaml | 19 -- common/oauth2-proxy/overlays/m2m/README.md | 27 --- .../kustomization.yaml | 8 - example/kustomization.yaml | 6 +- .../kustomization.yaml | 2 +- .../gh-actions/install_istio_with_ext_auth.sh | 9 +- tests/gh-actions/test_dex_login.py | 213 +++++++++++------- ...wait_for_kubeflow_m2m_oidc_configurator.sh | 51 ----- 55 files changed, 673 insertions(+), 795 deletions(-) delete mode 100644 common/dex/base/params.yaml delete mode 100644 common/dex/overlays/istio/params.yaml delete mode 100644 common/istio-1-22/istio-install/base/x-forwarded-host.yaml delete mode 100644 common/istio-cni-1-22/istio-install/base/x-forwarded-host.yaml create mode 100644 common/oauth2-proxy/base/kubeflow-logo.svg delete mode 100644 common/oauth2-proxy/base/oauth2-proxy-config.yaml create mode 100644 common/oauth2-proxy/base/oauth2_proxy.cfg delete mode 100644 common/oauth2-proxy/base/params.yaml delete mode 100644 common/oauth2-proxy/base/rbac.tokenreviews.yaml create mode 100644 common/oauth2-proxy/base/virtualservice.yaml create mode 100644 common/oauth2-proxy/components/cluster-jwks-proxy/README.md create mode 100644 common/oauth2-proxy/components/cluster-jwks-proxy/cluster-jwks-proxy.yaml create mode 100644 common/oauth2-proxy/components/cluster-jwks-proxy/kustomization.yaml delete mode 100644 common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/README.md delete mode 100644 common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/cronjob.kubeflow-m2m-oidc-configurator.yaml delete mode 100644 common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/kustomization.yaml delete mode 100644 common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/rbac.yaml delete mode 100644 common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/script.sh rename common/oauth2-proxy/components/istio-external-auth/{authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml => authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml} (50%) create mode 100644 common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.cloudflare.yaml create mode 100644 common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.yaml delete mode 100644 common/oauth2-proxy/components/istio-m2m/params.yaml create mode 100644 common/oauth2-proxy/overlays/m2m-dex-and-eks/kustomization.yaml create mode 100644 common/oauth2-proxy/overlays/m2m-dex-and-kind/kustomization.yaml rename common/oauth2-proxy/overlays/{m2m => m2m-dex-only}/kustomization.yaml (50%) delete mode 100644 common/oauth2-proxy/overlays/m2m-self-signed/kustomization.yaml delete mode 100644 common/oauth2-proxy/overlays/m2m/README.md delete mode 100644 common/oauth2-proxy/overlays/m2m/component-overwrite-m2m-token-issuer/kustomization.yaml delete mode 100755 tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh diff --git a/.github/workflows/kserve_m2m_test.yaml b/.github/workflows/kserve_m2m_test.yaml index 2f0b679c9f..fc92967090 100644 --- a/.github/workflows/kserve_m2m_test.yaml +++ b/.github/workflows/kserve_m2m_test.yaml @@ -59,10 +59,6 @@ jobs: nohup kubectl port-forward --namespace istio-system svc/${INGRESS_GATEWAY_SERVICE} 8080:80 & while ! curl localhost:8080; do echo waiting for port-forwarding; sleep 1; done; echo port-forwarding ready - - name: Wait for the kubeflow-m2m-oidc-configurator Job - run: | - ./tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh - - name: Run kserve tests with m2m token from SA default/default run: | export KSERVE_INGRESS_HOST_PORT=localhost:8080 diff --git a/.github/workflows/notebook_controller_m2m_test.yaml b/.github/workflows/notebook_controller_m2m_test.yaml index 4fddc3c326..3209cb9db6 100644 --- a/.github/workflows/notebook_controller_m2m_test.yaml +++ b/.github/workflows/notebook_controller_m2m_test.yaml @@ -51,10 +51,6 @@ jobs: nohup kubectl port-forward --namespace istio-system svc/${INGRESS_GATEWAY_SERVICE} 8080:80 & while ! curl localhost:8080; do echo waiting for port-forwarding; sleep 1; done; echo port-forwarding ready - - name: Wait for the kubeflow-m2m-oidc-configurator Job - run: | - ./tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh - - name: List notebooks over API with authorized SA Token run: | KF_PROFILE=kubeflow-user-example-com diff --git a/.github/workflows/pipeline_run_from_notebook.yaml b/.github/workflows/pipeline_run_from_notebook.yaml index f83b729a06..11454d1860 100644 --- a/.github/workflows/pipeline_run_from_notebook.yaml +++ b/.github/workflows/pipeline_run_from_notebook.yaml @@ -63,10 +63,6 @@ jobs: -f tests/gh-actions/kf-objects/notebook.test.kubeflow-user-example.com.yaml \ --timeout 600s - - name: Wait for the kubeflow-m2m-oidc-configurator Job - run: | - ./tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh - - name: Copy and execute the pipeline run script in KF Notebook run: | kubectl -n kubeflow-user-example-com cp \ diff --git a/.github/workflows/pipeline_test.yaml b/.github/workflows/pipeline_test.yaml index fec9c9eccd..d2d5585ae3 100644 --- a/.github/workflows/pipeline_test.yaml +++ b/.github/workflows/pipeline_test.yaml @@ -52,10 +52,6 @@ jobs: nohup kubectl port-forward --namespace istio-system svc/${ingress_gateway_service} 8080:80 & while ! curl localhost:8080; do echo waiting for port-forwarding; sleep 1; done; echo port-forwarding ready - - name: Wait for the kubeflow-m2m-oidc-configurator Job - run: | - ./tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh - - name: List and deploy test pipeline with authorized ServiceAccount Token run: | pip3 install kfp==2.4.0 diff --git a/.github/workflows/pss_test.yaml b/.github/workflows/pss_test.yaml index 8e313638cc..fbd0fccc35 100644 --- a/.github/workflows/pss_test.yaml +++ b/.github/workflows/pss_test.yaml @@ -27,12 +27,11 @@ jobs: - name: Install kubectl run: ./tests/gh-actions/install_kubectl.sh - - name: Install all istio-cni resources and kubeflow namespace - run: | - kustomize build common/kubeflow-namespace/base | kubectl apply -f - - ./tests/gh-actions/install_cert_manager.sh - ./tests/gh-actions/install_istio-cni.sh - kustomize build common/istio-cni-1-22/kubeflow-istio-resources/base | kubectl apply -f - + - name: Install cert-manager + run: ./tests/gh-actions/install_cert_manager.sh + + - name: Install Istio CNI (with external authentication) + run: ./tests/gh-actions/install_istio-cni.sh - name: Configure istio init container with seccompProfile attribute run: | @@ -44,15 +43,22 @@ jobs: kubectl apply -f temporary_patch.yaml rm temporary_patch.yaml - - name: Install all other deployments of static namespaces + - name: Create kubeflow namespace + run: kustomize build common/kubeflow-namespace/base | kubectl apply -f - + + - name: Install kubeflow-istio-resources + run: kustomize build common/istio-cni-1-22/kubeflow-istio-resources/base | kubectl apply -f - + + - name: Install KF Multi Tenancy + run: ./tests/gh-actions/install_multi_tenancy.sh + + - name: Install dex run: | - ./tests/gh-actions/install_multi_tenancy.sh - kustomize build ./common/oauth2-proxy/overlays/m2m-self-signed | kubectl apply -f - - echo "Waiting for all oauth2-proxy pods to become ready..." - kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=oauth2-proxy' --timeout=180s -n oauth2-proxy + echo "Installing Dex..." kustomize build ./common/dex/overlays/oauth2-proxy | kubectl apply -f - + echo "Waiting for pods in auth namespace to become ready..." - kubectl wait --for=condition=Ready pods --all --timeout=180s -n auth + kubectl wait --for=condition=ready pods --all --timeout=180s -n auth - name: Install KF Pipelines run: ./tests/gh-actions/install_pipelines.sh diff --git a/README.md b/README.md index c234b64b94..3df72e34e2 100644 --- a/README.md +++ b/README.md @@ -224,11 +224,25 @@ The oauth2-proxy extends your Istio Ingress-Gateway capabilities, to be able to ```sh echo "Installing oauth2-proxy..." -kustomize build common/oauth2-proxy/overlays/m2m-self-signed/ | kubectl apply -f - + +# Only uncomment ONE of the following overlays, they are mutually exclusive, +# see `common/oauth2-proxy/overlays/` for more options. + +# OPTION 1: works on most clusters, does NOT allow K8s service account +# tokens to be used from outside the cluster via the Istio ingress-gateway. +# +kustomize build common/oauth2-proxy/overlays/m2m-dex-only/ | kubectl apply -f - kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=oauth2-proxy' --timeout=180s -n oauth2-proxy + +# Option 2: works on Kind/K3D clusters, and allows K8s service account tokens to be used +# from outside the cluster via the Istio ingress-gateway. +# +#kustomize build common/oauth2-proxy/overlays/m2m-dex-and-kind/ | kubectl apply -f - +#kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=oauth2-proxy' --timeout=180s -n oauth2-proxy +#kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=cluster-jwks-proxy' --timeout=180s -n istio-system ``` -It supports user sessions as well as proper token-based machine to machine atuhhentication. +It supports user sessions as well as proper token-based machine to machine authentication. #### Dex @@ -237,7 +251,9 @@ Dex is an OpenID Connect Identity (OIDC) with multiple authentication backends. Install Dex: ```sh +echo "Installing Dex..." kustomize build common/dex/overlays/oauth2-proxy | kubectl apply -f - +kubectl wait --for=condition=ready pods --all --timeout=180s -n auth ``` #### Knative diff --git a/apps/pipeline/upstream/base/installs/multi-user/istio-authorization-config.yaml b/apps/pipeline/upstream/base/installs/multi-user/istio-authorization-config.yaml index 8b3144ad39..6a77328104 100644 --- a/apps/pipeline/upstream/base/installs/multi-user/istio-authorization-config.yaml +++ b/apps/pipeline/upstream/base/installs/multi-user/istio-authorization-config.yaml @@ -8,10 +8,21 @@ spec: matchLabels: app: ml-pipeline-ui rules: + # Allow all requests from the ingress gateway - from: - source: - namespaces: - - istio-system + principals: + - cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account + + # Allow all requests with an `authorization` header but NOT a `kubeflow-userid` header. + # This is needed to allow Kubernetes JWTs to be passed to the KFP API. + - when: + - key: request.headers[authorization] + values: + - "*" + - key: request.headers[kubeflow-userid] + notValues: + - "*" --- apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy @@ -32,11 +43,7 @@ spec: - cluster.local/ns/kubeflow/sa/ml-pipeline-scheduledworkflow - cluster.local/ns/kubeflow/sa/ml-pipeline-viewer-crd-service-account - cluster.local/ns/kubeflow/sa/kubeflow-pipelines-cache - # allow access by any trusted principal - - from: - - source: - requestPrincipals: ["*"] - # For user workloads, which cannot user http headers for authentication + # Allow all requests that dont have a `kubeflow-userid` header. - when: - key: request.headers[kubeflow-userid] notValues: ['*'] diff --git a/common/dex/base/params.yaml b/common/dex/base/params.yaml deleted file mode 100644 index af2393a65d..0000000000 --- a/common/dex/base/params.yaml +++ /dev/null @@ -1,5 +0,0 @@ -varReference: -- path: spec/template/spec/volumes/secret/secretName - kind: Deployment -- path: data/config.yaml - kind: ConfigMap diff --git a/common/dex/overlays/istio/kustomization.yaml b/common/dex/overlays/istio/kustomization.yaml index 7f2892f235..f993b8eeee 100644 --- a/common/dex/overlays/istio/kustomization.yaml +++ b/common/dex/overlays/istio/kustomization.yaml @@ -6,9 +6,6 @@ resources: - ../../base - virtual-service.yaml -configurations: -- params.yaml - replacements: - source: version: v1 diff --git a/common/dex/overlays/istio/params.yaml b/common/dex/overlays/istio/params.yaml deleted file mode 100644 index eea869e0d4..0000000000 --- a/common/dex/overlays/istio/params.yaml +++ /dev/null @@ -1,3 +0,0 @@ -varReference: -- path: spec/http/route/destination/host - kind: VirtualService diff --git a/common/dex/overlays/istio/virtual-service.yaml b/common/dex/overlays/istio/virtual-service.yaml index 1e1d733729..4b414e5b61 100644 --- a/common/dex/overlays/istio/virtual-service.yaml +++ b/common/dex/overlays/istio/virtual-service.yaml @@ -1,7 +1,3 @@ -# This config is gated on kiali upgrade to 0.21 from 0.16 in istio 1.1.6: -# https://github.com/kiali/kiali/issues/1154 -# https://github.com/istio/istio/issues/11131 - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: @@ -17,6 +13,6 @@ spec: prefix: /dex/ route: - destination: - host: $(DEX_SERVICE).$(DEX_NAMESPACE).svc.cluster.local + host: DEX_SERVICE.DEX_NAMESPACE.svc.cluster.local port: number: 5556 diff --git a/common/istio-1-22/README.md b/common/istio-1-22/README.md index e4ba791bab..d64912b336 100644 --- a/common/istio-1-22/README.md +++ b/common/istio-1-22/README.md @@ -84,7 +84,6 @@ The Istio kustomizations make the following changes: - Remove PodDisruptionBudget from `istio-install` and `cluster-local-gateway` kustomizations. See: - https://github.com/istio/istio/issues/12602 - https://github.com/istio/istio/issues/24000 -- Add EnvoyFilter for adding an `X-Forwarded-For` header in requests passing through the Istio Ingressgateway, inside the `istio-install` kustomization. - Add Istio AuthorizationPolicy to allow all requests to the Istio Ingressgateway and the Istio cluster-local gateway. - Add Istio AuthorizationPolicy in Istio's root namespace, so that sidecars deny traffic by default (explicit deny-by-default authorization model). - Add Gateway CRs for the Istio Ingressgateway and the Istio cluster-local gateway, as `istioctl` stopped generating them in later versions. diff --git a/common/istio-1-22/istio-install/base/kustomization.yaml b/common/istio-1-22/istio-install/base/kustomization.yaml index fdb6319b10..37d6f0b36e 100644 --- a/common/istio-1-22/istio-install/base/kustomization.yaml +++ b/common/istio-1-22/istio-install/base/kustomization.yaml @@ -8,7 +8,6 @@ resources: - gateway_authorizationpolicy.yaml - deny_all_authorizationpolicy.yaml - gateway.yaml -- x-forwarded-host.yaml patches: - path: patches/service.yaml diff --git a/common/istio-1-22/istio-install/base/x-forwarded-host.yaml b/common/istio-1-22/istio-install/base/x-forwarded-host.yaml deleted file mode 100644 index 4bae262aa6..0000000000 --- a/common/istio-1-22/istio-install/base/x-forwarded-host.yaml +++ /dev/null @@ -1,42 +0,0 @@ -# EnvoyFilter for adding the X-Forwarded-Host header. -# Needed for the Rok GW to work correctly. -# Older manifests used an Istio rule, but that relies on Mixer which -# is deprecated. This way is more performant and up-to-date. -# -# TODO: X-Forwarded-Host needs to be applied in two steps: -# 1. Put old host in `X-Forwarded-Host` -# 2. Update Host in request -# -# This filter only does (1). It can't do (2) because it doesn't know the new -# host yet. See if we can add an EnvoyFilter for (2). We currently have to do -# this per VirtualService, in each app that needs it. -apiVersion: networking.istio.io/v1alpha3 -kind: EnvoyFilter -metadata: - name: x-forwarded-host -spec: - workloadSelector: - labels: - istio: ingressgateway - configPatches: - # The first patch adds the lua filter to the listener/http connection manager - - applyTo: HTTP_FILTER - match: - context: GATEWAY - listener: - filterChain: - filter: - name: "envoy.http_connection_manager" - subFilter: - name: "envoy.router" - patch: - operation: INSERT_BEFORE - value: - name: envoy.filters.http.lua - typed_config: - "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" - inlineCode: | - function envoy_on_request(request_handle) - local host = request_handle:headers():get(":authority") - request_handle:headers():add("x-forwarded-host", host) - end diff --git a/common/istio-cni-1-22/README.md b/common/istio-cni-1-22/README.md index 444c652f02..89dba3c52e 100644 --- a/common/istio-cni-1-22/README.md +++ b/common/istio-cni-1-22/README.md @@ -87,7 +87,6 @@ The Istio kustomizations make the following changes: - Remove PodDisruptionBudget from `istio-install` and `cluster-local-gateway` kustomizations. See: - https://github.com/istio/istio/issues/12602 - https://github.com/istio/istio/issues/24000 -- Add EnvoyFilter for adding an `X-Forwarded-For` header in requests passing through the Istio Ingressgateway, inside the `istio-install` kustomization. - Add Istio AuthorizationPolicy to allow all requests to the Istio Ingressgateway and the Istio cluster-local gateway. - Add Istio AuthorizationPolicy in Istio's root namespace, so that sidecars deny traffic by default (explicit deny-by-default authorization model). - Add Gateway CRs for the Istio Ingressgateway and the Istio cluster-local gateway, as `istioctl` stopped generating them in later versions. diff --git a/common/istio-cni-1-22/istio-install/base/kustomization.yaml b/common/istio-cni-1-22/istio-install/base/kustomization.yaml index c3d6f9e06f..bb174d2dfa 100644 --- a/common/istio-cni-1-22/istio-install/base/kustomization.yaml +++ b/common/istio-cni-1-22/istio-install/base/kustomization.yaml @@ -6,7 +6,6 @@ resources: - gateway_authorizationpolicy.yaml - deny_all_authorizationpolicy.yaml - gateway.yaml -- x-forwarded-host.yaml patches: - path: patches/service.yaml diff --git a/common/istio-cni-1-22/istio-install/base/x-forwarded-host.yaml b/common/istio-cni-1-22/istio-install/base/x-forwarded-host.yaml deleted file mode 100644 index 4bae262aa6..0000000000 --- a/common/istio-cni-1-22/istio-install/base/x-forwarded-host.yaml +++ /dev/null @@ -1,42 +0,0 @@ -# EnvoyFilter for adding the X-Forwarded-Host header. -# Needed for the Rok GW to work correctly. -# Older manifests used an Istio rule, but that relies on Mixer which -# is deprecated. This way is more performant and up-to-date. -# -# TODO: X-Forwarded-Host needs to be applied in two steps: -# 1. Put old host in `X-Forwarded-Host` -# 2. Update Host in request -# -# This filter only does (1). It can't do (2) because it doesn't know the new -# host yet. See if we can add an EnvoyFilter for (2). We currently have to do -# this per VirtualService, in each app that needs it. -apiVersion: networking.istio.io/v1alpha3 -kind: EnvoyFilter -metadata: - name: x-forwarded-host -spec: - workloadSelector: - labels: - istio: ingressgateway - configPatches: - # The first patch adds the lua filter to the listener/http connection manager - - applyTo: HTTP_FILTER - match: - context: GATEWAY - listener: - filterChain: - filter: - name: "envoy.http_connection_manager" - subFilter: - name: "envoy.router" - patch: - operation: INSERT_BEFORE - value: - name: envoy.filters.http.lua - typed_config: - "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" - inlineCode: | - function envoy_on_request(request_handle) - local host = request_handle:headers():get(":authority") - request_handle:headers():add("x-forwarded-host", host) - end diff --git a/common/oauth2-proxy/base/deployment.yaml b/common/oauth2-proxy/base/deployment.yaml index eba3f09429..e92f4f92da 100644 --- a/common/oauth2-proxy/base/deployment.yaml +++ b/common/oauth2-proxy/base/deployment.yaml @@ -15,10 +15,12 @@ spec: app.kubernetes.io/name: oauth2-proxy spec: volumes: - - name: configmain + - name: oauth2-proxy-config configMap: name: oauth2-proxy - defaultMode: 420 + - name: oauth2-proxy-theme + configMap: + name: oauth2-proxy-theme containers: - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:latest @@ -69,9 +71,14 @@ spec: name: oauth2-proxy-parameters key: EXTRA_JWT_ISSUERS volumeMounts: - - name: configmain + - name: oauth2-proxy-config mountPath: /etc/oauth2_proxy/oauth2_proxy.cfg subPath: oauth2_proxy.cfg + readOnly: true + - name: oauth2-proxy-theme + mountPath: /custom-theme/kubeflow-logo.svg + subPath: kubeflow-logo.svg + readOnly: true livenessProbe: httpGet: path: /ping @@ -79,7 +86,7 @@ spec: scheme: HTTP readinessProbe: httpGet: - path: /ping + path: /ready port: http scheme: HTTP resources: {} diff --git a/common/oauth2-proxy/base/kubeflow-logo.svg b/common/oauth2-proxy/base/kubeflow-logo.svg new file mode 100644 index 0000000000..19a3174ae0 --- /dev/null +++ b/common/oauth2-proxy/base/kubeflow-logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/common/oauth2-proxy/base/kustomization.yaml b/common/oauth2-proxy/base/kustomization.yaml index 0e470f0603..57e5ac1828 100644 --- a/common/oauth2-proxy/base/kustomization.yaml +++ b/common/oauth2-proxy/base/kustomization.yaml @@ -6,15 +6,9 @@ namespace: oauth2-proxy resources: - namespace.yaml - deployment.yaml -- oauth2-proxy-config.yaml - serviceaccount.yaml - service.yaml - -# To use oauth2-proxy in OpenShift, use openshift distribution of oauth2-proxy -# available here: https://github.com/openshift/oauth-proxy -# and add RBAC to enable creation of tokenreviews -# Token Reviews for OpenShift -# - rbac.tokenreviews.yaml +- virtualservice.yaml secretGenerator: - name: oauth2-proxy @@ -25,6 +19,14 @@ secretGenerator: - cookie-secret=7d16fee92f8d11b8940b081b3f8b8acb configMapGenerator: +- name: oauth2-proxy + files: + - oauth2_proxy.cfg + +- name: oauth2-proxy-theme + files: + - kubeflow-logo.svg + - name: oauth2-proxy-parameters literals: # This will configure oauth2-proxy option --cookie-secure which can force @@ -54,6 +56,39 @@ configMapGenerator: # - EXTRA_JWT_ISSUERS=https://oidc.eks.region.amazonaws.com/id/1234abcd=https://kubernetes.default.svc - EXTRA_JWT_ISSUERS= +replacements: +- source: + version: v1 + kind: Service + name: oauth2-proxy + fieldPath: metadata.name + targets: + - fieldPaths: + - spec.http.0.route.0.destination.host + options: + delimiter: . + select: + version: v1alpha3 + group: networking.istio.io + kind: VirtualService + name: oauth2-proxy +- source: + fieldPath: metadata.namespace + kind: Service + name: oauth2-proxy + version: v1 + targets: + - fieldPaths: + - spec.http.0.route.0.destination.host + options: + delimiter: . + index: 1 + select: + version: v1alpha3 + group: networking.istio.io + kind: VirtualService + name: oauth2-proxy + images: - name: quay.io/oauth2-proxy/oauth2-proxy newName: quay.io/oauth2-proxy/oauth2-proxy diff --git a/common/oauth2-proxy/base/oauth2-proxy-config.yaml b/common/oauth2-proxy/base/oauth2-proxy-config.yaml deleted file mode 100644 index b79198af08..0000000000 --- a/common/oauth2-proxy/base/oauth2-proxy-config.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: oauth2-proxy - labels: - app: oauth2-proxy -data: - oauth2_proxy.cfg: | - provider = "oidc" - oidc_issuer_url = "http://dex.auth.svc.cluster.local:5556/dex" - scope = "profile email groups openid" - upstreams = "static://200" - email_domains = [ "*" ] - skip_auth_regex=["/dex/.*"] - # --- - # OIDC Discovery has to be skipped and login url has to be provided directly - # in order to enable relative auth redirect. - # Turning On OIDC Discovery would set the auth redirect location as the dex - # Issuer URL which is http://dex.auth.svc.cluster.local:5556 in the default, - # example installation. This address is usuallynot available through the Web - # Browser. If you have a setup where dex has it's url as other than the - # in-cluster service, this is optional. - skip_oidc_discovery = true - login_url = "/dex/auth" - redeem_url = "http://dex.auth.svc.cluster.local:5556/dex/token" - oidc_jwks_url = "http://dex.auth.svc.cluster.local:5556/dex/keys" - # --- - # Go to dex login page directly instead of showing the oauth2-proxy login - # page. - skip_provider_button = true - # --- - # Set Authorization Bearer response header. This is needed in order to - # forward the Authorization Bearer token to Istio and enable authorization - # based on JWT. - set_authorization_header = true - # --- - # set X-Auth-Request-User, X-Auth-Request-Groups, X-Auth-Request-Email and - # X-Auth-Request-Preferred-Username. This is optional for Kubeflow but you - # may have other services that use standard auth headers. - set_xauthrequest = true - # --- - cookie_name = "oauth2_proxy_kubeflow" - # --- - # Dex default cookie expiration is 24h. If set to 168h (default oauth2-proxy), - # Istio will not be able to use the JWT after 24h but oauth2-proxy will still - # consider the cookie valid. - # It's possible to configure the JWT Refresh Token to enable longer login - # session. - cookie_expire = "24h" - cookie_refresh = 0 - # --- - code_challenge_method = "S256" - # --- - redirect_url = "/oauth2/callback" - relative_redirect_url = true - -binaryData: {} diff --git a/common/oauth2-proxy/base/oauth2_proxy.cfg b/common/oauth2-proxy/base/oauth2_proxy.cfg new file mode 100644 index 0000000000..946768aa60 --- /dev/null +++ b/common/oauth2-proxy/base/oauth2_proxy.cfg @@ -0,0 +1,79 @@ +provider = "oidc" +oidc_issuer_url = "http://dex.auth.svc.cluster.local:5556/dex" +scope = "profile email groups openid" +email_domains = [ "*" ] + +# serve a static HTTP 200 upstream on for authentication success +# we are using oauth2-proxy as an ExtAuthz to "check" each request, not pass it on +upstreams = [ "static://200" ] + +# skip authentication for these paths +skip_auth_routes = [ + "^/dex/", +] + +# requests to paths matching these regex patterns will receive a 401 Unauthorized response +# when not authenticated, instead of being redirected to the login page with a 302, +# this prevents background requests being redirected to the login page, +# and the accumulation of CSRF cookies +api_routes = [ + # Generic + # NOTE: included because most background requests contain these paths + "/api/", + "/apis/", + + # Kubeflow Pipelines + # NOTE: included because KFP UI makes MANY background requests to these paths but because they are + # not `application/json` requests, oauth2-proxy will redirect them to the login page + "^/ml_metadata", +] + +# OIDC Discovery has to be skipped and login url has to be provided directly +# in order to enable relative auth redirect. Using OIDC Discovery would set +# the redirect location to http://dex.auth.svc.cluster.local:5556 in the example +# installation. This address is usually not available through the Web Browser. +# If you have a setup where dex has it's url as other than the in-cluster +# service, this is optional. +skip_oidc_discovery = true +login_url = "/dex/auth" +redeem_url = "http://dex.auth.svc.cluster.local:5556/dex/token" +oidc_jwks_url = "http://dex.auth.svc.cluster.local:5556/dex/keys" + +# if `false`, a sign-in page is displayed before starting the login flow +# prevents background requests starting their own login flow on token expiry, +# which can lead to many CSRF cookies, potentially exceeding the cookie limit +skip_provider_button = false + +# style the sign-in page +provider_display_name = "Dex" +custom_sign_in_logo = "/custom-theme/kubeflow-logo.svg" +banner = "-" +footer = "-" + +# oauth2-proxy sends "force" by default, which causes dex to always prompt for login +# https://github.com/dexidp/dex/pull/3086 +prompt = "none" + +# set Authorization Bearer response header. This is needed in order to +# forward the Authorization Bearer token to Istio and enable authorization +# based on JWT. +set_authorization_header = true + +# set X-Auth-Request-User, X-Auth-Request-Groups, X-Auth-Request-Email and +# X-Auth-Request-Preferred-Username. This is optional for Kubeflow but you +# may have other services that use standard auth headers. +set_xauthrequest = true + +cookie_name = "oauth2_proxy_kubeflow" + +# Dex default cookie expiration is 24h. +# If set to 168h (default oauth2-proxy), Istio will not be able to use the JWT after 24h, +# but oauth2-proxy will still consider the cookie valid. +# It's possible to configure the JWT Refresh Token to enable longer login session. +cookie_expire = "24h" +cookie_refresh = 0 + +code_challenge_method = "S256" + +redirect_url = "/oauth2/callback" +relative_redirect_url = true \ No newline at end of file diff --git a/common/oauth2-proxy/base/params.yaml b/common/oauth2-proxy/base/params.yaml deleted file mode 100644 index fcec4c57c4..0000000000 --- a/common/oauth2-proxy/base/params.yaml +++ /dev/null @@ -1,5 +0,0 @@ -varReference: -- path: spec/configPatches/patch/value/typed_config/http_service/server_uri/uri - kind: EnvoyFilter -- path: spec/configPatches/patch/value/typed_config/http_service/server_uri/cluster - kind: EnvoyFilter diff --git a/common/oauth2-proxy/base/rbac.tokenreviews.yaml b/common/oauth2-proxy/base/rbac.tokenreviews.yaml deleted file mode 100644 index 1b071279e8..0000000000 --- a/common/oauth2-proxy/base/rbac.tokenreviews.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: authn-delegator -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: authn-delegators -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: authn-delegator -subjects: -- kind: ServiceAccount - name: oauth2-proxy diff --git a/common/oauth2-proxy/base/virtualservice.yaml b/common/oauth2-proxy/base/virtualservice.yaml new file mode 100644 index 0000000000..516f582d29 --- /dev/null +++ b/common/oauth2-proxy/base/virtualservice.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: oauth2-proxy +spec: + gateways: + - kubeflow/kubeflow-gateway + hosts: + - '*' + http: + - match: + - uri: + prefix: /oauth2/ + route: + - destination: + host: OAUTH2_PROXY_SERVICE.OAUTH2_PROXY_NAMESPACE.svc.cluster.local + port: + number: 80 diff --git a/common/oauth2-proxy/components/README.md b/common/oauth2-proxy/components/README.md index aedbba080f..d44bb35fce 100644 --- a/common/oauth2-proxy/components/README.md +++ b/common/oauth2-proxy/components/README.md @@ -54,11 +54,6 @@ Below is a list of the available Kustomize Components with brief descriptions. C * **[central-dashboard](./central-dashboard.md)** - Configures the central dashboard to use oauth2-proxy logout URL. -* **[configure-self-signed-kubernetes-oidc-issuer](./configure-self-signed-kubernetes-oidc-issuer.md)** - - Creates a Kubernetes Job with RBAC to discover and configure the in-cluster, - self-signed default Kubernetes OIDC issuer, essential for using Kubernetes - OIDC for M2M Tokens. - * **[istio-external-auth](./istio-external-auth.md)** - Modifies Istio configuration to define oauth2-proxy as external authentication middleware via envoyExtAuthzHttp extension provider. Adds RequestAuthentication to trust Dex @@ -70,16 +65,6 @@ Below is a list of the available Kustomize Components with brief descriptions. C Authorization header. By default, the OIDC Issuer is the in-cluster Kubernetes OIDC. - -## OpenShift - -This deployment of `oauth2-proxy` does not support OpenShift out of the box. To facilitate -integration with OpenShift: -* Utilize the OpenShift-specific distribution of `oauth2-proxy`, accessible at: - * [OpenShift OAuth Proxy on GitHub](https://github.com/openshift/oauth-proxy) -* Enable RBAC for token reviews by incorporating the `rbac.tokenreviews.yaml` file into - your kustomize. For more details, refer to the relevant comment in `kustomization.yaml`. - ## CloudFlare CloudFlare requires that certain static, standard web browser assets are accessible without @@ -90,7 +75,7 @@ Kubeflow instance behind CloudFlare. This issue can be resolved by defining a set of assets in the Istio `AuthorizationPolicy` that do not require authentication. An example `AuthorizationPolicy` for this purpose is -provided in the file `authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml`. +provided in the file `authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml`. ## Explaining the Auth Routine @@ -179,7 +164,7 @@ make the following changes to the `example/kustomization.yaml` file: # from - ../common//oidc-authservice/base # to - - ../common/oauth2-proxy/overlays/m2m-self-signed + - ../common/oauth2-proxy/overlays/m2m-dex-and-kind ``` * change Dex overlay ``` @@ -211,7 +196,7 @@ index c1a85789..4a50440c 100644 -- ../common//oidc-authservice/base +- ../common/istio-1-22/istio-install/overlays/oauth2-proxy +# oauth2-proxy for OIDC -+- ../common/oauth2-proxy/overlays/m2m-self-signed ++- ../common/oauth2-proxy/overlays/m2m-dex-and-kind # Dex -- ../common/dex/overlays/istio +- ../common/dex/overlays/oauth2-proxy diff --git a/common/oauth2-proxy/components/cluster-jwks-proxy/README.md b/common/oauth2-proxy/components/cluster-jwks-proxy/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/oauth2-proxy/components/cluster-jwks-proxy/cluster-jwks-proxy.yaml b/common/oauth2-proxy/components/cluster-jwks-proxy/cluster-jwks-proxy.yaml new file mode 100644 index 0000000000..623949999e --- /dev/null +++ b/common/oauth2-proxy/components/cluster-jwks-proxy/cluster-jwks-proxy.yaml @@ -0,0 +1,80 @@ +# the default JWKS endpoint for Kind is not public, and uses a self-signed certificate +# for the Istio RequestAuthentication to trust it, we need to proxy the cluster's JWKS endpoint over HTTP +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-jwks-proxy + namespace: istio-system + labels: + app.kubernetes.io/name: cluster-jwks-proxy +--- +apiVersion: v1 +kind: Service +metadata: + name: cluster-jwks-proxy + namespace: istio-system + labels: + app.kubernetes.io/name: cluster-jwks-proxy +spec: + ports: + - name: http + port: 80 + targetPort: http + selector: + app.kubernetes.io/name: cluster-jwks-proxy +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cluster-jwks-proxy + namespace: istio-system + labels: + app.kubernetes.io/name: cluster-jwks-proxy +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: cluster-jwks-proxy + template: + metadata: + labels: + app.kubernetes.io/name: cluster-jwks-proxy + spec: + serviceAccountName: cluster-jwks-proxy + containers: + - name: kubectl-proxy + image: docker.io/bitnami/kubectl + ports: + - name: http + containerPort: 8080 + startupProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 2 + httpGet: + path: /openid/v1/jwks + port: http + livenessProbe: + initialDelaySeconds: 15 + periodSeconds: 15 + timeoutSeconds: 5 + httpGet: + path: /openid/v1/jwks + port: http + readinessProbe: + initialDelaySeconds: 15 + periodSeconds: 15 + timeoutSeconds: 5 + httpGet: + path: /openid/v1/jwks + port: http + args: + - proxy + - --address=0.0.0.0 + - --port=8080 + ## accept all hosts (default is local only) + - --accept-hosts=.* + ## only accept requests to '/openid/v1/jwks' and '/.well-known/openid-configuration' + - --accept-paths=^(?:/openid/v1/jwks)|(?:/.well-known/openid-configuration)$ + ## reject all methods except 'GET' + - --reject-methods=^(POST|PUT|PATCH|DELETE|HEAD|OPTIONS|CONNECT|TRACE)$ diff --git a/common/oauth2-proxy/components/cluster-jwks-proxy/kustomization.yaml b/common/oauth2-proxy/components/cluster-jwks-proxy/kustomization.yaml new file mode 100644 index 0000000000..aac972ca58 --- /dev/null +++ b/common/oauth2-proxy/components/cluster-jwks-proxy/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: +- cluster-jwks-proxy.yaml + +images: +- name: docker.io/bitnami/kubectl + newName: docker.io/bitnami/kubectl + newTag: 1.30.4 diff --git a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/README.md b/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/README.md deleted file mode 100644 index 0e178e58b7..0000000000 --- a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Configure Istio with Self-Signed Kubernetes OIDC Issuer - -## Overview - -This kustomize component is designed for scenarios where the Kubernetes OIDC Issuer is behind -self-signed certificates, causing trust issues with Istio in retrieving the JWKS. It creates a -Kubernetes Job and necessary RBAC configurations to address this issue. The job facilitates the -retrieval of JWKS from the OIDC Issuer and embeds it directly into Istio's configuration, thereby -bypassing trust issues with self-signed certificates. - -## Configuration Persistence and JWKS Public Accessibility - -The configuration created by this job is stored exclusively in etcd and is not persisted elsewhere. -This setup is compatible with ArgoCD, which by default does not delete properties absent in the -desired manifest. However, if the `RequestAuthentication` resource is modified erroneously or -deleted, the configuration would be lost, necessitating a rerun of the job. - -To circumvent the need for rerunning the job, it is advisable to store the JWKS in a repository. -JWKS are typically publicly accessible and contain no sensitive information, making them safe for -repository storage. By persisting the JWKS in a repository, consistent access is ensured regardless -of changes in the cluster or accidental deletions. - -## Functionality - -- **Reading OIDC Issuer URL**: The Job reads the `RequestAuthentication` resource to extract the - OIDC Issuer URL. -- **Fetching JWKS**: After identifying the Issuer URL, the Job retrieves the JWKS. -- **Patching RequestAuthentication**: The JWKS is used to patch the `RequestAuthentication` - resource, embedding the JWKS directly. -- **Static JWKS Configuration for Istio**: Ensures that Istio uses the JWKS provided by the Job - instead of requesting it independently. - -## Use Case - -This setup is particularly useful when: -- Kubernetes serves as an OIDC provider. -- The Kubernetes API is not served with publicly trusted certificates. - -This component ensures seamless M2M authentication by handling JWKS retrieval and configuration -internally, thus circumventing certificate validation issues for Istio fetching JWKS from an OIDC -provider with self-signed or private CA certificates. diff --git a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/cronjob.kubeflow-m2m-oidc-configurator.yaml b/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/cronjob.kubeflow-m2m-oidc-configurator.yaml deleted file mode 100644 index 5c3e305b5e..0000000000 --- a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/cronjob.kubeflow-m2m-oidc-configurator.yaml +++ /dev/null @@ -1,48 +0,0 @@ -apiVersion: batch/v1 -kind: CronJob -metadata: - name: kubeflow-m2m-oidc-configurator - namespace: istio-system -spec: - schedule: '*/5 * * * *' - concurrencyPolicy: Forbid - jobTemplate: - spec: - backoffLimit: 3 - ttlSecondsAfterFinished: 600 - template: - metadata: - labels: {} - spec: - restartPolicy: OnFailure - serviceAccountName: kubeflow-m2m-oidc-configurator - containers: - - image: docker.io/curlimages/curl - name: kubeflow-m2m-oidc-configurator - command: - - /script.sh - envFrom: - - configMapRef: - name: kubeflow-m2m-oidc-configurator-envs - volumeMounts: - - mountPath: /script.sh - name: script - subPath: script.sh - resources: {} - securityContext: - allowPrivilegeEscalation: false - seccompProfile: - type: RuntimeDefault - runAsNonRoot: true - runAsUser: 1000 - capabilities: - drop: - - ALL - volumes: - - name: script - configMap: - name: kubeflow-m2m-oidc-configurator-script - defaultMode: 0777 - items: - - key: script.sh - path: script.sh diff --git a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/kustomization.yaml b/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/kustomization.yaml deleted file mode 100644 index c60dc7fac4..0000000000 --- a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/kustomization.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: -- cronjob.kubeflow-m2m-oidc-configurator.yaml -- rbac.yaml - -configMapGenerator: -- name: kubeflow-m2m-oidc-configurator-script - namespace: istio-system - files: - - script.sh=script.sh - -- name: kubeflow-m2m-oidc-configurator-envs - namespace: istio-system - literals: - - ISTIO_ROOT_NAMESPACE=istio-system - - REQUEST_AUTHENTICATION_NAME=m2m-token-issuer - - KUBERNETES_API_SERVER_URL=https://kubernetes.default.svc - -- name: oauth2-proxy-parameters - behavior: merge - literals: - - ALLOW_SELF_SIGNED_ISSUER=true diff --git a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/rbac.yaml b/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/rbac.yaml deleted file mode 100644 index 9bb2578515..0000000000 --- a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/rbac.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kubeflow-m2m-oidc-configurator - namespace: istio-system - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: kubeflow-m2m-oidc-configurator - namespace: istio-system -rules: -- apiGroups: - - security.istio.io - resources: - - requestauthentications - verbs: - - get - - patch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: kubeflow-m2m-oidc-configurator - namespace: istio-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kubeflow-m2m-oidc-configurator -subjects: -- kind: ServiceAccount - name: kubeflow-m2m-oidc-configurator - namespace: istio-system diff --git a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/script.sh b/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/script.sh deleted file mode 100644 index bef022edda..0000000000 --- a/common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer/script.sh +++ /dev/null @@ -1,143 +0,0 @@ -#!/bin/sh -set -e - -KUBERNETES_API_SERVER_URL="${KUBERNETES_API_SERVER_URL:-https://kubernetes.default.svc}" -ISTIO_ROOT_NAMESPACE="${ISTIO_ROOT_NAMESPACE:-istio-system}" -REQUEST_AUTHENTICATION_NAME="${REQUEST_AUTHENTICATION_NAME:-m2m-token-issuer}" - -RESOURCE_URL="\ -${KUBERNETES_API_SERVER_URL}\ -/apis/security.istio.io/v1/namespaces/\ -${ISTIO_ROOT_NAMESPACE}\ -/requestauthentications/\ -${REQUEST_AUTHENTICATION_NAME}" - -wait_for_resource_ready() { - while true; do - response="$( - curl -s -o /dev/null \ - --url "${RESOURCE_URL}" \ - -w "%{http_code}" \ - --header "Authorization: Bearer $(cat /run/secrets/kubernetes.io/serviceaccount/token)" \ - --insecure - )" - if [ "${response}" = "200" ]; then - break - fi - sleep 5 - done -} - -get_request_authentication_obj() { - curl -s --request GET \ - --url "${RESOURCE_URL}" \ - --header "Authorization: Bearer $(cat /run/secrets/kubernetes.io/serviceaccount/token)" \ - --insecure -} - -get_issuer_url_from_obj() { - obj="${1}" - echo "${obj}" | awk -F'"' '/"issuer":/ { print $4 }' -} - -get_current_escaped_jwks_from_obj() { - obj="${1}" - echo "${obj}" | awk -F'"' '/"jwks":/' | sed -n 's/^.*"jwks": "\(.*\)".*$/\1/p' -} - -get_jwks_uri() { - issuer_url="${1}" - curl -s --request GET \ - --url "${issuer_url}/.well-known/openid-configuration" \ - --header "Authorization: Bearer $(cat /run/secrets/kubernetes.io/serviceaccount/token)" \ - --insecure | - grep -o '"jwks_uri":"https:\/\/[^"]\+"' | - sed 's/"jwks_uri":"\(.*\)"/\1/' - } - -get_jwks_from_uri() { - jwks_uri="${1}" - curl -s --request GET \ - --url "${jwks_uri}" \ - --header "Authorization: Bearer $(cat /run/secrets/kubernetes.io/serviceaccount/token)" \ - --insecure -} - -# Format JWKS in a way that can be accepted in resource patch. -parse_escaped_jwks() { - jwks="${1}" - echo "${jwks}" | sed 's/"/\\"/g' -} - -are_jwks_equal() { - jwks1="${1}" - jwks2="${2}" - test "$(echo "${jwks1}" | base64 -w0)" = "$(echo "${jwks2}" | base64 -w0)" -} - -patch_request_authentication_with_escaped_jwks() { - jwks_escaped="${1}" - curl -s --request PATCH \ - --url "${RESOURCE_URL}" \ - --header "Content-Type: application/json-patch+json" \ - --header "Authorization: Bearer $(cat /run/secrets/kubernetes.io/serviceaccount/token)" \ - -d '[{ "op": "add", "path": "/spec/jwtRules/0/jwks", "value": "'"${jwks_escaped}"'" }]' \ - --insecure - echo -} - -patch_request_authentication_with_jwks_if_required() { - echo "Getting RequestAuthentication object." - REQUEST_AUTHENTICATION_OBJ="$(get_request_authentication_obj)" - - ISSUER_URL="$(get_issuer_url_from_obj "${REQUEST_AUTHENTICATION_OBJ}")" - echo "Issuer Url in RequestAuthentication: ${ISSUER_URL}" - - CURRENT_JWKS_ESCAPED="$(get_current_escaped_jwks_from_obj "${REQUEST_AUTHENTICATION_OBJ}")" - printf "Current Jwks (escaped):\n%s\n" "${CURRENT_JWKS_ESCAPED}" - - JWKS_URI="$(get_jwks_uri "${ISSUER_URL}")" - echo "Jwks Uri from Well Known OpenID Configuration: ${JWKS_URI}" - - JWKS="$(get_jwks_from_uri "${JWKS_URI}")" - JWKS_ESCAPED="$(parse_escaped_jwks "${JWKS}")" - printf "JWKS from Well Known OpenID Configuration (escaped): \n%s\n" "${JWKS_ESCAPED}" - - if are_jwks_equal "${JWKS_ESCAPED}" "${CURRENT_JWKS_ESCAPED}"; then - echo "JWKS in RequestAuthentication ${REQUEST_AUTHENTICATION_NAME} is configured correctly." - else - echo "JWKS in RequestAuthentication ${REQUEST_AUTHENTICATION_NAME} needs to be configured." - patch_request_authentication_with_escaped_jwks "${JWKS_ESCAPED}" - fi -} - -verify_jwks_in_request_authentication() { - REQUEST_AUTHENTICATION_OBJ="$(get_request_authentication_obj)" - ISSUER_URL="$(get_issuer_url_from_obj "${REQUEST_AUTHENTICATION_OBJ}")" - CURRENT_JWKS_ESCAPED="$(get_current_escaped_jwks_from_obj "${REQUEST_AUTHENTICATION_OBJ}")" - JWKS_URI="$(get_jwks_uri "${ISSUER_URL}")" - JWKS="$(get_jwks_from_uri "${JWKS_URI}")" - JWKS_ESCAPED="$(parse_escaped_jwks "${JWKS}")" - if ! are_jwks_equal "${JWKS_ESCAPED}" "${CURRENT_JWKS_ESCAPED}"; then - echo "JWKS not properly configured, exit with error code 1" - exit 1 - fi -} - -main() { - echo "Wait until resource RequestAuthentication ${REQUEST_AUTHENTICATION_NAME} in namespace ${ISTIO_ROOT_NAMESPACE} is ready." - wait_for_resource_ready - echo "Resource RequestAuthentication ${REQUEST_AUTHENTICATION_NAME} in namespace ${ISTIO_ROOT_NAMESPACE} is ready." - - echo "Patch RequestAuthentication with JWKS if required." - patch_request_authentication_with_jwks_if_required - - echo "Wait 5 seconds before verifying RequestAuthentication JWKS configuration." - sleep 5 - - echo "Verify if RequestAuthentication is properly configured with JWKS..." - verify_jwks_in_request_authentication - echo "RequestAuthentication is properly configured with JWKS." -} - -main diff --git a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml similarity index 50% rename from common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml rename to common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml index be7772831f..57a67159be 100644 --- a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml +++ b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml @@ -11,9 +11,20 @@ spec: matchLabels: app: istio-ingressgateway rules: - - to: + # We ONLY authenticate requests that DON'T have an `Authorization` header using oauth2-proxy. + # This is because we use RequestAuthentication to authenticate requests with an `Authorization` header. + - when: + - key: request.headers[authorization] + notValues: ["*"] + to: - operation: notPaths: + # Exclude dex paths, otherwise users won't be able to log in. + - /dex/* + - /dex/** + - /oauth2/* + + # Exclude paths which are safe to cache by Cloudflare. - /favicon* - /webcomponentsjs* - /vendor.bundle.js diff --git a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml index 4618011073..ff80cab2fc 100644 --- a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml +++ b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml @@ -11,4 +11,15 @@ spec: matchLabels: app: istio-ingressgateway rules: - - {} + # We ONLY authenticate requests that DON'T have an `Authorization` header using oauth2-proxy. + # This is because we use RequestAuthentication to authenticate requests with an `Authorization` header. + - when: + - key: request.headers[authorization] + notValues: ["*"] + to: + - operation: + notPaths: + # Exclude dex paths, otherwise users won't be able to log in. + - /dex/* + - /dex/** + - /oauth2/* diff --git a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.cloudflare.yaml b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.cloudflare.yaml new file mode 100644 index 0000000000..57a3882237 --- /dev/null +++ b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.cloudflare.yaml @@ -0,0 +1,33 @@ +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: istio-ingressgateway-require-jwt + namespace: istio-system +spec: + action: DENY + selector: + matchLabels: + app: istio-ingressgateway + rules: + # Deny requests that don't have a verified JWT (from a RequestAuthentication) + # Note, even user requests that have been authenticated by oauth2-proxy will have a JWT, + # because oauth2-proxy injects a Dex JWT into the request. + - from: + - source: + notRequestPrincipals: ["*"] + to: + - operation: + notPaths: + # Exclude dex paths, otherwise users won't be able to log in. + - /dex/* + - /dex/** + - /oauth2/* + + # Exclude paths which are safe to cache by Cloudflare. + - /favicon* + - /webcomponentsjs* + - /vendor.bundle.js + - /app.bundle.js + - /dashboard_lib.bundle.js + - /assets* + - /app.css diff --git a/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.yaml b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.yaml new file mode 100644 index 0000000000..7f92eaf781 --- /dev/null +++ b/common/oauth2-proxy/components/istio-external-auth/authorizationpolicy.istio-ingressgateway-require-jwt.yaml @@ -0,0 +1,24 @@ +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: istio-ingressgateway-require-jwt + namespace: istio-system +spec: + action: DENY + selector: + matchLabels: + app: istio-ingressgateway + rules: + # Deny requests that don't have a verified JWT (from a RequestAuthentication) + # Note, even user requests that have been authenticated by oauth2-proxy will have a JWT, + # because oauth2-proxy injects a Dex JWT into the request. + - from: + - source: + notRequestPrincipals: ["*"] + to: + - operation: + notPaths: + # Exclude dex paths, otherwise users won't be able to log in. + - /dex/* + - /dex/** + - /oauth2/* diff --git a/common/oauth2-proxy/components/istio-external-auth/kustomization.yaml b/common/oauth2-proxy/components/istio-external-auth/kustomization.yaml index cf906f840c..f55f7af098 100644 --- a/common/oauth2-proxy/components/istio-external-auth/kustomization.yaml +++ b/common/oauth2-proxy/components/istio-external-auth/kustomization.yaml @@ -3,9 +3,10 @@ kind: Component resources: - authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml +- authorizationpolicy.istio-ingressgateway-require-jwt.yaml - requestauthentication.dex-jwt.yaml -# If you're running Kubeflow behind CloudFlare, use -# authorizationpolicy.istio-ingressgateway-oauth2-proxy-cloudflare.yaml -# instead of -# authorizationpolicy.istio-ingressgateway-oauth2-proxy.yaml +# If want to enable caching for some paths (e.g. when using Cloudflare), +# use the following AuthorizationPolicies instead of the default ones. +#- authorizationpolicy.istio-ingressgateway-oauth2-proxy.cloudflare.yaml +#- authorizationpolicy.istio-ingressgateway-require-jwt.cloudflare.yaml diff --git a/common/oauth2-proxy/components/istio-external-auth/requestauthentication.dex-jwt.yaml b/common/oauth2-proxy/components/istio-external-auth/requestauthentication.dex-jwt.yaml index 55f4565281..c99765e7e8 100644 --- a/common/oauth2-proxy/components/istio-external-auth/requestauthentication.dex-jwt.yaml +++ b/common/oauth2-proxy/components/istio-external-auth/requestauthentication.dex-jwt.yaml @@ -4,16 +4,41 @@ metadata: name: dex-jwt namespace: istio-system spec: + # we only apply to the ingress-gateway because: + # - there is no need to verify the same tokens at each sidecar + # - having no selector will apply to the RequestAuthentication to ALL + # Pods in the mesh, even ones which are not part of Kubeflow + # - some Kubeflow services accept direct connections with Kubernetes JWTs, + # and we don't want to require that users configure Istio to verify Kubernetes JWTs + # as there is no method to do this which works on all distributions. + selector: + matchLabels: + app: istio-ingressgateway + jwtRules: - # forwardOriginalToken must be set to true so the authorization header will - # be passed between Kubeflow Components and Istio can configure the - # Kubeflow Auth Headers based on this request authorization header. - - forwardOriginalToken: true - issuer: http://dex.auth.svc.cluster.local:5556/dex - # These 5 lines provides integration of istio/oauth2-proxy with - # Kubeflow custom auth headers. + - issuer: http://dex.auth.svc.cluster.local:5556/dex + + # `forwardOriginalToken` is not strictly required to be true. + # there are pros and cons to each value: + # - true: the original token is forwarded to the destination service + # which raises the risk of the token leaking + # - false: the original token is stripped from the request + # which will prevent the destination service from + # verifying the token (possibly with its own RequestAuthentication) + forwardOriginalToken: true + + # This will unpack the JWTs issued by dex into the expected headers. + # It is applied to BOTH the m2m tokens from outside the cluster (which skip + # oauth2-proxy because they already have a dex JWT), AND user requests which were + # authenticated by oauth2-proxy (which injected a dex JWT). outputClaimToHeaders: - header: kubeflow-userid claim: email - header: kubeflow-groups claim: groups + + # We explicitly set `fromHeaders` to ensure that the JWT is only extracted from the `Authorization` header. + # This is because we exclude requests that have an `Authorization` header from oauth2-proxy. + fromHeaders: + - name: Authorization + prefix: "Bearer " diff --git a/common/oauth2-proxy/components/istio-m2m/README.md b/common/oauth2-proxy/components/istio-m2m/README.md index 750f34de8e..04617a3a80 100644 --- a/common/oauth2-proxy/components/istio-m2m/README.md +++ b/common/oauth2-proxy/components/istio-m2m/README.md @@ -11,9 +11,3 @@ In Kubernetes clusters managed by platform providers, the OIDC issuer is usually provider and served behind publicly trusted certificates. In these cases, it's advisable to use the platform-managed Kubernetes OIDC issuer in the `RequestAuthentication` for seamless integration and authentication compliance with the platform's security standards. - -For scenarios where the OIDC issuer is served behind self-signed certificates, the kustomize -overlay using this component should include the `common/oauth2-proxy/components/configure-self-signed-kubernetes-oidc-issuer` -component. This additional configuration is necessary to handle the self-signed nature of the -certificates. This setup is the default in the Kustomize overlay defined in `common/oauth2-proxy/overlays/m2m-self-signed`, -which is tailored for environments with self-signed OIDC issuers. diff --git a/common/oauth2-proxy/components/istio-m2m/kustomization.yaml b/common/oauth2-proxy/components/istio-m2m/kustomization.yaml index ccfc1d4894..5b0371c692 100644 --- a/common/oauth2-proxy/components/istio-m2m/kustomization.yaml +++ b/common/oauth2-proxy/components/istio-m2m/kustomization.yaml @@ -3,27 +3,3 @@ kind: Component resources: - requestauthentication.yaml - -configMapGenerator: -- name: istio-m2m-params - literals: - - M2M_TOKEN_ISSUER=https://kubernetes.default.svc.cluster.local - -replacements: -- source: - kind: ConfigMap - version: v1 - name: istio-m2m-params - fieldPath: data.M2M_TOKEN_ISSUER - targets: - - fieldPaths: - - spec.jwtRules.0.issuer - select: - group: security.istio.io - version: v1beta1 - kind: RequestAuthentication - name: m2m-token-issuer - namespace: istio-system - -configurations: -- params.yaml diff --git a/common/oauth2-proxy/components/istio-m2m/params.yaml b/common/oauth2-proxy/components/istio-m2m/params.yaml deleted file mode 100644 index c9a20fdaef..0000000000 --- a/common/oauth2-proxy/components/istio-m2m/params.yaml +++ /dev/null @@ -1,3 +0,0 @@ -varReference: -- path: spec/jwtRules/issuer - kind: RequestAuthentication diff --git a/common/oauth2-proxy/components/istio-m2m/requestauthentication.yaml b/common/oauth2-proxy/components/istio-m2m/requestauthentication.yaml index 39563d5ef9..ec0f542848 100644 --- a/common/oauth2-proxy/components/istio-m2m/requestauthentication.yaml +++ b/common/oauth2-proxy/components/istio-m2m/requestauthentication.yaml @@ -4,11 +4,39 @@ metadata: name: m2m-token-issuer namespace: istio-system spec: + # we only apply to the ingress-gateway because: + # - there is no need to verify the same tokens at each sidecar + # - having no selector will apply the RequestAuthentication to ALL + # Pods in the mesh, even ones which are not part of Kubeflow + selector: + matchLabels: + app: istio-ingressgateway + jwtRules: - - forwardOriginalToken: true - issuer: M2M_TOKEN_ISSUER_PLACEHOLDER + - # The `issuer` must be replaced with a Kustomize patch. + issuer: PATCH_ME + + # `forwardOriginalToken` is not strictly required to be true. + # there are pros and cons to each value: + # - true: the original token is forwarded to the destination service + # which raises the risk of the token leaking + # - false: the original token is stripped from the request + # which will prevent the destination service from + # verifying the token (possibly with its own RequestAuthentication) + forwardOriginalToken: true + + # This will unpack the JWTs issued by Kubernetes into the expected headers. outputClaimToHeaders: - - claim: sub - header: x-auth-request-user - - claim: sub - header: kubeflow-userid + - header: kubeflow-userid + claim: sub + - # NOTE: K8S SA Tokens (e.g. those created with `kubectl create token`) do not contain a `groups` claim, + # but we need to ensure that any groups header provided by the request is overwritten to avoid + # users passing a valid JWT with `kubeflow-groups` header to impersonate other users. + header: kubeflow-groups + claim: groups + + # We explicitly set `fromHeaders` to ensure that the JWT is only extracted from the `Authorization` header. + # This is because we exclude requests that have an `Authorization` header from oauth2-proxy. + fromHeaders: + - name: Authorization + prefix: "Bearer " diff --git a/common/oauth2-proxy/overlays/m2m-dex-and-eks/kustomization.yaml b/common/oauth2-proxy/overlays/m2m-dex-and-eks/kustomization.yaml new file mode 100644 index 0000000000..18968c958d --- /dev/null +++ b/common/oauth2-proxy/overlays/m2m-dex-and-eks/kustomization.yaml @@ -0,0 +1,31 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../../base + +components: +- ../../components/istio-external-auth +- ../../components/istio-m2m + +configMapGenerator: +- name: oauth2-proxy-parameters + behavior: merge + literals: + # Configs for oauth2-proxy + - FORCE_HTTPS=true # sets `secure` flag on cookies, requires HTTPS on the gateway + +patches: +# patch the 'm2m-token-issuer' RequestAuthentication with correct `issuer` +# NOTE: we are using kustomize components, so we can't use the outer `configMapGenerator` to +# patch the inner one, so we are stuck with using a `patch` instead +- patch: |- + - op: replace + path: /spec/jwtRules/0/issuer + value: https://oidc.eks.AWS_REGION.amazonaws.com/id/CLUSTER_ID + target: + group: security.istio.io + version: v1beta1 + kind: RequestAuthentication + name: m2m-token-issuer + namespace: istio-system diff --git a/common/oauth2-proxy/overlays/m2m-dex-and-kind/kustomization.yaml b/common/oauth2-proxy/overlays/m2m-dex-and-kind/kustomization.yaml new file mode 100644 index 0000000000..78011721af --- /dev/null +++ b/common/oauth2-proxy/overlays/m2m-dex-and-kind/kustomization.yaml @@ -0,0 +1,35 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../../base + +components: +- ../../components/cluster-jwks-proxy +- ../../components/istio-external-auth +- ../../components/istio-m2m + +configMapGenerator: +- name: oauth2-proxy-parameters + behavior: merge + literals: + # Configs for oauth2-proxy + - ALLOW_SELF_SIGNED_ISSUER=true + +patches: +# patch the 'm2m-token-issuer' RequestAuthentication with correct `issuer` and `jwksUri` +# NOTE: we are using kustomize components, so we can't use the outer `configMapGenerator` to +# patch the inner one, so we are stuck with using a `patch` instead +- patch: |- + - op: replace + path: /spec/jwtRules/0/issuer + value: https://kubernetes.default.svc.cluster.local + - op: replace + path: /spec/jwtRules/0/jwksUri + value: http://cluster-jwks-proxy.istio-system.svc.cluster.local/openid/v1/jwks + target: + group: security.istio.io + version: v1beta1 + kind: RequestAuthentication + name: m2m-token-issuer + namespace: istio-system diff --git a/common/oauth2-proxy/overlays/m2m/kustomization.yaml b/common/oauth2-proxy/overlays/m2m-dex-only/kustomization.yaml similarity index 50% rename from common/oauth2-proxy/overlays/m2m/kustomization.yaml rename to common/oauth2-proxy/overlays/m2m-dex-only/kustomization.yaml index 90db4a289a..917345802c 100644 --- a/common/oauth2-proxy/overlays/m2m/kustomization.yaml +++ b/common/oauth2-proxy/overlays/m2m-dex-only/kustomization.yaml @@ -5,14 +5,11 @@ resources: - ../../base components: -- ../../components/istio-m2m - ../../components/istio-external-auth -- component-overwrite-m2m-token-issuer configMapGenerator: - name: oauth2-proxy-parameters behavior: merge literals: - - FORCE_HTTPS=true - - ENABLE_M2M_TOKENS=true - - EXTRA_JWT_ISSUERS=https://oidc.eks.region.amazonaws.com/id/1234abcd=https://kubernetes.default.svc + # Configs for oauth2-proxy + - ALLOW_SELF_SIGNED_ISSUER=true \ No newline at end of file diff --git a/common/oauth2-proxy/overlays/m2m-self-signed/kustomization.yaml b/common/oauth2-proxy/overlays/m2m-self-signed/kustomization.yaml deleted file mode 100644 index fd56fa3152..0000000000 --- a/common/oauth2-proxy/overlays/m2m-self-signed/kustomization.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../../base - -components: -- ../../components/istio-m2m -- ../../components/istio-external-auth -- ../../components/allow-unauthenticated-issuer-discovery -- ../../components/configure-self-signed-kubernetes-oidc-issuer - -configMapGenerator: -- name: oauth2-proxy-parameters - behavior: merge - literals: - - ALLOW_SELF_SIGNED_ISSUER=true - - ENABLE_M2M_TOKENS=true - - EXTRA_JWT_ISSUERS=https://kubernetes.default.svc.cluster.local=https://kubernetes.default.svc.cluster.local diff --git a/common/oauth2-proxy/overlays/m2m/README.md b/common/oauth2-proxy/overlays/m2m/README.md deleted file mode 100644 index 3bccab00d2..0000000000 --- a/common/oauth2-proxy/overlays/m2m/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Kustomize Overlay for M2M Authentication Integration with Istio - -## Overview - -This kustomize overlay facilitates the integration of M2M (Machine-to-Machine) authentication -with Istio in a Kubernetes environment. It includes components designed to enable effective -authentication within the service mesh. - -## Components - -The overlay consists of: - -1. **`istio-m2m`**: Configures Istio to trust JWTs in M2M communication, essential for enabling - M2M authentication within the service mesh. - -2. **`component-overwrite-m2m-token-issuer`**: This component is used when the OIDC issuer used - by Kubernetes is external to the cluster. It allows for the modification of the default - issuer URL in the M2M authentication setup to match the externally defined OIDC issuer. This - adjustment is necessary due to kustomize's handling of config map generators, requiring a - separate component for proper configuration merging. - -## Usage Scenario - -- **External OIDC Issuer Integration**: In cases where the OIDC Issuer integrated with Kubernetes - is defined outside the cluster, `component-overwrite-m2m-token-issuer` is used to update the - issuer URL for M2M authentication. This scenario is common in setups where an external OIDC - issuer is preferred over the default Kubernetes self-served OIDC issuer. \ No newline at end of file diff --git a/common/oauth2-proxy/overlays/m2m/component-overwrite-m2m-token-issuer/kustomization.yaml b/common/oauth2-proxy/overlays/m2m/component-overwrite-m2m-token-issuer/kustomization.yaml deleted file mode 100644 index 337fbe04d3..0000000000 --- a/common/oauth2-proxy/overlays/m2m/component-overwrite-m2m-token-issuer/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -configMapGenerator: -- name: istio-m2m-params - behavior: merge - literals: - - M2M_TOKEN_ISSUER=https://oidc.eks.region.amazonaws.com/id/1234abcd diff --git a/example/kustomization.yaml b/example/kustomization.yaml index 88c84cb325..f553452b06 100644 --- a/example/kustomization.yaml +++ b/example/kustomization.yaml @@ -41,7 +41,11 @@ resources: - ../common/istio-1-22/istio-namespace/base - ../common/istio-1-22/istio-install/overlays/oauth2-proxy # oauth2-proxy -- ../common/oauth2-proxy/overlays/m2m-self-signed +# NOTE: only uncomment ONE of the following overlays, depending on your cluster type +- ../common/oauth2-proxy/overlays/m2m-dex-only # for all clusters +#- ../common/oauth2-proxy/overlays/m2m-dex-and-kind # for KIND clusters (allows K8S JWTs for gateway auth) +#- ../common/oauth2-proxy/overlays/m2m-dex-and-eks # for EKS clusters (NOTE: requires you to configure issuer, see overlay) + # Dex - ../common/dex/overlays/oauth2-proxy # KNative diff --git a/tests/gh-actions/deploy-dex-login-environment/kustomization.yaml b/tests/gh-actions/deploy-dex-login-environment/kustomization.yaml index 2fbf5ee86d..0da06749e5 100644 --- a/tests/gh-actions/deploy-dex-login-environment/kustomization.yaml +++ b/tests/gh-actions/deploy-dex-login-environment/kustomization.yaml @@ -38,7 +38,7 @@ resources: - ../../../common/istio-1-22/istio-namespace/base - ../../../common/istio-1-22/istio-install/overlays/oauth2-proxy # oauth2-proxy -- ../../../common/oauth2-proxy/overlays/m2m-self-signed +- ../../../common/oauth2-proxy/overlays/m2m-dex-and-kind # Dex - ../../../common/dex/overlays/oauth2-proxy - ../../../common/istio-1-22/cluster-local-gateway/base diff --git a/tests/gh-actions/install_istio_with_ext_auth.sh b/tests/gh-actions/install_istio_with_ext_auth.sh index 6b56131ea3..a78580897d 100755 --- a/tests/gh-actions/install_istio_with_ext_auth.sh +++ b/tests/gh-actions/install_istio_with_ext_auth.sh @@ -13,5 +13,10 @@ kubectl wait --for=condition=Ready pods --all -n istio-system --timeout=300s \ echo "Installing oauth2-proxy..." cd common/ -kustomize build oauth2-proxy/overlays/m2m-self-signed/ | kubectl apply -f - -kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=oauth2-proxy' --timeout=180s -n oauth2-proxy \ No newline at end of file +kustomize build oauth2-proxy/overlays/m2m-dex-and-kind/ | kubectl apply -f - + +echo "Waiting for all oauth2-proxy pods to become ready..." +kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=oauth2-proxy' --timeout=180s -n oauth2-proxy + +echo "Waiting for all cluster-jwks-proxy pods to become ready..." +kubectl wait --for=condition=ready pod -l 'app.kubernetes.io/name=cluster-jwks-proxy' --timeout=180s -n istio-system \ No newline at end of file diff --git a/tests/gh-actions/test_dex_login.py b/tests/gh-actions/test_dex_login.py index b93c6ed5a9..e856c2a431 100755 --- a/tests/gh-actions/test_dex_login.py +++ b/tests/gh-actions/test_dex_login.py @@ -1,110 +1,159 @@ #!/usr/bin/env python3 import re +from urllib.parse import urlsplit, urlencode + import requests -import sys -from urllib.parse import urlsplit +import urllib3 + -def get_istio_auth_session(url: str, username: str, password: str) -> dict: +class DexSessionManager: """ - Determine if the specified URL is secured by Dex and try to obtain a session cookie. - WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported - (we default default to using `staticPasswords` if both are enabled) - - :param url: Kubeflow server URL, including protocol - :param username: Dex `staticPasswords` or `LDAP` username - :param password: Dex `staticPasswords` or `LDAP` password - :return: auth session information + This is a version of the KFPClientManager() which only generates the Dex session cookies. + See https://www.kubeflow.org/docs/components/pipelines/user-guides/core-functions/connect-api/#kubeflow-platform---outside-the-cluster """ - # define the default return object - auth_session = { - "endpoint_url": url, # KF endpoint URL - "redirect_url": None, # KF redirect URL, if applicable - "dex_login_url": None, # Dex login URL (for POST of credentials) - "is_secured": None, # True if KF endpoint is secured - "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" - } - - # use a persistent session (for cookies) - with requests.Session() as s: - - ################ - # Determine if Endpoint is Secured - ################ - resp = s.get(url, allow_redirects=True) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {url}" - ) - - auth_session["redirect_url"] = resp.url - - # if we were NOT redirected, then the endpoint is UNSECURED - if len(resp.history) == 0: - auth_session["is_secured"] = False - return auth_session - else: - auth_session["is_secured"] = True - ################ - # Get Dex Login URL - ################ - redirect_url_obj = urlsplit(auth_session["redirect_url"]) + def __init__( + self, + endpoint_url: str, + dex_username: str, + dex_password: str, + dex_auth_type: str = "local", + skip_tls_verify: bool = False, + ): + """ + Initialize the DexSessionManager + + :param endpoint_url: the Kubeflow Endpoint URL + :param skip_tls_verify: if True, skip TLS verification + :param dex_username: the Dex username + :param dex_password: the Dex password + :param dex_auth_type: the auth type to use if Dex has multiple enabled, one of: ['ldap', 'local'] + """ + self._endpoint_url = endpoint_url + self._skip_tls_verify = skip_tls_verify + self._dex_username = dex_username + self._dex_password = dex_password + self._dex_auth_type = dex_auth_type + self._client = None + + # disable SSL verification, if requested + if self._skip_tls_verify: + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + # ensure `dex_default_auth_type` is valid + if self._dex_auth_type not in ["ldap", "local"]: + raise ValueError( + f"Invalid `dex_auth_type` '{self._dex_auth_type}', must be one of: ['ldap', 'local']" + ) - # if we are at `/auth?=xxxx` path, we need to select an auth type - if re.search(r"/auth$", redirect_url_obj.path): + def get_session_cookies(self) -> str: + """ + Get the session cookies by authenticating against Dex + :return: a string of session cookies in the form "key1=value1; key2=value2" + """ - ####### - # TIP: choose the default auth type by including ONE of the following - ####### + # use a persistent session (for cookies) + s = requests.Session() - # OPTION 1: set "staticPasswords" as default auth type - redirect_url_obj = redirect_url_obj._replace( - path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) + # GET the endpoint_url, which should redirect to Dex + resp = s.get( + self._endpoint_url, allow_redirects=True, verify=not self._skip_tls_verify + ) + if resp.status_code == 200: + pass + elif resp.status_code == 403: + # if we get 403, we might be at the oauth2-proxy sign-in page + # the default path to start the sign-in flow is `/oauth2/start?rd=` + url_obj = urlsplit(resp.url) + url_obj = url_obj._replace( + path="/oauth2/start", query=urlencode({"rd": url_obj.path}) + ) + resp = s.get( + url_obj.geturl(), allow_redirects=True, verify=not self._skip_tls_verify + ) + else: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {self._endpoint_url}" ) - # OPTION 2: set "ldap" as default auth type - # redirect_url_obj = redirect_url_obj._replace( - # path=re.sub(r"/auth$", "/auth/ldap", redirect_url_obj.path) - # ) - # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) - if re.search(r"/auth/.*/login$", redirect_url_obj.path): - auth_session["dex_login_url"] = redirect_url_obj.geturl() + # if we were NOT redirected, then the endpoint is unsecured + if len(resp.history) == 0: + # no cookies are needed + return "" + + # if we are at `../auth` path, we need to select an auth type + url_obj = urlsplit(resp.url) + if re.search(r"/auth$", url_obj.path): + url_obj = url_obj._replace( + path=re.sub(r"/auth$", f"/auth/{self._dex_auth_type}", url_obj.path) + ) - # else, we need to be redirected to the actual login page + # if we are at `../auth/xxxx/login` path, then we are at the login page + if re.search(r"/auth/.*/login$", url_obj.path): + dex_login_url = url_obj.geturl() else: - # this GET should redirect us to the `/auth/xxxx/login` path - resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) + # otherwise, we need to follow a redirect to the login page + resp = s.get( + url_obj.geturl(), allow_redirects=True, verify=not self._skip_tls_verify + ) if resp.status_code != 200: raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" + f"HTTP status code '{resp.status_code}' for GET against: {url_obj.geturl()}" ) + dex_login_url = resp.url - # set the login url - auth_session["dex_login_url"] = resp.url - - ################ - # Attempt Dex Login - ################ + # attempt Dex login resp = s.post( - auth_session["dex_login_url"], - data={"login": username, "password": password}, - allow_redirects=True + dex_login_url, + data={"login": self._dex_username, "password": self._dex_password}, + allow_redirects=True, + verify=not self._skip_tls_verify, ) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for POST against: {dex_login_url}" + ) + + # if we were NOT redirected, then the login credentials were probably invalid + if len(resp.history) == 0: + raise RuntimeError( + f"Login credentials are probably invalid - " + f"No redirect after POST to: {dex_login_url}" + ) + + # if we are at `../approval` path, we need to approve the login + url_obj = urlsplit(resp.url) + if re.search(r"/approval$", url_obj.path): + dex_approval_url = url_obj.geturl() + + # approve the login + resp = s.post( + dex_approval_url, + data={"approval": "approve"}, + allow_redirects=True, + verify=not self._skip_tls_verify, + ) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for POST against: {url_obj.geturl()}" + ) - return resp.status_code + return "; ".join([f"{c.name}={c.value}" for c in s.cookies]) KUBEFLOW_ENDPOINT = "http://localhost:8080" KUBEFLOW_USERNAME = "user@example.com" KUBEFLOW_PASSWORD = "12341234" -resp = get_istio_auth_session( - url=KUBEFLOW_ENDPOINT, - username=KUBEFLOW_USERNAME, - password=KUBEFLOW_PASSWORD +# initialize a DexSessionManager +dex_session_manager = DexSessionManager( + endpoint_url=KUBEFLOW_ENDPOINT, + skip_tls_verify=True, + dex_username=KUBEFLOW_USERNAME, + dex_password=KUBEFLOW_PASSWORD, + dex_auth_type="local", ) -print(f"{resp}") -if resp == 200: - sys.exit(0) -else: - sys.exit(1) + +# try to get the session cookies +# NOTE: this will raise an exception if something goes wrong +session_cookies = dex_session_manager.get_session_cookies() diff --git a/tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh b/tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh deleted file mode 100755 index 2968885a72..0000000000 --- a/tests/gh-actions/wait_for_kubeflow_m2m_oidc_configurator.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -CRONJOB_NAME=kubeflow-m2m-oidc-configurator -NAMESPACE=istio-system -RETRY_INTERVAL=5 # Each loop iterates after 'RETRY_INTERVAL' seconds -MAX_RETRIES=20 # Each loop iterates for a total number of 'MAX_RETRIES' - -# Function to get the latest Job created by the CronJob -get_latest_job() { - kubectl get jobs -n "${NAMESPACE}" \ - --sort-by=.metadata.creationTimestamp -o json \ - | jq --arg cronjob_name "${CRONJOB_NAME}" -r '.items[] | select(.metadata.ownerReferences[] | select(.name==$cronjob_name)) | .metadata.name' \ - | tail -n 1 -} - -# Wait until a Job is created -echo "Waiting for a Job to be created by the ${CRONJOB_NAME} CronJob..." -for ((i=1; i<=MAX_RETRIES; i++)); do - JOB_NAME=$(get_latest_job) - if [[ -n "${JOB_NAME}" ]]; then - echo "Job ${JOB_NAME} created." - break - fi - if [[ $i -eq $MAX_RETRIES ]]; then - echo "Job creation timed out." - exit 1 - fi - sleep "${RETRY_INTERVAL}" - echo "Waiting..." -done - -# Wait for the Job to complete successfully -echo "Waiting for the Job ${JOB_NAME} to complete..." -for ((i=1; i<=MAX_RETRIES; i++)); do - STATUS=$(kubectl get job "${JOB_NAME}" -n "${NAMESPACE}" -o jsonpath='{.status.conditions[?(@.type=="Complete")].status}') - if [[ "${STATUS}" == "True" ]]; then - echo "Job ${JOB_NAME} completed successfully." - break - fi - - FAILED=$(kubectl get job "${JOB_NAME}" -n "${NAMESPACE}" -o jsonpath='{.status.conditions[?(@.type=="Failed")].status}') - if [[ "${FAILED}" == "True" ]]; then - echo "Job ${JOB_NAME} failed." - exit 1 - fi - if [[ $i -eq $MAX_RETRIES ]]; then - echo "Job completion timed out." - exit 1 - fi - sleep "${RETRY_INTERVAL}" -done From 4eea9df81adada92f2e6a41ef620e3adcfaa896d Mon Sep 17 00:00:00 2001 From: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:00:21 -0700 Subject: [PATCH 2/3] Split `install_istio_with_ext_auth.sh` into istio & oauth2-proxy scripts Signed-off-by: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> --- .github/workflows/kserve_m2m_test.yaml | 10 +++++++--- .github/workflows/model_registry_test.yaml | 7 +++++-- .github/workflows/notebook_controller_m2m_test.yaml | 10 +++++++--- .github/workflows/pipeline_run_from_notebook.yaml | 7 +++++-- .github/workflows/pipeline_test.yaml | 9 ++++++--- .github/workflows/ray_test.yaml | 7 +++++-- .github/workflows/training_operator_test.yaml | 7 +++++-- tests/gh-actions/install_istio-cni.sh | 4 ++-- tests/gh-actions/install_istio.sh | 4 ++-- ..._istio_with_ext_auth.sh => install_oauth2-proxy.sh} | 10 ---------- 10 files changed, 44 insertions(+), 31 deletions(-) rename tests/gh-actions/{install_istio_with_ext_auth.sh => install_oauth2-proxy.sh} (52%) diff --git a/.github/workflows/kserve_m2m_test.yaml b/.github/workflows/kserve_m2m_test.yaml index fc92967090..86e77f58c5 100644 --- a/.github/workflows/kserve_m2m_test.yaml +++ b/.github/workflows/kserve_m2m_test.yaml @@ -7,7 +7,8 @@ on: - contrib/kserve/** - common/oauth2-proxy/** - common/istio*/** - - tests/gh-actions/install_istio_with_ext_auth.sh* + - tests/gh-actions/install_istio.sh + - tests/gh-actions/install_oauth2-proxy.sh - tests/gh-actions/install_cert_manager.sh - common/cert-manager/** - tests/gh-actions/install_knative.sh @@ -30,8 +31,11 @@ jobs: - name: Create kubeflow namespace run: kustomize build common/kubeflow-namespace/base | kubectl apply -f - - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/.github/workflows/model_registry_test.yaml b/.github/workflows/model_registry_test.yaml index 2b18e27bfa..79d23ac224 100644 --- a/.github/workflows/model_registry_test.yaml +++ b/.github/workflows/model_registry_test.yaml @@ -25,8 +25,11 @@ jobs: - name: Create kubeflow namespace run: kustomize build common/kubeflow-namespace/base | kubectl apply -f - - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh* + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/.github/workflows/notebook_controller_m2m_test.yaml b/.github/workflows/notebook_controller_m2m_test.yaml index 3209cb9db6..bc0001e9f6 100644 --- a/.github/workflows/notebook_controller_m2m_test.yaml +++ b/.github/workflows/notebook_controller_m2m_test.yaml @@ -7,7 +7,8 @@ on: - apps/jupyter/** - common/oauth2-proxy/** - common/istio*/** - - tests/gh-actions/install_istio_with_ext_auth.sh* + - tests/gh-actions/install_istio.sh + - tests/gh-actions/install_oauth2-proxy.sh - tests/gh-actions/install_multi_tenancy.sh jobs: @@ -26,8 +27,11 @@ jobs: - name: Create kubeflow namespace run: kustomize build common/kubeflow-namespace/base | kubectl apply -f - - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install kubeflow-istio-resources run: kustomize build common/istio-1-22/kubeflow-istio-resources/base | kubectl apply -f - diff --git a/.github/workflows/pipeline_run_from_notebook.yaml b/.github/workflows/pipeline_run_from_notebook.yaml index 11454d1860..ff965b7937 100644 --- a/.github/workflows/pipeline_run_from_notebook.yaml +++ b/.github/workflows/pipeline_run_from_notebook.yaml @@ -24,8 +24,11 @@ jobs: - name: Install KinD, Create KinD cluster and Install kustomize run: ./tests/gh-actions/install_KinD_create_KinD_cluster_install_kustomize.sh - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/.github/workflows/pipeline_test.yaml b/.github/workflows/pipeline_test.yaml index d2d5585ae3..f5944e0643 100644 --- a/.github/workflows/pipeline_test.yaml +++ b/.github/workflows/pipeline_test.yaml @@ -7,10 +7,10 @@ on: - apps/pipeline/upstream/** - tests/gh-actions/install_istio.sh - tests/gh-actions/install_cert_manager.sh + - tests/gh-actions/install_oauth2-proxy.sh - common/cert-manager/** - common/oauth2-proxy/** - common/istio*/** - - tests/gh-actions/install_istio_with_ext_auth.sh jobs: build: @@ -25,8 +25,11 @@ jobs: - name: Install kubectl run: ./tests/gh-actions/install_kubectl.sh - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/.github/workflows/ray_test.yaml b/.github/workflows/ray_test.yaml index 5c3eb72c0b..e66e02fbce 100644 --- a/.github/workflows/ray_test.yaml +++ b/.github/workflows/ray_test.yaml @@ -16,8 +16,11 @@ jobs: - name: Install KinD, Create KinD cluster and Install kustomize run: ./tests/gh-actions/install_KinD_create_KinD_cluster_install_kustomize.sh - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/.github/workflows/training_operator_test.yaml b/.github/workflows/training_operator_test.yaml index 8d469e6c71..d63f0b934f 100644 --- a/.github/workflows/training_operator_test.yaml +++ b/.github/workflows/training_operator_test.yaml @@ -22,8 +22,11 @@ jobs: - name: Install kubectl run: ./tests/gh-actions/install_kubectl.sh - - name: Install Istio with external authentication - run: ./tests/gh-actions/install_istio_with_ext_auth.sh + - name: Install Istio + run: ./tests/gh-actions/install_istio.sh + + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh diff --git a/tests/gh-actions/install_istio-cni.sh b/tests/gh-actions/install_istio-cni.sh index 93d4b32b11..159ebae8fb 100755 --- a/tests/gh-actions/install_istio-cni.sh +++ b/tests/gh-actions/install_istio-cni.sh @@ -1,10 +1,10 @@ #!/bin/bash set -e -echo "Installing Istio-cni ..." +echo "Installing Istio-cni (with ExtAuthZ from oauth2-proxy) ..." cd common/istio-cni-1-22 kustomize build istio-crds/base | kubectl apply -f - kustomize build istio-namespace/base | kubectl apply -f - -kustomize build istio-install/base | kubectl apply -f - +kustomize build istio-install/overlays/oauth2-proxy | kubectl apply -f - echo "Waiting for all Istio Pods to become ready..." kubectl wait --for=condition=Ready pods --all -n istio-system --timeout 300s diff --git a/tests/gh-actions/install_istio.sh b/tests/gh-actions/install_istio.sh index 6fa6cab23b..6af5b748d4 100755 --- a/tests/gh-actions/install_istio.sh +++ b/tests/gh-actions/install_istio.sh @@ -1,10 +1,10 @@ #!/bin/bash set -e -echo "Installing Istio ..." +echo "Installing Istio (with ExtAuthZ from oauth2-proxy) ..." cd common/istio-1-22 kustomize build istio-crds/base | kubectl apply -f - kustomize build istio-namespace/base | kubectl apply -f - -kustomize build istio-install/base | kubectl apply -f - +kustomize build istio-install/overlays/oauth2-proxy | kubectl apply -f - echo "Waiting for all Istio Pods to become ready..." kubectl wait --for=condition=Ready pods --all -n istio-system --timeout 300s diff --git a/tests/gh-actions/install_istio_with_ext_auth.sh b/tests/gh-actions/install_oauth2-proxy.sh similarity index 52% rename from tests/gh-actions/install_istio_with_ext_auth.sh rename to tests/gh-actions/install_oauth2-proxy.sh index a78580897d..5fd935d624 100755 --- a/tests/gh-actions/install_istio_with_ext_auth.sh +++ b/tests/gh-actions/install_oauth2-proxy.sh @@ -1,15 +1,5 @@ #!/bin/bash set -e -echo "Installing Istio configured with external authorization..." -cd common/istio-1-22 -kustomize build istio-crds/base | kubectl apply -f - -kustomize build istio-namespace/base | kubectl apply -f - -kustomize build istio-install/overlays/oauth2-proxy | kubectl apply -f - -cd - - -echo "Waiting for all Istio Pods to become ready..." -kubectl wait --for=condition=Ready pods --all -n istio-system --timeout=300s \ - --field-selector=status.phase!=Succeeded echo "Installing oauth2-proxy..." cd common/ From 00c4f4ce304a2155dcabd743394ddf95ba1993d9 Mon Sep 17 00:00:00 2001 From: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:09:07 -0700 Subject: [PATCH 3/3] Fix PSS test (install oauth2-proxy) Signed-off-by: Mathew Wicks <5735406+thesuperzapper@users.noreply.github.com> --- .github/workflows/pss_test.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pss_test.yaml b/.github/workflows/pss_test.yaml index fbd0fccc35..fd28b64e13 100644 --- a/.github/workflows/pss_test.yaml +++ b/.github/workflows/pss_test.yaml @@ -30,7 +30,7 @@ jobs: - name: Install cert-manager run: ./tests/gh-actions/install_cert_manager.sh - - name: Install Istio CNI (with external authentication) + - name: Install Istio CNI run: ./tests/gh-actions/install_istio-cni.sh - name: Configure istio init container with seccompProfile attribute @@ -43,6 +43,9 @@ jobs: kubectl apply -f temporary_patch.yaml rm temporary_patch.yaml + - name: Install oauth2-proxy + run: ./tests/gh-actions/install_oauth2-proxy.sh + - name: Create kubeflow namespace run: kustomize build common/kubeflow-namespace/base | kubectl apply -f -