172 lines
5.4 KiB
Go
172 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
)
|
|
|
|
func (c *CaddyClient) AddBasicAuth(domain, username, password string) error {
|
|
log.Printf("[WARNING] Password for user %s on domain %s is being transmitted in plaintext through MCP", username, domain)
|
|
config, err := c.GetConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
apps, _ := config["apps"].(map[string]interface{})
|
|
httpApps, _ := apps["http"].(map[string]interface{})
|
|
servers, _ := httpApps["servers"].(map[string]interface{})
|
|
|
|
for srvName, server := range servers {
|
|
srv, _ := server.(map[string]interface{})
|
|
routes, _ := srv["routes"].([]interface{})
|
|
|
|
for routeIdx, route := range routes {
|
|
routeMap, _ := route.(map[string]interface{})
|
|
matches, _ := routeMap["match"].([]interface{})
|
|
|
|
for _, match := range matches {
|
|
matchMap, _ := match.(map[string]interface{})
|
|
hosts, _ := matchMap["host"].([]interface{})
|
|
if len(hosts) > 0 {
|
|
d, _ := hosts[0].(string)
|
|
if d == domain {
|
|
handle, _ := routeMap["handle"].([]interface{})
|
|
for i, h := range handle {
|
|
handlerMap, ok := h.(map[string]interface{})
|
|
if !ok {
|
|
continue
|
|
}
|
|
if handlerMap["handler"] == "subroute" {
|
|
subRoutes, _ := handlerMap["routes"].([]interface{})
|
|
if len(subRoutes) > 0 {
|
|
mainRoute, _ := subRoutes[0].(map[string]interface{})
|
|
handlers, _ := mainRoute["handle"].([]interface{})
|
|
|
|
// Check if auth already exists
|
|
var authIdx = -1
|
|
for idx, handler := range handlers {
|
|
hm, _ := handler.(map[string]interface{})
|
|
if hm["handler"] == "authentication" {
|
|
authIdx = idx
|
|
break
|
|
}
|
|
}
|
|
|
|
// WARNING: Passwords are transmitted in plaintext through MCP protocol.
|
|
// This is an architectural limitation of the Model Context Protocol.
|
|
// The password is stored hashed in Caddy (bcrypt), but travels
|
|
// unencrypted from the MCP client to this server.
|
|
newAccount := map[string]interface{}{
|
|
"username": username,
|
|
"password": password,
|
|
}
|
|
|
|
if authIdx >= 0 {
|
|
// Add to existing auth
|
|
authHandler, _ := handlers[authIdx].(map[string]interface{})
|
|
providers, _ := authHandler["providers"].(map[string]interface{})
|
|
httpBasic, _ := providers["http_basic"].(map[string]interface{})
|
|
accounts, _ := httpBasic["accounts"].([]interface{})
|
|
accounts = append(accounts, newAccount)
|
|
httpBasic["accounts"] = accounts
|
|
providers["http_basic"] = httpBasic
|
|
authHandler["providers"] = providers
|
|
handlers[authIdx] = authHandler
|
|
} else {
|
|
// Create new auth handler
|
|
authHandler := map[string]interface{}{
|
|
"handler": "authentication",
|
|
"providers": map[string]interface{}{
|
|
"http_basic": map[string]interface{}{
|
|
"accounts": []interface{}{newAccount},
|
|
"hash": map[string]interface{}{
|
|
"algorithm": "bcrypt",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
handlers = append([]interface{}{authHandler}, handlers...)
|
|
}
|
|
|
|
mainRoute["handle"] = handlers
|
|
subRoutes[0] = mainRoute
|
|
handlerMap["routes"] = subRoutes
|
|
handle[i] = handlerMap
|
|
routeMap["handle"] = handle
|
|
routes[routeIdx] = routeMap
|
|
|
|
configPath := fmt.Sprintf("apps/http/servers/%s/routes", srvName)
|
|
return c.SetConfig(configPath, routes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return fmt.Errorf("site not found: %s", domain)
|
|
}
|
|
|
|
func (c *CaddyClient) RemoveBasicAuth(domain string) error {
|
|
config, err := c.GetConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
apps, _ := config["apps"].(map[string]interface{})
|
|
httpApps, _ := apps["http"].(map[string]interface{})
|
|
servers, _ := httpApps["servers"].(map[string]interface{})
|
|
|
|
for srvName, server := range servers {
|
|
srv, _ := server.(map[string]interface{})
|
|
routes, _ := srv["routes"].([]interface{})
|
|
|
|
for routeIdx, route := range routes {
|
|
routeMap, _ := route.(map[string]interface{})
|
|
matches, _ := routeMap["match"].([]interface{})
|
|
|
|
for _, match := range matches {
|
|
matchMap, _ := match.(map[string]interface{})
|
|
hosts, _ := matchMap["host"].([]interface{})
|
|
if len(hosts) > 0 {
|
|
d, _ := hosts[0].(string)
|
|
if d == domain {
|
|
handle, _ := routeMap["handle"].([]interface{})
|
|
for i, h := range handle {
|
|
handlerMap, ok := h.(map[string]interface{})
|
|
if !ok {
|
|
continue
|
|
}
|
|
if handlerMap["handler"] == "subroute" {
|
|
subRoutes, _ := handlerMap["routes"].([]interface{})
|
|
if len(subRoutes) > 0 {
|
|
mainRoute, _ := subRoutes[0].(map[string]interface{})
|
|
handlers, _ := mainRoute["handle"].([]interface{})
|
|
var newHandlers []interface{}
|
|
for _, handler := range handlers {
|
|
hm, _ := handler.(map[string]interface{})
|
|
if hm["handler"] != "authentication" {
|
|
newHandlers = append(newHandlers, handler)
|
|
}
|
|
}
|
|
mainRoute["handle"] = newHandlers
|
|
subRoutes[0] = mainRoute
|
|
handlerMap["routes"] = subRoutes
|
|
handle[i] = handlerMap
|
|
routeMap["handle"] = handle
|
|
routes[routeIdx] = routeMap
|
|
|
|
configPath := fmt.Sprintf("apps/http/servers/%s/routes", srvName)
|
|
return c.SetConfig(configPath, routes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return fmt.Errorf("site not found: %s", domain)
|
|
}
|