Import Certificate via SonicOS API
Hi
I'm trying to automatically import a certificate into a Gen7 Sonicwall using the API, as this has to be done on a regular basis. According to the information found on https://sonicos-api.sonicwall.com, it's supposed to be a PUT call to
/api/sonicos/import/certificates/cert-key-pair/name/{NAME}/password/{PASSWD}
But it looks like it's missing important information about how to transmit the certificate itself.
Testing the API using CURL (after successful authentication indeed):
# curl -ksX PUT -H "accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer eyJ...snip...uxw" https://192.168.168.168/api/sonicos/import/certificates/cert-key-pair/name/myKey/password/myPass -d {}
Returns an error indicating that the file is in the wrong format:
{ "status": { "success": false, "cli": { "mode": "certificate_mode", "depth": 2, "command": "import cert-key-pair myCert password myPass api", "configuring": true, "pending_config": false, "restart_required": "FALSE" }, "info": [ { "level": "error", "code": "E_ERROR", "message": "Improper file format. Please select PKCS#12 (*.p12) file." } ] } }
As the CLI command requires to add a scp or ftp URL, I've tried to send something in the body like this:
{ "name":"myCert", "password":"myPass", "ftp":"ftp://user:pass@ftp.server/myCert.p12" }
But as this is completely made up, I get the same error message as above. Also sending the full certificate inside the body doesn't work as it immediately crashes the firewall.
Has anyone an idea how to do this properly?
Answers
Hi @Mario,
Either I haven't figured out how to properly use that endpoint or there's a problem with the endpoint. I'm working with Engineering to identify why it's not working. In the meantime, here's an alternative method using the API to send direct CLI commands. An FTP server hosts the certificate:
Send a POST to /api/sonicos/direct/cli with a text/plain body of CLI commands.
Send the Content-Type header: text/plain
The text/plain body should be one command per line. Send the following commands to import a PFX/P12:
certificates
import cert-key-pair CERTIFICATE-NAME password CERTIFICATE-PASSWORD ftp ftp://FTP_USER:FTP_PASSWORD@FTP_HOST_NAME_OR_IP/CERTIFICATE_FILENAME.PFX
exit
I'll follow up on this thread once I figure out the issue with the endpoint. Good luck!
To make this work you need to send the PUT to
with Content-Type: multipart/form-data in the header.
The body should be a .PFX/.P12 file opened in binary mode with the Content-Type included. I used application/octet-stream.
I was able to get it working in Postman, ARC, and Python with the Requests module.
I'm not very familiar with curl. You can try this, but may need to change the Content-Type to application/octet-stream:
curl -k --location --request PUT 'https://firewall/api/sonicos/import/certificates/cert-key-pair/name/MYCERTNAME/password/MYCERTPASSWORD' --header 'Content-Type: application/json' -F 'file=@/path/to/file.pfx'
Hi, just checking in. Did my responses help?
Hello, @Jaime - I know this thread is a bit older, and I've been able to get my API calls to work using the ftp variant of the endpoint (ref. SonicOS API Endpoint for Importing SSL Certificate), but I'm trying to build a more generic utility method that doesn't require the use of an FTP server using your suggestions here. Here's what I've got:
certificates/import/cert-key-pair/name/{CERTFRIENDLYNAME}/password/{PFXPASSWORD}
endpointmultipart/form-data
" (I've also tried this with "application/octet-stream
" and "application/x-pkcs12
")application/octet-stream
" (I've also tried this with "application/x-pkcs12
")It seems like no matter what I try I get a
406 - Not Acceptable
result from the API (unless I just use "application/json
" in one/both of the headers, which produces a500 - Bad Method
error).You said that you were able to get it working in Postman, but I'm getting the same result when I try through Postman by adding the file to the Body section with the binary option selected.
Here are all of the headers in the request:
text/plain, application/json
UTF-8
multipart/form-data
(see above)application/octet-stream
(see above)Just for the sake of "completeness", here's the full (obfuscated) URL to which I'm sending the request:
Since the above-referenced thread involved me installing an updated firmware, I wouldn't guess that the issue is directly related, but I'm not sure what else to look at. I would've started a new thread, but I figured it'd be more helpful to anyone looking for answers to keep the discussion all in one place. Would you mind reviewing the above and let me know what I might be overlooking? Thanks so much.
ADDITIONAL INFORMATION FOR PREVIOUS COMMENT:
(I waited too long to edit)
I forgot to mention that I'm developing my solution in a (VB).NET application. I've tried a couple of ways to submit the PFX to the endpoint in addition to copying the
FileStream
to the request stream. These methods involve converting the PFX to anX509Certificate2
object and passing the raw data as either a byte array or a hexadecimal string representation. These methods result in the same406 - Not Acceptable
response.UPDATE:
In my previous tests with Postman, I wasn't receiving any JSON response from the API - only the
406 - Not Acceptable
message showing in the Status label in the response section at the bottom of the window. However, I removed all of the additional headers and left only:multipart/form-data
(orapplication/octet-stream
orapplication/x-pkcs12
)I tried again with the PFX file selected under the binary option of the Body section in Postman. This time in addition to the
406 - Not Acceptable
status, I actually got a JSON response from the SonicWALL:So, clearly I'm still not using the correct Content-Type for this call. Just to see what would happen, I changed the Content-Type to
text/plain
. This time, with everything else the same in Postman, I got the following JSON response:So, this leads me to believe that the issue might possibly be another of the little "gotchas" in the Gen6 "default" firmware.
Oh, did I forget to mention that little piece of information? 😝
I'm using a Gen6 SonicWALL device, whereas the OP was using a Gen7 (I wish I could just edit that info back into my previous comment for readability). Based on what I've read through here and other threads, the API endpoints are named a little differently between the two, so I'm adding them here for reference:
Gen6
Gen7
It's just a swap of the
import
andcertificates
elements in the path, but I'd hate for someone to be struggling with it because they had them in the wrong order. 😉I spent some time reviewing my old code and testing against Gen6. After beating my head against my desk and staring at my code for a while, I tried to compare it against a Gen7. The Gen7 worked. I'll keep trying with Gen6, but I suspect there's a problem with the endpoint.
Yeah, that was my guess as well after seeing the "
API endpoint is incomplete
" message. It isn't a critical thing for me at present as I have an FTP server I can use for my own, personal implementation, but it'd be nice to have the option to bypass the need for it by directly submitting the PFX data. Especially because, as I said in that other thread, I'd like to have something to post on GitHub for other Gen6 users to be able to implement in their own environments where an FTP server may not be readily accessible. Of course, they'd need to get any firmware fixes in place first, but that wouldn't be something I could control anyway.If it does require an additional firmware "fix" to get this API endpoint working, I just want to ensure that the fix for the FTP issue doesn't get wiped out.
Hi @G_Hosa_Phat,
I'm still working through this one. Engineering confirmed that Gen6 supports FTP/SCP import, but does not support direct API import. Gen7 does, but Gen6 does not. The Swagger API docs for Gen6 need to be updated. I'm working with the team to update the docs.
Thanks!
Thank you for the confirmation, even if it's a little disappointing. I assume from your comments about updating the documentation that there is no intention to go back and add the direct import functionality to the older Gen6. That makes sense considering the "next-gen" is already in place. At least the FTP/SCP method is available and functional through the API, so I'll simply add some additional error handling into the library I'm building.