Přeskočit obsah

SeaCat Mutual TLS

PKI pro mobilní aplikace a IoT.

Toto je rozšíření SeaCat pro kryptografickou rodinu certifikátů X.509.

Inicializace PKI

$ openssl ecparam -name prime256v1 -genkey -noout -out seacat_private_key.pem

[tenants]
ids=TENANT

[seacatpki:private_key:TENANT_seacat_private_key]
tenants=TENANT
keyfile=./TENANT/seacat_private_key.pem

[seacatpki:x509:ca:TENANT]
ca_key=TENANT_seacat_private_key

Poznámka: Předpokládá se, že "TENANT" je název nájemce.


Certifikační autorita klienta

curl -X PUT \
  'http://localhost:8080/TENANT/x509/self-signed' \
  -H 'Content-Type: application/json' \
  -d '{
        "serialNumber": 1,
        "subject": {
            "O": "My Org", "CN": "Root CA"
        },
        "validity": {
            "notBefore": "now",
            "notAfter": { "weeks": 1040 }
        },
        "extensions": [
            { "basicConstraints": {
                "CA": true,
                "pathLen": 0
            }, "critical": true } ,
            { "keyUsage": [
                "keyCertSign",
                "cRLSign"
            ] }
        ]
    }'

[tenants]
ids=TENANT

[seacatpki:private_key:TENANT_seacat_private_key]
tenants=TENANT
keyfile=./TENANT/seacat_private_key.pem

[seacatpki:x509:ca:TENANT]
ca_key=TENANT_seacat_private_key
ca_cert=TENANT:18222c51d1c5e96f9a3ceb5b2b739943ce7c0b5e2dcb639c7fd0c1cab06a088f74dfd9988bade47bb18273d039753ef8
seacat=yes

Specifikace SeaCat TLS

Vzájemná autentizace TLS/SSL

Certifikační autorita klienta

CA se používá k registraci klientů SeaCat a v procesu ověřování klienta během TLS handshake.

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: O=TeskaLabs, OU=SeaCat, CN=Devel Root CA
        Validity
            Not Before: Sep 22 00:00:00 2019 GMT
            Not After : Sep 21 23:59:59 2039 GMT
        Subject: O=TeskaLabs, OU=SeaCat, CN=Devel Root CA
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:db:16:df:53:73:9a:b4:22:aa:e9:21:22:0c:de:
                    84:c4:2f:23:1e:eb:86:37:1f:54:7b:6d:b6:47:04:
                    37:e2:fb:b2:34:e1:0f:a2:95:0e:c8:c7:ab:fc:78:
                    fc:ae:9f:78:72:e7:03:d2:19:2f:dd:4c:1e:e3:57:
                    a9:f1:ae:a5:c0
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Subject Key Identifier:
                75:BD:5E:00:9E:C3:F5:1D:8E:7B:AD:33:C5:C9:0C:E9:79:B8:A7:22
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:1c:6e:54:ba:70:a5:46:e0:a4:b0:d3:70:90:ce:
         35:f6:2d:ec:e4:2e:c6:96:91:47:00:1b:d7:30:d7:b8:92:dc:
         02:21:00:c2:88:0c:ac:51:c4:bd:66:44:85:c8:53:84:8e:b3:
         0f:db:37:27:63:ab:d1:7c:dd:5a:1a:c1:02:9a:11:a4:1c

Hlavní body:

  • Samopodepsaný (root) certifikát
  • EC Nist P-256 / prime256v1
  • CA:TRUE, pathlen:0
  • Použití klíče: Certificate Sign, CRL Sign

Brána

  • EC Klíč NIST P-256 aka secp256r1 a prime256r1 (P-384 je podporován iOS a Android > 7)
  • Šifry: ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-CHACHA20-POLY1305
  • ID relace povoleno
  • Relace Tickets zakázány
  • Odeslat certifikát CA klienta (z SeaCat PKI)
  • Ověření hloubky: 1

Příklad konfigurace z OpenSSL:

openssl s_server -www -accept "*:443" \
    -key seacat_gw.key \
    -cert seacat_gw.cert \
    -Verify 1 \
    -CAfile seacat_client_ca.pem

Poznámka: V tomto příkladu je pokryto pouze ověření klienta.

NGINX jako brána

proxy_cache_path seacat_auth.cache keys_zone=seacat_auth:40m max_size=100m;

server {
    listen       80 default_server;
    server_name  _;
    server_tokens off;

    access_log /log/nginx-access.log;
    error_log /log/nginx-error.log;

    # Používáme acme.sh pro certifikát brány
    location /.well-known/acme-challenge/ {
        default_type          text/plain;
        proxy_read_timeout    60;
        proxy_connect_timeout 60;
        proxy_redirect        off;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto $scheme;
        proxy_set_header      Host $host;
        proxy_pass            http://acme-sh;
    }

    location / {
        return 301 https://teskalabs.com;
    }
}

server {
    listen 443 default_server ssl http2;
    server_name  _;
    server_tokens off;

    access_log /log/nginx-access-ssl.log;
    error_log /log/nginx-error-ssl.log;

    ssl_certificate /acme.sh/example.com_ecc/fullchain.cer;
    ssl_certificate_key /acme.sh/example.com_ecc/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:!aNULL:!MD5:!DSS:!AESCCM;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 4h;
    add_header Strict-Transport-Security max-age=31536000;

    # Ověření certifikátů klienta
    ssl_verify_client optional;
    ssl_client_certificate conf.d/seacat_ca.pem;

    # Veřejné API SeaCat PKI
    location /seacat {
        proxy_redirect        off;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto $scheme;
        proxy_set_header      Host $host;
        proxy_pass            http://seacatpki:8080/seacat/seacat;
    }

    # Umístění, které je omezeno pouze na autentizované klienty
    location /restricted {
        # Autentizace pomocí SeaCat PKI
        auth_request /_seacat_pki_auth;

        # Nastavit hlavičku X-SeaCat-Identity na základě hodnoty přijaté z volání autentizace SeaCat PKI
        auth_request_set $seacat_identity $upstream_http_x_seacat_identity;
        proxy_set_header X-SeaCat-Identity $seacat_identity;

        #proxy_pass https://restricted.example.com;
        #proxy_ssl_server_name on;
    }

    # Toto je interní autentizační volání na SeaCat PKI pro ověření identity klienta
    location = /_seacat_pki_auth {
        internal;
        proxy_method          PUT;
        proxy_set_header      X-SSL-Client-Verify $ssl_client_verify;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Host $host;
        proxy_set_header      X-Forwarded-Request $request;
        proxy_set_body        "$ssl_client_raw_cert";
        proxy_pass            http://seacatpki:8080/seacat-tenant/seacat/nginx_authenticate;

        # Odpovědi jsou ukládány do cache, aby se snížila zátěž na SeaCat PKI
        proxy_cache           seacat_auth;
        proxy_cache_key       $ssl_client_fingerprint;
        proxy_cache_lock      on;
        proxy_cache_valid     200 360s;
        proxy_ignore_headers  Cache-Control Expires Set-Cookie;
    }

    location / {
        return 301 https://teskalabs.com;
    }
}

Poznámka: Pro více informací viz kapitola docker.

Let's Encrypt pro certifikát brány

Certifikát brány (nebo serverový certifikát) může být vydán např. Let's Encrypt.
Je nutné použít klienta acme.sh, protože je potřeba EC klíčový pár (ne RSA).

Příklad z Docker Compose:

docker-compose exec acme-sh acme.sh --standalone --keylength ec-256 --issue -d CHANGEME.seacat.io

Poznámka: Klient certbot má omezenou podporu pro ECC (v zásadě, automatická obnova je velmi složitá).
Je možné použít certbot, ale důrazně to nedoporučujeme.

Klient

TODO: Jakýkoli druh pinning certifikátu serveru?

Ověření registrace

Toto je REST volání klienta, které SeaCat PKI může provést na externí službu, aby ověřilo, zda může být CR schválen a tím pádem udělena identita SeaCat klientovi.

URL konfigurace jde do položky konfigurace approve

[seacat:seacat]
ca_cert=...
ca_key=...
approve=http://example.com/validate_cr

SeaCat PKI provede POST volání s následujícím tělem:

{
    '_c': '2019-12-13T13:31:11.158000',
    '_id': '...',
    '_m': '2019-12-13T13:31:11.158000',
    '_v': 1,
    'data': '3081f2a0819a800219028119636f6d2e7465736b616c6162732e7365616361742e64656d6f820d3139313231333134333131305a830d3139313231333134333631305aa459a01380072a8648ce3d020181082a8648ce3d03010781420004161ed21a40c02116ff718edd3333e68ef1976627d790548a084fd9dcaee8cb95df5b49a81d403a3ef7a3ba41c662d731fc5ca8523333b02a542411d5953a4ef2a500a10a80082a8648ce3d0403028247304502210086b3c27afb163412a655b89f62a3a969a1d7732857e2598240ae8e61e614b76a022042e159e02c8b5cd7892587f4ad76caf68796197bc58d4204c3dd3c90f6926c4d',
    'family': 'seacat',
    'info': {
        'application': 'com.teskalabs.seacat.demo',
        'identity': 'HDKXPDREZADFK4G2'
    },
    'label': 'HDKXPDREZADFK4G2 (com.teskalabs.seacat.demo)',
    'seacat_application': 'com.teskalabs.seacat.demo',
    'seacat_identity': 'HDKXPDREZADFK4G2',
    'tenant': 'seacat',
    'type': 'cr'
}

Poznámka: Je to ekvivalentní informace k REST volání "Získat meta informace o kryptomateriálu" SeaCat PKI.

Očekávaná odpověď MUSÍ BÝT JSON.
CR bude schválen pouze tehdy, pokud obsah má následující strukturu:

{ "result": "OK" }