Okay, it's actually not that hard or abstract — in this post I'll walk you through the core ideas behind Zero Trust and apply it hands-on in a real environment.
What is Zero Trust?
You can find plenty of definitions of Zero Trust online — I can boil them down to one sentence: "Zero Trust means trusting nobody at all; whoever wants in needs to authenticate and be authorized." This is the core idea that makes Zero Trust considered more secure than traditional methods.
Zero Trust is not a tool or third-party solution — it's a set of principles we need to follow. Once we follow these principles, that means we've applied Zero Trust to our business or infrastructure. Basically, Zero Trust's principles can apply to most businesses, though each business will need to adjust the policies to fit its specifics. So what are these principles?
- Least privilege — users accessing the system only get just enough permission to do their task within a specific window of time (not forever).
- Support Multi-Factor Authentication (could be Username-password, fingerprint, OAuth, SSO, hardware identity devices, etc.) — this is also how we'll try applying Zero Trust to a real environment in a bit.
- Control or identify every device on the network — in other words, we always need to know what devices exist on our network, and who manages them.
- Any connection request sent to services like a database, web-server, etc. needs to be authenticated.
- You need policies that fit each business's environment — for example, on Saturday and Sunday, no Developer user can access production server infrastructure — only DevOps or SysAdmin have access — to avoid incidents happening on a day off.
- And more...
Hope this quick summary of the main points helps you understand what Zero Trust actually is. As I mentioned above, Zero Trust isn't a tool — but applying Zero Trust manually is fairly hard. So people have developed tools to help us apply these principles more easily. In this post I'll introduce a tool named Pomerium
Applying Zero Trust in a real environment
Most businesses today usually use a VPN (Virtual Private Network) to split things into a private and public environment, so when you want to access services in the private network, you need to connect to the VPN. And usually, once connected to the VPN, that user can connect to every single service in that network. This is considered fairly dangerous and violates the Least privilege principle.
Pomerium gives us a mechanism to set policies for each service, so whenever a user requests a connection to any service, they need to verify their identity to see whether they have access.
Setting up Pomerium isn't too hard — Pomerium needs a centralized domain so it can act as a Proxy for every request passing through. For a lab, you can fake the host in /etc/hosts, or if running for real you'll need to buy a Domain. Pomerium will also need SSL/TLS to encrypt requests (this is also one of Zero Trust's prerequisites). I won't walk through installing Pomerium itself — you can check it out on Pomerium's homepage (pomerium.com/docs)
During setup you'll need to choose an Identity Provider (IDP), a third party that authenticates users — Pomerium supports quite a few: Google, Okta, Auth0, Ping, GitHub, GitLab, etc. In this post I'll use GitHub.
When accessing any Application behind it, the user always calls through a domain of the form ***.yourdomain.com. These requests go through Pomerium, acting as a "Gateway," and get authenticated there. If the user isn't authenticated yet, they get pushed over to the Identity Provider to authenticate; once authenticated, it checks whether that user has access to the requested service — if not, it returns a 403, and of course if they have access, it allows the request through. Here are the steps when a user requests access:
So now you have a basic picture of Pomerium — let's apply it to a few policies. I've spun up a test Pomerium instance so you can try it. Visiting this page authenticate.0trust.site/.pomerium (hopefully it's still alive by the time you read this, otherwise just look at the screenshot), Pomerium will push you over to GitHub to request login or authorization since you haven't accessed this Pomerium instance before. Once authenticated, it returns a page like below:
This page contains info about how your user got authenticated with Pomerium — you'll see fields like Session ID, User ID, when the User expires, authentication status, etc. This info gets pulled when a user requests a service, to compare against the policy and see if that user has access.
Scenario 1: Allow user access as long as they have a valid account
In practice, when a business offers a trial version of a service to a specific group of customers, they'll want to record user info to improve the experience and get customer feedback. I configure a Pomerium policy like this:
So any user who's authenticated can access this service! You can visit it via the link beta-trangchu.0trust.site If you already authenticated at the authenticate link above, you won't be asked to log into github again — if not, you'll get pushed to Github to authenticate.
The log stored on the server side will look like this for each request:
Sep 15 15:50:39 pomerium pomerium[1275311]:
{
"level": "info",
"service": "authorize",
"request-id": "dd55d49a-9b32-4811-acd8-293b8ee253b2",
"check-request-id": "dd55d49a-9b32-4811-acd8-293b8ee253b2",
"method": "GET",
"path": "/assets/css/app.css",
"host": "beta-trangchu.0trust.site",
"query": "",
"ip": "123.30.170.999",
"session-id": "c813d89b-5356-4ce8-b896-2755dbcc15a2",
"allow": true,
"allow-why-true": [
"user-ok"
],
"deny": false,
"deny-why-false": [
"valid-client-certificate-or-none-required"
],
"user": "User",
"email": "email@gmail.com",
"time": "2022-09-15T15:50:39+07:00",
"message": "authorize check"
}
Scenario 2: Authenticating employees within a business based on email domain
Within a business, we usually have our own company email domain like @vccorp.vn, @vtc.gov.vn, etc. This is also a factor we can authenticate on. Here, to only allow employees within the business to access, we can authenticate based on this domain. I configure the policy as follows:
So only Users with an @vccorp.vn email domain can access the domain grafana.0trust.site — anyone else gets Denied and shown the interface
Pomerium also lets us configure policies based on plenty of other factors, like:
- device
- email domain
- groups
- http_method
- http_path
- pomerium_routes
- user
The paid version also supports a few advanced factors like:
- date
- day_of_week
- time_of_day
- record
Beyond supporting Web Applications, Pomerium also supports authenticating applications using the TCP protocol — to connect, we use pomerium-cli or Pomerium Desktop, which run on all platforms. You can read more about this in Pomerium's Docs: pomerium.com/docs/tcp
Wrapping up
So, can access control through Pomerium specifically, or Zero Trust in general, replace VPN? The answer is: it depends. Applying Zero Trust across an entire application is genuinely hard and fairly inconvenient, especially for applications already built with a traditional authentication approach. Instead, we can run VPN and Zero Trust side by side for individual applications — apply Zero Trust to a few simple applications first, then gradually expand it across all your apps. Hope you learned something new after this post.
A book for dummies wanting to start learning about Zero Trust: book link
If you're running into technical challenges or need help with systems, DevOps tools, I'm confident I can help. Get in touch at hoangviet.io.vn