The SSL/TLS communication occurs between the client (e.g., Artifactory) and the server (e.g., DockerHub or Red Hat CDN) in two ways.
In one way SSL, the server does not validate the identity of the client to start the secure communication. Here is the flow of events during the One-way SSL handshake process.
-
The client will say Hello to the server and request the resource over HTTPS protocol.
-
The server responds with its public certificate and public key by saying Hello.
-
The client checks the server's public certificate against its trust store and verifies the received server certificate, including the expiration date of the certificate, the common name, etc.
-
The client uses the server's public key to send a symmetric session key which can be decrypted by the server's private key.
-
The server decrypts the symmetric session key using its private certificate and sends back the encrypted session key to the client to establish secure communication.
Here is a sample demonstration for your reference.
curl -v https://testjpd.jfrog.io/artifactory/api/system/ping
* Trying X.X.X.X:443...
* Connected to testjpd.jfrog.io (X.X.X.X) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted http/1.1
* Server certificate:
* subject: CN=*.jfrog.io
* start date: Jan 17 00:00:00 2025 GMT
* expire date: Feb 16 23:59:59 2026 GMT
* subjectAltName: host "testjpd.jfrog.io" matched cert's "*.jfrog.io"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust TLS RSA CA G1
* SSL certificate verify ok.
* using HTTP/1.1
> GET /artifactory/api/system/ping HTTP/1.1
> Host: testjpd.jfrog.io
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200
< Date: Tue, 08 July 2025 06:55:55 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-JFrog-Version: Artifactory/7.78.3 77803900
< X-Artifactory-Id: 5fd23443d0a231b74bfc50461aa513ef4dfcd619
< X-Artifactory-Node-Id: testjpd-artifactory-primary-2
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Request-ID: bd73946cf93ac6069e5cd438713ffa18
<
* Connection #0 to host testjpd.jfrog.io left intact
OK
In Two-Way SSL, the server also validates the identity of the client to start the secure communication. In Artifactory, the two-way SSL implementation can be seen if we configure a remote registry that requires certificate-based authentication (Ex: RedHat CDN).
For example, after importing the certificate, create a new RPM remote repository. Under URL pass the URL to the repository(e.g.https://cdn.redhat.com/content/dist/rhel/server/7/7Server/x86_64/sat-tools/6.5/os) and add the certificate by navigating to Advanced => Remote Authentication => SSL / TLS Certificate and select the certificate from the drop-down list.
If we perform the test connection on such types of remote repositories, the upstream registry requests a client certificate and validates it before establishing secure communication. In case the client certificate is invalid, we will encounter the “forbidden” error.