0.27.0 — Infisical hardening: runtime refresh, audit logging, CLI verify/audit, startup verification, SSH host key verification, interface consolidation
This commit is contained in:
@@ -5,11 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/dtoro/oikos/internal/secrets"
|
||||
"github.com/google/uuid"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// mockSecretBackend implements secretBackend for testing.
|
||||
type mockSecretBackend struct {
|
||||
data map[string]string
|
||||
}
|
||||
@@ -17,7 +17,7 @@ type mockSecretBackend struct {
|
||||
func (m *mockSecretBackend) Get(ctx context.Context, key string) (string, error) {
|
||||
v, ok := m.data[key]
|
||||
if !ok {
|
||||
return "", &secretErr{msg: "secret not found: " + key}
|
||||
return "", secrets.ErrNotFound
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
@@ -35,12 +35,10 @@ func (m *mockSecretBackend) List(ctx context.Context) ([]string, error) {
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
type secretErr struct{ msg string }
|
||||
|
||||
func (e *secretErr) Error() string { return e.msg }
|
||||
func (m *mockSecretBackend) Name() string { return "mock" }
|
||||
|
||||
// findToolHandler locates a tool's handler from allTools by name.
|
||||
func findToolHandler(t *testing.T, pool interface{}, name string, sec secretBackend) func(context.Context, *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
func findToolHandler(t *testing.T, pool interface{}, name string, sec secrets.Backend) func(context.Context, *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
t.Helper()
|
||||
for _, r := range allTools(nil, uuid.Nil, sec) {
|
||||
if r.tool.Name == name {
|
||||
@@ -51,7 +49,7 @@ func findToolHandler(t *testing.T, pool interface{}, name string, sec secretBack
|
||||
return nil
|
||||
}
|
||||
|
||||
func callToolJSON(t *testing.T, name string, sec secretBackend, args map[string]any) any {
|
||||
func callToolJSON(t *testing.T, name string, sec secrets.Backend, args map[string]any) any {
|
||||
t.Helper()
|
||||
handler := findToolHandler(t, nil, name, sec)
|
||||
argBytes, _ := json.Marshal(args)
|
||||
@@ -74,7 +72,7 @@ func callToolJSON(t *testing.T, name string, sec secretBackend, args map[string]
|
||||
return out
|
||||
}
|
||||
|
||||
func callToolText(t *testing.T, name string, sec secretBackend, args map[string]any) string {
|
||||
func callToolText(t *testing.T, name string, sec secrets.Backend, args map[string]any) string {
|
||||
t.Helper()
|
||||
handler := findToolHandler(t, nil, name, sec)
|
||||
argBytes, _ := json.Marshal(args)
|
||||
|
||||
@@ -19,12 +19,14 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/dtoro/oikos/internal/actuator"
|
||||
"github.com/dtoro/oikos/internal/db"
|
||||
"github.com/dtoro/oikos/internal/db/sqlcgen"
|
||||
"github.com/dtoro/oikos/internal/execlog"
|
||||
"github.com/dtoro/oikos/internal/observability"
|
||||
"github.com/dtoro/oikos/internal/policy"
|
||||
"github.com/dtoro/oikos/internal/remote"
|
||||
"github.com/dtoro/oikos/internal/secrets"
|
||||
"github.com/google/jsonschema-go/jsonschema"
|
||||
"github.com/google/uuid"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
@@ -47,18 +49,9 @@ func objSchema(props ...prop) *jsonschema.Schema {
|
||||
return s
|
||||
}
|
||||
|
||||
// secretBackend is the interface MCP tools use to access the secrets store.
|
||||
// Defined here to avoid importing the full secrets package (which brings in
|
||||
// the Infisical SDK). Mirrors the subset of secrets.Backend used by tools.
|
||||
type secretBackend interface {
|
||||
Get(ctx context.Context, key string) (string, error)
|
||||
Set(ctx context.Context, key string, value string) error
|
||||
List(ctx context.Context) ([]string, error)
|
||||
}
|
||||
|
||||
// NewHandler creates an http.Handler that serves the Oikos MCP server.
|
||||
// agentID is the Nomos agent entity UUID; tool calls are logged to agent_activity.
|
||||
func NewHandler(pool *db.Pool, token string, agentID uuid.UUID, sec secretBackend) http.Handler {
|
||||
func NewHandler(pool *db.Pool, token string, agentID uuid.UUID, sec secrets.Backend) http.Handler {
|
||||
s := newServer(pool, agentID, sec)
|
||||
handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
|
||||
if token != "" {
|
||||
@@ -74,7 +67,7 @@ func NewHandler(pool *db.Pool, token string, agentID uuid.UUID, sec secretBacken
|
||||
// toolHandler is the function signature registered via AddTool.
|
||||
type toolHandler = mcp.ToolHandler
|
||||
|
||||
func newServer(pool *db.Pool, agentID uuid.UUID, sec secretBackend) *mcp.Server {
|
||||
func newServer(pool *db.Pool, agentID uuid.UUID, sec secrets.Backend) *mcp.Server {
|
||||
s := mcp.NewServer(&mcp.Implementation{Name: "oikos", Version: "dev"}, &mcp.ServerOptions{
|
||||
Logger: slog.Default(),
|
||||
})
|
||||
@@ -499,7 +492,7 @@ func sshExecStream(ctx context.Context, host, user, command string, sink execlog
|
||||
cfg := &ssh.ClientConfig{
|
||||
User: user,
|
||||
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
HostKeyCallback: actuator.HostKeyCallback(),
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/dtoro/oikos/internal/db/sqlcgen"
|
||||
"github.com/dtoro/oikos/internal/observability"
|
||||
"github.com/dtoro/oikos/internal/policy"
|
||||
"github.com/dtoro/oikos/internal/secrets"
|
||||
"github.com/google/uuid"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
@@ -29,7 +30,7 @@ type toolReg struct {
|
||||
// allTools returns every MCP tool registration. Tool definitions, schemas,
|
||||
// descriptions, and handler bodies are kept verbatim from the former inline
|
||||
// newServer registrations.
|
||||
func allTools(pool *db.Pool, agentID uuid.UUID, sec secretBackend) []toolReg {
|
||||
func allTools(pool *db.Pool, agentID uuid.UUID, sec secrets.Backend) []toolReg {
|
||||
return []toolReg{
|
||||
{tool: &mcp.Tool{Name: "ping", Description: "Lightweight connectivity check. Returns server identity, no DB hit.",
|
||||
InputSchema: objSchema(),
|
||||
|
||||
Reference in New Issue
Block a user