Skip to content

Commit a2994c2

Browse files
feat(tls): Add end-to-end test for TLS auth
1 parent 6f456e7 commit a2994c2

File tree

10 files changed

+180
-17
lines changed

10 files changed

+180
-17
lines changed

.github/workflows/end-to-end-auto-prepend-test-suite.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ jobs:
103103
- name: Prepare for playwright test
104104
run: |
105105
cd ${{ github.workspace }}
106+
cp -r .ddev/custom_files/crowdsec/cfssl/* my-own-modules/${{ env.EXTENSION_PATH }}/tls
107+
cd my-own-modules/${{ env.EXTENSION_PATH }}
108+
docker cp "tls" ddev-${{ env.WP_VERSION_CODE }}-playwright://var/www/html/wp-content/plugins/crowdsec
106109
ddev maxmind-download DEFAULT GeoLite2-City /var/www/html/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation
107110
ddev maxmind-download DEFAULT GeoLite2-Country /var/www/html/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation
108111
cd ${{ github.workspace }}/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation

.github/workflows/end-to-end-test-suite.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ jobs:
103103
- name: Prepare for playwright test
104104
run: |
105105
cd ${{ github.workspace }}
106-
mkdir -p wp-content/plugins/crowdsec/tls
107-
cp -r .ddev/custom_files/crowdsec/cfssl/* wp-content/plugins/crowdsec/tls
106+
cp -r .ddev/custom_files/crowdsec/cfssl/* my-own-modules/${{ env.EXTENSION_PATH }}/tls
107+
cd my-own-modules/${{ env.EXTENSION_PATH }}
108+
docker cp "tls" ddev-${{ env.WP_VERSION_CODE }}-playwright://var/www/html/wp-content/plugins/crowdsec
108109
ddev maxmind-download DEFAULT GeoLite2-City /var/www/html/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation
109110
ddev maxmind-download DEFAULT GeoLite2-Country /var/www/html/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation
110111
cd ${{ github.workspace }}/my-own-modules/${{ env.EXTENSION_PATH }}/geolocation

.github/workflows/end-to-end/run-single-test/action.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ runs:
2323
if [[ $PENDING_TESTS == "0" ]]
2424
then
2525
echo "No pending tests: OK"
26-
echo "### ${{ inputs.file_path }} test was successful :rocket:" >> $GITHUB_STEP_SUMMARY
2726
else
2827
echo "There are pending tests: $PENDING_TESTS (KO)"
2928
exit 1

.github/workflows/release.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ jobs:
2222
name: Deploy and create release
2323
runs-on: ubuntu-latest
2424

25-
env:
26-
GITHUB_URL: "https://github.com/crowdsecurity/cs-wordpress-bouncer"
27-
2825
steps:
2926
- name: Check naming convention
3027
run: |
@@ -50,15 +47,15 @@ jobs:
5047
echo $CURRENT_DATE
5148
echo $CHANGELOG_VERSION
5249
echo "##[${{ env.VERSION_NUMBER }}]-$CURRENT_DATE"
53-
if [[ $CHANGELOG_VERSION == "##[${{ env.VERSION_NUMBER }}](${{ env.GITHUB_URL }}/releases/tag/v${{ env.VERSION_NUMBER }})-$CURRENT_DATE" ]]
50+
if [[ $CHANGELOG_VERSION == "##[${{ env.VERSION_NUMBER }}](${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/releases/tag/v${{ env.VERSION_NUMBER }})-$CURRENT_DATE" ]]
5451
then
5552
echo "Version in CHANGELOG.md: OK"
5653
else
5754
echo "Version in CHANGELOG.md: KO"
5855
exit 1
5956
fi
6057
COMPARISON=$(grep -oP "\/compare\/\K(.*)$" CHANGELOG.md | head -1)
61-
LAST_TAG=$(curl -Ls -o /dev/null -w %{url_effective} ${{ env.GITHUB_URL }}/releases/latest | grep -oP "\/tag\/\K(.*)$")
58+
LAST_TAG=$(curl -Ls -o /dev/null -w %{url_effective} ${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/releases/latest | grep -oP "\/tag\/\K(.*)$")
6259
if [[ $COMPARISON == "$LAST_TAG...v${{ env.VERSION_NUMBER }})" ]]
6360
then
6461
echo "VERSION COMPARISON OK"
@@ -135,7 +132,7 @@ jobs:
135132

136133
- name: Prepare release notes
137134
run: |
138-
VERSION_RELEASE_NOTES=$(awk -v ver="[${{ env.VERSION_NUMBER }}](${{ env.GITHUB_URL }}/releases/tag/v${{ env.VERSION_NUMBER }})" '/^## / { if (p) { exit }; if ($2 == ver) { p=1; next} } p && NF' CHANGELOG.md | sed ':a;N;$!ba;s/\n---/ /g')
135+
VERSION_RELEASE_NOTES=$(awk -v ver="[${{ env.VERSION_NUMBER }}](${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/releases/tag/v${{ env.VERSION_NUMBER }})" '/^## / { if (p) { exit }; if ($2 == ver) { p=1; next} } p && NF' CHANGELOG.md | sed ':a;N;$!ba;s/\n---/ /g')
139136
echo "$VERSION_RELEASE_NOTES" >> CHANGELOG.txt
140137
cat CHANGELOG.txt
141138

inc/Bounce.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ public function getBouncerInstance(array $settings): Bouncer
4545
// LAPI connection
4646
'api_key' => $this->escape($this->getStringSettings('crowdsec_api_key')),
4747
'auth_type' => $this->getStringSettings('crowdsec_auth_type')?:Constants::AUTH_KEY,
48-
'tls_cert_path' => $this->getStringSettings('crowdsec_tls_cert_path'),
49-
'tls_key_path' => $this->getStringSettings('crowdsec_tls_key_path'),
48+
'tls_cert_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim($this->getStringSettings('crowdsec_tls_cert_path'), '/'),
49+
'tls_key_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim($this->getStringSettings('crowdsec_tls_key_path'), '/'),
5050
'tls_verify_peer' => $this->getBoolSettings('crowdsec_tls_verify_peer'),
51-
'tls_ca_cert_path' => $this->getStringSettings('crowdsec_tls_ca_cert_path'),
51+
'tls_ca_cert_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim($this->getStringSettings('crowdsec_tls_ca_cert_path'), '/'),
5252
'api_url' => $this->escape($this->getStringSettings('crowdsec_api_url')),
5353
'use_curl' => $this->getBoolSettings('crowdsec_use_curl'),
5454
'api_user_agent' => Constants::CROWDSEC_BOUNCER_USER_AGENT,

inc/Constants.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ class Constants extends LibConstants
2424
public const CROWDSEC_CONFIG_PATH = __DIR__ . '/standalone-settings.php';
2525
public const CROWDSEC_BOUNCER_USER_AGENT = 'WordPress CrowdSec Bouncer/v1.8.1';
2626
public const CROWDSEC_BOUNCER_GEOLOCATION_DIR = __DIR__ . '/../geolocation';
27+
public const CROWDSEC_BOUNCER_TLS_DIR = __DIR__ . '/../tls';
2728

2829
}

inc/admin/settings.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function adminSettings()
5656
'crowdsec_settings', 'crowdsec_admin_connection', function () {}, function () {}, '<p>This option determines whether request handler verifies the authenticity of the peer\'s certificate</p>');
5757

5858
// Field "crowdsec_tls_ca_cert_path"
59-
addFieldString('crowdsec_ca_cert_path', 'Path to the CA used to process peer verification', 'crowdsec_plugin_settings', 'crowdsec_settings',
59+
addFieldString('crowdsec_tls_ca_cert_path', 'Path to the CA used to process peer verification', 'crowdsec_plugin_settings', 'crowdsec_settings',
6060
'crowdsec_admin_connection', function ($input) {
6161
return $input;
6262
}, '<p>Relative path from <i>wp-content/plugins/crowdsec/tls</i> folder</p>', 'ca-chain.pem', 'width: 180px;',

inc/bouncer-instance.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ function getDatabaseSettings(): array
2323
// Local API connection
2424
'api_key' => esc_attr(get_option('crowdsec_api_key')),
2525
'auth_type' => esc_attr(get_option('crowdsec_auth_type'))?:Constants::AUTH_KEY,
26-
'tls_cert_path' => esc_attr(get_option('crowdsec_tls_cert_path')),
27-
'tls_key_path' => esc_attr(get_option('crowdsec_tls_key_path')),
26+
'tls_cert_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim(esc_attr(get_option('crowdsec_tls_cert_path')), '/'),
27+
'tls_key_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim(esc_attr(get_option('crowdsec_tls_key_path')), '/'),
2828
'tls_verify_peer' => !empty(get_option('crowdsec_tls_verify_peer')),
29-
'tls_ca_cert_path' => esc_attr(get_option('crowdsec_tls_ca_cert_path')),
29+
'tls_ca_cert_path' => Constants::CROWDSEC_BOUNCER_TLS_DIR. '/'.ltrim(esc_attr(get_option('crowdsec_tls_ca_cert_path')), '/'),
3030
'api_url' => esc_attr(get_option('crowdsec_api_url')),
3131
'use_curl' => !empty(get_option('crowdsec_use_curl')),
3232
'api_user_agent' => Constants::CROWDSEC_BOUNCER_USER_AGENT,

inc/templates/settings.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,50 @@
11
<div class="wrap">
22
<h1>Configure your CrowdSec Bouncer</h1>
3+
<script type="text/javascript">
4+
5+
jQuery(() => {
6+
const $authType = jQuery('[name=crowdsec_auth_type]');
7+
const $verifyPeer = jQuery('[name=crowdsec_tls_verify_peer]');
8+
const $apiKeyTr = jQuery('[name=crowdsec_api_key]').parent().parent();
9+
const $tlsCertTr = jQuery('[name=crowdsec_tls_cert_path]').parent().parent();
10+
const $tlsKeyTr = jQuery('[name=crowdsec_tls_key_path]').parent().parent();
11+
const $tlsVerifyPeerTr = $verifyPeer.parent().parent().parent();
12+
const $tlsCaTr = jQuery('[name=crowdsec_tls_ca_cert_path]').parent().parent();
13+
14+
function handleCaCert () {
15+
if(!$verifyPeer.is(":checked")) {
16+
$tlsCaTr.hide();
17+
} else {$tlsCaTr.show()}
18+
}
19+
20+
function updateTlsDisplay () {
21+
$tlsCertTr.addClass('crowdsec-tls');
22+
$tlsKeyTr.addClass('crowdsec-tls');
23+
$tlsVerifyPeerTr.removeClass('ui-toggle').addClass('crowdsec-tls');
24+
$tlsCaTr.addClass('crowdsec-tls');
25+
$apiKeyTr.addClass('crowdsec-api-key');
26+
switch ($authType.val()) {
27+
case 'api_key':
28+
jQuery('[class=crowdsec-tls]').hide();
29+
jQuery('[class=crowdsec-api-key]').show();
30+
break;
31+
case 'tls':
32+
jQuery('[class=crowdsec-tls]').show();
33+
jQuery('[class=crowdsec-api-key]').hide();
34+
if(!$verifyPeer.is(":checked")) {
35+
$tlsCaTr.hide();
36+
}
37+
break;
38+
default:
39+
jQuery('[class=crowdsec-tls]').hide();
40+
jQuery('[class=crowdsec-api-key]').show();
41+
}
42+
}
43+
updateTlsDisplay();
44+
$authType.change(updateTlsDisplay);
45+
$verifyPeer.change(handleCaCert);
46+
});
47+
</script>
348
<?php settings_errors(); ?>
449
<div class="tab-content">
550
<div id="tab-1" class="tab-pane active">

tests/e2e-ddev/__tests__/3-live-mode-more.js

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ const {
1515
onLoginPageLoginAsAdmin,
1616
setDefaultConfig,
1717
banOwnIpForSeconds,
18+
selectByName,
19+
setToggle
1820
} = require("../utils/helpers");
1921

20-
const { CURRENT_IP, PROXY_IP } = require("../utils/constants");
22+
const { CURRENT_IP, PROXY_IP, TLS_PATH, BOUNCER_KEY_FILE, BOUNCER_CERT_FILE, AGENT_CERT_FILE, CA_CERT_FILE } = require("../utils/constants");
2123

2224
describe(`Run in Live mode`, () => {
2325
beforeAll(async () => {
@@ -111,4 +113,119 @@ describe(`Run in Live mode`, () => {
111113
// Should be banned
112114
await publicHomepageShouldBeBanWall();
113115
});
116+
117+
describe(`Test TLS auth in Live mode`, () => {
118+
it("Should configure TLS", async () => {
119+
await goToAdmin();
120+
await onAdminGoToSettingsPage();
121+
await setToggle("crowdsec_use_curl", true);
122+
await selectByName(
123+
"crowdsec_auth_type",
124+
"tls",
125+
);
126+
127+
await fillInput(
128+
"crowdsec_tls_key_path",
129+
`${BOUNCER_KEY_FILE}`,
130+
);
131+
await setToggle("crowdsec_tls_verify_peer",true);
132+
await fillInput(
133+
"crowdsec_tls_ca_cert_path",
134+
`${CA_CERT_FILE}`,
135+
);
136+
// Bad path
137+
await fillInput(
138+
"crowdsec_tls_cert_path",
139+
"bad-path",
140+
);
141+
await onAdminSaveSettings();
142+
await page.click("#crowdsec_action_test_connection #submit");
143+
144+
await wait(2000);
145+
await expect(page).toMatchText(
146+
".notice.notice-error",
147+
/Technical error.*could not load PEM client certificate/,
148+
);
149+
// Bad cert
150+
await fillInput(
151+
"crowdsec_tls_cert_path",
152+
`${AGENT_CERT_FILE}`,
153+
);
154+
await onAdminSaveSettings();
155+
await page.click("#crowdsec_action_test_connection #submit");
156+
await wait(2000);
157+
await expect(page).toMatchText(
158+
".notice.notice-error",
159+
/Technical error.*unable to set private key file/,
160+
);
161+
162+
// Bad CA with verify peer
163+
await fillInput(
164+
"crowdsec_tls_cert_path",
165+
`${BOUNCER_CERT_FILE}`,
166+
);
167+
await fillInput(
168+
"crowdsec_tls_ca_cert_path",
169+
`${AGENT_CERT_FILE}`,
170+
);
171+
await onAdminSaveSettings();
172+
await page.click("#crowdsec_action_test_connection #submit");
173+
await wait(2000);
174+
await expect(page).toMatchText(
175+
".notice.notice-error",
176+
/Technical error.*unable to get local issuer certificate/,
177+
);
178+
179+
// Bad CA without verify peer
180+
await setToggle("crowdsec_tls_verify_peer",false);
181+
await onAdminSaveSettings();
182+
await page.click("#crowdsec_action_test_connection #submit");
183+
await wait(2000);
184+
await expect(page).toMatchText(
185+
".notice.notice-success",
186+
/Bouncing has been successfully tested/,
187+
);
188+
189+
// Good settings with curl
190+
await setToggle("crowdsec_tls_verify_peer",true);
191+
192+
await fillInput(
193+
"crowdsec_tls_ca_cert_path",
194+
`${CA_CERT_FILE}`,
195+
);
196+
await fillInput(
197+
"crowdsec_tls_cert_path",
198+
`${BOUNCER_CERT_FILE}`,
199+
);
200+
201+
await onAdminSaveSettings();
202+
await page.click("#crowdsec_action_test_connection #submit");
203+
await wait(2000);
204+
await expect(page).toMatchText(
205+
".notice.notice-success",
206+
/Bouncing has been successfully tested/,
207+
);
208+
209+
// Good settings without curl
210+
await setToggle("crowdsec_use_curl", true);
211+
await onAdminSaveSettings();
212+
await page.click("#crowdsec_action_test_connection #submit");
213+
await wait(2000);
214+
await expect(page).toMatchText(
215+
".notice.notice-success",
216+
/Bouncing has been successfully tested/,
217+
);
218+
219+
});
220+
221+
it("Should display the homepage with no remediation", async () => {
222+
await removeAllDecisions();
223+
await publicHomepageShouldBeAccessible();
224+
});
225+
226+
it("Should display a ban wall", async () => {
227+
await banIpForSeconds(CURRENT_IP, 15 * 60);
228+
await publicHomepageShouldBeBanWall();
229+
});
230+
});
114231
});

0 commit comments

Comments
 (0)