Browse Source

make docker env to use SSL for OSCAR

Mike 11 months ago
parent
commit
240e96aa45
8 changed files with 133 additions and 44 deletions
  1. 16 3
      Makefile
  2. 22 9
      cmd/config_generator/main.go
  3. 9 9
      config/config.go
  4. 0 10
      config/settings.env
  5. 73 0
      config/ssl/settings.env
  6. 9 0
      config/ssl/stunnel.conf
  7. 3 12
      docker-compose.yaml
  8. 1 1
      docker-setup.sh

+ 16 - 3
Makefile

@@ -12,9 +12,14 @@ DOCKER_RUN_GO_RELEASER := @docker run \
 	$(DOCKER_IMAGE_TAG_GO_RELEASER)
 OSCAR_HOST ?= ras.dev
 
-.PHONY: config
-config: ## Generate config file template from Config struct
-	go generate ./config
+.PHONY: config-basic config-ssl config
+config-basic: ## Generate basic config file template
+	go run ./cmd/config_generator unix config/settings.env basic
+
+config-ssl: ## Generate SSL config file template
+	go run ./cmd/config_generator unix config/ssl/settings.env ssl
+
+config: config-basic config-ssl ## Generate all config file templates from Config struct
 
 .PHONY: release
 release: ## Run a clean, full GoReleaser run (publish + validate)
@@ -41,8 +46,16 @@ docker-images: docker-image-ras docker-image-stunnel docker-image-certgen
 
 .PHONY: docker-run
 docker-run:
+	OSCAR_HOST=$(OSCAR_HOST) docker compose up retro-aim-server stunnel
+
+.PHONY: docker-run-bg
+docker-run-bg: ## Run Retro AIM Server in background with docker-compose
 	OSCAR_HOST=$(OSCAR_HOST) docker compose up -d retro-aim-server stunnel
 
+.PHONY: docker-run-stop
+docker-run-stop: ## Stop Retro AIM Server docker-compose services
+	OSCAR_HOST=$(OSCAR_HOST) docker compose down
+
 ################################################################################
 # SSL Helpers
 ################################################################################

+ 22 - 9
cmd/config_generator/main.go

@@ -1,7 +1,7 @@
 // This program generates env config scripts from config.Config struct tags for
 // unix and windows platforms.
-// Usage: go run ./cmd/config_generator [platform] [filename]
-// Example: go run ./cmd/config_generator unix settings.env
+// Usage: go run ./cmd/config_generator [platform] [filename] [value_tag]
+// Example: go run ./cmd/config_generator unix settings.basic.env basic
 package main
 
 import (
@@ -32,18 +32,22 @@ var platformKeywords = map[string]struct {
 
 func main() {
 	args := os.Args[1:]
-	if len(args) < 2 {
-		fmt.Fprintln(os.Stderr, "usage: go run cmd/config_generator [platform] [filename]")
+	if len(args) < 3 {
+		fmt.Fprintln(os.Stderr, "usage: go run cmd/config_generator [platform] [filename] [value_tag]")
 		os.Exit(1)
 	}
 
-	keywords, ok := platformKeywords[args[0]]
+	platform := args[0]
+	filename := args[1]
+	valueTag := args[2] // e.g., "basic", "ssl"
+
+	keywords, ok := platformKeywords[platform]
 	if !ok {
-		fmt.Fprintf(os.Stderr, "unable to find platform `%s`\n", os.Args[1])
+		fmt.Fprintf(os.Stderr, "unable to find platform `%s`\n", platform)
 		os.Exit(1)
 	}
-	fmt.Println("writing to", args[1])
-	f, err := os.Create(args[1])
+	fmt.Println("writing to", filename)
+	f, err := os.Create(filename)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error creating file: %s\n", err.Error())
 		os.Exit(1)
@@ -53,6 +57,16 @@ func main() {
 	configType := reflect.TypeOf(config.Config{})
 	for i := 0; i < configType.NumField(); i++ {
 		field := configType.Field(i)
+
+		// Check if field is optional and has empty value
+		required := field.Tag.Get("required")
+		val := field.Tag.Get(valueTag) // Use the specified value tag
+
+		// Skip optional fields with empty values
+		if required == "false" && val == "" {
+			continue
+		}
+
 		comment := field.Tag.Get("description")
 		if err := writeComment(f, comment, 80, keywords.comment); err != nil {
 			fmt.Fprintf(os.Stderr, "error writing to file: %s\n", err.Error())
@@ -60,7 +74,6 @@ func main() {
 		}
 
 		varName := field.Tag.Get("envconfig")
-		val := field.Tag.Get("val")
 		if err := writeAssignment(f, keywords.assignment, varName, val); err != nil {
 			fmt.Fprintf(os.Stderr, "error writing to file: %s\n", err.Error())
 			os.Exit(1)

+ 9 - 9
config/config.go

@@ -8,17 +8,17 @@ import (
 	"strings"
 )
 
-//go:generate go run github.com/mk6i/retro-aim-server/cmd/config_generator unix settings.env
+//go:generate go run ../cmd/config_generator unix settings.env ssl
 type Config struct {
-	BOSListeners       string `envconfig:"OSCAR_LISTENERS" required:"true" val:"LOCAL://0.0.0.0:5190" description:"Network listeners for core OSCAR services. For multi-homed servers, allows users to connect from multiple networks. For example, you can allow both LAN and Internet clients to connect to the same server using different connection settings.\n\nFormat:\n\t- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]\n\t- Listener names and ports must be unique\n\t- Listener names are user-defined\n\t- Each listener needs OSCAR_ADVERTISED_LISTENERS/KERBEROS_LISTENERS configs\n\nExamples:\n\t// Listen on all interfaces\n\tLAN://0.0.0.0:5190\n\t// Separate Internet and LAN config\n\tWAN://142.250.176.206:5190,LAN://192.168.1.10:5191"`
-	BOSAdvertisedHosts string `envconfig:"OSCAR_ADVERTISED_LISTENERS" required:"true" val:"LOCAL://127.0.0.1:5190" description:"Hostnames published by the server that clients connect to for accessing various OSCAR services. These hostnames are NOT the bind addresses. For multi-homed use servers, allows clients to connect using separate hostnames per network.\n\nFormat:\n\t- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]\n\t- Each listener config must correspond to a config in OSCAR_LISTENERS\n\t- Clients MUST be able to connect to these hostnames\n\nExamples:\n\t// Local LAN config, server behind NAT\n\tLAN://0.0.0.0:5190\n\t// Separate Internet and LAN config\n\tWAN://aim.example.com:5190,LAN://192.168.1.10:5191"`
-	KerberosListeners  string `envconfig:"KERBEROS_LISTENERS" required:"false" val:"LOCAL://0.0.0.0:1088" description:"Network listeners for Kerberos authentication. See OSCAR_LISTENERS doc for more details.\n\nExamples:\n\t// Listen on all interfaces\n\tLAN://0.0.0.0:1088\n\t// Separate Internet and LAN config\n\tWAN://142.250.176.206:1088,LAN://192.168.1.10:1087"`
-	TOCListeners       string `envconfig:"TOC_LISTENERS" required:"true" val:"0.0.0.0:9898" description:"Network listeners for TOC protocol service.\n\nFormat: Comma-separated list of hostname:port pairs.\n\nExamples:\n\t// All interfaces\n\t0.0.0.0:9898\n\t// Multiple listeners\n\t0.0.0.0:9898,192.168.1.10:9899"`
-	APIListener        string `envconfig:"API_LISTENER" required:"true" val:"127.0.0.1:8080" description:"Network listener for management API binds to. Only 1 listener can be specified. (Default 127.0.0.1 restricts to same machine only)."`
+	BOSListeners       string `envconfig:"OSCAR_LISTENERS" required:"true" basic:"LOCAL://0.0.0.0:5190" ssl:"PLAINTEXT://0.0.0.0:5190,SSL://0.0.0.0:5192" description:"Network listeners for core OSCAR services. For multi-homed servers, allows users to connect from multiple networks. For example, you can allow both LAN and Internet clients to connect to the same server using different connection settings.\n\nFormat:\n\t- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]\n\t- Listener names and ports must be unique\n\t- Listener names are user-defined\n\t- Each listener needs OSCAR_ADVERTISED_LISTENERS/KERBEROS_LISTENERS configs\n\nExamples:\n\t// Listen on all interfaces\n\tLAN://0.0.0.0:5190\n\t// Separate Internet and LAN config\n\tWAN://142.250.176.206:5190,LAN://192.168.1.10:5191"`
+	BOSAdvertisedHosts string `envconfig:"OSCAR_ADVERTISED_LISTENERS" required:"true" basic:"LOCAL://127.0.0.1:5190" ssl:"PLAINTEXT://127.0.0.1:5190,SSL://127.0.0.1:5193" description:"Hostnames published by the server that clients connect to for accessing various OSCAR services. These hostnames are NOT the bind addresses. For multi-homed use servers, allows clients to connect using separate hostnames per network.\n\nFormat:\n\t- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]\n\t- Each listener config must correspond to a config in OSCAR_LISTENERS\n\t- Clients MUST be able to connect to these hostnames\n\nExamples:\n\t// Local LAN config, server behind NAT\n\tLAN://0.0.0.0:5190\n\t// Separate Internet and LAN config\n\tWAN://aim.example.com:5190,LAN://192.168.1.10:5191"`
+	KerberosListeners  string `envconfig:"KERBEROS_LISTENERS" required:"false" basic:"" ssl:"SSL://0.0.0.0:1088" description:"Network listeners for Kerberos authentication. See OSCAR_LISTENERS doc for more details.\n\nExamples:\n\t// Listen on all interfaces\n\tLAN://0.0.0.0:1088\n\t// Separate Internet and LAN config\n\tWAN://142.250.176.206:1088,LAN://192.168.1.10:1087"`
+	TOCListeners       string `envconfig:"TOC_LISTENERS" required:"true" basic:"0.0.0.0:9898" ssl:"0.0.0.0:9898" description:"Network listeners for TOC protocol service.\n\nFormat: Comma-separated list of hostname:port pairs.\n\nExamples:\n\t// All interfaces\n\t0.0.0.0:9898\n\t// Multiple listeners\n\t0.0.0.0:9898,192.168.1.10:9899"`
+	APIListener        string `envconfig:"API_LISTENER" required:"true" basic:"127.0.0.1:8080" ssl:"127.0.0.1:8080" description:"Network listener for management API binds to. Only 1 listener can be specified. (Default 127.0.0.1 restricts to same machine only)."`
 
-	DBPath      string `envconfig:"DB_PATH" required:"true" val:"oscar.sqlite" description:"The path to the SQLite database file. The file and DB schema are auto-created if they doesn't exist."`
-	DisableAuth bool   `envconfig:"DISABLE_AUTH" required:"true" val:"true" description:"Disable password check and auto-create new users at login time. Useful for quickly creating new accounts during development without having to register new users via the management API."`
-	LogLevel    string `envconfig:"LOG_LEVEL" required:"true" val:"info" description:"Set logging granularity. Possible values: 'trace', 'debug', 'info', 'warn', 'error'."`
+	DBPath      string `envconfig:"DB_PATH" required:"true" basic:"oscar.sqlite" ssl:"oscar.sqlite" description:"The path to the SQLite database file. The file and DB schema are auto-created if they doesn't exist."`
+	DisableAuth bool   `envconfig:"DISABLE_AUTH" required:"true" basic:"true" ssl:"true" description:"Disable password check and auto-create new users at login time. Useful for quickly creating new accounts during development without having to register new users via the management API."`
+	LogLevel    string `envconfig:"LOG_LEVEL" required:"true" basic:"info" ssl:"info" description:"Set logging granularity. Possible values: 'trace', 'debug', 'info', 'warn', 'error'."`
 }
 
 type Build struct {

+ 0 - 10
config/settings.env

@@ -33,16 +33,6 @@ export OSCAR_LISTENERS=LOCAL://0.0.0.0:5190
 # 	WAN://aim.example.com:5190,LAN://192.168.1.10:5191
 export OSCAR_ADVERTISED_LISTENERS=LOCAL://127.0.0.1:5190
 
-# Network listeners for Kerberos authentication. See OSCAR_LISTENERS doc for
-# more details.
-# 
-# Examples:
-# 	// Listen on all interfaces
-# 	LAN://0.0.0.0:1088
-# 	// Separate Internet and LAN config
-# 	WAN://142.250.176.206:1088,LAN://192.168.1.10:1087
-export KERBEROS_LISTENERS=LOCAL://0.0.0.0:1088
-
 # Network listeners for TOC protocol service.
 # 
 # Format: Comma-separated list of hostname:port pairs.

+ 73 - 0
config/ssl/settings.env

@@ -0,0 +1,73 @@
+# Network listeners for core OSCAR services. For multi-homed servers, allows
+# users to connect from multiple networks. For example, you can allow both LAN
+# and Internet clients to connect to the same server using different connection
+# settings.
+# 
+# Format:
+# 	- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]
+# 	- Listener names and ports must be unique
+# 	- Listener names are user-defined
+# 	- Each listener needs OSCAR_ADVERTISED_LISTENERS/KERBEROS_LISTENERS configs
+# 
+# Examples:
+# 	// Listen on all interfaces
+# 	LAN://0.0.0.0:5190
+# 	// Separate Internet and LAN config
+# 	WAN://142.250.176.206:5190,LAN://192.168.1.10:5191
+export OSCAR_LISTENERS=PLAINTEXT://0.0.0.0:5190,SSL://0.0.0.0:5192
+
+# Hostnames published by the server that clients connect to for accessing
+# various OSCAR services. These hostnames are NOT the bind addresses. For
+# multi-homed use servers, allows clients to connect using separate hostnames
+# per network.
+# 
+# Format:
+# 	- Comma-separated list of [NAME]://[HOSTNAME]:[PORT]
+# 	- Each listener config must correspond to a config in OSCAR_LISTENERS
+# 	- Clients MUST be able to connect to these hostnames
+# 
+# Examples:
+# 	// Local LAN config, server behind NAT
+# 	LAN://0.0.0.0:5190
+# 	// Separate Internet and LAN config
+# 	WAN://aim.example.com:5190,LAN://192.168.1.10:5191
+export OSCAR_ADVERTISED_LISTENERS=PLAINTEXT://localhost:5190,SSL://ras.dev:5193
+
+# Network listeners for Kerberos authentication. See OSCAR_LISTENERS doc for
+# more details.
+# 
+# Examples:
+# 	// Listen on all interfaces
+# 	LAN://0.0.0.0:1088
+# 	// Separate Internet and LAN config
+# 	WAN://142.250.176.206:1088,LAN://192.168.1.10:1087
+export KERBEROS_LISTENERS=SSL://0.0.0.0:1088
+
+# Network listeners for TOC protocol service.
+# 
+# Format: Comma-separated list of hostname:port pairs.
+# 
+# Examples:
+# 	// All interfaces
+# 	0.0.0.0:9898
+# 	// Multiple listeners
+# 	0.0.0.0:9898,192.168.1.10:9899
+export TOC_LISTENERS=0.0.0.0:9898
+
+# Network listener for management API binds to. Only 1 listener can be
+# specified. (Default 127.0.0.1 restricts to same machine only).
+export API_LISTENER=127.0.0.1:8080
+
+# The path to the SQLite database file. The file and DB schema are auto-created
+# if they doesn't exist.
+export DB_PATH=oscar.sqlite
+
+# Disable password check and auto-create new users at login time. Useful for
+# quickly creating new accounts during development without having to register
+# new users via the management API.
+export DISABLE_AUTH=true
+
+# Set logging granularity. Possible values: 'trace', 'debug', 'info', 'warn',
+# 'error'.
+export LOG_LEVEL=info
+

+ 9 - 0
config/ssl/stunnel.conf

@@ -8,4 +8,13 @@ options = NO_TLSv1_1
 ciphers = ALL
 accept = 443
 connect = retro-aim-server:1088
+cert = /etc/stunnel/certs/server.pem
+
+[oscar_proxy]
+options = NO_SSLv2
+options = NO_SSLv3
+options = NO_TLSv1_1
+ciphers = ALL
+accept = 5193
+connect = retro-aim-server:5192
 cert = /etc/stunnel/certs/server.pem

+ 3 - 12
docker-compose.yaml

@@ -24,8 +24,6 @@ services:
       - ./certs:/work/certs
     working_dir: /work/certs
     entrypoint: [ "/bin/sh", "-c" ]
-    environment:
-      - OSCAR_HOST=${OSCAR_HOST}
     command: >
       '
       mkdir -p nss &&
@@ -37,23 +35,16 @@ services:
     image: ras:latest
     ports:
       - "5190:5190"
-      - "5191:5191"
-      - "5192:5192"
-      - "5193:5193"
-      - "5194:5194"
-      - "5195:5195"
-      - "5196:5196"
-      - "5197:5197"
+      - "9898:9898"
       - "8080:8080"
     env_file:
-      - ./config/settings.env
-    environment:
-      - OSCAR_HOST=${OSCAR_HOST}
+      - ./config/ssl/settings.env
 
   stunnel:
     image: ras-stunnel:5.75-openssl-1.0.2u
     ports:
       - "443:443"
+      - "5193:5193"
     volumes:
       - ./config/ssl/stunnel.conf:/etc/stunnel/stunnel.conf:ro
       - ./certs:/etc/stunnel/certs:ro

+ 1 - 1
docker-setup.sh

@@ -79,7 +79,7 @@ generate_nss() {
 
 start_server() {
     log "Starting Retro AIM Server with hostname $OSCAR_HOST..."
-    make docker-run OSCAR_HOST="$OSCAR_HOST" || error "Failed to start server"
+    make docker-run-bg OSCAR_HOST="$OSCAR_HOST" || error "Failed to start server"
     success "Retro AIM Server is running."
 }