With this demo you will be able to:
- Sync the Ingress Gateway and the Online Boutique apps
- Enforce policies
- Istio sidecar injection policy enforcement
STRICT
mTLS in the Mesh policy enforcementAuthorizationPolicies
policy 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
EOF
This 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 -A
NAMESPACE 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 -A
NAMESPACE 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 version
client 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 : ; 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'
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
EOF
This 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 -A
NAMESPACE 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 constrainttemplates
Output 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 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
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 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
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"}
Here are the three policies previously deployed in order to guarantee STRICT
mTLS in the Mesh:
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
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"
}
]
Here is the policy previously deployed in order to guarantee that the default AuthorizationPolicy
in the Mesh is denying all request:
AuthzPolicyDefaultDeny
- requires a defaultdeny
AuthorizationPolicy
for the entire mesh in theistio-system
namespace
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"
}
]
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
EOF
This RootSync
will sync the manifests contained in the istio-system
folder.
Wait for the RootSync
to be synced:
kubectl get rootsync -A
NAMESPACE 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 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
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: