Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions dev-environments/mtls/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
.DEFAULT_GOAL := gateway
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
DOCKER ?= $(shell which docker 2> /dev/null || echo "docker")

gateway: ## run gateway configured to access upstream powered with TLS
$(DOCKER) compose -f docker-compose.yml up --attach gateway

clean:
$(DOCKER) compose down --volumes --remove-orphans
$(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans
$(MAKE) clean -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile

certs:
$(MAKE) clean -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile
$(MAKE) all -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile

template: export WHITELIST=$(shell cat cert/intermediate.cert.pem | tr '\n' ' ')
template: export CRL=$(shell cat cert/intermediate.crl.pem | tr '\n' ' ')
template:
yq -i '.services[0].proxy.policy_chain[0].configuration.whitelist[0].pem_certificate="$(WHITELIST)"' apicast-config.json
yq -i '.services[0].proxy.policy_chain[0].configuration.revoke_list[0].pem_certificate="$(CRL)"' apicast-config.json
yq -i '.services[1].proxy.policy_chain[0].configuration.whitelist[0].pem_certificate="$(WHITELIST)"' apicast-config.json

61 changes: 61 additions & 0 deletions dev-environments/mtls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Making APIcast listen on HTTPS

## Create the SSL Certificates

```sh
make certs
```

## Prepare apicast-config.json

```sh
make template
```

## Run the gateway

Running local `apicast-test` docker image

```sh
make gateway
```

Running custom apicast image

```sh
make gateway IMAGE_NAME=quay.io/3scale/apicast:latest
```

## Testing CRL

Send request with valid cert

```
curl --resolve example.com:8443:127.0.0.1 -H "Host: crl.example.com" --cacert cert/rootCA.cert.pem --cert cert/client-chain.cert.pem --key cert/client.key.pem "https://example.com:8443/?user_key=123" --http1.1 -v
```

Request with revoked cert

```sh
curl --resolve example.com:8443:127.0.0.1 -H "Host: crl.example.com" --cacert cert/rootCA.cert.pem --cert cert/revoked_client-chain.cert.pem --key cert/revoked_client.key.pem "https://example.com:8443/?user_key=123" --http1.1 -v
```

## Testing OCSP

Send request with valid cert

```
curl --resolve example.com:8443:127.0.0.1 -H "Host: ocsp.example.com" --cacert cert/rootCA.cert.pem --cert cert/client-chain.cert.pem --key cert/client.key.pem "https://example.com:8443/?user_key=123" --http1.1 -v
```

Request with revoked cert

```sh
curl --resolve example.com:8443:127.0.0.1 -H "Host: ocsp.example.com" --cacert cert/rootCA.cert.pem --cert cert/revoked_client-chain.cert.pem --key cert/revoked_client.key.pem "https://example.com:8443/?user_key=123" --http1.1 -v
```

## Clean env

```sh
make clean
```
93 changes: 93 additions & 0 deletions dev-environments/mtls/apicast-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"services": [
{
"id": "1",
"backend_version": "1",
"proxy": {
"hosts": [
"crl.example.com"
],
"api_backend": "http://one.upstream/get",
"backend": {
"endpoint": "http://127.0.0.1:8081",
"host": "backend"
},
"policy_chain": [
{
"name": "tls_validation",
"version": "builtin",
"configuration": {
"whitelist": [
{
"pem_certificate": ""
}
],
"allow_partial_chain": true,
"revocation_check_type": "crl",
"revoke_list": [
{
"pem_certificate": ""
}
]
}
},
{
"name": "apicast.policy.apicast"
}
],
"proxy_rules": [
{
"http_method": "GET",
"pattern": "/",
"metric_system_name": "hits",
"delta": 1,
"parameters": [],
"querystring_parameters": {}
}
]
}
},
{
"id": "2",
"backend_version": "1",
"proxy": {
"hosts": [
"ocsp.example.com"
],
"api_backend": "http://one.upstream/get",
"backend": {
"endpoint": "http://127.0.0.1:8081",
"host": "backend"
},
"policy_chain": [
{
"name": "tls_validation",
"version": "builtin",
"configuration": {
"whitelist": [
{
"pem_certificate": ""
}
],
"allow_partial_chain": true,
"revocation_check_type": "ocsp"
}
},
{
"name": "apicast.policy.apicast"
}
],
"proxy_rules": [
{
"http_method": "GET",
"pattern": "/",
"metric_system_name": "hits",
"delta": 1,
"parameters": [],
"querystring_parameters": {}
}
]
}
}
]
}
94 changes: 94 additions & 0 deletions dev-environments/mtls/cert/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
DOMAIN=example.com

clean:
- rm *.crt *.key *.pem *.csr index.* crlnumber crlnumber.* serial serial.* *.srl

all: index ca intermediate ca-chain ocsp server client revoked_client crl client-chain revoked-client-chain

index:
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber

ca:
openssl genrsa -out rootCA.key.pem 2048
openssl req -config root-ca.cnf \
-key rootCA.key.pem \
-new -x509 -days 3650 -sha256 -extensions v3_ca \
-out rootCA.cert.pem \
-subj "/C=US/CN=ca.$(DOMAIN)"

intermediate:
openssl genrsa -out intermediate.key.pem 2048
openssl req -config intermediate.cnf \
-key intermediate.key.pem \
-new -sha256 \
-out intermediate.csr.pem \
-subj "/CN=intermediate-cert.$(DOMAIN)"
openssl ca -config root-ca.cnf \
-extensions v3_intermediate_ca -days 2650 -notext -batch \
-in intermediate.csr.pem \
-out intermediate.cert.pem

ca-chain:
cat intermediate.cert.pem rootCA.cert.pem > ca-chain.cert.pem

crl:
openssl ca -config intermediate.cnf \
-gencrl -out intermediate.crl.pem

ocsp:
openssl genrsa -out ocsp.$(DOMAIN).key.pem 2048
openssl req -config intermediate.cnf -new -sha256 \
-key ocsp.$(DOMAIN).key.pem \
-out ocsp.$(DOMAIN).csr.pem \
-nodes \
-subj "/CN=ocsp.$(DOMAIN)"
openssl ca -config intermediate.cnf \
-extensions v3_ocsp -days 2650 -notext -batch \
-in ocsp.$(DOMAIN).csr.pem \
-out ocsp.$(DOMAIN).cert.pem

server:
openssl req -subj '/CN=$(DOMAIN)' -newkey rsa:4096 -nodes \
-sha256 \
-days 3650 \
-keyout $(DOMAIN).key \
-out $(DOMAIN).csr
chmod +r $(DOMAIN).key
openssl x509 -req -in $(DOMAIN).csr -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial -out $(DOMAIN).crt -days 500 -sha256
openssl ca -config root-ca.cnf \
-extensions v3_intermediate_ca -days 2650 -notext -batch \
-in $(DOMAIN).csr \
-out $(DOMAIN).pem

client:
openssl genrsa -out client.key.pem 2048
openssl req -config intermediate.cnf -new -sha256 \
-key client.key.pem \
-out client.csr.pem \
-nodes \
-subj "/CN=client-cert.$(DOMAIN)"
echo -e "y\ny\n" | openssl ca -config intermediate.cnf \
-extensions v3_leaf -days 375 -notext -md sha256 \
-in client.csr.pem \
-out client.cert.pem

revoked_client:
openssl genrsa -out revoked_client.key.pem 2048
openssl req -config intermediate.cnf -new -sha256 \
-key revoked_client.key.pem \
-out revoked_client.csr.pem \
-nodes \
-subj "/CN=revoked_client-cert.$(DOMAIN)"
echo -e "y\ny\n" | openssl ca -config intermediate.cnf \
-extensions v3_leaf -days 375 -notext -md sha256 \
-in revoked_client.csr.pem \
-out revoked_client.cert.pem
openssl ca -config intermediate.cnf -revoke revoked_client.cert.pem

client-chain:
cat client.cert.pem intermediate.cert.pem > client-chain.cert.pem

revoked-client-chain:
cat revoked_client.cert.pem intermediate.cert.pem > revoked_client-chain.cert.pem
82 changes: 82 additions & 0 deletions dev-environments/mtls/cert/intermediate.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
[ ca ]
default_ca = CA_default

[ CA_default ]
dir = .
certificate = $dir/intermediate.cert.pem
database = $dir/index.txt
new_certs_dir = $dir
serial = $dir/serial
crlnumber = $dir/crlnumber

private_key = $dir/intermediate.key.pem

name_opt = ca_default
cert_opt = ca_default

default_days = 365
default_crl_days= 30
default_md = sha256
preserve = no
policy = policy_anything

[ policy_match ]
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 4096
default_md = sha256
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
string_mask = nombstr

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = CA
localityName = Locality Name (eg, city)
localityName_default = Testland
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Testers
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
emailAddress_default = sec@test.testing

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true

[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = OCSPSigning

[ v3_ocsp ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning

[ v3_leaf ]
extendedKeyUsage = serverAuth, clientAuth
authorityInfoAccess = OCSP;URI:http://ocsp:2560
Loading
Loading