# Ruby Driver Test TLS Certificates

## File Types

All files in this directory are in the PEM format. They are generated by
the x509gen MongoDB tool.

The file extensions map to content as follows:

- `.key` - private key
- `.crt` - certificate or a certificate chain
- `.pem` - certificate (or a certificate chain) and private key combined
in the same file

The file name fragments have the following meaning:

- `second-level` - these certificates are signed by the intermediate
certificates (`client-int.crt` & `server-int.crt`) rather than directly
by the CA certificates.
- `int` - these are intermediate certificates used for testing certificate
chains. The server and the client sides have their own intermediate certificates.
- `bundle` - these files contain the leaf certificates followed by intermediate
certificates up to the CA certificates, but do not include the CA certificates.

## Generation

Keep in mind the following important notes:

- In multi-ca.crt, the Ruby driver CA certificate must be last (the first
certificate must be an unrelated certificate).
- All server certificates should have `localhost.test.build.10gen.cc` in
the Subject Alternate Name field for testing SRV monitoring.

## Tools

To inspect a certificate:

    openssl x509 -text -in path.pem

## Manual Testing - openssl

Start a test server using the simple certificate:

    openssl s_server -port 29999 -CAfile ca.crt -cert server.pem -verify 1

Use OpenSSL's test client to test certificate verification using the
simple certificate:

    openssl s_client -connect :29999 -CAfile ca.crt -cert client.pem \
        -verify 1 -verify_return_error

Same thing but using the second level certificate with the intermediate
certificate (server follows chain up to the CA):

    openssl s_client -connect :29999 -CAfile ca.crt \
        -cert client-second-level-bundle.pem \
        -verify 1 -verify_return_error

Note however, that even though a client to server connection succeeds using
the second level client bundle, openssl appears to be incapable to simply
verify the same certificate chain using the verify command:

    # This fails
    openssl verify -verbose -CAfile ca.crt -untrusted client-int.crt \
        client-second-level.pem 

    # Also fails
    openssl verify -trusted client-int.crt client-second-level.crt

And when the server's certificate uses an intermediate certificate, the
client seems to be unable to verify it also:

    openssl s_server -port 29999  -CAfile ca.crt -verify 1 \
        -cert server-second-level-bundle.pem

    # This fails
    openssl s_client -connect :29999 -CAfile ca.crt -cert client.pem \
        -verify 1 -verify_return_error

To sum up, openssl's command line tools appear to only handle certificate
chains provided by the client when the server is verifying them, not the
other way around and not when trying to standalone verify the chain.

## Manual Testing - mongosh

When it comes to `mongod` and `mongosh`, certificate chains are supported in
both directions:

    mongod --sslMode requireSSL \
        --sslCAFile ca.crt \
        --sslPEMKeyFile server-second-level-bundle.pem \
        --sslClientCertificate client.pem

    mongosh --host localhost --ssl \
        --sslCAFile ca.crt \
        --sslPEMKeyFile client-second-level-bundle.pem

The `--host` option needs to be given to `mongosh` because the certificates here
do not include 127.0.0.1 in subject alternate name.

If the intermediate certificate is not provided, the connection should fail.

    # Expected to fail
    mongosh --host localhost --ssl \
        --sslCAFile ca.crt \
        --sslPEMKeyFile client-second-level.pem
