diff --git a/docs/add-ons/presentation.md b/docs/add-ons/presentation.md index b002725d..fa6e8b32 100644 --- a/docs/add-ons/presentation.md +++ b/docs/add-ons/presentation.md @@ -43,7 +43,15 @@ If you are in need of a guide on keeping a changelog, we would recommend checkin ## AppArmor -You can use own security profile for your add-on with AppArmor. By default it is enabled and uses the Docker default profile. Putting a `apparmor.txt` file into your add-on folder, will load that file as the primary profile instead. Use the config options to set the name of that profile. +In the event, an API call returns something you, as a developer were not expecting, access to too many resources could be a liability for your users. As an add-on developer, it is your responsibility to ensure your add-on will not ruin your user's machine, or perform actions that you would never expect. That's where AppArmor comes in. + +While your talents in input validation, handling sensitive data and other defensive programming tactics are not being judged here, AppArmor is your add-on's second line of defense against malicious API calls, malformed settings or other forms of system hijacking. + +By default, AppArmor gives you a certain level of security by restricting some general actions that are deemed inappropriate for a Docker container. You can read more about Docker's AppArmor implementation on the [Docker Security page](https://docs.docker.com/engine/security/apparmor/). + +As for Home Assistant's implementation, you can activate your own custom AppArmor profile by putting a `apparmor.txt` file into your add-on folder. Adding your own `apparmor.txt` will load that file as the primary AppArmor profile instead of the default implementation. On top of knowing your add-on will run in a constrained and effective manner, writing your own custom `apparmor.txt` file will earn your add-on a security point after your add-on is installed, thus improving your user's confidence and perception of your add-on. + +An `apparmor.txt` goes in the same folder as your `config.json` file. Below is an example `apparmor.txt`. Replace `ADDON_SLUG` with the slug defined in your add-on configuration. apparmor.txt ```txt @@ -51,6 +59,9 @@ apparmor.txt profile ADDON_SLUG flags=(attach_disconnected,mediate_deleted) { #include + + # Capabilities + file, # S6-Overlay /bin/** ix, @@ -61,25 +72,107 @@ profile ADDON_SLUG flags=(attach_disconnected,mediate_deleted) { /etc/services.d/** rwix, /etc/cont-init.d/** rwix, /etc/cont-finish.d/** rwix, + /var/run/** rw, - # Data access + # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container + ptrace (trace,read) peer=docker-default, + + # docker daemon confinement requires explict allow rule for signal + signal (receive) set=(kill,term) peer=/usr/bin/docker, + + # Access to hardware devices + # /dev/ttyUSB0 rw, + + # Access to Options.json and other files within your addon /data/** rw, } ``` ## Ingress -Ingress allow users to access the add-on web interface via the Home Assistant UI. Authentication is handled by Home Assistant, so neither the user nor the add-on developer will need to care about the security or port forwarding. Users love this feature, however it is not every time simple to implement for the add-on developer. +Ingress allows users to access the add-on web interface via the Home Assistant UI. Authentication is handled by Home Assistant, so neither the user nor the add-on developer will need to care about the security or port forwarding. Users love this feature! It connects your user directly to the add-on, can provide a seamless UX within Home Assistant and grants your add-on 2 points of security. -To add Ingress support, follow the following steps: +Here are the requirements of Ingress: +- Ingress must be enabled. Set `ingress: true` in [`config.json`](/docs/add-ons/configuration#add-on-config). +- Your server may run on port 8099. If it does not run on 8099, you must set `ingress_port: PORT_NUMBER` in [`config.json`](/docs/add-ons/configuration/#add-on-config) to match your configuration. +- Only connections from `172.30.32.2` must be allowed. You should deny access to all other IP addresses within your add-on server. +- Users are previously authenticated via Home Assistant. Authentication is not required. -- The add-on will need to provide the web interface on port `8099`. Make sure that the add-on accepts only connections from `172.30.32.2` on that port and that the connections are treated as authenticated. -- Update add-on configuration and set `ingress: true`. Here it is also possible to configure the Ingress port by using the option `ingress_port: PORT_NUMBER` (default 8099). -- If you need to configure the application inside your add-on with the right path and port, query the add-on info API endpoint. -- If the application doesn't support relative paths or you can't set a base url, you can use nginx filter to replace the URL with correct path. Ingress adds a request header `X-Ingress-Path` that can be used. +:::tip +Configuration of path and port information may be queried via [add-ons info API endpoint](/docs/api/supervisor/endpoints/#addons). If the Home Assistant URL is required by your addon, Ingress adds a request header `X-Ingress-Path` which may be filtered to obtain the base URL. +::: Ingress API gateway supports the following: - HTTP/1.x - Streaming content - Websockets + + +## Basic Ingress Example with Nginx + +The following is a basic ingress implementation with an Nginx server. This contains an example`Dockerfile`, `config.json`, and `ingress.conf` configuration. + +The `ingress.conf` is configured to accept only connections from IP address `172.30.32.2` as we are only expecting connections from this IP address for Ingress purposes. Any other IP address will be rejected. The ingress port 8099 is utilized to reduce configuration work. If you wish to configure a different ingress port you may, but the `config.json` option `ingress_port` must be defined to match. + +ingress.conf +```nginx +server { + listen 8099; + allow 172.30.32.2; + deny all; +} +``` + +Our example `Dockerfile` is configured to support only our Nginx server and does not support a `run.sh` like most add-ons. You may replace the `CMD` with your own command to allow more configuration options while launching your add-on. This Dockerfile will `RUN` to install our Nginx dependencies, `COPY` our example `ingress.conf` from above to the add-on container, then `CMD` start Nginx. + +Dockerfile +```Dockerfile +ARG BUILD_FROM +FROM $BUILD_FROM +ENV LANG C.UTF-8 + +#Add nginx and create the run folder for nginx. +RUN apk --no-cache add nginx;mkdir -p /run/nginx; +#Copy our conf into the nginx http.d folder. +COPY ingress.conf /etc/nginx/http.d/ +#Launch nginx with debug options. +CMD [ "nginx","-g","daemon off;error_log /dev/stdout debug;" ] +``` + +In order to enable Ingress, our `config.json` file _must_ include `ingress: true` and _may_ specify the `ingress_port`, along with other required information. + +config.json +```json +{ + "name": "Ingress Example", + "version": "0.00.0.0.000.0.000", + "slug": "nginx-ingress-example", + "description": "ingress testing", + "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], + "ingress": true, + "ingress_port": 8099 +} +``` + +After the add-on is started, you should be able to view your Ingress server by clicking "OPEN WEB UI" within the add-on info screen. + +# Security + +Add-on security should be a matter of pride. You should strive for the highest level of security you can possibly attain. If your add-on has a lower security rating, then users will be less likely to trust it. + +Each add-on starts with a base rating of 5, on a scale of 1 to 6. Depending on decisions made during development, you will be assigned a score based on certain actions. There are some actions that have additional consequences. These additional consequences appear in the Notes section of the following table. + +| Action | Change | Notes | +|---|---|---| +| Use `ingress: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | +2 | overrides `auth_api` rating | +| Use `auth_api: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | +1 | overridden by `ingress` | +| Use custom [`apparmor.txt`](/docs/add-ons/presentation#apparmor)| +1| Rating applied after installation | +| Set `apparmor: false` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -1 | | +| Use `privileged: NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_PTRACE`, `SYS_MODULE`, or `DAC_READ_SEARCH` in [`config.json`](/docs/add-ons/configuration#add-on-config)| -1 | Rating applied only once if multiple are used. | +| Use `hassio_role: manager` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -1 | | +| Use `host_network: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -1 | | +| Use `hassio_role: admin` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -2 | | +| Use `host_pid: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -2 | | +| Use `full_access: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | -2 | | +| Use `docker_api: true` in [`config.json`](/docs/add-ons/configuration#add-on-config) | Security set to 1 | Overrides all other adjustments |