With this demo you will be able to:
- Sync the Ingress Gateway and the Online Boutique apps
- Enforce policies
- Istio sidecar injection policy enforcement
STRICTmTLS in the Mesh policy enforcementAuthorizationPoliciespolicy enforcement
- Fix the policies violations
As prerequisites, you need to have these tools installed:
Sync the Ingress Gateway and the Online Boutique apps in dedicated namespaces with the istio-ingress istio-injection=enabled label:
cat << EOF | kubectl apply -f -
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: root-sync-apps
namespace: config-management-system
spec:
sourceFormat: unstructured
git:
repo: https://github.com/mathieu-benoit/istio-gatekeeper-demos
revision: HEAD
branch: main
dir: root-sync
auth: none
EOFThis RootSync will sync the manifests contained in the root-sync folder. This folder contains the RepoSyncs in order to sync both Ingress Gateway and the Online Boutique apps. Each RepoSync has also it's own RoleBinding in order to sync Istio resources.
Wait for the RootSync to be synced:
kubectl get rootsync -ANAMESPACE NAME RENDERINGCOMMIT RENDERINGERRORCOUNT SOURCECOMMIT SOURCEERRORCOUNT SYNCCOMMIT SYNCERRORCOUNT
config-management-system root-sync-apps 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
Wait for the 3 RepoSyncs to be synced:
kubectl get reposync -ANAMESPACE NAME RENDERINGCOMMIT RENDERINGERRORCOUNT SOURCECOMMIT SOURCEERRORCOUNT SYNCCOMMIT SYNCERRORCOUNT
best-app-ever repo-sync 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
istio-ingress repo-sync 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
onlineboutique repo-sync 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
Check that the Istio sidecar proxies have been injected and successfully deployed:
istioctl versionclient version: 1.15.2
control plane version: 1.15.2
data plane version: 1.15.2 (13 proxies)
Note: 13 proxies = 12 from onlineboutique + 1 from istio-ingress.
Wait for the public IP address to be provisioned:
until kubectl get svc istio-ingressgateway -n istio-ingress -o jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; doneOpen the generated public IP address to browse the Online Boutique website:
echo -n "http://" && \
kubectl get svc istio-ingressgateway -n istio-ingress -o json | jq -r '.status.loadBalancer.ingress[0].ip'cat << EOF | kubectl apply -f -
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: root-sync-policies
namespace: config-management-system
spec:
sourceFormat: unstructured
git:
repo: https://github.com/mathieu-benoit/istio-gatekeeper-demos
revision: HEAD
branch: main
dir: policies
auth: none
EOFThis RootSync will sync the manifests contained in the policies folder. This folder contains the Constraints and ConstraintTemplates as well as the Gatekeeper config (referential-constraints-config.yaml) in order to evaluate the referential constraints.
Wait for the RootSync to be synced:
kubectl get rootsync -ANAMESPACE NAME RENDERINGCOMMIT RENDERINGERRORCOUNT SOURCECOMMIT SOURCEERRORCOUNT SYNCCOMMIT SYNCERRORCOUNT
config-management-system root-sync-apps 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
config-management-system root-sync-policies 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73 82b96a9a1a70646c3251ec8edbe5274a4ab14f73
Verify that the ConstraintTemplates have been deployed successfully:
kubectl get constrainttemplatesOutput similar to:
NAME AGE
allowedserviceportname 115s
authzpolicydefaultdeny 115s
destinationruletlsenabled 115s
k8srequiredlabels 115s
peerauthnmeshstrictmtls 115s
peerauthnstrictmtls 115s
sidecarinjectionannotation 115s
Verify that the Constraints has been deployed successfully:
kubectl get constraintsOutput similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
sidecarinjectionannotation.constraints.gatekeeper.sh/sidecar-injection-annotation deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
allowedserviceportname.constraints.gatekeeper.sh/port-name-constraint deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
authzpolicydefaultdeny.constraints.gatekeeper.sh/default-deny-authorization-policies dryrun 1
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls dryrun 1
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnstrictmtls.constraints.gatekeeper.sh/peer-authentication-strict-mtls deny 0
In order to have peerauthnmeshstrictmtls and authzpolicydefaultdeny Constraints working, we needed to extend the default Gatekeeper config to take into account the Istio resources. See the referential-constraints-config.yaml file already synced in your cluster, for more details.
Here are the two policies previously deployed in order to guarantee that the wokloads are included in the Mesh:
K8sRequiredLabels- requires anyNamespacein the mesh to contain the specific Istio sidecar proxy injection label:istio-injectionwith the valueenabledSidecarInjectionAnnotation- prohibits anyPodin the mesh to by-pass the Istio proxy sidecar injection
Try to create a test namespace without the required label:
kubectl create namespace testOutput similar to:
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [namespace-sidecar-injection-label] you must provide labels: {"istio-injection"}
Here are the three policies previously deployed in order to guarantee STRICT mTLS in the Mesh:
PeerAuthnMeshStrictMtls- requires a defaultSTRICTmTLSPeerAuthenticationfor the entire mesh in theistio-systemnamespacePeerAuthnStrictMtls- prohibits disablingSTRICTmTLS for allPeerAuthenticationsDestinationRuleTLSEnabled- prohibits disablingSTRICTmTLS for all hosts and host subsets inDestinationRules
Look at the violation detected for the PeerAuthnMeshStrictMtls Constraint to get more details:
kubectl get peerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls \
-ojsonpath='{.status.violations}' | jqThe output is similar to:
[
{
"enforcementAction": "dryrun",
"kind": "Namespace",
"message": "Root namespace <istio-system> does not have a strict mTLS PeerAuthentication",
"name": "istio-system"
}
]
Here is the policy previously deployed in order to guarantee that the default AuthorizationPolicy in the Mesh is denying all request:
AuthzPolicyDefaultDeny- requires a defaultdenyAuthorizationPolicyfor the entire mesh in theistio-systemnamespace
Look at the violation detected for the AuthzPolicyDefaultDeny Constraint to get more details:
kubectl get authzpolicydefaultdeny.constraints.gatekeeper.sh/default-deny-authorization-policies \
-ojsonpath='{.status.violations}' | jqThe output is similar to:
[
{
"enforcementAction": "dryrun",
"kind": "Namespace",
"message": "Root namespace <istio-system> does not have a default deny AuthorizationPolicy",
"name": "istio-system"
}
]
Fix these violations by syncing the default deny-all AuthorizationPolicy and the default STRICT PeerAuthentication in the istio-system namespace:
cat << EOF | kubectl apply -f -
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: root-sync-istio-system
namespace: config-management-system
spec:
sourceFormat: unstructured
git:
repo: https://github.com/mathieu-benoit/istio-gatekeeper-demos
revision: HEAD
branch: main
dir: istio-system
auth: none
EOFThis RootSync will sync the manifests contained in the istio-system folder.
Wait for the RootSync to be synced:
kubectl get rootsync -ANAMESPACE NAME RENDERINGCOMMIT RENDERINGERRORCOUNT SOURCECOMMIT SOURCEERRORCOUNT SYNCCOMMIT SYNCERRORCOUNT
config-management-system root-sync-apps cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c
config-management-system root-sync-istio-system cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c
config-management-system root-sync-policies cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c cd74a14de51de93046b8040c217c9bd4ebafc14c
After a few minutes, verify that the Constraints don't have any remaining violations:
kubectl get constraintsThe output is similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
sidecarinjectionannotation.constraints.gatekeeper.sh/sidecar-injection-annotation deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
allowedserviceportname.constraints.gatekeeper.sh/port-name-constraint deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
authzpolicydefaultdeny.constraints.gatekeeper.sh/default-deny-authorization-policies dryrun 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls dryrun 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnstrictmtls.constraints.gatekeeper.sh/peer-authentication-strict-mtls deny 0
Visit the Online Boutique website from your browser, you should still see it working successfully.
Congrats! You have secured your cluster, your mesh and your Online Boutique website with STRICT mTLS and fine granular AuthorizationPolicies, while enforcing this secure setup with associated policies and Constraints!
If you are using Google Service Mesh, you could see these security features here:

Here is the summary of the RootSyncs and RepoSyncs you have configured with Config Sync:
