Skip to content

Commit efc4dbd

Browse files
authored
Feature/165 certificate setup (#194)
Https with certificate setup on install
1 parent d0fd3f1 commit efc4dbd

File tree

9 files changed

+119
-16
lines changed

9 files changed

+119
-16
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
node_modules/
66
target/
77
*.zip
8+
service/web/config

Makefile

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
run-backend: build-backend
3-
cd service/web && go run cmd/pi-web-agent.go || cd -
3+
ln -sfn ../system/etc/piwebagent2/config service/web/config \
4+
&&cd service/web && go run cmd/pi-web-agent.go || cd -
45

56
run-frontend:
67
cd ui/pi-web-agent-app && ng serve || cd -
@@ -11,13 +12,13 @@ test-backend:
1112
cd service/web && go test ./test/ && cd -
1213

1314
build-dev-ui:
14-
cd ui/pi-web-agent-app && npm i && ng build --base-href / && cd -
15+
npm --prefix ui/pi-web-agent-app i &&npm --prefix ui/pi-web-agent-app run ng build -- --base-href /
1516

1617
build-backend:
1718
cd service/web && go build -o pi-web-agent cmd/pi-web-agent.go && cd -
1819

1920
install-dev:
20-
sudo apt-get update && sudo apt-get install git && curl -L https://git.io/vQhTU | bash -s -- --version 1.16
21+
sudo apt-get update && sudo apt-get install git nodejs npm && curl -L https://git.io/vQhTU | bash -s -- --version 1.16
2122

2223
uninstall-go:
2324
curl -L https://git.io/vQhTU | bash -s -- --remove
@@ -40,7 +41,8 @@ make uninstall:
4041

4142

4243
build-rpi-ui:
43-
cd ui/pi-web-agent-app && npm i && ng build --prod --base-href / && cd -
44+
npm --prefix ui/pi-web-agent-app i \
45+
&&npm --prefix ui/pi-web-agent-app run ng build -- --prod --base-href /
4446

4547
build-rpi-backend:
4648
cd service/web && env GOOS=linux GOARCH=arm GOARM=5 go build -o pi-web-agent cmd/pi-web-agent.go && cd -

install.sh

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function install_assets() {
3232
function install_config() {
3333
mkdir -p $CONFIG_DIR
3434
cp $CONFIG_FILE /$CONFIG_FILE
35-
chown -R piwebagent2 /$CONFIG_FILE
35+
chown -R piwebagent2 /$CONFIG_DIR
3636
}
3737

3838
function prepare_unpack() {
@@ -41,6 +41,7 @@ function prepare_unpack() {
4141
echo $target
4242
}
4343

44+
4445
work_dir=$(prepare_unpack)
4546
set -e
4647
cd $work_dir

installation_paths

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ SERVICE_PATH=lib/systemd/system/piwebagent2.service
33
BINARY_PATH=usr/bin/piwebagent2
44
SHARED_PATH=usr/share/piwebagent2
55
SUDOERS_PATH=etc/sudoers.d/piwebagent2
6+
PWA_CA_PATH=/etc/pwa_ca
67
CONFIG_DIR=etc/piwebagent2/config
7-
CONFIG_FILE=${CONFIG_DIR}/config.env
8+
CONFIG_FILE=${CONFIG_DIR}/config.env

scripts/postinstall.sh

+26
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
1+
#!/bin/bash
2+
3+
function install_pwa_ca(){
4+
PWA_CA_PATH='/etc/pwa_ca'
5+
tmp=$(mktemp -d)
6+
cd $tmp
7+
git clone https://github.com/jsha/minica.git
8+
cd minica
9+
go build
10+
mkdir -p $PWA_CA_PATH
11+
cd $PWA_CA_PATH
12+
$tmp/minica/minica --domains rpi
13+
groupadd pwassl
14+
# group read execute for direcotries
15+
find $PWA_CA_PATH -type d -print0 | xargs -0 chmod 750
16+
# group read for files
17+
find $PWA_CA_PATH -type f -print0 | xargs -0 chmod 640
18+
sudo chown root:pwassl -R $PWA_CA_PATH
19+
usermod -a -G pwassl piwebagent2 # pi web agent can only read
20+
cd -
21+
}
22+
123

224
echo "Giving permissions to piwebagent to access its static content"
325
chown piwebagent2 /usr/share/piwebagent2/assets
426

27+
echo "Setup PWA CA"
28+
install_pwa_ca
29+
530
echo "Enabling piwebagent2.service"
631
systemctl enable piwebagent2.service
32+
733
echo "Starting piwebagent2.service"
834
systemctl start piwebagent2.service
935

Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
TLS_CERT_FILE=/etc/pwa_ca/rpi/cert.pem
2+
TLS_KEY_FILE=/etc/pwa_ca/rpi/key.pem
13
PASSWORD_HASH=
2-
PORT_NUMBER=8080
4+
PORT_NUMBER=8080
5+
TLS_PORT_NUMBER=8443

service/web/cmd/pi-web-agent.go

+22-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import (
55
"io"
66
"log"
77
"net/http"
8+
"os"
89

910
net "github.com/vaslabs/pi-web-agent/net"
1011
api "github.com/vaslabs/pi-web-agent/pkg"
1112
)
1213

1314
func main() {
14-
1515
single_user_session := net.NewSession()
16+
config := single_user_session.PWA_Config
17+
addr := fmt.Sprintf(":%d", config.Port())
18+
tls_addr := fmt.Sprintf(":%d", config.TLS_Port())
19+
key_path := config.TLS_Key_File()
20+
cert_path := config.TLS_Cert_File()
1621

1722
api_action_prefix := "/api/action/"
1823

@@ -27,8 +32,21 @@ func main() {
2732
http.HandleFunc(api_action_prefix, dummyHandler)
2833
http.HandleFunc("/api/control/stream", action_dispatcher_handler)
2934
http.Handle("/", http.FileServer(http.Dir("assets")))
35+
if _, err := os.Stat(key_path); err == nil {
36+
log.Println("Redirecting from ", addr)
37+
go net.RedirectToHTTPS(addr, config.TLS_Port())
38+
log.Println("Serving over TLS on ", tls_addr)
39+
log.Fatal(
40+
http.ListenAndServeTLS(
41+
tls_addr,
42+
cert_path,
43+
key_path,
44+
nil,
45+
),
46+
)
47+
} else {
48+
log.Println("Listening to ", addr)
49+
log.Fatal(http.ListenAndServe(addr, nil))
50+
}
3051

31-
addr := fmt.Sprintf(":%d", single_user_session.PWA_Config.Port())
32-
33-
log.Fatal(http.ListenAndServe(addr, nil))
3452
}

service/web/internal/configuration.go

+33-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ package shell
22

33
import (
44
"fmt"
5+
"os"
6+
"path"
57

68
"github.com/spf13/viper"
79
)
810

911
type RPI_Config interface {
1012
Port() uint32
1113
Password_Hash() string
14+
TLS_Cert_File() string
15+
TLS_Key_File() string
16+
TLS_Port() uint32
1217
Update_Passphrase(phrase string)
1318
}
1419

@@ -17,16 +22,31 @@ type Dynamic_RPI_Config struct {
1722
}
1823

1924
const (
20-
PASSWORD_HASH_KEY = "PASSWORD_HASH"
21-
PORT_NUMBER_KEY = "PORT_NUMBER"
25+
PASSWORD_HASH_KEY = "PASSWORD_HASH"
26+
PORT_NUMBER_KEY = "PORT_NUMBER"
27+
TLS_CERT_FILE_KEY = "TLS_CERT_FILE"
28+
TLS_KEY_FILE_KEY = "TLS_KEY_FILE"
29+
TLS_PORT_NUMBER_KEY = "TLS_PORT_NUMBER"
2230
)
2331

32+
func (config *Dynamic_RPI_Config) Password_Hash() string {
33+
return config.config.GetString(PASSWORD_HASH_KEY)
34+
}
35+
2436
func (config *Dynamic_RPI_Config) Port() uint32 {
2537
return config.config.GetUint32(PORT_NUMBER_KEY)
2638
}
2739

28-
func (config *Dynamic_RPI_Config) Password_Hash() string {
29-
return config.config.GetString(PASSWORD_HASH_KEY)
40+
func (config *Dynamic_RPI_Config) TLS_Cert_File() string {
41+
return config.config.GetString(TLS_CERT_FILE_KEY)
42+
}
43+
44+
func (config *Dynamic_RPI_Config) TLS_Key_File() string {
45+
return config.config.GetString(TLS_KEY_FILE_KEY)
46+
}
47+
48+
func (config *Dynamic_RPI_Config) TLS_Port() uint32 {
49+
return config.config.GetUint32(TLS_PORT_NUMBER_KEY)
3050
}
3151

3252
func (config *Dynamic_RPI_Config) Update_Passphrase(phrase string) {
@@ -41,13 +61,21 @@ func Load_PWA_config(path string) RPI_Config {
4161
}
4262

4363
func Load_RPI_PWA_Config() RPI_Config {
44-
return Load_PWA_config("/etc/piwebagent2/config")
64+
pwa_path := "/etc/piwebagent2"
65+
config_path := "config"
66+
if _, err := os.Stat(pwa_path); err == nil {
67+
return Load_PWA_config(path.Join(pwa_path, config_path))
68+
}
69+
return Load_PWA_config(config_path)
4570
}
4671

4772
func load_PWA_config(path string) (*viper.Viper, error) {
4873
config := viper.New()
4974
config.SetDefault(PASSWORD_HASH_KEY, "")
5075
config.SetDefault(PORT_NUMBER_KEY, uint32(8080))
76+
config.SetDefault(TLS_PORT_NUMBER_KEY, uint32(8443))
77+
config.SetDefault(TLS_CERT_FILE_KEY, "/etc/pwa_ca/rpi/cert.pem")
78+
config.SetDefault(TLS_KEY_FILE_KEY, "/etc/pwa_ca/rpi/key.pem")
5179
config.AddConfigPath(path)
5280
config.SetConfigType("env")
5381
config.WatchConfig()

service/web/net/https_redircet.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net
2+
3+
import (
4+
"log"
5+
"net"
6+
"net/http"
7+
"strconv"
8+
)
9+
10+
func RedirectToHTTPS(httpAddr string, tlsPort uint32) {
11+
httpSrv := http.Server{
12+
Addr: httpAddr,
13+
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14+
host, _, _ := net.SplitHostPort(r.Host)
15+
u := r.URL
16+
u.Host = net.JoinHostPort(host, strconv.FormatUint(uint64(tlsPort), 10))
17+
u.Scheme = "https"
18+
log.Println("Redirecting http request to:", u.String())
19+
http.Redirect(w, r, u.String(), http.StatusMovedPermanently)
20+
}),
21+
}
22+
log.Println(httpSrv.ListenAndServe())
23+
}

0 commit comments

Comments
 (0)