Skip to content

Commit 69028d4

Browse files
committed
test: Remove strict mode, use host header instead
1 parent e05e03f commit 69028d4

8 files changed

Lines changed: 33 additions & 188 deletions

File tree

.github/workflows/CI.yaml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Build the image
1616
run: docker build -t codeorigin ./
1717

18-
- name: Test the container in open mode
18+
- name: Test the container
1919
run: |
2020
docker run --rm -p 4000:80/tcp --detach codeorigin
2121
# The first error is "Empty reply from server", which curl
@@ -24,14 +24,5 @@ jobs:
2424
# instead of hardcoded sleep. --krinkle 2021-08-21
2525
sleep 2
2626
curl -f --retry 5 --retry-delay 1 --retry-connrefused -I http://localhost:4000/jquery-3.0.0.js
27-
php test/static-open.php
27+
php test/CodeoriginTest.php
2828
docker kill $(docker ps -q -f ancestor=codeorigin)
29-
30-
- name: Test the container in strict mode
31-
env:
32-
CDN_ACCESS_KEY: aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddd
33-
run: |
34-
docker run --rm -p 4000:80/tcp -e "CDN_ACCESS_KEY=$CDN_ACCESS_KEY" --detach codeorigin
35-
sleep 2
36-
curl -f --retry 5 --retry-delay 1 --retry-connrefused -I http://localhost:4000/jquery-3.0.0.js
37-
php test/static-strict.php

.github/workflows/deploy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
docker run --rm -p 4000:80/tcp --detach ${{ env.IMAGE_NAME }}
2929
sleep 2
3030
curl -f --retry 5 --retry-delay 1 --retry-connrefused -I http://127.0.0.1:4000/jquery-3.0.0.js
31-
php test/static-open.php
31+
php test/CodeoriginTest.php
3232
3333
# https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions#upgrading-a-workflow-that-accesses-ghcrio
3434
- name: Login to Container Registry

Dockerfile

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ COPY cdn/ /var/www/cdn/
3434
#
3535
RUN find /var/www/cdn/ -type f -print0 | TZ=UTC xargs -0 -P 4 -n 50 touch --date='1991-10-18 12:00:00' {} +
3636

37-
# Define the environment variable that will be used in the origin pull magic header
38-
# Set this via `docker run`
39-
ENV CDN_ACCESS_KEY=''
40-
4137
# Copy in the necessary config files
4238
COPY cfg/vimrc /etc/vim/vimrc
4339
COPY cfg/default.conf /etc/nginx/templates/default.conf.template

README.md

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Build the image, by running the following in a clone of this repo:
2323
docker build -t codeorigin ./
2424
```
2525

26-
**Test the container in open mode**:
26+
**Test the container**:
2727

2828
1. Start a container, exposing port 80:
2929
```
@@ -46,43 +46,14 @@ docker run --rm -p 4000:80/tcp -it --entrypoint /bin/sh codeorigin
4646
...
4747
```
4848

49-
Inspect restricted mode:
50-
51-
```
52-
docker run --rm -p 4000:80/tcp -e "CDN_ACCESS_KEY=$CDN_ACCESS_KEY" -it --entrypoint /bin/sh codeorigin
53-
```
54-
5549
**Debug nginx**:
5650

5751
In `cfg/default.conf`, change `error_log … crit` to `error_log … debug` and then build+run as usual.
5852

59-
**Test the container in restricted mode**:
60-
61-
There is a restricted mode, which responds to unauthorized static file requests with a redirect instead of serving files.
62-
63-
1. Run `export CDN_ACCESS_KEY="$(openssl rand -hex 32)"`
64-
1. Start a container, exposing port 80, and given the environment variable:
65-
```
66-
docker run --rm -p 4000:80/tcp -e "CDN_ACCESS_KEY=$CDN_ACCESS_KEY" codeorigin
67-
````
68-
1. The site is now running at <http://localhost:4000/jquery-3.0.0.js>.
69-
To stop the container, press `ctrl+c`
70-
71-
In the restricted mode:
72-
73-
* Simple requests for static files redirect to `code.jquery.com/*`, e.g. `curl -i 'http://localhost/jquery-3.0.0.js'`.
74-
* Requests with the access key will respond by serving the file: `curl -i -H "x-cdn-access: $CDN_ACCESS_KEY" 'http://localhost/jquery-3.0.0.js'`
75-
* Requests with an invalid key will redirect the same as without: `curl -i -H "x-cdn-access: wrong" 'http://localhost/jquery-3.0.0.js'`
76-
7753
### Production deployment
7854

79-
1. First, generate a CDN access key: `openssl rand -hex 32`.
80-
1. At a hosting platform of your choosing, build or pull the container, and pass the CDN access key as run environment variable.
81-
1. Finally, configure the CDN to use the container address as its origin, with special handling to augment origin pulls with a `Host: code.jquery.com` header, and a `x-cdn-access` header with the access key.
82-
83-
### In case of emergency
84-
85-
If you need to deploy a standalone codeorigin site immediately, or if there are origin pull failures and you're not sure why, then deploy the container without any `CDN_ACCESS_KEY` environment variable. The codeorigin container then default to its unrestricted mode (no offload redirects).
55+
1. At a hosting platform of your choosing, build or pull the container.
56+
1. Finally, configure the CDN to use the container address as its origin, with special handling to augment origin pulls with a `Host: code.jquery.com` header.
8657

8758
-------
8859

cfg/default.conf

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,9 @@
11
#
2-
# This file is responsible for the site which serves the main releases from codeorigin. By default,
3-
# it generates a site that operates in "break glass" emergency mode. All requests are served,
4-
# regardless of where they come from.
5-
#
6-
# In production, the CDN should add a private header to origin fetches. All requests which do not
7-
# include the correct header should be bounced via 301 redirect back to the CDN. This ensures that
8-
# even if a client attempts to link to codeorigin, it will still be served from the CDN. The end
9-
# result should be that codeorigin is only reachable for origin pulls from the CDN, decreasing its
10-
# load and reducing the attack surface for DDOSs.
2+
# This file is responsible for the site which serves the releases from codeorigin.
113
#
124
# Configuration information is in the README.md file.
135
#
146

15-
# Increase map_hash_bucket_size to accommodate longer CDN tokens
16-
map_hash_bucket_size 128;
17-
18-
# If the CDN_ACCESS_KEY environment variable is *not* set, operate in "break glass" mode where the
19-
# container openly serves files without restriction. Otherwise, it responds with redirects to requests
20-
# that don't carry a matching x-cdn-access request header.
21-
#
22-
# NOTE: We're using the "envsubst" feature that comes with docker-nginx because nginx does not
23-
# currently have a way to access environment variables without significant workarounds.
24-
# This is interpreted at run-time just before the server starts.
25-
#
26-
# This is preferred over substitution at build-time in Dockerfile as that would put the
27-
# credentials inside the image, making it unsuitable to push to a public container registry.
28-
map "${CDN_ACCESS_KEY}" $origin_mode {
29-
"" open;
30-
default key;
31-
}
32-
map $origin_mode $key_input { key $http_x_cdn_access; default none; }
33-
map $origin_mode $key_expect {
34-
key "${CDN_ACCESS_KEY}";
35-
default none;
36-
}
37-
387
server {
398
listen 80;
409
listen [::]:80;
@@ -64,9 +33,6 @@ server {
6433
# https://stackoverflow.com/a/6475493/319266
6534
gzip_types text/plain text/xml application/xml text/css text/javascript application/javascript application/x-javascript text/x-component application/json application/xhtml+xml application/rss+xml application/atom+xml application/vnd.ms-fontobject image/svg+xml application/x-font-ttf font/opentype;
6635

67-
# Proxies must not mix up differently keyed responses
68-
add_header Vary "x-cdn-access";
69-
7036
add_header Cache-Control "public";
7137
add_header Access-Control-Allow-Origin *;
7238
expires max;
@@ -76,9 +42,6 @@ server {
7642

7743
# Applies to charset_types (mainly for JS and CSS)
7844
charset utf-8;
79-
80-
# Let rerouting responses be cached for a shorter time for faster recovery from mistakes
81-
if ($key_expect != $key_input) { expires 5m; return 302 https://code.jquery.com$uri; }
8245
}
8346

8447
# Legacy redirects for renamed files
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
/**
33
* Usage:
44
*
5-
* $ php test/static-open.php
5+
* $ php test/CodeoriginTest.php
66
*
7-
* $ php test/static-open.php "localhost:4000"
7+
* $ php test/CodeoriginTest.php "localhost:4000"
8+
*
9+
* $ php test/CodeoriginTest.php "code.jquery.com"
810
*/
911

1012
require_once __DIR__ . '/Unit.php';
@@ -29,7 +31,7 @@
2931
'content-length' => '263268',
3032
'last-modified' => 'Fri, 18 Oct 1991 12:00:00 GMT',
3133
'connection' => 'keep-alive',
32-
'vary' => 'Accept-Encoding, x-cdn-access',
34+
'vary' => 'Accept-Encoding',
3335
'etag' => '"28feccc0-40464"',
3436
'cache-control' => 'max-age=315360000, public',
3537
'access-control-allow-origin' => '*',
@@ -43,7 +45,7 @@
4345
'content-length' => '7456',
4446
'last-modified' => 'Fri, 18 Oct 1991 12:00:00 GMT',
4547
'connection' => 'keep-alive',
46-
'vary' => 'Accept-Encoding, x-cdn-access',
48+
'vary' => 'Accept-Encoding',
4749
'etag' => '"28feccc0-1d20"',
4850
'cache-control' => 'max-age=315360000, public',
4951
'access-control-allow-origin' => '*',
@@ -76,7 +78,7 @@
7678
'accept-ranges' => 'bytes',
7779
] );
7880

79-
// Static asset with a key when no key is required
81+
// Static asset
8082

8183
Unit::testHttp( $server, '/jquery-3.0.0.js', [
8284
"x-cdn-access: there-is-no-spoon"
@@ -87,7 +89,7 @@
8789
'content-length' => '263268',
8890
'last-modified' => 'Fri, 18 Oct 1991 12:00:00 GMT',
8991
'connection' => 'keep-alive',
90-
'vary' => 'Accept-Encoding, x-cdn-access',
92+
'vary' => 'Accept-Encoding',
9193
'etag' => '"28feccc0-40464"',
9294
'cache-control' => 'max-age=315360000, public',
9395
'access-control-allow-origin' => '*',

test/Unit.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
<?php
22

3+
// Support: PHP < 8.0
4+
if ( !function_exists( 'str_starts_with' ) ) {
5+
function str_starts_with( $haystack, $needle ) {
6+
return strpos( $haystack, $needle ) === 0;
7+
}
8+
}
9+
310
function jq_req( $url, array $reqHeaders = [] ) {
411
print "# $url\n";
512
$ch = curl_init( $url );
@@ -71,6 +78,17 @@ public static function testHttp( $server, $path, array $reqHeaders, array $expec
7178
try {
7279
$resp = jq_req( "http://{$server}{$path}", $reqHeaders );
7380
foreach ( $expectHeaders as $key => $val ) {
81+
// Tolerate E-Tag weakning (which Highwinds CDN does)
82+
if ( $key == 'etag' ) {
83+
$actualVal = @$resp['headers'][$key];
84+
if ( $val !== $actualVal && $actualVal === "W/$val" ) {
85+
$val = "W/$val";
86+
}
87+
if ( $val !== $actualVal && $val === "W/$actualVal" ) {
88+
$actualVal = "W/$actualVal";
89+
}
90+
}
91+
7492
self::test( "GET $path > header $key", @$resp['headers'][$key], $val );
7593
}
7694
} catch ( Exception $e ) {

test/static-strict.php

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)