acmesh-official / acme.sh

A pure Unix shell script implementing ACME client protocol
https://acme.sh
GNU General Public License v3.0
38.79k stars 4.92k forks source link

Report bugs to unifi deploy hook #3359

Closed medmunds closed 2 weeks ago

medmunds commented 3 years ago

This is the place to report bugs in the unifi deploy hook.

If you experience a bug with --deploy-hook unifi, please report it in this issue. (Please include the --debug output to assist in diagnosing any problems.)

Thanks!

blackjack4494 commented 3 years ago

just curious tho this might not be related purely to the unifi deploy hook (first time using acmesh, used certbot before) but i couldn't find something on that matter: does the cronjob that comes with acme is also deploying the certs?
I wrote a brief 'how-to' gist on how to freshly install, issue and deploy a cert on a unifi controller. And the answer to my question would be nice to know.
Thanks in advance (:

medmunds commented 3 years ago

@blackjack4494 yes, acme.sh saves your deploy-hook settings, and re-deploys with those same settings after a successful cron certificate renewal. (This applies to all deploy hooks, not just unifi.)

SupersixEvo commented 2 years ago

I'm just replacing an Ubuntu 16.04 VM running Unifi with a new VM running 22.04.

When trying to use the unifi hook (which worked great on 16.04), I get

[Fri 22 Jul 22:49:28 UTC 2022] Installing certificate for Unifi Controller (Java keystore)
[Fri 22 Jul 22:49:28 UTC 2022] _unifi_keystore='/usr/lib/unifi/data/keystore'
[Fri 22 Jul 22:49:28 UTC 2022] Generate import pkcs12
[Fri 22 Jul 22:49:28 UTC 2022] Import into keystore: /usr/lib/unifi/data/keystore
Importing keystore /tmp/tmp.UHja0HRWf4 to /usr/lib/unifi/data/keystore...
keytool error: java.io.IOException: keystore password was incorrect
[Fri 22 Jul 22:49:29 UTC 2022] Error importing into Unifi Java keystore.
[Fri 22 Jul 22:49:29 UTC 2022] Please re-run with --debug and report a bug.
[Fri 22 Jul 22:49:29 UTC 2022] Error deploy for domain:unifi.xxx.me.uk
[Fri 22 Jul 22:49:29 UTC 2022] Deploy error.

I can run

keytool -list -v -keystore /usr/lib/unifi/data/keystore

and see 1 existing certificate in the keystore (either providing no password or the default one in the script).

I wonder if this relates to it as it mentions Ubuntu Jammy (which is v22) but I'm unsure if I can add the -legacy parameter in the script and if, so where.

SupersixEvo commented 2 years ago

I realised the topkcs routine called in unifi.sh lives in the main acme.sh file, so I added -legacy to the first call in that (line 1427 on my system). That line now reads:

${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname" -legacy

And the import now works.

medmunds commented 2 years ago

@SupersixEvo thanks for tracking this down.

@Neilpang this affects _toPkcs in the main acme.sh. When openssl is v3 or later, the unifi deploy script needs _toPkcs to invoke openssl with the -legacy parameter. What would be the best way to do that?

Neilpang commented 2 years ago

@medmunds add one more parameter to the _toPKcs() function, eg: usLegacy (or whatever), default is empty.

in the deploy hook, invoke it with value 1.

Neilpang commented 2 years ago

also, you should check if current openssl supports "-legacy" option first.

cengbrecht commented 2 years ago

${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname" -legacy

Can confirm that this works, though my openssl does not accept -legacy directly?

robinalden commented 1 year ago

I had a problem with a CloudKey G2+. The deploy script seemed to think it was a Gen1, so deployment failed.

acme.sh --deploy -d unifi.MYDOMAIN.me --deploy-hook unifi --debug
[Mon Jan 30 12:35:20 GMT 2023] Lets find script dir.
[Mon Jan 30 12:35:20 GMT 2023] _SCRIPT_='/root/.acme.sh/acme.sh'
[Mon Jan 30 12:35:20 GMT 2023] _script='/root/.acme.sh/acme.sh'
[Mon Jan 30 12:35:20 GMT 2023] _script_home='/root/.acme.sh'
[Mon Jan 30 12:35:20 GMT 2023] Using config home:/root/.acme.sh
https://github.com/acmesh-official/acme.sh
v3.0.6
[Mon Jan 30 12:35:20 GMT 2023] Running cmd: deploy
[Mon Jan 30 12:35:20 GMT 2023] Using config home:/root/.acme.sh
[Mon Jan 30 12:35:20 GMT 2023] default_acme_server
[Mon Jan 30 12:35:20 GMT 2023] ACME_DIRECTORY='https://acme.zerossl.com/v2/DV90'
[Mon Jan 30 12:35:21 GMT 2023] DOMAIN_PATH='/root/.acme.sh/unifi.MYDOMAIN.me'
[Mon Jan 30 12:35:21 GMT 2023] _deployApi='/root/.acme.sh/deploy/unifi.sh'
[Mon Jan 30 12:35:21 GMT 2023] _cdomain='unifi.MYDOMAIN.me'
[Mon Jan 30 12:35:21 GMT 2023] _ckey='/root/.acme.sh/unifi.MYDOMAIN.me/unifi.MYDOMAIN.me.key'
[Mon Jan 30 12:35:21 GMT 2023] _ccert='/root/.acme.sh/unifi.MYDOMAIN.me/unifi.MYDOMAIN.me.cer'
[Mon Jan 30 12:35:21 GMT 2023] _cca='/root/.acme.sh/unifi.MYDOMAIN.me/ca.cer'
[Mon Jan 30 12:35:21 GMT 2023] _cfullchain='/root/.acme.sh/unifi.MYDOMAIN.me/fullchain.cer'
[Mon Jan 30 12:35:21 GMT 2023] Installing certificate for Unifi Controller (Java keystore)
[Mon Jan 30 12:35:21 GMT 2023] _unifi_keystore='/usr/lib/unifi/data/keystore'
[Mon Jan 30 12:35:21 GMT 2023] Generate import pkcs12
[Mon Jan 30 12:35:21 GMT 2023] Import into keystore: /usr/lib/unifi/data/keystore
Importing keystore /tmp/tmp.zJAEBB7Qp6 to /usr/lib/unifi/data/keystore...
Warning: Overwriting existing alias unifi in destination keystore
[Mon Jan 30 12:35:24 GMT 2023] Import keystore success!
[Mon Jan 30 12:35:24 GMT 2023] Install Unifi Controller certificate success!
[Mon Jan 30 12:35:24 GMT 2023] Installing certificate for Cloud Key Gen1 (nginx admin pages)
[Mon Jan 30 12:35:24 GMT 2023] _cloudkey_certdir='/etc/ssl/private'
[Mon Jan 30 12:35:24 GMT 2023] Unsupported Cloud Key configuration: keystore not found at '/etc/ssl/private/unifi.keystore.jks'
[Mon Jan 30 12:35:24 GMT 2023] Error deploy for domain:unifi.MYDOMAIN.me
[Mon Jan 30 12:35:24 GMT 2023] Deploy error.

The script was looking for /etc/ssl/private/cloudkey.key to identify it as a G1, and that file did exist but was > 2 years old. I wonder if it used to use nginx before it upgraded itself to use Unifi OS. I moved the whole /etc/ssl/private directory with mv /etc/ssl/private/ /etc/ssl/private-renamed

and then the deploy ran fine.

...
[Mon Jan 30 12:51:05 GMT 2023] Installing certificate for UnifiOS
[Mon Jan 30 12:51:05 GMT 2023] _unifi_core_config='/data/unifi-core/config'
[Mon Jan 30 12:51:05 GMT 2023] Install UnifiOS certificate success!
[Mon Jan 30 12:51:05 GMT 2023] Reload services (this may take some time): service unifi restart && systemctl restart unifi-core
[Mon Jan 30 12:52:46 GMT 2023] Reload success!
[Mon Jan 30 12:52:46 GMT 2023] Success
robhardman commented 1 year ago

https://github.com/acmesh-official/acme.sh/issues/3359#issuecomment-1408696009

Just to add a +1 to robinalden's comment above. My CloudKey2 was upgraded from UnifiOS 1 --> 2.x --> 3.x and I had exactly the same issue with the deploy hook until I renamed /etc/ssl/private. Perhaps there is a better way to detect the OS version?

bhannigan commented 1 year ago

from unifi-utilities

case "$(ubnt-device-info firmware || true)" in 1*)

version 1

;;

2*)

version 2

;;

3*)

version 3

;;

*)

version not handled

exit 1
;;

esac

kdknigga commented 1 year ago

Not strictly a deploy issue, but ECC certs borked unifi-core on my CloudKey Gen2 Plus running firmware v3.1.13. Blew away the ECC certs, reissued RSA certs, and redeployed to fix.

derekschrock commented 11 months ago

There should be a status check var. You're assuming we're (FreeBSD) using systemd. The same for the other systectl usage.

tapayne88 commented 10 months ago

I found I had trouble deploying my certs on my UDR running Unifi OS (3.1.16).

It seems I'd fall foul of this line as for some reason I had a keystore file at /usr/lib/unifi/data/keystore. This resulted in the deploy script erroring with keytool not found.

root@UDR:~# acme.sh --deploy --domain unifi.mydomain.com --deploy-hook unifi
[Fri Nov 17 13:51:46 GMT 2023] Installing certificate for Unifi Controller (Java keystore)
[Fri Nov 17 13:51:46 GMT 2023] keytool not found
[Fri Nov 17 13:51:46 GMT 2023] Error deploy for domain:unifi.mydomain.com
[Fri Nov 17 13:51:46 GMT 2023] Deploy error.

From a bit of searching around it seems that the guest hotspot portal (which I have enabled) may use the keystore file to manage its certs rather than the Unifi OS standard in /data/unifi-core/config (source).

I ended up hacking the deploy hook to avoid running the _unifi_keystore block and found it to complete successfully. The caveat being I wasn't able to enable SSL for the guest hotspot portal, only the admin interface.

rtfmoz2 commented 8 months ago

Trying this on a Unifi Express ... wish me luck! == will delete this comment if no issues

No keytool (line 103) on Unifi Express. Wonder what they use? Asked in the community over there, see if I get a response. https://community.ui.com/questions/Keytool-alternative-on-UniFi-Express/5154559a-b064-4f41-a183-a106b9e690dc

rtfmoz2 commented 7 months ago

We need a check for keytool and if it does not exist use openssl.

3VAbdAVE commented 5 months ago

We need a check for keytool and if it does not exist use openssl.

Running a Unifi Dream Machine with the same poblem. I'm not sure openssl can create a Java keystore. You'll notice that the java binaries are also removed.

I got my response from Ubiquiti support yesterday, told me SSL isn't their problem.

Hacky fix is just to reinstall keytool: apt update && apt install openjdk-11-jre-headless -y puts it in place with a few other packages that seem harmless enough. YMMV with support on that, and likely need to re-run after an update. openjdk-17 is newer, but loads a lot more packages.

There's also a minor problem with the UDM running hotspot portal. I need to redeploy a few times to see what's going on, but I think the keystore shouldn't have the CA as well. Error in the log is that "2 certificates were found, only 1 expected." Manually creating the keystore fixes it.

3VAbdAVE commented 5 months ago

Once the keytool problem is sorted and the certificates correctly converted to a JKS keystore, the next problem is that the default Unifi console uses weak ciphers that aren't compatible with the default RSA certificates from letsencrypt. The system configuration needs to be updated for hotspot portal (and potentially other services to work.)

mcdoogs commented 4 months ago

I recently updated my CloudKey G2 to Firmware version: v3.2.12. The update wiped the existing certs, and I ran into other problems (which turned out to be with my DNS provider, not acme.sh) that prompted me to update acme.sh to v3.0.8.

After getting the certs issued and running this hook, I could see /data/unifi-core/config/unifi-core.key and unifi-core.crt update at first, but when the unifi service restarted, both files were replaced with self-signed RSA certs. I noticed that the certs getting wiped out were ECC, which seemed new with this version of acme.sh. After fiddling with some different options, issuing with -k 4096 got the certs to persist through a unifi restart.

rtfmoz2 commented 4 months ago

We need a check for keytool and if it does not exist use openssl.

Running a Unifi Dream Machine with the same poblem. I'm not sure openssl can create a Java keystore. You'll notice that the java binaries are also removed.

I got my response from Ubiquiti support yesterday, told me SSL isn't their problem.

Hacky fix is just to reinstall keytool: apt update && apt install openjdk-11-jre-headless -y puts it in place with a few other packages that seem harmless enough. YMMV with support on that, and likely need to re-run after an update. openjdk-17 is newer, but loads a lot more packages.

There's also a minor problem with the UDM running hotspot portal. I need to redeploy a few times to see what's going on, but I think the keystore shouldn't have the CA as well. Error in the log is that "2 certificates were found, only 1 expected." Manually creating the keystore fixes it.

Openssl can create a java compatible keystore. If fact you should be using it instead of keytool these days for acme.sh. The instructions are here https://docs.oracle.com/cd/E19509-01/820-3503/ggfhb/index.html

Modern java implementations are moving away from the old proprietry keystore format to the new pkcs12 format which is the type openssl can create. Example below. The alias should be the same as the one it uses now for the current certificate and key in the keystore. You cannot use this to update a keystore, only create it. Please note a password is mandatory for it to be a java compatible keystore.

$ cat mykey.pem.txt mycertificate.pem.txt>mykeycertificate.pem.txt
$ openssl pkcs12 -export -in mykeycertificate.pem.txt -out mykeystore.pkcs12 
-name myAlias -noiter -nomaciter
3VAbdAVE commented 4 months ago

Openssl can create a java compatible keystore. If fact you should be using it instead of keytool these days for acme.sh. The instructions are here https://docs.oracle.com/cd/E19509-01/820-3503/ggfhb/index.html

It looks like you're correct. Every implementation of this Unifi certificate installation was converting to PKCS12 and then importing that to JKS. All the historical documents I could find from Unifi have that as the process as well. I just re-deployed, skipping the JKS import, and it handles the pkcs12 just fine.

rtfmoz2 commented 4 months ago

Fantastic! Does that mean we have solved the problem? That would be a great outcome! Can you send me links to the historical documents? I am itching to use this on my UX. Happy to drop in a patched unifi deploy hook to test for here then I can write it up. You guys have a wiki or a pages site for this place?

3VAbdAVE commented 4 months ago

Potentially. Tested on a UDM (not the UDM Pro), and don't have any other devices to test with.

Welcome to take a look at my updates: https://github.com/3VAbdAVE/acme.sh/blob/dev/deploy/unifi.sh

Here's where I am with it: In addition to falling back to openssl, it now backs up existing cert/key/keystores, and makes a change to system.properties to support the correct cipher suites. This backup is not smart: If you don't move those backups, they'll get overwritten on next deploy.

I also had to change the logic for service restart. If unifi is running while unifi-core restarts, it throws an error: ERROR system - Unable to read certificate from the unifi chain. There are 2 certificates, but exactly 1 is expected

This seems to break both wifiman and the hotspot portal, but I don't use wifiman. The hotspot portal now works, but you have to turn encryption off and back on after deploying a new cert for some reason. That's not a new bug though.

medmunds commented 2 months ago

Hey all: I no longer own a working CloudKey, so can't really provide support for the unifi deploy hook. (Also, I didn't create it—I just fixed a bug and opened this issue.)

If something's broken and you're able to fix it, please open a PR. And mention #3359 in your PR comments so it shows up here. Neilpang (the acme.sh creator/maintainer) has been really responsive about merging fixes while maintaining high project quality. (Especially considering the huge number of PRs this project gets.) But Neil also doesn't run Unifi, so the folks here that are using it will need to make sure proposed fixes work for all the versions of CloudKey and self-hosted Unifi Controller the unifi deploy hook supports.

If anyone is able to help with unifi deploy hook maintenance and wants to be on the "assignees" list for this issue, let Neilpang know. (I've removed myself as the assignee.)

Also, if the unifi deploy hook doesn't meet your needs, there are a couple of alternatives depending on your setup:

petrus9 commented 2 months ago

Found a patch to unifi.sh tested on UnifiOS 4.0.7 on Cloud Gateway Ultra. Here it is. https://gist.github.com/mry/61125fba7b474c0c61cccc4100dd6e02 but this fix only works for the admin console and not the guest captive portal at domain.tld:8843/guest/s/default/# Anyone have a fix for that?

petrus9 commented 2 months ago

@3VAbdAVE

Potentially. Tested on a UDM (not the UDM Pro), and don't have any other devices to test with.

Welcome to take a look at my updates: https://github.com/3VAbdAVE/acme.sh/blob/dev/deploy/unifi.sh

Here's where I am with it: In addition to falling back to openssl, it now backs up existing cert/key/keystores, and makes a change to system.properties to support the correct cipher suites. This backup is not smart: If you don't move those backups, they'll get overwritten on next deploy.

I also had to change the logic for service restart. If unifi is running while unifi-core restarts, it throws an error: ERROR system - Unable to read certificate from the unifi chain. There are 2 certificates, but exactly 1 is expected

This seems to break both wifiman and the hotspot portal, but I don't use wifiman. The hotspot portal now works, but you have to turn encryption off and back on after deploying a new cert for some reason. That's not a new bug though.

Whats required to get your revisions commited? I could potentially test it on a CKG2+ and a Cloud Gateway Ultra.

charlestephen commented 2 months ago

@petrus9 If you combine the patch you've linked with this proposed change from @3VAbdAVE , it will work for UnifiOS 4.0.6 on the Cloud Gateway Ultra (I have a CGU and just implemented it using this exact method).

3VAbdAVE commented 2 months ago

@petrus9 If you combine the patch you've linked with this proposed change from @3VAbdAVE , it will work for UnifiOS 4.0.6 on the Cloud Gateway Ultra (I have a CGU and just implemented it using this exact method).

It looks like the Unifi has yet another new keystore to manage. @petrus9 's linked patch removes compatibility with other/older devices. I'll get back on this in the next few days.

Edit: The new unifi-core-direct.crt file which @petrus9 's link modifies appears to be a LE signed certificate for a cn ".id.ui.direct" Changing this seems like a bad idea, since I don't know what Ubiquiti is using it for. This patch does specifically fix the keytool not found error to allow the web interface certificate to work, but it also breaks a lot of other things, such as the captive portal and probably CloudKey compatibility.

3VAbdAVE commented 2 months ago

I'm away from my network for another week and I'm not going to test this over VPN in case it breaks VPN. But if you want to test before then, I've pushed my latest to my dev branch. Note, I did not integrate the above patch for reasons in my above post. I'll do a PR and finally get it merged once I'm able to test myself.

https://github.com/3VAbdAVE/acme.sh/blob/dev/deploy/unifi.sh

charlestephen commented 1 month ago

@3VAbdAVE I recently redeployed my Cloud Gateway Ultra and tried your fix: it seems to work without breaking any of the aforementioned endpoints. Huzzah!

charlestephen commented 1 month ago

@3VAbdAVE I noticed that this doesn't configure the RADIUS server certificates. Is it supposed to?

charlestephen commented 1 month ago

@3VAbdAVE I noticed that this doesn't configure the RADIUS server certificates. Is it supposed to?

I figured out how to replace the RADIUS cert myself. I'll do a pull request with that once I get caught up on some things.

3VAbdAVE commented 1 month ago

@3VAbdAVE I noticed that this doesn't configure the RADIUS server certificates. Is it supposed to?

No, I don't use that feature. Quick search looks like it's just another copy to /etc/freeradius? I'd advise symlinking it so you don't end up with copies of the PK all over the filesystem.

Good to hear it's working though. I'll be able to test myself on Monday, and can pull request after that.

3VAbdAVE commented 1 month ago

Ok, well my pull request got rejected twice because of shellfmt, which works fine on my end. If someone wants to look at it and let me know what I'm missing, plz have at it.

Dadeos commented 1 week ago

I've encountered a couple of minor issues whilst attempting to use the deploy/unifi.sh script with a self-hosted controller…

https://github.com/acmesh-official/acme.sh/blob/fc7f86104ee509cae2cd6a64553f46d78b535ad5/deploy/unifi.sh#L144-L150

makes assumptions regarding the location of the "system.properties" file (i.e. that it will be located at "/usr/lib/unifi/data/system.properties"), this is not the case for my deployment; mine happens to be located at "/usr/local/unifi/data/system.properties". It's probably reasonable to assume that the "system.properties" configuration is in the same directory as the "keystore" , in which case "${DEPLOY_UNIFI_KEYSTORE%/*}/system.properties" would be a reasonable substitution for occurrences of /usr/lib/unifi/data/system.properties.

Also, my system doesn't use systemd, so the unguarded use of systemctl results in an error:

https://github.com/acmesh-official/acme.sh/blob/fc7f86104ee509cae2cd6a64553f46d78b535ad5/deploy/unifi.sh#L159

Something like [ -x systemctl ] && systemctl … avoids the error, but it feels like dealing, or not, with "unifi-core" should be better detected; like it is further down the script:

https://github.com/acmesh-official/acme.sh/blob/fc7f86104ee509cae2cd6a64553f46d78b535ad5/deploy/unifi.sh#L205-L207

3VAbdAVE commented 1 week ago

I've encountered a couple of minor issues whilst attempting to use the deploy/unifi.sh script with a self-hosted controller… ...

Good points, mostly artifacts of only having my own udm to test with. I can tinker with making things more dynamic in the next few days, but someone else will need to test.

3VAbdAVE commented 1 week ago

Kinda punted on this, moved @Dadeos concerns into DEPLOY environment variables. I did remove the explicit calls to systemctl. Probably safe to assume the service is running if the files/directories exist.

I just don't have any way to test it outside my UDM.

joshuaspence commented 6 days ago

On UnifiOS 4.0.18 with a CloudKey Gen 2 tghe Unifi deploy hook fasils with the following error:

[Sat Sep 28 13:56:25 AEST 2024] Install Unifi Controller certificate success!
[Sat Sep 28 13:56:25 AEST 2024] Installing certificate for Cloud Key Gen1 (nginx admin pages)
[Sat Sep 28 13:56:25 AEST 2024] Unsupported Cloud Key configuration: keystore not found at '/etc/ssl/private/unifi.keystore.jks'
[Sat Sep 28 13:56:25 AEST 2024] Error deploying for domain: REDACTED
[Sat Sep 28 13:56:25 AEST 2024] Error encountered while deploying.

Commenting out https://github.com/acmesh-official/acme.sh/blob/master/deploy/unifi.sh#L186-L189 and run acme.sh did deploy the certificate correctly.

$ acme.sh --deploy --domain REDACTED --deploy-hook unifi
[Sat Sep 28 14:19:46 AEST 2024] Installing certificate for Unifi Controller (Java keystore)
[Sat Sep 28 14:19:46 AEST 2024] Previous keystore saved to /usr/lib/unifi/data/keystore_original.
Importing keystore /tmp/tmp.Wn9J9f7eBr to /usr/lib/unifi/data/keystore...
[Sat Sep 28 14:19:48 AEST 2024] Updating system configuration for cipher compatibility.
[Sat Sep 28 14:19:48 AEST 2024] Saved original system config to /usr/lib/unifi/data/system.properties_original
[Sat Sep 28 14:19:48 AEST 2024] System configuration updated.
[Sat Sep 28 14:19:48 AEST 2024] Install Unifi Controller certificate success!
[Sat Sep 28 14:19:48 AEST 2024] Installing certificate for Cloud Key Gen1 (nginx admin pages)
[Sat Sep 28 14:19:48 AEST 2024] Install Cloud Key Gen1 certificate success!
[Sat Sep 28 14:19:48 AEST 2024] Installing certificate for UnifiOS
[Sat Sep 28 14:19:49 AEST 2024] Previous certificate and key saved to /data/unifi-core/config/unifi-core_original.crt/key.
[Sat Sep 28 14:19:49 AEST 2024] Install UnifiOS certificate success!
[Sat Sep 28 14:19:49 AEST 2024] Reload services (this may take some time): systemctl stop unifi && service nginx restart && systemctl restart unifi-core
[Sat Sep 28 14:20:03 AEST 2024] Reload success!
[Sat Sep 28 14:20:03 AEST 2024] Success