Join the Conversation

To sign in, use your existing MySonicWall account. To create a free MySonicWall account click "Register".

SonicOS API Endpoint for Importing SSL Certificate

G_Hosa_PhatG_Hosa_Phat Newbie ✭
edited March 2022 in Developer Hub

I'm having difficulty figuring out how to get my new SSL certificate from Let's Encrypt installed on my SonicWALL device via the SonicOS API. I'm calling the certificates-import-cert-key-pair endpoint with an HTTP PUT request as according to the Swagger documentation:

https://[SONICWALL_IP]:[PORT]/api/sonicos/certificates/import/cert-key-pair/name/"sub.domain.com [Certify] 3/11/2022 10:06:59 AM to 6/9/2022 11:06:58 AM"/password/"[PFX_P@$$w0?d]"/ftp/ftp%3a%2f%2f[FTP_USER]%3a[FTP_PASS]%40[FTP_SERVER_IP]%2f20220609_49b0413b.pfx

I've verified that the PFX file is on the FTP server and accessible to the FTP_USER account but, when I try to call this endpoint, I get a 404 - Not Found response.

I'm using (VB).NET to construct the API URL from an X509Certificate2 object to get the Friendly Name to use for the name element of the API call. The password element is populated from a Net.NetworkCredential object. The request is being sent as a System.Net.WebRequest object with the following properties:

.Method = "PUT"

.ContentType = "text/plain, application/json"

.Accept = "text/plain, application/json"

.PreAuthenticate = True

.Headers("Authorization") = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(Username + ":" + Password))

.Headers("Accept-Encoding") = "text/plain, application/json"

.Headers("Charset") = "UTF-8"

After looking at this thread from nearly a year ago, I tried flipping the API URL elements for certificates and import:

/api/sonicos/import/certificates/cert-key-pair/name/

but I still get the 404 - Not Found error.

Also from that thread, I tried reading the PFX file's raw data into a byte array and submitting it as the request's content with Content-Type: multipart/form-data, as well as Content-Type: application/octet-stream (to the original endpoint), but those didn't work either, this time returning a 406 - Not Acceptable error.

I have not yet tried with the /api/sonicos/direct/cli option presented in that thread, but that's probably going to be my next step in trying to make this work. I'm probably just overlooking something or being "dense" here, but perhaps someone could point me in the right direction.

Category: Developer Hub
Reply

Best Answers

  • CORRECT ANSWER
    JaimeJaime SonicWall Employee
    Answer ✓

    Hi @G_Hosa_Phat,

    I just got through reading your comments. I believe the issue you're facing now is an issue that was reported to Engineering and was fixed but is not available in a posted firmware release. If you can create a support case and message me the case number, I can make sure you get the hotfix.

    About your side note: It sounds like the root CA certificate is not imported. Import the root certificate (and any intermediate CA certificates) to complete the chain.

    Thanks.

    Jaime

  • CORRECT ANSWER
    JaimeJaime SonicWall Employee
    Answer ✓

    Hi @G_Hosa_Phat,

    Send a PUT to /administration/global with the following JSON:

    {
      "administration": {
        "web_management": {
          "certificate": {
            "name": "MY_CERT_FRIENDLY_NAME"
          }
        }
      }
    }
    

    Send a POST to /config/pending to commit. I just tried it out and it successfully changed the management certificate selection.

    Just FYI, I'm still working on the question you had about the certificate's friendly name length. On Gen6, the length of the name field is limited to 30 characters. On Gen7 it seems the length is not limited on the field. I'm not sure at this time if the length is limited via CLI or API.

Answers

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    UPDATE: I tried with the direct/cli endpoint as the above referenced thread described. This time, I got a 405 - Method not allowed error. I made sure the FTP_HOST_NAME_OR_IP value was not URL encoded, and I tried with the CERTIFICATE-NAME and CERTIFICATE-PASSWORD both with and without surrounding quotation marks. I made sure to add line breaks to the CLI commands for the API request body:

    CLICommands = "certificates" + Environment.NewLine

    CLICommands += $"import cert-key-pair {NAME} password {PASSWD} ftp {FTPURL}" + Environment.NewLine

    CLICommands += "exit" + Environment.NewLine

    I also tried changing the Charset header to use ASCII instead of UTF-8, but it still returns the same 405 - Method not allowed error.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    UPDATE #2: Okay, so I was finally able to get away from the 404 - Not found error with the certificates/import/cert-key-pair endpoint by URL encoding the certificate's Friendly Name and the PFX password values in the API call. However, that still fails with a 405 - Method not allowed error.

    I went back to my previous posting when I was trying to handle CSR creation to see if that might provide any clues, but I feel like I've been over everything there multiple times. I feel like I'm getting closer to the solution, but I'm still missing some key piece of the puzzle.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭
    edited March 2022

    UPDATE #3: Well, I THOUGHT I had it figured out. I used Postman to submit the request and got this result:

    {
        "status": {
            "success": false,
            "cli": {
                "mode": "top_mode",
                "depth": 0,
                "command": "configure",
                "configuring": false
            },
            "info": [
                {
                    "level": "error",
                    "code": "E_READ_ONLY",
                    "message": "An administrator is already logged in for configuration."
                }
            ]
        }
    }
    

    That's totally on me. I still had a browser open logged in to the SonicWALL in configuration mode. I logged out of the SonicWALL management interface and tried again from my application. This time I didn't get any errors from the certificates/import/cert-key-pair/ endpoint (URL-encoded Friendly Name and PFX password). Everything seemed to have worked, but when I logged back into the SonicWALL device, I went to the Appliance/Certificates section only to find that my shiny new certificate isn't listed.

    I tried again using the direct/cli method (after deleting the certificate and logging back out of the SonicWALL, of course) and, again, it did not give me any errors and the JSON reply from the API indicated a Success. However, when I logged back in to the SonicWALL, it still doesn't show me my certificate anywhere.

    Next troubleshooting step: I tried to manually import the certificate through the management interface. It imported just fine BUT the name is drastically truncated (it stops after the [Certify] bit). So, thinking that my API call may be having problems with such a long Name value, I had my application truncate that before submitting it. The certificate still doesn't show up after what the API call says is a "successful" import. So, while I'm closer than before, I'm still not all the way there yet.

    SIDE NOTE: When I imported the certificate manually, even though the certificate is a CA signed PFX with the private key, it still said that the certificate could not be validated. Not sure what kind of problems that's going to cause me later, but I'm going to tackle one piece at a time.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    Thank you so much, @Jaime . I will get that ticket submitted as soon as possible and make sure that the other certificates in the chain are imported. I thought they were as I remember seeing that everything "looked" correct, but maybe I missed a step or something.

    On a quick tangent, I'm just curious: From my testing, it looks like the name element is limited to 30 characters when imported through the management interface but, when I look at the full list, there are several CA certificates and such that have much longer names. Do you happen to know if that is just a limitation of the web UI, or if importing them with the API is going to result in/require a name that's a maximum of 30 characters?

    Not that it really matters that much, but the Friendly Name extracted from these Let's Encrypt certificates is actually pretty descriptive and could be somewhat helpful. I mean, I'm hoping to have this process pretty well automated so that I don't have to really mess with them, but it would be nice for the sake of "consistency" (I've got a few other servers/endpoints that I'm trying to automate with Let's Encrypt certs).

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    FYI, I've opened another thread for the question about the CA/intermediate certificates. I've tried re-importing the CA certificates both individually and as a part of the chain from the PFX, but the site certificate still shows up as "Not Verified". The new thread is "Let's Encrypt Certificate Chain Imported From PFX - Certificate Can't Be Verified". Thank you again for all of your help.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭
    edited March 2022

    Sorry... I jumped the gun a little on that last bit. I found the resolution for the "Not Verified" issue by exporting the root CA from another endpoint using a Let's Encrypt certificate and importing that .p7b file into the SonicWALL appliance. The problem was, as you said, that the CA certificates weren't (properly) imported from the PFX, but it looks like it has more to do with the PFX than anything else. I intend to bring this particular "issue" up with the Certify developers, just in case they can actually do anything about it.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    I do have one additional question about the imported (and now verified) certificate. I need to get the new certificate "activated" for the web management interface. In the management UI, I'd go to System Setup -> Appliance -> Base Settings -> Web Management Settings -> Certificate Selection and choose the new certificate from the drop-down. I've successfully tested this manually but, since I'm trying to automate the entire SSL renewal process using the SonicOS API, I'd like to figure out how to avoid the manual selection.

    Looking through the Swagger documentation, there's a "model" listed for the administration_web_management_certificate_name, but I'm not sure what API endpoint to call to actually set this value so that the SonicWALL will start using my new certificate.

    My guess based on what I have been able to find with Google-fu and liberal use of the "Find" within the loaded page of the API documentation would be to send a PUT request to the /administration/global endpoint with something like this:

    {
     "administration": {
      "web_management": {
       "administration_web_management_certificate_name": "{MY_NEW_CERTIFICATE_FRIENDLY_NAME}"
       }
     }
    }
    

    Of course, I could be way off there. As I said, that's just my guess, so I wanted to try to confirm or correct what it is I actually need to do so that I can pretty much finalize my project.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    Ahh! I was SO CLOSE! 😝

    Thank you again. All of this information is incredibly helpful to finishing up my automation project. Maybe I'll even put it on GitHub at some point for other users to poke around in.

    I've applied the hotfix to the device, but I haven't yet had the chance to test the import. I'll let you know as soon as I've done so, but I have a feeling I'm in the final stretch here.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    @Jaime - First of all, thank you so much! The hotfix seems to have resolved the problem with uploading the certificates. I was able to successfully import the new certificate from my application and have it show up in the certificate list through the SonicWALL management UI just fine.

    Additionally, it looks like I can confirm the 30-character limit through the Gen6 API. Since the names need to be unique, I can't just truncate the Friendly Name of these certificates - they come in as "sub.domain.com [Certify] M/d/yyyy H:mm:ss AM/PM to M/d/yyyy H:mm:ss AM/PM", so it's very possible that the first 30 characters of the certificate will conflict with another (mine cut off at "sub.domain.com [Certify] "). I've come up with a "scheme" for creating unique names and should be good to go, but I just wanted to let you know. (side-note: Apparently apostrophes in the name cause all sorts of havoc with the API)

    However, I'm not sure what's wrong with my "commit" call. As you mentioned, I'm sending an empty POST request (no JSON or URL parameters) to /config/pending, but I'm getting the following response:

    {
       "status": {
         "success": false
    
        ,"cli": {
           "mode": "config_mode"
          ,"depth": 1
          ,"command": "commit"
          ,"configuring": true
          ,"pending_config": true
          ,"restart_required": "FALSE"
         }
    
        ,"info": [
           {
             "level": "error"
            ,"code": "E_ERROR"
            ,"message": "Not allowed in current mode"
           }
         ]
       }
    }
    

    As far as I can see, my session is still active and all of the other commands up to that point seem to execute normally and successfully, so I'm not sure what that "Not allowed in current mode" message is all about. I can only assume it's referring to either the "mode" or "depth" property of the "cli" object.

    Once that's done, I have a final piece of the operation that will schedule a restart of the firewall at 6PM by calling the /restart/at/{AT_TIME} endpoint. It doesn't look like that's even 100% necessary but I'm not even going to start trying to test that until I get everything else working properly.

  • JaimeJaime SonicWall Employee
    edited March 2022

    I'm happy that I was able to help. Thanks for confirming the character limit. That's helpful. I suspect that's changed in Gen7 given the character limit was lifted from the GUI.

    The E_ERROR "Not allowed in current mode" tells me that you possibly were preempted, and are now in non-config mode. Interesting that the JSON says you are in config_mode though...

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    Well, I had tried a few times with the same result before including that bit about the commit error in the previous comment. But, I just tried again and it worked without a problem this time. I've connected to the web management UI again to verify that it's using my new certificate, and it all looks exactly as expected. I can't tell you how grateful I am for all of your assistance and helpful communication along the way.

    I'm pretty much the only one with admin login privileges (the only other person with permission only gets in there when I have a question), so maybe I just had an old session stuck somewhere since I'm constantly going back and forth between the management UI and my application's API calls. At this point I'm just going to chalk it up as a "user error" type of thing and move on down the road now that everything seems to work the way I need it to for this automation project. Since it doesn't really require a reboot of the appliance after the application of the new certificate, I may just leave that out of the process for now to avoid unnecessary "complications". But, thank you again. Without that hotfix, I would've been sunk.

  • JaimeJaime SonicWall Employee

    Thanks for the great posts. I'm sure these will be really helpful to future readers. I hope to see your project on Github one day 😎.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    I just came up with one quick follow-up question, when you get a minute, @Jaime: I'm trying to put together all of the SSL certificate upload/installation stuff, but the thought occurred to me, what if I (the user) needed to specify a port for the FTP server (e.g., ftp.example.com:990 for implicit TLS)? In my testing, it looks like specifying the port causes a problem.

    {
       "status": {
         "success": false
    
        ,"cli": {
           "mode": "certificate_mode"
          ,"depth": 2
          ,"command": "import cert-key-pair Friendly\ Name\ password PfXpAsSwOrD ftp ftp://ftpuser:FtPpAsSwOrD@99.99.99.99:990/PFXFileName.pfx"
          ,"configuring": true
          ,"pending_config": false
          ,"restart_required": "FALSE"
         }
    
        ,"info": [
           {
             "level": "error"
            ,"code": "E_ERROR"
            ,"message": "Unable to establish an FTP client connection to '99.99.99.99:990' as user 'ftpuser'"
           }
          ,{
             "level": "error"
            ,"code": "E_ERROR"
            ,"message": "Please verify connectivity and that the FTP username, password and filename are correct."
           }
          ,{
             "level": "error"
            ,"code": "E_ERROR"
            ,"message": "Could not download file."
           }
         ]
       }
    }
    

    The FTP server's URI for the API endpoint is formatted as ftp://{USERNAME}:{PASSWORD}@{HOSTADDRESS}/{PFXFILENAME}, so I would have guessed that the {HOSTADDRESS} could include the port specification (99.99.99.99:990), but it doesn't appear from my testing that the SonicOS is capable of connecting that way.

    I've tested the connection using an FTP client (FileZilla) to that server/port, and it works fine. I also tried using the "default" port 21 explicitly defined (99.99.99.99:21), but it gives me the same results. I even tried changing the URI to use the FTPS protocol (ftps://{USERNAME}:{PASSWORD}@{HOSTADDRESS}/{PFXFILENAME}) instead, but it still fails, this time with a syntax error:

      "status": {
       "success": false,
       "cli": {
        "mode": "certificate_mode",
        "depth": 2,
        "command": "import cert-key-pair Friendly\ Name\ password PfXpAsSwOrD ftp ftps://ftpuser:FtPpAsSwOrD@99.99.99.99:990/PFXFileName.pfx",
        "configuring": true,
        "pending_config": false,
        "restart_required": "FALSE"
       },
       "info": [
        {
         "level": "error",
         "code": "E_SYNTAX",
         "message": "Invalid input detected."
        }
       ]
      }
    

    Of course, if I omit the port number and leave the URI's protocol as FTP, the exact same API call works exactly as it should. So, since I'm trying to build a somewhat generic SonicOS API handler for my .NET project, I just want to make certain that I'm not simply doing something stupid here. But, with these "issues" and the additional questions I brought up over in @Mario's Import Certificate via SonicOS API thread, it looks like my library is going to have some pretty significant restrictions, especially if the user isn't on a SonicOS Gen7 device. If I AM simply overlooking something here, please feel free to let me know. Obviously, if I come up with anything else, I'll be sure to post another update, but I've tested every way I can think of so far.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    FYI, I also tried using the SCP endpoint (certificates/import/cert-key-pair/name/{CERTNAME}/password/{PASSWORD}/scp/{SCPURI}) and got basically the same result:

      "status": {
       "success": false,
       "cli": {
        "mode": "certificate_mode",
        "depth": 2,
        "command": "import cert-key-pair Friendly\ Name password PfXpAsSwOrD scp scp://ftpuser@99.99.99.99/PFXFileName.pfx",
        "configuring": true,
        "pending_config": false,
        "restart_required": "FALSE"
       },
       "info": [
        {
         "level": "error",
         "code": "E_ERROR",
         "message": "File transfer error."
        },
        {
         "level": "error",
         "code": "E_ERROR",
         "message": "Could not download file."
        }
       ]
      }
    

    Now, I'm not sure if that has to do with the SSH fingerprint not being recognized (since this is the first time I've tried using SCP), but it's just one more piece of the puzzle I'm trying to put together here.

  • G_Hosa_PhatG_Hosa_Phat Newbie ✭

    Oh, and one MORE thing... If getting all of these various import methods functional requires an update to the SonicWALL appliance's firmware, I might need to look into using the /import/firmware endpoint (or whatever it takes to install a new firmware version through the API), but that's a whole OTHER set of potential issues I'm not sure I'm ready to get into yet. Just trying to look at the entire picture here and get an idea of what I'm in for.

Sign In or Register to comment.