Important note about SSL VPN compatibility for 20.0 MR1 with EoL SFOS versions and UTM9 OS. Learn more in the release notes.

This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Upload Certificate using API

Hi folks,
 
I've started having a play around with XG. I have a PowerShell script for generating a new Let's Encrypt certificate and updating my various components that use it, and wanted to integrate this with XG Home. It looks like the obvious way of achieving this should be the API, but I'm struggling a little with the certificate upload.

I've taken a look at the documentation and fired off a few API calls successfully, but the upload operation is a little different as it references data in a multipart request.
I'm using the v16.5 documentation because the v17 docs appear to be missing this particular page (it appears in the menu but the link is broken because the AddCertificate&UpdateCertificate.html file is missing).
I am not a developer but I did a bit of Googling and have come up with what I think is a multipart request. A Fiddler trace shows this when I fire off my request (PFX file data redacted and passwords changed).
 
POST sophos:4444/.../APIController
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-GB) WindowsPowerShell/5.1.16299.251
Content-Type: multipart/mixed; boundary=Certificate_File_Upload
Host: sophos:4444
Content-Length: 2712
Connection: Keep-Alive
 
--Certificate_File_Upload
Content-Disposition: attachment; filename="test.pfx"
Content-Type: application/x-pkcs12
 
<<<<Encoded PFX data here>>>>
--Certificate_File_Upload--

Tidying that up for readability the decoded XML in the URL is:
<Request>
  <Login>
    <Username>admin</Username>
    <Password>MyPassword</Password>
  </Login>
  <Set operation="add">
    <Certificate>
      <Action>UploadCertificate</Action>
      <Name>Test</Name>
      <Password>PfxPassword</Password>
      <CertificateFormat>pkcs12</CertificateFormat>
      <CertificateFile>test.pfx</CertificateFile>
      <PrivateKeyFile></PrivateKeyFile>
    </Certificate>
  </Set>
</Request>
 
The response I get from the API is: <Status code="510">Operation failed. Deleting entity referred by another entity.</Status>
Going by the documentation this means "Certificate could not be uploaded due to invalid private key or passphrase. Choose a proper key".
 
I've also tried a version with the certificate and key in PEM format rather than PFX and get: <Status code="500">Operation could not be performed on Entity.</Status>
Going by the documentation this means "Certificate could not be updated".
 
I tried a multipart/form-data request initially, but the API didn't provide any feedback - I got an HTTP 200 response, but no XML in the body. The multipart/mixed version at least responds with some XML so I'm assuming that's what it wants.
 
I'm assuming there's something wrong with the way I'm uploading the PFX file - perhaps I've misunderstood what the multipart request should look like? I couldn't find an example in the docs. The encoded PFX file data looks correct though, because it appears to be the same in Fiddler when I upload the PFX via the web UI (successfully). I was hoping one of you might have tried this and could point me in the right direction, please?
 
Thanks,
Andrew


This thread was automatically locked due to age.
  • curl -k  -F "reqxml=<uploadTest.txt" -F file=@Certificates.p12 "https://<DNS or IP here>:4444/webconsole/APIController?"

    What mattered was using the @ and not < for the "file=" section.

    From the Curl man page:
    The difference between @ and < is then that @ makes a file get attached in the post as a  file  upload, while  the  <  makes  a text field and just get the contents for that text field from a file.

     

    The rest of this post is for those still learning/trying to figure things out:

    ---Contents of the file called uploadTest.txt---
    <Request>
      <Login>
        <Username>username</Username>
        <Password>password</Password>
      </Login>

      <Set operation="add">
        <Certificate>
          <Action>UploadCertificate</Action>
          <Name>friendly name for us humans goes here</Name>
          <Password>password to decrypt the certificate file</Password>
          <CertificateFormat>pkcs12</CertificateFormat>
          <CertificateFile>Certificates.p12</CertificateFile>
          <PrivateKeyFile></PrivateKeyFile>
        </Certificate>
      </Set>
    </Request>
    ---End content of file uploadTest.txt---

    **In the example above, Certificates.p12 is a placeholder for the filename of your certificate, and if you don't have a separate private key file you can omit the PrivateKeyFile line.

    I created a .p12 file for my certificate and private key simply because it was less to type in the file above and command line when testing. Valid formats are listed in the API documentation

  • Most likely, if you have trouble in uploading the certificate (any file to XG via API), use a Test page and check, what you "actually" upload to the server / xg.

    http://ptsv2.com/s/howitworks.html

    Most likely your file is not proper uploaded / wrong format etc. 

    So you should verify, what you are uploading because XG has no proper storage of the file, if the request was invalid. It will simply flush the upload after parsing the command. 

    __________________________________________________________________________________________________________________

  • Thanks everyone who contributed to this thread. It has been valuable to me figuring out how to upload the Let's Encrypt certificates from my Synology NAS to Sophos XG. Here's how it is done.

    Enable API (optionally create a special API Administration user) as described here: https://community.sophos.com/kb/en-us/132560

    On your Synology NASfollow the instructions for Let's Encrypt here and include your firewall's fqdn as a subject alternative name: https://www.synology.com/en-global/knowledgebase/DSM/help/DSM/AdminCenter/connection_certificate

    Then create this XML file, e.g. in your home directory:

    <?xml version="1.0" encoding="UTF-8"?>
    <Request APIVersion="1702.1">

    <!-- API Authentication -->
    <Login>
    <Username>apiuser</Username>
    <Password>randompw</Password>
    </Login>

    <Set operation="add">
            <Certificate>
                    <Action>UploadCertificate</Action>
                    <Name>yourdomain</Name>
                    <CertificateFormat>pem</CertificateFormat>
                    <CertificateFile>yourdomain.pem</CertificateFile>
                    <PrivateKeyFile>yourdomain.key</PrivateKeyFile>
            </Certificate>
    </Set>
    </Request>

    Under Control Panel, Task Scheduler, create the following User-defined script as Scheduled Task, that runs as User root.

    /bin/curl -F "reqxml=</var/services/homes/youruser/updatecertificate.xml"  -F "file=@/usr/syno/etc/certificate/system/default/cert.pem;filename=yourdomain.pem" -F "file=@/usr/syno/etc/certificate/system/default/privkey.pem;filename=yourdomain.key" -k https://yourfirewall:4443/webconsole/APIController

    Click "Run" to test and run it once. You should now have your Synology certificate and private key under SYSTEM, Certificates. If that worked, then make the following change in the the XML file: <Set operation="update">

    That should be it. From now on your firewall should be certified by Let's Encrypt and updated timely with renewed certificates. I run the task weekly on Sunday morning.

    Cheers!

  • I have finally got this setup. The add worked properly but when the update executes every Sunday I get this output

    <?xml version="1.0" encoding="UTF-8"?>
    <Response APIVersion="1702.1" IPS_CAT_VER="1">
    <Login>
    <status>Authentication Successful</status>
    </Login>
    <Certificate transactionid="">
    <Status code="500">Operation could not be performed on Entity.</Status>
    </Certificate>
    </Response>



    Any ideas on what I am doing wrong. I have confirmed that I have changed the operation from add to update.

  • So basically you can add with your script a Certificate, but you cannot update it? 

    As far as i know, you cannot "overwrite" the used Certificate. Because it is loaded in different places by XG. 

    What you have to do, would be reupload the certificate with different namens and change those uses in each place, you like. 

    __________________________________________________________________________________________________________________

  • The 'Set operation="update"' works fine for me. This is the output that I see at the weekly update:

    <?xml version="1.0" encoding="UTF-8"?>
    <Response APIVersion="1702.1" IPS_CAT_VER="1">
      <Login>
        <status>Authentication Successful</status>
      </Login>
      <Certificate transactionid="">
        <Status code="200">Configuration applied successfully.</Status>
      </Certificate>
    </Response>
  • But is the certificate in use with anything? Mine is configured to be used with the portal (admin/user) as well as e-mail.  Are you doing anything manually on Sunday's?  Just want to make sure I am not missing anything.

  • Yes, it's in use and selected in SYSTEM, Administration, Admin settings. Not performing any manual action, this just works as described.

    Maybe you can find out more by checking the log files?

  • Ok, found the issue. It appears to have been a permissions issue. All fixed and running properly

  • Can you elaborate on the permission issue? I'm having the same problem