First test for Cloudflare Access
Today I will show you my first attempt to work with Cloudflare Access service.
As a proof of concept, I created a small instance (code) with the Racktables application installed (in Docker) and protected its access with Cloudflare.
At this point, I didn’t configure external IdP, but used the built-in ‘One-Time Pin Login’ feature (Cloudflare Access can send a one-time PIN to approved email addresses). Essentially it’s password-less access to the application.
In this test, I didn’t validate the JWT tokens on the origin (I will walk you through the JWT scenario in the next posts), but instead extracted the ‘Cf-Access-Authenticated-User-Email’ value and used it for authorization on application (Racktables) level.
Here the diagram:
- Visitor open application URL. The request hits the Cloudflare load balancer and gets redirected to a separate portal for authentication.
- Enter the email address and get the one time code.
- After successful authentication visitors get redirected back to the application.
Step by step instruction to reproduce the environment:
- Clone the repo with Dockerized Racktables application: kariedo/racktables-docker
- Replace
MYSQL_PASSWORD
,DBPASS
andMYSQL_RANDOM_ROOT_PASSWORD
values in thedocker-compose.yml
- Start the environment:
docker-compose up
- In the separate shell review the list of started containers. You should have 4 of them up and running:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae5bf0205930 racktables-docker_nginx "/docker-entrypoint.…" 20 hours ago Up 20 hours 80/tcp, 0.0.0.0:443->443/tcp racktables-docker_nginx_1
b0b81dd6fe65 brndnmtthws/nginx-echo-headers "/usr/local/openrest…" 23 hours ago Up 20 hours 8080/tcp racktables-docker_nginx-echo-headers_1
78fb03fb67e6 racktables-docker_racktables "/entrypoint.sh /usr…" 24 hours ago Up 20 hours 9000/tcp racktables-docker_racktables_1
b52b00a70165 mariadb "docker-entrypoint.s…" 24 hours ago Up 20 hours 3306/tcp racktables-docker_mariadb_1
I left the extra container with nginx-echo as found it very useful for header debug purposes.
- Open the HTTPS page with the server IP address, skip the TLS cert warning.
Add/?module=installer&step=5
to the URL and finilize the Racktables setup:
- Open “Configuration” > “Permissions” > “Edit” and add extra line to allow new user to authenticate.
Username should be the text before the@
in the email address.
In my case, I used email address [email protected]
, so the resulting username is just stas
allow {$username_stas}
Transformation is done with the nginx map
:
map $http_cf_access_authenticated_user_email $cf_remote_user {
~^(?<prefix>.*)@(?<suffix>.*)$ "${prefix}";
}
- Open
/opt/racktables/wwwroot/inc/secret.php
file fromracktables-docker_nginx_1
container and replace the lines 5 and 6 with the following:
dockerhost# docker exec -ti racktables-docker_nginx_1 sh
racktables-docker_nginx_1# chmod 644 /opt/racktables/wwwroot/inc/secret.php
racktables-docker_nginx_1# vi /opt/racktables/wwwroot/inc/secret.php
From:
$user_auth_src = 'database';
to $user_auth_src = 'httpd';
From:
$require_local_account = TRUE;
to $require_local_account = FALSE;
Result should like this:
- Create new DNS record in Cloudflare panel and point it to the server IP
- Enable Cloudflare Access and create the new policy:
- Open the application URL, authenticate with the OTP pin and here we are - logged in with the correct username and without use of any passwords:
Q&A:
Question: Can I use the same approach for the other applications?
Answer: Sure! You can use this idea to manage access to all applications that support HTTP_AUTH (BasicAuth) method: Nagios, Icinga, Grafana, Zabbix, and others.
Question: Why you didn’t use the full email address as username in Racktables?
Answer: Racktables doesn’t support the “@” symbol in the permissions logic, so I came with the work-around.