Juniper SRX 1600 SSL auto enrollment not working

This is my config:

set security pki ca-profile ISRG_Root_X1 ca-identity ISRG_Root_X1
set security pki ca-profile ISRG_Root_X1 pre-load
set security pki ca-profile ISRG_Root_X1 revocation-check disable
set security pki ca-profile Lets_Encrypt revocation-check disable

set security pki ca-profile Lets_Encrypt ca-identity Lets_Encrypt
set security pki ca-profile Lets_Encrypt enrollment url https://acme-v02.api.letsencrypt.org/directory

request security pki generate-key-pair size 4096 type rsa certificate-id ACME-KEY
request security pki generate-key-pair size 4096 type rsa certificate-id GALLEON_Cert1

request security pki local-certificate enroll acme acme-key-id ACME-KEY certificate-id GALLEON_Cert1 ca-profile Lets_Encrypt domain-name armada-tc.armada.ai,vpn.armada.ai email network@armada.ai letsencrypt-enrollment yes terms-of-service agree

set security pki acme-account-key acme-key-id ACME-KEY

set security pki auto-re-enrollment acme certificate-id GALLEON_Cert1 acme-key-id ACME-KEY ca-profile-name Lets_Encrypt re-enroll-trigger-time-percentage 72 re-generate-keypair

set security pki auto-re-enrollment acme certificate-id GALLEON_Cert1 re-generate-keypair

This is my error in my logs:
Jul 1 16:18:58 mgd[58670]: UI_CMDLINE_READ_LINE: User 'mist', command 'request security pki local-certificate enroll acme acme-key-id ACME-KEY certificate-id GALLEON_Cert1 ca-profile Lets_Encrypt domain-names armada-tc.armada.ai,vpn.armada.ai email "network@armada.ai" letsencrypt-enrollment yes terms-of-service agree '
Jul 1 16:19:08 mgd[58670]: UI_CMDLINE_READ_LINE: User 'mist', command 'show log messages | match pki '
Jul 1 16:19:09 pkid[10245]: PKID_ACME_EE_CERT_ENROLL_FAIL: Enrollment for certificate GALLEON_Cert1 failed due to server reponse parsing failure

No clue how to get past this

This seems like a problem better asked of Juniper support. Their system seems to be failing to understand a response it got presumably from Let's Encrypt. Yet, we don't see what that response is. And, Let's Encrypt sends all errors in a standard format so I don't know why it would have trouble being parsed.

Still, if the Juniper system is using an HTTP Challenge it might be because the domain names you are requesting a cert for are not reachable by HTTP on port 80 from the public internet. Perhaps Juniper better prepares your system for that challenge when it runs. I don't know. But, right now those names are not reachable.

For example, see: Let's Debug

Yeah someone turned my firewall off at the moment. ugh. working to get it back online

Ok now I'm getting this weird error:

UnexpectedHttpResponse

Warning

Sending an ACME HTTP validation request to armada-tc.armada.ai results in unexpected HTTP response 405 Method Not Allowed. This indicates that the webserver is misconfigured or misbehaving.

405 Method Not Allowed

Method Not Allowed

Access Error: 405 -- Method Not Allowed




Trace:
@0ms: Making a request to http://armada-tc.armada.ai/.well-known/acme-challenge/letsdebug-test (using initial IP 216.234.199.40)
@0ms: Dialing 216.234.199.40
@382ms: Server response: HTTP 405 Method Not Allowed

You are using an HTTP Challenge to validate the cert. That means the Let's Encrypt servers send an HTTP request on port 80 to confirm you can satisfy the challenge.

But, your system is replying with an HTTP error 405. You need to figure out why that is.

Again, I think these are better directed to Juniper support. I am sure there are guidelines on how to setup their system to acquire certs.

The 405 is easily reproduced by making a similar request to your domain. The below should result in an HTTP 404 (Not found)

curl -i http://armada-tc.armada.ai/.well-known/acme-challenge/Test404 

HTTP/1.1 405 Method Not Allowed
Vary: Accept-Encoding
X-Frame-Options: SAMEORIGIN
Content-Type: text/html
X-Content-Type-Options: nosniff
Date: Thu, 02 Jul 2026 16:56:20 GMT

Requests to your "home" page using HTTP work fine. Something about these ACME Challenges are being handled differently by your system.

I have 2 way communication with letsencrypt at the bottom like 10 lines is this one:

Jul 2 20:43:20 Enrollment for certificate GALLEON_Cert1 failed due to server reponse parsing failure

I don't know if that's from my firewall or from letsencrypt. And yes I have Juniper support looking also.

Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 158
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 1312 total-len 0 read-len 1312
Jul 2 20:43:14 pkid-comm: data length 1312 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1312
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 1290
Jul 2 20:43:14 http_parser_for_scep: status- 200
Jul 2 20:43:14 acme-process-resp: response received length 1290 LSYS 0 with encoded chunk as 0
Jul 2 20:43:14 acme-handle-response: GET_DIR
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/new-acct
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/new-nonce
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/new-order
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/revoke-cert
Jul 2 20:43:14 acme-send-request: GET_NONCE
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 246 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 362 total-len 0 read-len 362
Jul 2 20:43:14 pkid-comm: data length 362 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 362
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 340
Jul 2 20:43:14 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:14 acme-send-request: CREATE_ACCOUNT
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 2290 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 1323 total-len 0 read-len 1323
Jul 2 20:43:14 pkid-comm: data length 1323 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1323
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 1301
Jul 2 20:43:14 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:14 http_parser_for_scep: status- 200
Jul 2 20:43:14 acme-process-resp: response received length 1301 LSYS 0 with encoded chunk as 0
Jul 2 20:43:14 acme-handle-response: CREATE_ACCOUNT
Jul 2 20:43:14 acme-send-request: ENROLL_REQUEST
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1463 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 1031 total-len 0 read-len 1031
Jul 2 20:43:14 pkid-comm: data length 1031 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1031
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 1009
Jul 2 20:43:14 acme-process-resp: got new nonce, status = 201
Jul 2 20:43:14 http_parser_for_scep: status- 201
Jul 2 20:43:14 acme-process-resp: response received length 1009 LSYS 0 with encoded chunk as 0
Jul 2 20:43:14 acme-handle-response: ENROLL_REQUEST
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/authz/3496502631/732251953191
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/authz/3496502631/732253106501
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/finalize/3496502631/527937570141
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/order/3496502631/527937570141
Jul 2 20:43:14 acme-send-request: AUTHORIZE_DOMAIN
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1364 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 1228 total-len 0 read-len 1228
Jul 2 20:43:14 pkid-comm: data length 1228 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1228
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 1206
Jul 2 20:43:14 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:14 http_parser_for_scep: status- 200
Jul 2 20:43:14 acme-process-resp: response received length 1206 LSYS 0 with encoded chunk as 0
Jul 2 20:43:14 acme-handle-response: AUTHORIZE_DOMAIN
Jul 2 20:43:14 acme-send-request: AUTHORIZE_DOMAIN
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1364 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:14 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:14 pkid-comm: data received sd 29 len 1267 total-len 0 read-len 1267
Jul 2 20:43:14 pkid-comm: data length 1267 received from sd 29.
Jul 2 20:43:14 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1267
Jul 2 20:43:14 acme-context-search: context search successful
Jul 2 20:43:14 acme-process-resp: processed length 1245
Jul 2 20:43:14 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:14 http_parser_for_scep: status- 200
Jul 2 20:43:14 acme-process-resp: response received length 1245 LSYS 0 with encoded chunk as 0
Jul 2 20:43:14 acme-handle-response: AUTHORIZE_DOMAIN
Jul 2 20:43:14 httpUrlParser: Success, port=443
Jul 2 20:43:14 httpUrlParser: host=
Jul 2 20:43:14 httpUrlParser: urlPath=
Jul 2 20:43:14 httpUrlParser: input url=https://acme-v02.api.letsencrypt.org/acme/chall/3496502631/732253106501/wrewrg
Jul 2 20:43:14 acme-send-request: HANDLE_CHALLENGE
Jul 2 20:43:14 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:14 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1383 LSYS 0
Jul 2 20:43:14 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:15 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:15 pkid-comm: data received sd 29 len 821 total-len 0 read-len 821
Jul 2 20:43:15 pkid-comm: data length 821 received from sd 29.
Jul 2 20:43:15 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 821
Jul 2 20:43:15 acme-context-search: context search successful
Jul 2 20:43:15 acme-process-resp: processed length 799
Jul 2 20:43:15 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:15 http_parser_for_scep: status- 200
Jul 2 20:43:15 acme-process-resp: response received length 799 LSYS 0 with encoded chunk as 0
Jul 2 20:43:15 acme-handle-response: HANDLE_CHALLENGE
Jul 2 20:43:15 acme-send-request: AUTHORIZE_DOMAIN
Jul 2 20:43:15 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:15 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1364 LSYS 0
Jul 2 20:43:15 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:15 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:15 pkid-comm: data received sd 29 len 1267 total-len 0 read-len 1267
Jul 2 20:43:15 pkid-comm: data length 1267 received from sd 29.
Jul 2 20:43:15 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1267
Jul 2 20:43:15 acme-context-search: context search successful
Jul 2 20:43:15 acme-process-resp: processed length 1245
Jul 2 20:43:15 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:15 http_parser_for_scep: status- 200
Jul 2 20:43:15 acme-process-resp: response received length 1245 LSYS 0 with encoded chunk as 0
Jul 2 20:43:15 acme-handle-response: AUTHORIZE_DOMAIN
Jul 2 20:43:15 acme-send-request: nothing: AUTHORIZE_DOMAIN_WAIT
Jul 2 20:43:20 acme-context-search: context search successful
Jul 2 20:43:20 acme-timer: get authz result from server
Jul 2 20:43:20 acme-send-request: AUTHORIZE_DOMAIN
Jul 2 20:43:20 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:20 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 1364 LSYS 0
Jul 2 20:43:20 pkid_write_conn_callback: Sending data to CA(CDP) server
Jul 2 20:43:20 pkid_process_received_messages p_conn 0x1d47680
Jul 2 20:43:20 pkid-comm: data received sd 29 len 1074 total-len 0 read-len 1074
Jul 2 20:43:20 pkid-comm: data length 1074 received from sd 29.
Jul 2 20:43:20 acme-recv: recv data id 1d476a8 id_len 20 data 2201000 data-len 1074
Jul 2 20:43:20 acme-context-search: context search successful
Jul 2 20:43:20 acme-process-resp: processed length 1052
Jul 2 20:43:20 acme-process-resp: got new nonce, status = 200
Jul 2 20:43:20 http_parser_for_scep: status- 200
Jul 2 20:43:20 acme-process-resp: response received length 1052 LSYS 0 with encoded chunk as 0
Jul 2 20:43:20 acme-handle-response: AUTHORIZE_DOMAIN
Jul 2 20:43:20 acme-context-search: context search successful
Jul 2 20:43:20 Enrollment for certificate GALLEON_Cert1 failed due to server reponse parsing failure
Jul 2 20:43:20 Sending data host acme-v02.api.letsencrypt.org port 443 routing-inst null source-ip null
Jul 2 20:43:20 acme-send: sending request to host acme-v02.api.letsencrypt.org:443 request-len 24 LSYS 0
Jul 2 20:43:20 acme-conn-close: close connection for id 1d1a388 len 20

I do not know why Juniper is not showing you the failed challenge but you can see the response by following those URL requests

  "type": "http-01",
  "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3496502631/732253106501/wrewrg",
  "status": "invalid",
  "validated": "2026-07-02T20:43:14Z",
  "error": {
    "type": "urn:ietf:params:acme:error:dns",
    "detail": "no valid A records found for vpn.armada.ai; no valid AAAA records found for vpn.armada.ai",
    "status": 400

I fixed it. There were 2 issues. You can't use j-web and AMCE on the srx at the same time.

2nd issue a typo in my cname field.

Cert installed now.

Thanks for you help
[/quote]

There was 1 more thing that needed to be fixed for Juniper secure connect client to work successfully

  1. Download new public certificates from let’s Encrypt certificate
    a. https://letsencrypt.org/certs/gen-y/int-yr2.pem
    b. https://letsencrypt.org/certs/gen-y/root-yr-by-x1.pem
  2. Move the files to the certificates directory
    a. Windows
    1. C:\ProgramData\Juniper\SecureConnect\cacert
  3. Delete the Let’s Encrypt certificate ending in R3

The included certificate with the juniper secure connect client download has a certificate that expired in sept of 2025

While those steps might have worked for now, that can't possibly be the intended way of using it (unless they have a really broken way of doing things). Intermediates change regularly (so you're quite likely to not get YR2 the next time you get a certificate) and the ACME client should automatically configure a server to send the correct one. For a client side, all that should be needed is having Let's Encrypt roots in the trust store, not the intermediates.

As Peter noted you should not be saving intermediate certs in your client's trust store. Most client's should already have the Let's Encrypt roots in their trust stores. But, if not you can add the roots for special cases (not the intermediates).

I think the problem with your domain armada-tc.armada.ai is that it does not send the complete intermediate chain that Let's Encrypt gave it. Your server only sends your "leaf" cert and one intermediate. It was given two intermediates by LE but your server is only using the first one. The intermediate you "lost" links to Let's Encrypt root ISRG Root X1 which is widely trusted by clients.

Perhaps this is a problem with your Juniper setup. If they don't know how to fix that please ask them to visit here and we can help.

Here is the cert chain your server sends

openssl s_client -connect armada-tc.armada.ai:443 

Certificate chain
 0 s:CN=armada-tc.armada.ai
   i:C=US, O=Let's Encrypt, CN=YR2
   a:PKEY: RSA, 4096 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Jul  3 17:34:28 2026 GMT; NotAfter: Oct  1 17:34:27 2026 GMT
 1 s:C=US, O=Let's Encrypt, CN=YR2
   i:C=US, O=ISRG, CN=Root YR
   a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Sep  3 00:00:00 2025 GMT; NotAfter: Sep  2 23:59:59 2028 GMT

A server that properly handles the chain it was given will send a result like below

Certificate chain
 0 s: example.com
   i:C=US, O=Let's Encrypt, CN=YR2
   a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Jul  1 22:33:02 2026 GMT; NotAfter: Jul  8 14:33:01 2026 GMT
 1 s:C=US, O=Let's Encrypt, CN=YR2
   i:C=US, O=ISRG, CN=Root YR
   a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Sep  3 00:00:00 2025 GMT; NotAfter: Sep  2 23:59:59 2028 GMT
 2 s:C=US, O=ISRG, CN=Root YR
   i:C=US, O=Internet Security Research Group, CN=ISRG Root X1
   a:PKEY: RSA, 4096 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: May 13 00:00:00 2026 GMT; NotAfter: Sep  2 23:59:59 2032 GMT

If I could post a screen shot you would see that the certficiate included with secure connect client is expired.

When the client connects to the firewall it tries to validate the lets encrypt certifcate and the client fails. Not not the connection to the firewall.

Download the latest juniper secure connect client and you'll see what I'm saying.
https://support.juniper.net/support/downloads/?p=jsc-win

Then goto connections>certificates>display ca certificate. And you will see the expired certificate

Okay. What did Juniper support say about that?

If they include an expired cert with their client they would need to fix that. But, more important they should be validating any cert and chain sent by the firewall using the root certs.

I believe you. It just isn't something we can fix for you. That's Juniper's software doing that

Below is what Juniper is saying. I'm not taking sides. just putting all that I know or have received in 1 place for the next person to hopefully help reduce their pain/frustrations when running into this issue.

Juniper KB79434 adding let's encrypt info

Important Note:

  • If you are using Let's Encrypt certificates, please review Let's Encrypt site for any updates on their Root CA and Intermediate CA certificates changes as this may cause issues with re-enrollment. Make sure to update the certificates on both, SRX and JSC client to avoid receiving the error mentioned on this KB. Updating JSC client release does not update Let's Encrypt certificates.

The certificate file URLs are stable and remain published by Let's Encrypt indefinitely. However, because Let's Encrypt randomly selects the issuing intermediate at each renewal, the RSA intermediate that signs the gateway certificate may be YR1 or YR2 (and potentially YR3 if the backup is activated). To avoid recurrence, install all three RSA Gen Y intermediates plus the Root YR cross-sign into the client CA store:

[SRX] JSC client unable to get issuer certificate
https://supportportal.juniper.net/s/article/SRX-JSC-client-unable-to-get-issuer-certificate

Okay. Thanks. I don't know why they wouldn't just need the roots but for whatever reason they require you to have updated intermediates.

You may wish to subscribe to the API Announcements category to be alerted to routine changes. See: API Announcements - Let's Encrypt Community Support

Or, subscribe to the email announcements. Scroll to bottom of this page: Documentation - Let's Encrypt