Skip to content

Commit 17b675c

Browse files
authored
feat: Support custom CA roots (#1015)
Mount a certificate folder to local ca storage in containers, and add update command to cron image's entrypoint. Result of poking and prodding from getsentry/sentry#26851
1 parent bd6f573 commit 17b675c

File tree

13 files changed

+157
-9
lines changed

13 files changed

+157
-9
lines changed

.github/workflows/test.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defaults:
1515
shell: bash
1616
jobs:
1717
unit-test:
18-
runs-on: ubuntu-18.04
18+
runs-on: ubuntu-20.04
1919
name: "unit tests"
2020
steps:
2121
- name: Checkout
@@ -26,8 +26,8 @@ jobs:
2626
run: find ./ -type f -name "*-test.sh" -exec "./{}" \;
2727

2828
integration-test:
29-
runs-on: ubuntu-18.04
30-
name: "test"
29+
runs-on: ubuntu-20.04
30+
name: "integration test"
3131
steps:
3232
- name: Pin docker-compose
3333
run: |
@@ -42,13 +42,16 @@ jobs:
4242
- name: Integration Test
4343
run: |
4444
echo "Testing initial install"
45+
# Create ./certificates here because install.sh will create it with root:root
46+
# and then run.sh (-> setup.sh) won't be able to write to it.
47+
mkdir certificates
4548
./install.sh
46-
./test.sh
49+
./_integration-test/run.sh
4750
echo "Testing in-place upgrade"
4851
# Also test plugin installation here
4952
echo "sentry-auth-oidc" >> sentry/requirements.txt
5053
./install.sh --minimize-downtime
51-
./test.sh
54+
./_integration-test/run.sh
5255
5356
- name: Inspect failure
5457
if: failure()

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,10 @@ geoip/.geoipupdate.lock
8787

8888
# wal2json download
8989
postgres/wal2json
90+
91+
# custom certificate authorities
92+
certificates
93+
94+
# integration testing
95+
_integration-test/custom-ca-roots/nginx/*
96+
sentry/test-custom-ca-roots.py

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- feat: Support custom CA roots ([#27062](https://github.com/getsentry/sentry/pull/27062)), see the [docs](https://develop.sentry.dev/self-hosted/custom-ca-roots/) for more details.
6+
37
## 21.7.0
48

59
- No documented changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: '3.4'
2+
services:
3+
fixture-custom-ca-roots:
4+
image: nginx:1.21.0-alpine
5+
restart: unless-stopped
6+
volumes:
7+
- ./_integration-test/custom-ca-roots/nginx:/etc/nginx:ro
8+
networks:
9+
default:
10+
aliases:
11+
- self.test
12+
- fail.test
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
user nginx;
2+
worker_processes 1;
3+
4+
error_log /var/log/nginx/error.log warn;
5+
pid /var/run/nginx.pid;
6+
7+
events {
8+
worker_connections 1024;
9+
}
10+
11+
http {
12+
server {
13+
listen 443 ssl;
14+
server_name "self.test";
15+
ssl_certificate "/etc/nginx/self.test.crt";
16+
ssl_certificate_key "/etc/nginx/self.test.key";
17+
location / {
18+
add_header Content-Type text/plain;
19+
return 200 'ok';
20+
}
21+
}
22+
server {
23+
listen 443 ssl;
24+
server_name "fake.test";
25+
ssl_certificate "/etc/nginx/fake.test.crt";
26+
ssl_certificate_key "/etc/nginx/fake.test.key";
27+
location / {
28+
add_header Content-Type text/plain;
29+
return 200 'bad';
30+
}
31+
}
32+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#! /usr/bin/env bash
2+
set -e
3+
4+
export COMPOSE_FILE="../docker-compose.yml:./custom-ca-roots/docker-compose.test.yml"
5+
6+
TEST_NGINX_CONF_PATH="./custom-ca-roots/nginx"
7+
CUSTOM_CERTS_PATH="../certificates"
8+
9+
# generate tightly constrained CA
10+
# NB: `-addext` requires LibreSSL 3.1.0+, or OpenSSL (brew install openssl)
11+
openssl req -x509 -new -nodes -newkey rsa:2048 -keyout $TEST_NGINX_CONF_PATH/ca.key \
12+
-sha256 -days 1 -out $TEST_NGINX_CONF_PATH/ca.crt -batch \
13+
-subj "/CN=TEST CA *DO NOT TRUST*" \
14+
-addext "keyUsage = critical, keyCertSign, cRLSign" \
15+
-addext "nameConstraints = critical, permitted;DNS:self.test"
16+
17+
## Lines like the following are debug helpers ...
18+
# openssl x509 -in nginx/ca.crt -text -noout
19+
20+
mkdir -p $CUSTOM_CERTS_PATH
21+
cp $TEST_NGINX_CONF_PATH/ca.crt $CUSTOM_CERTS_PATH/test-custom-ca-roots.crt
22+
23+
# generate server certificate
24+
openssl req -new -nodes -newkey rsa:2048 -keyout $TEST_NGINX_CONF_PATH/self.test.key \
25+
-addext "subjectAltName=DNS:self.test" \
26+
-out $TEST_NGINX_CONF_PATH/self.test.req -batch -subj "/CN=Self Signed with CA Test Server"
27+
28+
# openssl req -in nginx/self.test.req -text -noout
29+
30+
openssl x509 -req -in $TEST_NGINX_CONF_PATH/self.test.req -CA $TEST_NGINX_CONF_PATH/ca.crt -CAkey $TEST_NGINX_CONF_PATH/ca.key \
31+
-extfile <(printf "subjectAltName=DNS:self.test") \
32+
-CAcreateserial -out $TEST_NGINX_CONF_PATH/self.test.crt -days 1 -sha256
33+
34+
# openssl x509 -in nginx/self.test.crt -text -noout
35+
36+
# sanity check that signed certificate passes OpenSSL's validation
37+
openssl verify -CAfile $TEST_NGINX_CONF_PATH/ca.crt $TEST_NGINX_CONF_PATH/self.test.crt
38+
39+
# self signed certificate, for sanity check of not just accepting all certs
40+
openssl req -x509 -newkey rsa:2048 -nodes -days 1 -keyout $TEST_NGINX_CONF_PATH/fake.test.key \
41+
-out $TEST_NGINX_CONF_PATH/fake.test.crt -addext "subjectAltName=DNS:fake.test" -subj "/CN=Self Signed Test Server"
42+
43+
# openssl x509 -in nginx/fake.test.crt -text -noout
44+
45+
cp ./custom-ca-roots/test.py ../sentry/test-custom-ca-roots.py
46+
47+
$dc up -d fixture-custom-ca-roots
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
$dc rm -s -f -v fixture-custom-ca-roots
3+
rm -f ../certificates/test-custom-ca-roots.crt ../sentry/test-custom-ca-roots.py
4+
unset COMPOSE_FILE
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import unittest
2+
import requests
3+
4+
5+
class CustomCATests(unittest.TestCase):
6+
def test_valid_self_signed(self):
7+
self.assertEqual(requests.get("https://self.test").text, 'ok')
8+
9+
def test_invalid_self_signed(self):
10+
with self.assertRaises(requests.exceptions.SSLError):
11+
requests.get("https://fail.test")
12+
13+
14+
if __name__ == '__main__':
15+
unittest.main()

test.sh renamed to _integration-test/run.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
set -e
33

4-
source "$(dirname $0)/install/_lib.sh"
4+
source "$(dirname $0)/../install/_lib.sh"
55

66
echo "${_group}Setting up variables and helpers ..."
77
export SENTRY_TEST_HOST="${SENTRY_TEST_HOST:-http://localhost:9000}"
@@ -42,6 +42,7 @@ echo 'SENTRY_BEACON=False' >> $SENTRY_CONFIG_PY
4242
$dcr web createuser --superuser --email $TEST_USER --password $TEST_PASS || true
4343
$dc up -d
4444
printf "Waiting for Sentry to be up"; timeout 60 bash -c 'until $(curl -Isf -o /dev/null $SENTRY_TEST_HOST); do printf '.'; sleep 0.5; done'
45+
echo ""
4546
echo "${_endgroup}"
4647

4748
echo "${_group}Running tests ..."
@@ -99,7 +100,7 @@ export -f sentry_api_request get_csrf_token
99100
export SENTRY_TEST_HOST COOKIE_FILE EVENT_PATH
100101
printf "Getting the test event back"
101102
timeout 30 bash -c 'until $(sentry_api_request "$EVENT_PATH" -Isf -X GET -o /dev/null); do printf '.'; sleep 0.5; done'
102-
echo "";
103+
echo " got it!";
103104

104105
EVENT_RESPONSE=$(sentry_api_request "$EVENT_PATH")
105106
declare -a EVENT_TEST_STRINGS=(
@@ -119,3 +120,9 @@ echo "${_endgroup}"
119120
echo "${_group}Ensure cleanup crons are working ..."
120121
$dc ps | grep -q -- "-cleanup_.\+[[:space:]]\+Up[[:space:]]\+"
121122
echo "${_endgroup}"
123+
124+
echo "${_group}Test custom CAs work ..."
125+
source ./custom-ca-roots/setup.sh
126+
$dcr --no-deps web python3 /etc/sentry/test-custom-ca-roots.py
127+
source ./custom-ca-roots/teardown.sh
128+
echo "${_endgroup}"

cron/entrypoint.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#!/usr/bin/env bash
22

3+
if [ "$(ls -A /usr/local/share/ca-certificates/)" ]; then
4+
update-ca-certificates
5+
fi
6+
37
# Prior art:
48
# - https://git.io/fjNOg
59
# - https://blog.knoldus.com/running-a-cron-job-in-docker-container/

0 commit comments

Comments
 (0)