Skip to content

Client certificate options seemingly ignored #325

@Terrance

Description

@Terrance

I'm trying to configure Posting 2.9.2 to send client certificates, but as far as I can tell they're not being used?

I've tried all of environment variables, an environment file, and the global settings file, but only ssl.ca_bundle seems to be honoured, and not either of ssl.certificate_path or ssl.key_file. There doesn't seem to be any indication within the UI as to what it's doing here, so I'm not really sure how to dig into this further.

Image
Repro environment

HTTPS server: server.py

#!/usr/bin/env python3

import http.server
import json
import ssl

BIND = ("localhost", 8443)

class Handler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        cert = self.connection.getpeercert()
        print(cert)
        if cert:
            data = json.dumps(cert, indent=2).encode()
            self.send_response(200)
        else:
            data = b""
            self.send_response(401)
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

def make_server():
    server = http.server.HTTPServer(BIND, Handler)
    ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ctx.load_cert_chain(certfile="cert.pem", keyfile="cert.key")
    ctx.load_verify_locations("cert.pem")
    ctx.verify_mode = ssl.CERT_OPTIONAL
    server.socket = ctx.wrap_socket(server.socket, server_side=True)
    return server

if __name__ == "__main__":
    print("Listening: https://{}:{}".format(*BIND))
    make_server().serve_forever()

Certificate config: cert.cfg

For demo simplicity, one certificates acts as all of CA / server identity / client identity, but the lack of client certificates being sent by Posting is also reproducible against a more complete certificate ecosystem.

[req]
req_extensions = extensions
distinguished_name = name
prompt = no

[name]
CN = localhost

[extensions]
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost

To generate the certificate:

$ openssl genrsa -out cert.key 2048
$ openssl req -new -x509 -key cert.key -out cert.pem -config cert.cfg

Both resulting files are PEM-encoded (BEGIN CERTIFICATE / BEGIN PRIVATE KEY).

Working requests with curl

$ curl -v --cacert cert.pem https://localhost:8443
...
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/8.17.0
> Accept: */*
>
< HTTP/1.0 401 Unauthorized
< Server: SimpleHTTP/0.6 Python/3.13.11
< Date: Wed, 17 Dec 2025 23:47:05 GMT
< Content-Length: 0
<
$ curl -v --cacert cert.pem --cert cert.pem --key cert.key https://localhost:8443
...
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/8.17.0
> Accept: */*
>
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.13.11
< Date: Wed, 17 Dec 2025 23:46:56 GMT
< Content-Length: 344
<
{
  "subject": [
    [
      [
        "commonName",
        "localhost"
      ]
    ]
  ],
  "issuer": [
    [
      [
        "commonName",
        "localhost"
      ]
    ]
  ],
  "version": 3,
  "serialNumber": "07D88195F5B803151AAE7CFA7D33FC344AE73311",
  "notBefore": "Dec 17 19:52:18 2025 GMT",
  "notAfter": "Jan 16 19:52:18 2026 GMT"
}

Posting configuration: ~/.config/posting/config.yaml

ssl:
  ca_bundle: .../cert.pem
  certificate_path: .../cert.pem
  key_file: .../cert.key

Posting environment: .env

POSTING_SSL__CA_BUNDLE=.../cert.pem
POSTING_SSL__CERTIFICATE_PATH=.../cert.pem
POSTING_SSL__KEY_FILE=.../cert.key

Using either of the above, I'm getting a 401 Unauthorized back, despite it being configured to use client credentials. Also tried both relative and absolute paths; no change there.

Connection trace

connection.connect_tcp: 29.40ms
connection.start_tls: 16.64ms
http11.send_request_headers: 3.71ms
http11.send_request_body: 3.86ms
http11.receive_response_headers: 5.44ms
http11.receive_response_body: 4.78ms
http11.response_closed: 6.19ms

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions