-
Notifications
You must be signed in to change notification settings - Fork 43
feat(pam): add --target flag to select a host on pam access #286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: pam-revamp
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,17 +17,17 @@ import ( | |
|
|
||
| // Account type constants (match API enum) | ||
| const ( | ||
| AccountTypePostgres = "postgres" | ||
| AccountTypeSSH = "ssh" | ||
| AccountTypeMySQL = "mysql" | ||
| AccountTypeMsSQL = "mssql" | ||
| AccountTypeMongoDB = "mongodb" | ||
| AccountTypeOracleDB = "oracledb" | ||
| AccountTypeRedis = "redis" | ||
| AccountTypeKubernetes = "kubernetes" | ||
| AccountTypeAwsIam = "aws-iam" | ||
| AccountTypeWindows = "windows" | ||
| AccountTypeActiveDirectory = "active-directory" | ||
| AccountTypePostgres = "postgres" | ||
| AccountTypeSSH = "ssh" | ||
| AccountTypeMySQL = "mysql" | ||
| AccountTypeMsSQL = "mssql" | ||
| AccountTypeMongoDB = "mongodb" | ||
| AccountTypeOracleDB = "oracledb" | ||
| AccountTypeRedis = "redis" | ||
| AccountTypeKubernetes = "kubernetes" | ||
| AccountTypeAwsIam = "aws-iam" | ||
| AccountTypeWindows = "windows" | ||
| AccountTypeWindowsAd = "windows-ad" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ) | ||
|
|
||
| // normalizePath ensures the path has a leading slash for display purposes. | ||
|
|
@@ -53,7 +53,7 @@ func parsePath(path string) (folder, account string) { | |
|
|
||
| // StartPAMAccess initiates a PAM session for the account at the given path. | ||
| // The account type is determined from the API response and routed to the appropriate handler. | ||
| func StartPAMAccess(accessToken, path, reason, durationStr string, port int) { | ||
| func StartPAMAccess(accessToken, path, reason, durationStr, targetHost string, port int) { | ||
| // Normalize path for display (ensure leading slash) | ||
| displayPath := normalizePath(path) | ||
|
|
||
|
|
@@ -65,9 +65,10 @@ func StartPAMAccess(accessToken, path, reason, durationStr string, port int) { | |
| httpClient.SetHeader("User-Agent", api.USER_AGENT) | ||
|
|
||
| pamResponse, err := CallPAMAccessWithMFA(httpClient, api.PAMAccessRequest{ | ||
| Path: path, | ||
| Duration: durationStr, | ||
| Reason: reason, | ||
| Path: path, | ||
| Duration: durationStr, | ||
| Reason: reason, | ||
| TargetHost: targetHost, | ||
| }, true) | ||
| if err != nil { | ||
| util.HandleError(err, "Failed to create PAM session") | ||
|
|
@@ -91,10 +92,8 @@ func StartPAMAccess(accessToken, path, reason, durationStr string, port int) { | |
| startKubernetesProxy(httpClient, &pamResponse, displayPath, durationStr, port) | ||
| case AccountTypeAwsIam: | ||
| util.PrintErrorMessageAndExit("AWS IAM access not yet supported in the new PAM model") | ||
| case AccountTypeWindows: | ||
| case AccountTypeWindows, AccountTypeWindowsAd: | ||
| startRDPProxy(httpClient, &pamResponse, displayPath, durationStr, port) | ||
| case AccountTypeActiveDirectory: | ||
| util.PrintErrorMessageAndExit("Active Directory access not yet supported in the new PAM model") | ||
| default: | ||
| util.PrintErrorMessageAndExit(fmt.Sprintf("Unsupported account type: %s", pamResponse.AccountType)) | ||
| } | ||
|
|
@@ -276,10 +275,11 @@ func startRDPProxy(httpClient *resty.Client, response *api.PAMAccessResponse, pa | |
| gatewayServerCertChain: response.GatewayServerCertificateChain, | ||
| sessionExpiry: time.Now().Add(duration), | ||
| sessionId: response.SessionId, | ||
| resourceType: response.AccountType, | ||
| ctx: ctx, | ||
| cancel: cancel, | ||
| shutdownCh: make(chan struct{}), | ||
| // Windows AD is brokered through the Windows RDP gateway protocol | ||
| resourceType: AccountTypeWindows, | ||
| ctx: ctx, | ||
| cancel: cancel, | ||
| shutdownCh: make(chan struct{}), | ||
| }, | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
targetHostis accepted from the command line and forwarded verbatim to the API astargetHostin the PAM access request. If the server uses this value to initiate a backend connection without validating it against a per-account allowlist, a user could supply an arbitrary internal address (e.g.,169.254.169.254,10.0.0.1) to pivot through the gateway into network segments they would not otherwise reach. Client-side format validation (e.g., rejecting bare IPs, enforcing a valid FQDN pattern) would reduce the attack surface, but the authoritative guard must live on the server side.Context Used: Flag SSRF risks (source)