You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

115 lines
3.5 KiB

// tera-accessd owns the target's dynamically configured management listeners.
package main
import (
"context"
"errors"
"log"
"net"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"tera-clone/services/tera-api/internal/managementaccess"
"tera-clone/services/tera-api/internal/webgateway"
)
func main() {
socketPath := accessGetenv("TERA_ACCESSD_SOCKET", managementaccess.DefaultSocketPath)
handler, err := webgateway.NewHandler(webgateway.Options{
WebUpstream: os.Getenv("TERA_ACCESSD_WEB_UPSTREAM"),
StaticRoot: accessGetenv("TERA_ACCESSD_STATIC_ROOT", "/usr/share/tera-web"),
APIUpstream: accessGetenv("TERA_ACCESSD_API_UPSTREAM", "http://127.0.0.1:8082"),
SessionUpstream: accessGetenv("TERA_ACCESSD_SESSION_UPSTREAM", "http://127.0.0.1:8081"),
})
if err != nil {
log.Fatalf("tera-accessd web setup failed: %v", err)
}
runtime, err := managementaccess.NewRuntime(managementaccess.RuntimeOptions{
BindHost: accessGetenv("TERA_ACCESSD_BIND_HOST", "0.0.0.0"),
Handler: handler,
CertFile: accessGetenv("TERA_ACCESSD_TLS_CERT", "/var/lib/tera-accessd/tls/server.crt"),
KeyFile: accessGetenv("TERA_ACCESSD_TLS_KEY", "/var/lib/tera-accessd/tls/server.key"),
TLSHosts: accessGetenvList("TERA_ACCESSD_TLS_HOSTS", []string{"192.168.0.223", "localhost", "127.0.0.1"}),
})
if err != nil {
log.Fatalf("tera-accessd runtime setup failed: %v", err)
}
defer runtime.Close()
listener, err := listenControlSocket(socketPath)
if err != nil {
log.Fatalf("tera-accessd control socket setup failed: %v", err)
}
defer func() {
_ = listener.Close()
_ = os.Remove(socketPath)
}()
server := managementaccess.SocketServer{Controller: runtime}
errorsChannel := make(chan error, 1)
go func() { errorsChannel <- server.Serve(listener) }()
log.Printf("tera-accessd serving management access control on %s", socketPath)
signalContext, stopSignals := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stopSignals()
select {
case <-signalContext.Done():
_ = listener.Close()
if err := <-errorsChannel; err != nil {
log.Printf("tera-accessd control shutdown failed: %v", err)
}
case err := <-errorsChannel:
if err != nil {
log.Fatalf("tera-accessd control service failed: %v", err)
}
}
}
func listenControlSocket(socketPath string) (net.Listener, error) {
if socketPath == "" || !filepath.IsAbs(socketPath) {
return nil, errors.New("TERA_ACCESSD_SOCKET must be an absolute path")
}
if err := os.MkdirAll(filepath.Dir(socketPath), 0o750); err != nil {
return nil, err
}
if info, err := os.Lstat(socketPath); err == nil {
if info.Mode()&os.ModeSocket == 0 {
return nil, errors.New("refusing to replace non-socket management access path")
}
if err := os.Remove(socketPath); err != nil {
return nil, err
}
} else if !os.IsNotExist(err) {
return nil, err
}
listener, err := net.Listen("unix", socketPath)
if err != nil {
return nil, err
}
if err := os.Chmod(socketPath, 0o660); err != nil {
_ = listener.Close()
return nil, err
}
return listener, nil
}
func accessGetenv(key, fallback string) string {
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
return value
}
return fallback
}
func accessGetenvList(key string, fallback []string) []string {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return fallback
}
result := make([]string, 0)
for _, item := range strings.Split(value, ",") {
if item = strings.TrimSpace(item); item != "" {
result = append(result, item)
}
}
return result
}