@@ -4,14 +4,18 @@ import (
44 "context"
55 "crypto/tls"
66 "crypto/x509"
7+ "encoding/json"
78 "fmt"
9+ "io"
810 "net"
11+ "slices"
912 "strconv"
1013 "strings"
1114 "sync"
1215 "time"
1316
1417 "github.com/Infisical/infisical-merge/packages/api"
18+ "github.com/Infisical/infisical-merge/packages/pam"
1519 "github.com/Infisical/infisical-merge/packages/util"
1620 "github.com/go-resty/resty/v2"
1721 "github.com/rs/zerolog/log"
@@ -29,6 +33,7 @@ type BaseProxyServer struct {
2933 gatewayServerCertChain string
3034 sessionExpiry time.Time
3135 sessionId string
36+ resourceType string
3237 ctx context.Context
3338 cancel context.CancelFunc
3439 activeConnections sync.WaitGroup
@@ -88,6 +93,64 @@ func (b *BaseProxyServer) CreateRelayConnection() (net.Conn, error) {
8893 return conn , nil
8994}
9095
96+ // FetchGatewayCapabilities fetches the supported resource types from the gateway
97+ func (b * BaseProxyServer ) FetchGatewayCapabilities () (* pam.PAMCapabilitiesResponse , error ) {
98+ relayConn , err := b .CreateRelayConnection ()
99+ if err != nil {
100+ return nil , fmt .Errorf ("failed to connect to relay: %w" , err )
101+ }
102+ defer relayConn .Close ()
103+
104+ gatewayConn , err := b .CreateGatewayConnection (relayConn , ALPNInfisicalPAMCapabilities )
105+ if err != nil {
106+ return nil , fmt .Errorf ("failed to connect to gateway: %w" , err )
107+ }
108+ defer gatewayConn .Close ()
109+
110+ // Read length prefix (4 bytes)
111+ lengthBytes := make ([]byte , 4 )
112+ if _ , err := io .ReadFull (gatewayConn , lengthBytes ); err != nil {
113+ return nil , fmt .Errorf ("failed to read length prefix: %w" , err )
114+ }
115+
116+ length := uint32 (lengthBytes [0 ])<< 24 | uint32 (lengthBytes [1 ])<< 16 | uint32 (lengthBytes [2 ])<< 8 | uint32 (lengthBytes [3 ])
117+
118+ // Read JSON data
119+ data := make ([]byte , length )
120+ if _ , err := io .ReadFull (gatewayConn , data ); err != nil {
121+ return nil , fmt .Errorf ("failed to read capabilities response: %w" , err )
122+ }
123+
124+ var response pam.PAMCapabilitiesResponse
125+ if err := json .Unmarshal (data , & response ); err != nil {
126+ return nil , fmt .Errorf ("failed to parse capabilities response: %w" , err )
127+ }
128+
129+ log .Debug ().Strs ("supportedTypes" , response .SupportedResourceTypes ).Msg ("Received gateway capabilities" )
130+ return & response , nil
131+ }
132+
133+ // ValidateResourceTypeSupported checks if the resource type is supported by the gateway
134+ func (b * BaseProxyServer ) ValidateResourceTypeSupported () error {
135+ capabilities , err := b .FetchGatewayCapabilities ()
136+ if err != nil {
137+ return fmt .Errorf ("failed to fetch gateway capabilities: %w" , err )
138+ }
139+
140+ if slices .Contains (capabilities .SupportedResourceTypes , b .resourceType ) {
141+ return nil
142+ }
143+
144+ return fmt .Errorf (`Your Gateway does not support '%s' PAM accounts.
145+
146+ To fix this:
147+ 1. Update your Gateway deployment
148+ 2. Restart the Gateway service
149+ 3. Retry your access command
150+
151+ Gateway upgrade guide: https://infisical.com/docs/documentation/platform/gateways/gateway-deployment` , b .resourceType )
152+ }
153+
91154// CreateGatewayConnection establishes a mTLS connection to the gateway over the relay
92155func (b * BaseProxyServer ) CreateGatewayConnection (relayConn net.Conn , alpn ALPN ) (net.Conn , error ) {
93156 // Load gateway certificates
0 commit comments