feat: add psql shell and username-to-shell routing
Add a PostgreSQL psql interactive terminal shell with backslash meta-commands, SQL statement handling with multi-line buffering, and canned responses for common queries. Add username-based shell routing via [shell.username_routes] config (second priority after credential- specific shell, before random selection). Bump version to 0.13.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,10 +28,11 @@ type WebConfig struct {
|
||||
}
|
||||
|
||||
type ShellConfig struct {
|
||||
Hostname string `toml:"hostname"`
|
||||
Banner string `toml:"banner"`
|
||||
FakeUser string `toml:"fake_user"`
|
||||
Shells map[string]map[string]any `toml:"-"` // per-shell config extracted manually
|
||||
Hostname string `toml:"hostname"`
|
||||
Banner string `toml:"banner"`
|
||||
FakeUser string `toml:"fake_user"`
|
||||
UsernameRoutes map[string]string `toml:"username_routes"`
|
||||
Shells map[string]map[string]any `toml:"-"` // per-shell config extracted manually
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
@@ -165,9 +166,10 @@ func applyDefaults(cfg *Config) {
|
||||
|
||||
// knownShellKeys are top-level keys in [shell] that are not per-shell sub-tables.
|
||||
var knownShellKeys = map[string]bool{
|
||||
"hostname": true,
|
||||
"banner": true,
|
||||
"fake_user": true,
|
||||
"hostname": true,
|
||||
"banner": true,
|
||||
"fake_user": true,
|
||||
"username_routes": true,
|
||||
}
|
||||
|
||||
// extractShellTables pulls per-shell config sub-tables from the raw [shell] section.
|
||||
|
||||
@@ -313,6 +313,42 @@ func TestLoadInvalidTOML(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadUsernameRoutes(t *testing.T) {
|
||||
content := `
|
||||
[shell]
|
||||
hostname = "myhost"
|
||||
|
||||
[shell.username_routes]
|
||||
postgres = "psql"
|
||||
admin = "bash"
|
||||
|
||||
[shell.bash]
|
||||
custom_key = "value"
|
||||
`
|
||||
path := writeTemp(t, content)
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if cfg.Shell.UsernameRoutes == nil {
|
||||
t.Fatal("UsernameRoutes should not be nil")
|
||||
}
|
||||
if cfg.Shell.UsernameRoutes["postgres"] != "psql" {
|
||||
t.Errorf("UsernameRoutes[\"postgres\"] = %q, want %q", cfg.Shell.UsernameRoutes["postgres"], "psql")
|
||||
}
|
||||
if cfg.Shell.UsernameRoutes["admin"] != "bash" {
|
||||
t.Errorf("UsernameRoutes[\"admin\"] = %q, want %q", cfg.Shell.UsernameRoutes["admin"], "bash")
|
||||
}
|
||||
// username_routes should NOT appear in the Shells map.
|
||||
if _, ok := cfg.Shell.Shells["username_routes"]; ok {
|
||||
t.Error("username_routes should not appear in Shells map")
|
||||
}
|
||||
// bash should still appear in Shells map.
|
||||
if _, ok := cfg.Shell.Shells["bash"]; !ok {
|
||||
t.Error("Shells[\"bash\"] should still be present")
|
||||
}
|
||||
}
|
||||
|
||||
func writeTemp(t *testing.T, content string) string {
|
||||
t.Helper()
|
||||
path := filepath.Join(t.TempDir(), "config.toml")
|
||||
|
||||
Reference in New Issue
Block a user