With this demo you will be able to:
- Deploy an Ingress Gateway
- Deploy Online Boutique apps
- Enforce Istio sidecar injection
- Enforce
STRICT
mTLS in the Mesh - Enforce
AuthorizationPolicies
- Clean up
As prerequisites, you need to have these tools installed:
Deploy the Ingress Gateway in a dedicated namespace with the istio-ingress istio-injection=enabled
label:
kubectl apply \
-f root-sync/istio-ingress/namespace.yaml
kubectl apply \
-f istio-ingress/app-manifests.yaml
kubectl apply \
-f istio-ingress/gateway.yaml
Deploy the Online Boutique apps in a dedicated namespace with the istio-ingress istio-injection=enabled
label:
kubectl apply \
-f root-sync/onlineboutique/namespace.yaml
kubectl apply \
-f onlineboutique/apps-manifests.yaml
kubectl apply \
-f onlineboutique/frontend-virtualservice.yaml
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 : ; done
Open 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'
K8sRequiredLabels
- requires anyNamespace
in the mesh to contain the specific Istio sidecar proxy injection label:istio-injection
with the valueenabled
SidecarInjectionAnnotation
- prohibits anyPod
in the mesh to by-pass the Istio proxy sidecar injection
Let's deploy these Constraints
and ConstraintTemplates
:
kubectl apply \
-f policies/constrainttemplates/sidecar-injection
kubectl apply \
-f policies/constraints/sidecar-injection
Verify that the ConstraintTemplates
have been deployed successfully:
kubectl get constrainttemplates
Output similar to:
NAME AGE
k8srequiredlabels 47s
sidecarinjectionannotation 47s
Verify that the Constraints
have been deployed successfully:
kubectl get constraints
Output 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
Try to create a test
namespace without the required label
:
kubectl create namespace test
Output similar to:
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [namespace-sidecar-injection-label] you must provide labels: {"istio-injection"}
PeerAuthnMeshStrictMtls
- requires a defaultSTRICT
mTLSPeerAuthentication
for the entire mesh in theistio-system
namespacePeerAuthnStrictMtls
- prohibits disablingSTRICT
mTLS for allPeerAuthentications
DestinationRuleTLSEnabled
- prohibits disablingSTRICT
mTLS for all hosts and host subsets inDestinationRules
Let's extend the default Gatekeeper config in order to take into account Istio resources:
kubectl apply \
-f policies/gatekeeper-system/referential-constraints-config.yaml
Let's deploy these Constraints
and ConstraintTemplates
:
kubectl apply \
-f policies/constrainttemplates/strict-mtls
kubectl apply \
-f policies/constraints/strict-mtls
Verify that the ConstraintTemplates
have been deployed successfully:
kubectl get constrainttemplates
Output similar to:
NAME AGE
destinationruletlsenabled 18s
k8srequiredlabels 56m
peerauthnmeshstrictmtls 17s
peerauthnstrictmtls 17s
sidecarinjectionannotation 56m
Verify that the Constraints
have been deployed successfully:
kubectl get constraints
Output similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls dryrun 1
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnstrictmtls.constraints.gatekeeper.sh/peer-authentication-strict-mtls deny 0
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
We could 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}' | jq
The output is similar to:
[
{
"enforcementAction": "dryrun",
"kind": "Namespace",
"message": "Root namespace <istio-system> does not have a strict mTLS PeerAuthentication",
"name": "istio-system"
}
]
We could fix this violation by deploying the default STRICT
mTLS PeerAuthentication
in the istio-system
namespace:
kubectl apply \
-f istio-system/default-strict-peerauthentication.yaml
After a few minutes, verify that the Constraints
don't have any remaining violations:
kubectl get constraints
The output is similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled deny 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls dryrun 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
peerauthnstrictmtls.constraints.gatekeeper.sh/peer-authentication-strict-mtls deny 0
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
AuthzPolicyDefaultDeny
- requires a defaultdeny
AuthorizationPolicy
for the entire mesh in theistio-system
namespace
Let's deploy these Constraints
and ConstraintTemplates
:
kubectl apply \
-f policies/constrainttemplates/authorization-policies
kubectl apply \
-f policies/constraints/authorization-policies
Verify that the ConstraintTemplates
have been deployed successfully:
kubectl get constrainttemplates
Output similar to:
NAME AGE
authzpolicydefaultdeny 10s
destinationruletlsenabled 13h
k8srequiredlabels 13h
peerauthnmeshstrictmtls 13h
peerauthnstrictmtls 13h
sidecarinjectionannotation 13h
Verify that the Constraints
have been deployed successfully:
kubectl get constraints
Output similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
sidecarinjectionannotation.constraints.gatekeeper.sh/sidecar-injection-annotation deny 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
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 0
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label deny 0
We could 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}' | jq
The output is similar to:
[
{
"enforcementAction": "dryrun",
"kind": "Namespace",
"message": "Root namespace <istio-system> does not have a default deny AuthorizationPolicy",
"name": "istio-system"
}
]
We could fix this violation by deploying the default deny AuthorizationPolicy
in the istio-system
namespace:
kubectl apply -f istio-system/default-deny-authorizationpolicy.yaml
After a few minutes, verify that the Constraints
don't have any remaining violations:
kubectl get constraints
The output is similar to:
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
sidecarinjectionannotation.constraints.gatekeeper.sh/sidecar-injection-annotation deny 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
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
k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label deny 0
Visit the Online Boutique website from your browser, you should receive the error: RBAC: access denied
which confirms that the default deny AuthorizationPolicy
applies to the entire mesh.
Fix this issue by deploying more granular AuthorizationPolicy
resources in both the Ingress Gateway and the Online Boutique namespaces:
kubectl apply \
-f istio-ingress/authorizationpolicy.yaml
kubectl apply \
-f onlineboutique/authorizationpolicies.yaml
Visit again the Online Boutique website from your browser, you should now 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:
In case you run multiple times this section of demos in the same cluster, here is the cleanup routine you can run to have a clean setup:
kubectl delete constraints \
--all
kubectl delete constrainttemplates \
--all
kubectl delete peerauthentication strict-mtls \
-n istio-system
kubectl delete authorizationpolicy deny-all \
-n istio-system
kubectl delete authorizationpolicy istio-ingressgateway \
-n istio-ingress
kubectl delete authorizationpolicy \
--all \
-n onlineboutique