diff --git a/hawkbit-https.md b/hawkbit-https.md index 9608d68..f476d1c 100644 --- a/hawkbit-https.md +++ b/hawkbit-https.md @@ -1,131 +1,127 @@ # Deploying HTTPS on Hawkbit -In this document, we will see how to deploy https on Hawkbit and how to configure it on your -targets with FullMetalUpdate. +In this document, we will see how to set up HTTPS transactions on Hawkbit and how to configure it on your +targets. The final goal of this process is to make your OTA updates secure. ## Setting up the server ### Getting a certificate Like every other HTTPS service, Hawkbit requires a signed certificate from a Certificate -Authority to comply with SSL protocols. We will not through how to get one, as there -plenty of resources already available on them. Hawkbit also requires the private key -linked to the certificate. +Authority to comply with SSL protocols. -**Warning:** this setup will not work with self-signed certificates. Please reach out to -us [on gitter][gitter] if you need to configure self-signed certificates. +The following lines will allow you to get a self signed certificate **suitable for test environments only**. -### Modifying the docker-compose +``` +sudo apt-get update && sudo apt-get upgrade +sudo apt-get install openssh +openssl req -x509 -newkey rsa:4096 -keyout privateKey.pem -out certificate.crt -days 3650 -nodes +openssl pkcs12 -export -out keyStore.p12 -inkey privateKey.pem -in certificate.crt +``` +You will need a passphrase for `privateKey.pem`, which we will denote as #key-passphrase, as well as an export password for the `keyStore.p12`, which we will denote as #p12-password. -Go to the cloud directory (`fullmetalupdate-cloud-demo`) and edit `docker-composer.yml`. -Go the `hawkbit:`, and change all the `8080` to `8443` in the `expose` and `ports` -subsections. +**Warning:** Password of `keyStore.p12` (ie, #p12-password) must be at least 6 characters long and contains letters AND numbers. -Exit, and restart the server using `./StopServer.sh` and `./StartServer.sh`. The server is -not yet configured for https. +You will then obtain a certificate `certificate.crt` (the public key is included into this certificate), a private key `privateKey.pem` and a pkcs12 binary `keyStore.p12`. This last one is a special kind of file storing cryptographic objects, in our case your certificate as well as your private key. -### Getting the server's CONTAINER ID +**Warning:** This setup will not work for production environments. Please reach out to +us [on gitter][gitter] if you need to configure proper certificates. -Before setting HTTPS up, you need to take note of the Hawkbit's server container id. You -must have run `./StartServer.sh` from the `fullmetalupdate-cloud-demo` directory. +**Coming soon:** Proper certificate generation with Let's Encrypt and certbot python tool. -Run this command: -``` -docker ps -a -``` +### Modifying the docker-compose -And take note of the `fullmetalupdate/hawkbit`'s CONTAINER ID. We will denote it as -`` in this document. +Go to the cloud directory (`fullmetalupdate-cloud-demo`) and do : -### Setting up the certificates for Hawkbit +`git checkout add-https` -Hawkbit requires a single certificate file generated from the `pem` and the `key` files, -assuming that the `pem` file is the certificate, and the `key` file is the private key -linked to it. +This branch holds everything you need to set up Hawkbit to work with HTTPS. We will come back to this repo later. -First, create a [`p12` file][wiki_p12] from the last two file: +### Converting the `p12` file into a `jks` file -``` -openssl pkcs12 -export -out cert.p12 -in CA.pem -inkey CA.key -``` +`keytool`is a tool used to manage Java KeyStore (JKS) files. +JavaKeyStore objects are used by Hawkbit (note that Hawkbit client is written in Java) to manage certificates. We have to use it because Hawkbit does not seem to be able to deal with pkcs12 files. -`CA.pem` and `CA.key` are the certificate and the private key. Enter the private key's -passphrase, which we will denote as `` in this document, and type in the -export password, which we will denote as ``. **Warning**: this password must -be at least 6 character long, and contain letters and numbers. +Go in a the directoy where you generated `privateKey.pem`, `certificate.crt` and `keyStore.p12`. -This will create a `cert.p12` file. Copy this file to the currently running container : +You can now generate the jks file : ``` -docker cp cert.p12 :/opt/hawkbit/ +sudo apt-get install keytool +keytool -importkeystore -srckeystore keyStore.p12 -srcstoretype pkcs12 \ + -destkeystore keyStore.jks -deststoretype pkcs12 \ + -alias 1 -deststorepass #p12-password ``` -### Converting the `p12` file into a `jks` file +First, enter the destination keystore password : **this must be the same as #p12-password**. Then, enter the source keystore password : #p12-password. -The Hawkbit container embeds `keytool`, the tool used to manage the Java KeyStore (JKS). -This is what is used by Hawkbit to manage certificates. +You finally get a JKS file as `keyStore.jks`, which you can use to configure Hawkbit. -Run a shell in the container by executing: +### Building new docker image fullmetalupdate/build-yocto:v2.0 -``` -docker exec -it /bin/sh -``` +#### Configuring Hawkbit's options for SSL/TLS -Execute `ls`: you should see the `cert.p12` file generated above. Execute the following -command to convert the `p12` file into a `jks` file: - -``` -keytool -importkeystore -srckeystore cert.p12 -srcstoretype pkcs12 \ - -destkeystore cert.jks -deststoretype pkcs12 \ - -alias 1 -``` +Go to your FullMetalupdate local repo `dockerfiles` (or clone it on our Github) and configure `hawkbit/application.properties` file with the appropriate parameters. -First, enter the destination keystore password : **this must be the same as -``**. +**1st solution : Use config.sh script** -Then, enter the source keystore password : ``. +Move your JavaKeyStore file to the `hawkbit` directory. -You can now exit the container by executing `exit`. +`mv /home/user/path/to/keyStore.jks hawkbit/` -### Setting up Hawkbit's options for SSL/TLS +Run `config.sh` script and give #p12-password when it is required. -Create an `application.properties` file which contains these parameters : +**2nd solution : By hand** ``` -# UI demo account +1) UI demo account hawkbit.server.ui.demo.password=admin hawkbit.server.ui.demo.user=admin hawkbit.server.ui.demo.tenant=DEFAULT -# User Security +2) User Security security.user.name=admin security.user.password=admin -# SSL/TLS Configuration +3) SSL/TLS Configuration server.port=8443 hawkbit.artifact.url.protocols.download-http.protocol=https hawkbit.artifact.url.protocols.download-http.port=8443 security.require-ssl=true server.use-forward-headers=true -server.ssl.key-store=/opt/hawkbit/cert.jks -server.ssl.key-password= -server.ssl.key-store-password= +server.ssl.key-store=/opt/hawkbit/keyStore.jks +server.ssl.key-password=#p12-password +server.ssl.key-store-password=#p12-password ``` +Don't forget to replace #p12-password accordingly. -Replace `` accordingly. - -Copy this file the currently running container : +#### Setting up the build +You will need to generate a new docker image based on a Dockerfile specially written to set up HTTPS on Hawkbit. This step can take up to 1 hour depending on your computer. ``` -docker cp application.properties :/opt/hawkbit/ +git clone https://github.com/FullMetalUpdate/dockerfiles.git +git checkout add-https +docker build -t "fullmetalupdate/hawkbit:v2.0" hawkbit/Dockerfile ``` -This will replace the existing `application.properties`. If you already configured it -please `sh` into the container and append the previous content instead. +**Note:** When the container is running, you can access it by running `docker exec -it fullmetalupdate-cloud-demo_hawkbit_1 sh`. This will give you the hand on the container by opening a bourne shell inside the container. + +At this point, the Hawkbit server is ready to be started. + +Go to the cloud directory (`fullmetalupdate-cloud-demo`) and do : + +`./StartServer` + +Eventually if it is the first time you configure your target, you can lauch : + +`./ConfigureServer` + +Finally : + +`firefox https://localhost:8443 &` -The server is all set up! One last step: stop the server (`./StopServer`) and start it -again (`./StartServer`). You can now connect to `https://.local:8443`. +This last command will open the Hawkbit Web Client, working well in HTTPS! But your embedded target is not ready yet to support HTTPS OTA updates. ## Setting up the targets @@ -136,24 +132,53 @@ Before proceeding further, **close any instanciation of the build-yocto docker** 1. Go to your Yocto directory (`fullmetalupdate-yocto-demo`) - 1. Edit the `config.cfg.sample` and make the following changes : + 2. Edit the `config.cfg` file and make the following changes : * change `hawkbit_url_port` to `8443` * change `hawkbit_ssl` to `true` - 1. Exit, and execute `bash ConfigureBuild.sh` + 3. Move your certificate (after renaiming it) into Yocto build container : - 1. Execute `./Startbuild.sh fullmetalupdate-os`. It should build the fullmetalupdate +``` +mv /path/to/certificate.crt /path/to/ca-certificates.crt +docker cp /path/to/ca-certificates.crt \ + fullmetalupdate/hawkbit:v2.0:/data/yocto/build/tmp/fullmetalupdate-os/work/x86_65-linux/curl-native/7.69.1-r0/ recipe-sysroot-native/etc/ssl/certs +``` + + 4. Modify a few things to leverage SSL/TLS security (our current certificate is self signed, and whether your browser, curl, or the HTTP API do not like it and fail to compile or execute beacuse of that) : + +First, add `-k` option to `curl` bash command in `curl_post()` Yocto function in `build/yocto/source/meta-fullmetalupdate/classes/fullmetalupdae.bbclass` file. + +Secondly, go to FMU client repo (`fullmetalupdate/`, a repo you can clone on FullMetalUpdate Github) and modify the source code in `fullmetalupdate.py`: +``` +@@ -76,8 +76,8 @@ async def main(): + logging.basicConfig(level=LOG_LEVEL, + format='%(asctime)s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S') +- +- async with aiohttp.ClientSession() as session: ++ connTCP = aiohttp.TCPConnector(verify_ssl=False) ++ async with aiohttp.ClientSession(connector=connTCP) as session: + client = FullMetalUpdateDDIClient(session, HOST, SSL, TENANT_ID, TARGET_NAME, + AUTH_TOKEN, ATTRIBUTES) +``` + + 5. Execute `./Startbuild.sh fullmetalupdate-os`. It should build the fullmetalupdate client again. Then you can flash the new image to your target, which will contain the new settings. - 1. After starting the target, you should see your device's IP in the target's - information panel + 6. After starting the target, you should see your device's new IP in the target's information panel on Hawkbit Web Client, which we will denote as #IP. + + 7. To finish the deployment, you can use the `send-file` script furnished in FullMetalUpdate/dev-scripts to apply the modification done to FMU client source code. + +`./send-file.sh fullmetalupdate.py #IP` + +After this final step, you can start deploying your apps updates and OS updates as usual, but by benefiting from the security of HTTPS. ### Configuration on the already deployed target > Note : these changes will be permanent only if you made the changes on the build system -> as described in the last section. Otherwise, the following changes will be lost on the +> as described in the last section. Otherwise, the following changes, made to the target, will be lost on the > next OS update. If you have already deployed your target and have remote access to it, please follow these @@ -161,17 +186,34 @@ steps : 1. Remount `/usr` as read-write by executing: `mount -o remount,rw /usr` - 1. Edit the configuration file by executing `vi - /usr/fullmetalupdate/rauc_hawkbit/config.cfg` + 1. Edit the configuration file by executing `vi /usr/fullmetalupdate/rauc_hawkbit/config.cfg` 1. Make the following changes : * change `hawkbit_url_port` to `8443` * change `hawkbit_ssl` to `true` - 1. Restart the FullMetalUpdate client by executing `systemctl restart fullmetalupdate` + 1. go to FMU client repo (`fullmetalupdate/`, a repo you can clone on FullMetalUpdate Github) and modify the source code in `fullmetalupdate.py`: +``` +@@ -76,8 +76,8 @@ async def main(): + logging.basicConfig(level=LOG_LEVEL, + format='%(asctime)s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S') +- +- async with aiohttp.ClientSession() as session: ++ connTCP = aiohttp.TCPConnector(verify_ssl=False) ++ async with aiohttp.ClientSession(connector=connTCP) as session: + client = FullMetalUpdateDDIClient(session, HOST, SSL, TENANT_ID, TARGET_NAME, + AUTH_TOKEN, ATTRIBUTES) +``` + + 1. After starting the target, you should see your device's new IP in the target's information panel, which we will denote as #IP. + + 1. To finish the deployment, you can use the send-file script furnished in fullmetalupdate/dev-scripts to apply the modification done to FMU client source code. + +`./send-file.sh fullmetalupdate.py #IP` - 1. You should see your device's IP in the target's information panel +You can verify with `journalctl -f | grep fullmetalupdate.sh` that your FMU client is working properly again, in HTTPS. [wiki_p12]: https://fr.wikipedia.org/wiki/PKCS12