@@ -2,18 +2,22 @@ package pam
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "io"
78 "net"
89 "os"
910 "os/signal"
11+ "strings"
1012 "syscall"
1113 "time"
1214
1315 "github.com/Infisical/infisical-merge/packages/api"
16+ "github.com/Infisical/infisical-merge/packages/config"
1417 "github.com/Infisical/infisical-merge/packages/pam/session"
1518 "github.com/Infisical/infisical-merge/packages/util"
1619 "github.com/go-resty/resty/v2"
20+ "github.com/manifoldco/promptui"
1721 "github.com/rs/zerolog/log"
1822)
1923
@@ -30,6 +34,18 @@ const (
3034 ALPNInfisicalPAMCancellation ALPN = "infisical-pam-session-cancellation"
3135)
3236
37+ func askForApprovalRequestTrigger () (bool , error ) {
38+ prompt := promptui.Prompt {
39+ Label : "This action requires approval. You may create an approval request now. Continue?" ,
40+ IsConfirm : true ,
41+ }
42+ result , err := prompt .Run ()
43+ if err != nil {
44+ return false , err
45+ }
46+ return strings .ToLower (result ) == "y" , nil
47+ }
48+
3349func StartDatabaseLocalProxy (accessToken string , accountPath string , projectID string , durationStr string , port int ) {
3450 log .Info ().Msgf ("Starting database proxy for account: %s" , accountPath )
3551 log .Info ().Msgf ("Session duration: %s" , durationStr )
@@ -46,6 +62,48 @@ func StartDatabaseLocalProxy(accessToken string, accountPath string, projectID s
4662
4763 pamResponse , err := api .CallPAMAccess (httpClient , pamRequest )
4864 if err != nil {
65+ var apiErr * api.APIError
66+ if errors .As (err , & apiErr ) && apiErr .ErrorMessage == "A policy is in place for this resource" {
67+ if v , ok := apiErr .Details .(map [string ]any ); ok {
68+ log .Info ().Msgf ("Account is protected by approval policy: %s" , v ["policyName" ])
69+
70+ shouldSendRequest , err := askForApprovalRequestTrigger ()
71+ if err != nil {
72+ if errors .Is (err , promptui .ErrAbort ) {
73+ log .Info ().Msgf ("Approval request was not created." )
74+ } else {
75+ util .HandleError (err , "Failed to send PAM account request" )
76+ }
77+ return
78+ }
79+
80+ if ! shouldSendRequest {
81+ log .Info ().Msgf ("Approval request was not created." )
82+ return
83+ }
84+
85+ approvalReq , err := api .CallPAMAccessApprovalRequest (httpClient , api.PAMAccessApprovalRequest {
86+ ProjectId : projectID ,
87+ RequestData : api.PAMAccessApprovalRequestPayloadRequestData {
88+ AccountPath : accountPath ,
89+ AccessDuration : durationStr ,
90+ },
91+ })
92+ if err != nil {
93+ util .HandleError (err , "Failed to send PAM account request" )
94+ return
95+ }
96+
97+ url := fmt .Sprintf ("%s/organizations/%s/projects/pam/%s/approval-requests/%s" , strings .TrimSuffix (config .INFISICAL_URL , "/api" ), approvalReq .Request .OrgId , approvalReq .Request .ProjectId , approvalReq .Request .ID )
98+ if err := util .OpenBrowser (url ); err != nil {
99+ log .Error ().Msgf ("Failed to do browser redirect: %v" , err )
100+ }
101+ log .Info ().Msgf ("Approval request created." )
102+ log .Info ().Msgf ("View details at: %s" , url )
103+ return
104+ }
105+ }
106+
49107 util .HandleError (err , "Failed to access PAM account" )
50108 return
51109 }
0 commit comments