feat: load agent bridge from protected storage
This commit is contained in:
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.cin.su/m/Assistant/adapters/agentbridge"
|
||||
@@ -39,7 +41,7 @@ func main() {
|
||||
}
|
||||
defer repository.Close()
|
||||
var executor ports.AgentExecutor
|
||||
if bridgeURL := os.Getenv("AGENT_EXECUTION_BRIDGE_URL"); bridgeURL != "" {
|
||||
if bridgeURL, bridgeConfigured := loadProtectedBridgeURL(); bridgeConfigured {
|
||||
executor, err = agentbridge.NewHTTPExecutor(bridgeURL, &http.Client{Timeout: *leaseTTL})
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
@@ -81,6 +83,27 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func loadProtectedBridgeURL() (string, bool) {
|
||||
return loadProtectedBridgeURLFrom("/run/secrets", "/run/secrets/agent_execution_bridge_url")
|
||||
}
|
||||
|
||||
func loadProtectedBridgeURLFrom(root, path string) (string, bool) {
|
||||
clean := filepath.Clean(path)
|
||||
cleanRoot := filepath.Clean(root)
|
||||
if clean != cleanRoot && !strings.HasPrefix(clean, cleanRoot+string(os.PathSeparator)) {
|
||||
return "", false
|
||||
}
|
||||
payload, err := os.ReadFile(clean)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
value := strings.TrimSpace(string(payload))
|
||||
if value == "" || strings.ContainsAny(value, "\r\n") {
|
||||
return "", false
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
func resolveDatabasePassword(name, refName string, consumer secretcontracts.RuntimeConsumer) (string, error) {
|
||||
if _, ok := os.LookupEnv(name); ok {
|
||||
return "", fmt.Errorf("%s direct environment secret is forbidden", name)
|
||||
|
||||
@@ -19,7 +19,7 @@ func workerStatusHandler(executorConfigured bool) http.Handler {
|
||||
ExecutorConfigured: executorConfigured,
|
||||
Mode: "recovery-only",
|
||||
Ready: false,
|
||||
Reason: "AGENT_EXECUTION_BRIDGE_URL is not configured",
|
||||
Reason: "protected agent execution bridge URL is not configured",
|
||||
}
|
||||
if executorConfigured {
|
||||
status.Mode = "execution"
|
||||
|
||||
@@ -4,9 +4,28 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadProtectedBridgeURL(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
path := filepath.Join(root, "agent_execution_bridge_url")
|
||||
if err := os.WriteFile(path, []byte("http://bridge.local\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if value, configured := loadProtectedBridgeURLFrom(root, path); !configured || value != "http://bridge.local" {
|
||||
t.Fatalf("protected bridge was not loaded: %q %v", value, configured)
|
||||
}
|
||||
if value, configured := loadProtectedBridgeURLFrom(root, filepath.Join(root, "missing")); configured || value != "" {
|
||||
t.Fatalf("missing bridge was accepted: %q %v", value, configured)
|
||||
}
|
||||
if value, configured := loadProtectedBridgeURLFrom(root, "/tmp/not-protected"); configured || value != "" {
|
||||
t.Fatalf("path outside protected root was accepted: %q %v", value, configured)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkerStatusReportsRecoveryOnlyWithoutExecutor(t *testing.T) {
|
||||
response := httptest.NewRecorder()
|
||||
workerStatusHandler(false).ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/status", nil))
|
||||
|
||||
Reference in New Issue
Block a user