mirror of
https://github.com/hassio-addons/addon-vscode.git
synced 2025-05-03 18:51:23 +00:00
✨ Adds HA Authentication
This commit is contained in:
parent
02b8296a99
commit
07fd06720e
10 changed files with 279 additions and 39 deletions
|
@ -60,17 +60,22 @@ RUN \
|
|||
build-essential=12.4ubuntu1 \
|
||||
colordiff=1.0.18-1 \
|
||||
git=1:2.17.1-1ubuntu0.4 \
|
||||
libnginx-mod-http-lua=1.14.0-0ubuntu1.2 \
|
||||
locales=2.27-3ubuntu1 \
|
||||
luarocks=2.4.2+dfsg-1 \
|
||||
mosquitto-clients=1.4.15-2ubuntu0.18.04.2 \
|
||||
net-tools=1.60+git20161116.90da8a0-1ubuntu1 \
|
||||
nginx=1.14.0-0ubuntu1.2 \
|
||||
nmap=7.60-1ubuntu5 \
|
||||
openssh-client=1:7.6p1-4ubuntu0.3 \
|
||||
openssl=1.1.0g-2ubuntu4.3 \
|
||||
python3=3.6.7-1~18.04 \
|
||||
python3-dev=3.6.7-1~18.04 \
|
||||
python3=3.6.7-1~18.04 \
|
||||
wget=1.19.4-1ubuntu2.1 \
|
||||
zsh=5.4.2-3ubuntu3.1 \
|
||||
\
|
||||
&& luarocks install lua-resty-http 0.13-0 \
|
||||
\
|
||||
&& curl https://bootstrap.pypa.io/get-pip.py | python3 \
|
||||
\
|
||||
&& locale-gen en_US.UTF-8 \
|
||||
|
@ -106,8 +111,9 @@ RUN \
|
|||
&& pip3 install --no-cache-dir -r /tmp/requirements.txt \
|
||||
\
|
||||
&& apt-get purge -y --auto-remove \
|
||||
python3-dev \
|
||||
build-essential \
|
||||
luarocks \
|
||||
python3-dev \
|
||||
\
|
||||
&& find /usr/local/lib/python3.6/ -type d -name tests -depth -exec rm -rf {} \; \
|
||||
&& find /usr/local/lib/python3.6/ -type d -name test -depth -exec rm -rf {} \; \
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
],
|
||||
"boot": "auto",
|
||||
"hassio_api": true,
|
||||
"auth_api": true,
|
||||
"hassio_role": "manager",
|
||||
"homeassistant_api": true,
|
||||
"host_network": false,
|
||||
|
@ -26,7 +27,6 @@
|
|||
"backup:rw"
|
||||
],
|
||||
"options": {
|
||||
"password": "",
|
||||
"ssl": true,
|
||||
"certfile": "fullchain.pem",
|
||||
"keyfile": "privkey.pem",
|
||||
|
@ -35,7 +35,6 @@
|
|||
},
|
||||
"schema": {
|
||||
"log_level": "match(^(trace|debug|info|notice|warning|error|fatal)$)?",
|
||||
"password": "str",
|
||||
"ssl": "bool",
|
||||
"certfile": "str",
|
||||
"keyfile": "str",
|
||||
|
|
|
@ -4,24 +4,3 @@
|
|||
# This files check if all user configuration requirements are met
|
||||
# ==============================================================================
|
||||
bashio::config.require.ssl
|
||||
|
||||
if ! bashio::config.true 'leave_front_door_open'; then
|
||||
if ! bashio::config.true 'i_like_to_be_pwned'; then
|
||||
bashio::config.require.safe_password
|
||||
else
|
||||
bashio::config.require.password
|
||||
fi
|
||||
fi
|
||||
|
||||
if bashio::config.true 'leave_front_door_open' \
|
||||
&& bashio::config.true 'ssl';
|
||||
then
|
||||
bashio::log.fatal
|
||||
bashio::log.fatal "Due to a bug in code-server (which this add-on uses),"
|
||||
bashio::log.fatal "it is impossible to disable authentication while"
|
||||
bashio::log.fatal "using SSL."
|
||||
bashio::log.fatal
|
||||
bashio::log.fatal "Please enable authentication and set a password."
|
||||
bashio::log.fatal
|
||||
bashio::exit.nok
|
||||
fi
|
||||
|
|
17
vscode/rootfs/etc/cont-init.d/11-nginx.sh
Normal file
17
vscode/rootfs/etc/cont-init.d/11-nginx.sh
Normal file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: Visual Studio Code
|
||||
# Configures NGINX for use with code-server
|
||||
# ==============================================================================
|
||||
declare certfile
|
||||
declare keyfile
|
||||
|
||||
mkdir -p /var/log/nginx
|
||||
|
||||
if bashio::config.true 'ssl'; then
|
||||
certfile=$(bashio::config 'certfile')
|
||||
keyfile=$(bashio::config 'keyfile')
|
||||
|
||||
sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/nginx-ssl.conf
|
||||
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/nginx-ssl.conf
|
||||
fi
|
83
vscode/rootfs/etc/nginx/ha-auth.lua
Normal file
83
vscode/rootfs/etc/nginx/ha-auth.lua
Normal file
|
@ -0,0 +1,83 @@
|
|||
local http = require "resty.http"
|
||||
local auths = ngx.shared.auths
|
||||
|
||||
function authenticate()
|
||||
|
||||
--- Test Authentication header is set and with a value
|
||||
local header = ngx.req.get_headers()['Authorization']
|
||||
if header == nil or header:find(" ") == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
local divider = header:find(' ')
|
||||
if header:sub(0, divider-1) ~= 'Basic' then
|
||||
return false
|
||||
end
|
||||
|
||||
local auth = ngx.decode_base64(header:sub(divider+1))
|
||||
if auth == nil or auth:find(':') == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
divider = auth:find(':')
|
||||
local username = auth:sub(0, divider-1)
|
||||
local password = auth:sub(divider+1)
|
||||
|
||||
--- Check if authentication is cached
|
||||
if auths:get(username) == password then
|
||||
ngx.log(ngx.DEBUG, "Authenticated user against Home Assistant (cache).")
|
||||
return true
|
||||
end
|
||||
|
||||
--- HTTP request against Hassio API
|
||||
local httpc = http.new()
|
||||
local res, err = httpc:request_uri("http://hassio/auth", {
|
||||
method = "POST",
|
||||
body = ngx.encode_args({["username"]=username, ["password"]=password}),
|
||||
headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded",
|
||||
["X-HASSIO-KEY"] = os.getenv("HASSIO_TOKEN"),
|
||||
},
|
||||
keepalive_timeout = 60,
|
||||
keepalive_pool = 10
|
||||
})
|
||||
|
||||
--- Error during API request
|
||||
if err then
|
||||
ngx.log(ngx.WARN, "Error during Hassio user authentication.", err)
|
||||
return false
|
||||
end
|
||||
|
||||
--- No result? Something went wrong...
|
||||
if not res then
|
||||
ngx.log(ngx.WARN, "Error during Hassio user authentication.")
|
||||
return false
|
||||
end
|
||||
|
||||
--- Valid response, the username/password is valid
|
||||
if res.status == 200 then
|
||||
ngx.log(ngx.INFO, "Authenticated user against Home Assistant.")
|
||||
auths:set(username, password, 60)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Whatever the response is, it is invalid
|
||||
ngx.log(ngx.WARN, "Authentication against Home Assistant failed!")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Only authenticate if its not disabled
|
||||
if not os.getenv('DISABLE_HA_AUTHENTICATION') then
|
||||
|
||||
--- Try to authenticate against HA
|
||||
local authenticated = authenticate()
|
||||
|
||||
--- If authentication failed, throw a basic auth
|
||||
if not authenticated then
|
||||
ngx.header.content_type = 'text/plain'
|
||||
ngx.header.www_authenticate = 'Basic realm="Home Assistant"'
|
||||
ngx.status = ngx.HTTP_UNAUTHORIZED
|
||||
ngx.say('401 Access Denied')
|
||||
ngx.exit(ngx.HTTP_UNAUTHORIZED)
|
||||
end
|
||||
end
|
71
vscode/rootfs/etc/nginx/nginx-ssl.conf
Normal file
71
vscode/rootfs/etc/nginx/nginx-ssl.conf
Normal file
|
@ -0,0 +1,71 @@
|
|||
worker_processes 1;
|
||||
pid /var/run/nginx.pid;
|
||||
error_log stderr;
|
||||
env HASSIO_TOKEN;
|
||||
env DISABLE_HA_AUTHENTICATION;
|
||||
load_module "/usr/lib/nginx/modules/ndk_http_module.so";
|
||||
load_module "/usr/lib/nginx/modules/ngx_http_lua_module.so";
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
access_log stdout;
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
lua_shared_dict auths 16k;
|
||||
resolver 127.0.0.11;
|
||||
|
||||
upstream code {
|
||||
ip_hash;
|
||||
server 127.0.0.1:8443;
|
||||
}
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name hassio.local;
|
||||
listen 1337 default_server ssl;
|
||||
root /dev/null;
|
||||
|
||||
ssl_certificate /ssl/%%certfile%%;
|
||||
ssl_certificate_key /ssl/%%keyfile%%;
|
||||
ssl_protocols TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
|
||||
ssl_ecdh_curve secp384r1;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_tickets off;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
|
||||
location / {
|
||||
access_by_lua_file /etc/nginx/ha-auth.lua;
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_pass http://code;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header Authorization "";
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
}
|
||||
}
|
||||
}
|
57
vscode/rootfs/etc/nginx/nginx.conf
Normal file
57
vscode/rootfs/etc/nginx/nginx.conf
Normal file
|
@ -0,0 +1,57 @@
|
|||
worker_processes 1;
|
||||
pid /var/run/nginx.pid;
|
||||
error_log stderr;
|
||||
env HASSIO_TOKEN;
|
||||
env DISABLE_HA_AUTHENTICATION;
|
||||
load_module "/usr/lib/nginx/modules/ndk_http_module.so";
|
||||
load_module "/usr/lib/nginx/modules/ngx_http_lua_module.so";
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
access_log stdout;
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
lua_shared_dict auths 16k;
|
||||
resolver 127.0.0.11;
|
||||
|
||||
upstream code {
|
||||
ip_hash;
|
||||
server 127.0.0.1:8443;
|
||||
}
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name hassio.local;
|
||||
listen 1337 default_server;
|
||||
root /dev/null;
|
||||
|
||||
location / {
|
||||
access_by_lua_file /etc/nginx/ha-auth.lua;
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_pass http://code;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header Authorization "";
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,22 +7,13 @@ declare -a options
|
|||
|
||||
bashio::log.info 'Starting the code server...'
|
||||
|
||||
# Non-interactive
|
||||
options+=(--port 1337)
|
||||
options+=(--port 8443)
|
||||
options+=(--data-dir "/data/vscode")
|
||||
options+=(--host 127.0.0.1)
|
||||
options+=(--allow-http)
|
||||
|
||||
if bashio::config.false 'ssl'; then
|
||||
options+=(--allow-http)
|
||||
else
|
||||
options+=(--cert "/ssl/$(bashio::config 'certfile')")
|
||||
options+=(--cert-key "/ssl/$(bashio::config 'keyfile')")
|
||||
fi
|
||||
|
||||
if ! bashio::config.has_value 'password'; then
|
||||
options+=(--no-auth)
|
||||
else
|
||||
options+=(--password "$(bashio::config 'password')")
|
||||
fi
|
||||
# Disable code authentication, we use HA authentication
|
||||
options+=(--no-auth)
|
||||
|
||||
# Export env variables for the Home Assistant extension
|
||||
export HASS_SERVER="http://hassio/homeassistant"
|
||||
|
|
9
vscode/rootfs/etc/services.d/nginx/finish
Normal file
9
vscode/rootfs/etc/services.d/nginx/finish
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/execlineb -S0
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: Visual Studio Code
|
||||
# Take down the S6 supervision tree when Nginx fails
|
||||
# ==============================================================================
|
||||
if -n { s6-test $# -ne 0 }
|
||||
if -n { s6-test ${1} -eq 256 }
|
||||
|
||||
s6-svscanctl -t /var/run/s6/services
|
28
vscode/rootfs/etc/services.d/nginx/run
Normal file
28
vscode/rootfs/etc/services.d/nginx/run
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: Visual Studio Code
|
||||
# Runs the Nginx daemon
|
||||
# ==============================================================================
|
||||
declare -a options
|
||||
|
||||
# Wait for code-server to become available
|
||||
s6-svwait -u -t 5000 /var/run/s6/services/code
|
||||
timeout 15 \
|
||||
bash -c \
|
||||
'until echo > /dev/tcp/localhost/8443 ; do sleep 0.5; done' \
|
||||
> /dev/null 2>&1
|
||||
|
||||
bashio::log.info "Starting NGinx..."
|
||||
|
||||
# Disable HA Authentication if front door is open
|
||||
if bashio::config.true 'leave_front_door_open'; then
|
||||
export DISABLE_HA_AUTHENTICATION=true
|
||||
fi
|
||||
|
||||
options+=(-g "daemon off;")
|
||||
|
||||
if bashio::config.true 'ssl'; then
|
||||
options+=(-c /etc/nginx/nginx-ssl.conf)
|
||||
fi
|
||||
|
||||
exec nginx "${options[@]}"
|
Loading…
Add table
Add a link
Reference in a new issue