From 7f412ea93144cc055512c74406b2391a3910197e Mon Sep 17 00:00:00 2001 From: Scott Leggett Date: Fri, 23 Aug 2024 20:55:51 +0800 Subject: [PATCH] chore: add keycloak debug command --- README.md | 13 ++++++++++ cmd/keycloak-debug/dumpgroups.go | 42 ++++++++++++++++++++++++++++++++ cmd/keycloak-debug/main.go | 33 +++++++++++++++++++++++++ go.mod | 2 +- 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 cmd/keycloak-debug/dumpgroups.go create mode 100644 cmd/keycloak-debug/main.go diff --git a/README.md b/README.md index 4dc209fa..38f65068 100644 --- a/README.md +++ b/README.md @@ -157,3 +157,16 @@ If a user gets an error from a Lagoon SSH service it may not contain much detail However, errors returned to the user will contain a unique Session ID (SID). This SID is also logged to the standard error of the SSH service along with any errors, so it will appear in the container logs along with more detail about exactly what went wrong. This helps to correlate error messages reported by users with detailed errors in service logs visible only to administrators. + +## Development tips + +### Debugging Keycloak permissions + +A command to debug Keycloak permissions locally is included in `./cmd/keycloak-debug`. +This command uses the same Keycloak client and permissions code as the `ssh-portal-api`. +Run it to dump the Keycloak `group-name:group-id` map, and easily reproduce any errors. + +```bash +export KEYCLOAK_BASE_URL=http://lagoon-keycloak.example.com/ KEYCLOAK_SERVICE_API_CLIENT_SECRET=abc-123 +go run ./cmd/keycloak-debug +``` diff --git a/cmd/keycloak-debug/dumpgroups.go b/cmd/keycloak-debug/dumpgroups.go new file mode 100644 index 00000000..2308da4e --- /dev/null +++ b/cmd/keycloak-debug/dumpgroups.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "fmt" + "log/slog" + "os/signal" + "syscall" + + "github.com/davecgh/go-spew/spew" + "github.com/uselagoon/ssh-portal/internal/keycloak" +) + +// DumpGroupsCmd represents the dump-groups command. +type DumpGroupsCmd struct { + KeycloakBaseURL string `kong:"required,env='KEYCLOAK_BASE_URL',help='Keycloak Base URL'"` + KeycloakClientID string `kong:"default='service-api',env='KEYCLOAK_SERVICE_API_CLIENT_ID',help='Keycloak OAuth2 Client ID'"` + KeycloakClientSecret string `kong:"required,env='KEYCLOAK_SERVICE_API_CLIENT_SECRET',help='Keycloak OAuth2 Client Secret'"` + KeycloakRateLimit int `kong:"default=10,env='KEYCLOAK_RATE_LIMIT',help='Keycloak API Rate Limit (requests/second)'"` +} + +// Run the serve command to ssh-portal API requests. +func (cmd *DumpGroupsCmd) Run(log *slog.Logger) error { + // get main process context, which cancels on SIGTERM + ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM) + defer stop() + // init keycloak client + k, err := keycloak.NewClient(ctx, log, + cmd.KeycloakBaseURL, + cmd.KeycloakClientID, + cmd.KeycloakClientSecret, + cmd.KeycloakRateLimit) + if err != nil { + return fmt.Errorf("couldn't init keycloak client: %v", err) + } + groupMap, err := k.GroupNameGroupIDMap(ctx) + if err != nil { + return fmt.Errorf("couldn't get keycloak group map: %v", err) + } + spew.Dump(groupMap) + return nil +} diff --git a/cmd/keycloak-debug/main.go b/cmd/keycloak-debug/main.go new file mode 100644 index 00000000..5c8327f2 --- /dev/null +++ b/cmd/keycloak-debug/main.go @@ -0,0 +1,33 @@ +// Package main implements the ssh-portal-api service. +package main + +import ( + "log/slog" + "os" + + "github.com/alecthomas/kong" +) + +// CLI represents the command-line interface. +type CLI struct { + Debug bool `kong:"env='DEBUG',help='Enable debug logging'"` + DumpGroups DumpGroupsCmd `kong:"cmd,default=1,help='(default) Serve ssh-portal-api requests'"` +} + +func main() { + // parse CLI config + cli := CLI{} + kctx := kong.Parse(&cli, + kong.UsageOnError(), + ) + // init logger + var log *slog.Logger + if cli.Debug { + log = slog.New(slog.NewJSONHandler(os.Stderr, + &slog.HandlerOptions{Level: slog.LevelDebug})) + } else { + log = slog.New(slog.NewJSONHandler(os.Stderr, nil)) + } + // execute CLI + kctx.FatalIfErrorf(kctx.Run(log)) +} diff --git a/go.mod b/go.mod index 75a59ad5..82eca93b 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/MicahParks/keyfunc/v2 v2.1.0 github.com/alecthomas/assert/v2 v2.10.0 github.com/alecthomas/kong v0.9.0 + github.com/davecgh/go-spew v1.1.1 github.com/gliderlabs/ssh v0.3.7 github.com/go-sql-driver/mysql v1.8.1 github.com/golang-jwt/jwt/v5 v5.2.1 @@ -35,7 +36,6 @@ require ( github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.2 // indirect