Commit d135e33c authored by Evaryont's avatar Evaryont

New post

parent ffeb6c5d
Pipeline #16 failed with stage
in 2 minutes and 5 seconds
---
title: "Automatically adding UptimeRobot to Gitlab's monitoring whitelist with Ansible"
date: 2018-10-20 23:51 UTC
tags: ansible, sysadmin, gitlab, monitoring
---
GitLab has a number of [monitoring endpoints][] you can ping to make sure that
not only is the rails process running (and not just your webserver) but that
also the background services Gitlab depends on are running successfully too.
[monitoring endpoints]: https://gitlab.com/help/user/admin_area/monitoring/health_check.md
I want to monitor [my personal Gitlab](https://library.evaryont.me) instance
with [UptimeRobot][] hitting those endpoints for a more accurate uptime
measurement. Gitlab does have a monitoring token I could append to the URL but
that is deprecated. Instead, you should add the monitoring machines to an [IP
whitelist][]. Thankfully, UptimeRobot provides a list of all of their [incoming
IP addresses][].
[UptimeRobot]: https://uptimerobot.com/
[incoming IP addresses]: https://uptimerobot.com/locations
[IP whitelist]: https://gitlab.com/help/administration/monitoring/ip_whitelist.md
Thing is, I'm lazy. I don't want to have to manually add all of those IP
addresses to the whitelist. I already have the Omnibus GitLab configuration
managed as a template via Ansible, so the best way is to have Ansible
automatically download those lists.
First we'll set the IP URLs as variables:
```yaml
uptimerobot_ipv4_url: "https://uptimerobot.com/inc/files/ips/IPv4.txt"
uptimerobot_ipv6_url: "https://uptimerobot.com/inc/files/ips/IPv6.txt"
```
Then have Ansible download the remote files and register a local variable:
```yaml
- name: Download the list of IPv4 address of UptimeRobot network
uri:
url: "{{ uptimerobot_ipv4_url }}"
return_content: yes
register: _ur_ipv4_uri
- name: Download the list of IPv6 address of UptimeRobot network
uri:
url: "{{ uptimerobot_ipv6_url }}"
return_content: yes
register: _ur_ipv6_uri
```
Now that we have the two variables, *_ur_ipv4_uri* and *_ur_ipv6_uri*, we
can split up the plain text list of IP addresses:
```yaml
- name: Split up the list of IPs
set_fact:
_ur_ipv4_ip_list: "{{ _ur_ipv4_uri.content.split() }}"
_ur_ipv6_ip_list: "{{ _ur_ipv6_uri.content.split() }}"
```
Then we merge the two lists into a single one of all of UptimeRobot's IP
addresses:
```yaml
- name: Combining the list of IPv4 and IPv6 addresses
set_fact:
_ur_all_ips: "{{ _ur_ipv4_ip_list | union(_ur_ipv6_ip_list) }}"
```
Lastly, here's the tricky part. I want to include this list of IP addresses
into the monitoring whitelist, while not overriding the current values that
may be included already. Thus, I want to take these two dictionaries:
<table>
<tr>
<th>UptimeRobot IPs</th>
<th>Personal whitelist</th>
</tr>
<tr>
<td>
<pre>
_ur_all_ips:
- 216.144.250.150
- 69.162.124.226
- ...
</pre>
</td>
<td>
<pre>
gitlab_rb:
gitlab_rails:
monitoring_whitelist:
- 127.0.0.1
- 10.0.0.0/8
- ...
</pre>
</td>
</tr>
</table>
And merge them together into the sub-key
`gitlab_rb.gitlab_rails.monitoring_whitelist`. This is done via the lovely
[`combine` filter](https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-hashes-dictionaries):
```yaml
- name: Inject UptimeRobot IP list into monitoring whitelist
set_fact:
gitlab_rb: "{{ gitlab_rb | combine({'gitlab_rails': {'monitoring_whitelist': gitlab_rb.gitlab_rails.monitoring_whitelist | default([]) | union(_ur_all_ips) }}, recursive=True) }}"
```
The important magic happens all in that one line. I take the existing gitlab
configuration dictionary and build a new dictionary that matches it's
structure. I then take the current monitoring whitelist (which might not
already exist so I default to an empty list) and do a set union with the
UptimeRobot IP addresses. Both dictionaries are passed to the combine filter,
with recursive set to true to not override any other sibling keys in the
original dictionary.
Simple in concept, but Ansible's defaults don't make it easy. It took a while
to figure out the appropriate combination of filters to make this merge work
out. Hopefully it'll save someone else some time.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment