In the previous tutorial, Secure Application with Consul Service Mesh, you deployed two services into your Consul service mesh and secured service-to-service communication with sidecar proxies. Injecting the service mesh sidecars is the first step in configuring a zero-trust network and ensuring that the communication between your services is automatically authenticated and encrypted using mutual TLS (mTLS). The second step is to configure authorization policies for inter-service communications.
Before microservices, authorization was primarily enforced using firewall rules and routing tables. Consul simplifies the management of inter-service authorization with intentions. Intentions allow operators to define service-to-service communication permissions by service name. This paradigm is a vastly improved operator user experience compared to firewall rules and routing tables. Intentions are the second cornerstone of zero-trust networking in Consul.
In this tutorial, you will secure network traffic using Consul intentions.
»Prerequisites
A Kubernetes cluster with Consul service mesh installed. In the previous tutorial you used
kubectl
to deploy two services, acting as a two-tier web application into your Consul service mesh on a local Kubernetes cluster. You will be using that cluster to test the commands in this tutorial.kubectl to interact with your Kubernetes cluster and connect to Consul containers.
NOTE: A similar, Minikube based interactive hands-on lab is also available if you do not have a Consul environment to perform the steps described in this tutorial. Click the Show Tutorial button to launch the lab experience.
»Create your first intention
If you have not enabled Consul ACLs, the default policy for intentions is to permit all traffic. This allows all the services to communicate with each other when you first setup your Consul service mesh. If you enabled Consul ACLs, then the default intentions policy is inherited from the default ACL policy.
»Create the intention
The first intention you will create changes the allow-all policy where all traffic is allowed unless denied in specific rules, to a deny-all policy where all traffic is denied and only specific connections are enabled.
First, access the Consul server container using kubectl exec
.
$ kubectl exec -it hashicorp-consul-server-0 -- /bin/sh
/ #
Once on the Consul container, you can use the consul intention create
command.
$ consul intention create -deny "*" "*"
Created: * => * (deny)
»Check intentions
Once created this intention will prevent all service-to-service communication, including traffic between your two previously deployed services.
$ consul intention check web api
Denied
Check the UI for the web
service, http://localhost:9090/ui.
You will notice that the api
service is not reachable.
»Allow service communication with intentions
Once you have defined the default policy as deny all, you can authorize traffic between your two services web and api.
First, if you disconnected from the Consul server previously, access it again
using kubectl exec
.
$ kubectl exec -it hashicorp-consul-server-0 -- /bin/sh
/ #
Create the allow intention using consul intention
command. You will use the
service names as the source and destination parameters, and assign the desired
permission to the communication rule you are creating, which in this case, is allow.
$ consul intention create -allow web api
Created: web => api (allow)
At this point you can confirm the communication is permitted by using the same
consul intention check
command again.
$ consul intention check web api
Allowed
Check the UI for the web
service at http://localhost:9090/ui.
You will notice that the api
service is now reachable again.
»Understand the anatomy of an intention
Intentions control which services can communicate with each another and are enforced by the sidecar proxy on inbound connections. The identity of the inbound service is verified by its TLS client certificate. The sidecar proxy then checks if an intention exists that authorizes the inbound service to communicate with the destination service. If the inbound service is not authorized, the connection will be terminated.
An intention has four parts:
- Source service. Specifies the service that initiates the communication. It can be
the full name of a service or
*
to refer to all services. - Destination service. Specifies the service that receives the communication. This
will be the upstream you configured in your service definition. It can be the
full name of a service or
*
to refer to all services. - Permission. Defines whether the communication between source and destination is
permitted. This can be set to either
allow
ordeny
. - Description. Optional metadata field to associate a description with an intention.
For both source and destination, the Consul UI will provide you with a dropdown that lists all the services inside your service mesh. In case you want to define intentions for services that are not already deployed, you can add any service name into the text box and it will be applied to future services with that name.
»Next steps
At this point you have learned how to define traffic rules for your service mesh without the need to manually add firewall rules or use any other traffic shaping software. You learned how to create intentions using the UI and the CLI interface for Consul.
Using Consul as your service mesh solution allows you to also leverage the functionalities exposed by the sidecar proxies to employ observability and traffic shaping for your L7 traffic. The next tutorial Observe Network Traffic with Consul Service Mesh will give you more information on the use cases Consul supports.