@@ -20,14 +20,18 @@ import (
20
20
"context"
21
21
"errors"
22
22
"fmt"
23
+ "io"
24
+ "net/http"
23
25
"net/url"
26
+ "strings"
24
27
"sync"
25
28
"time"
26
29
27
30
"github.com/vmware/govmomi/vapi/rest"
28
31
"github.com/vmware/govmomi/vapi/tags"
29
32
"github.com/vmware/govmomi/vim25/mo"
30
33
"github.com/vmware/govmomi/vim25/types"
34
+ "github.com/vmware/govmomi/vim25/xml"
31
35
32
36
"github.com/google/uuid"
33
37
"github.com/vmware/govmomi"
@@ -57,6 +61,88 @@ type Session struct {
57
61
sessionKey string
58
62
}
59
63
64
+ // #### Start: This section was added by cursor
65
+
66
+ // SOAPResponse represents the structure of SOAP responses
67
+ type SOAPResponse struct {
68
+ XMLName xml.Name `xml:"Envelope"`
69
+ Body struct {
70
+ XMLName xml.Name `xml:"Body"`
71
+ Fault * struct {
72
+ XMLName xml.Name `xml:"Fault"`
73
+ Code struct {
74
+ XMLName xml.Name `xml:"faultcode"`
75
+ Value string `xml:",chardata"`
76
+ } `xml:"faultcode"`
77
+ Reason struct {
78
+ XMLName xml.Name `xml:"faultstring"`
79
+ Value string `xml:",chardata"`
80
+ } `xml:"faultstring"`
81
+ Detail struct {
82
+ XMLName xml.Name `xml:"detail"`
83
+ Content string `xml:",chardata"`
84
+ } `xml:"detail"`
85
+ } `xml:"Fault,omitempty"`
86
+ } `xml:"Body"`
87
+ }
88
+
89
+ // CustomTransport wraps the default transport to intercept SOAP responses
90
+ type CustomTransport struct {
91
+ http.RoundTripper
92
+ }
93
+
94
+ func (t * CustomTransport ) RoundTrip (req * http.Request ) (* http.Response , error ) {
95
+ // Call the original transport
96
+ resp , err := t .RoundTripper .RoundTrip (req )
97
+ if err != nil {
98
+ return resp , err
99
+ }
100
+
101
+ // Read the response body
102
+ body , err := io .ReadAll (resp .Body )
103
+ if err != nil {
104
+ return resp , err
105
+ }
106
+ resp .Body .Close ()
107
+
108
+ // Check if it's a SOAP response
109
+ if strings .Contains (string (body ), "<?xml" ) && strings .Contains (string (body ), "Envelope" ) {
110
+ // Parse SOAP response for privilege errors
111
+ var soapResp SOAPResponse
112
+ if err := xml .Unmarshal (body , & soapResp ); err == nil {
113
+ if soapResp .Body .Fault != nil {
114
+ klog .Error ("=== PRIVILEGE ERROR DETECTED ===" )
115
+ klog .Errorf ("Fault Code: %s\n " , soapResp .Body .Fault .Code .Value )
116
+ klog .Errorf ("Fault Reason: %s\n " , soapResp .Body .Fault .Reason .Value )
117
+ klog .Errorf ("Fault Detail: %s\n " , soapResp .Body .Fault .Detail .Content )
118
+ klog .Error ("================================\n " )
119
+ }
120
+ }
121
+
122
+ // Check for privilege-related error messages in the response
123
+ bodyStr := string (body )
124
+ privilegeKeywords := []string {
125
+ "privilege" , "permission" , "access denied" , "unauthorized" , "forbidden" ,
126
+ "NoPermission" , "InvalidLogin" , "InvalidPrivilege" ,
127
+ }
128
+ for _ , keyword := range privilegeKeywords {
129
+ if strings .Contains (strings .ToLower (bodyStr ), strings .ToLower (keyword )) {
130
+ klog .Errorf ("=== POTENTIAL PRIVILEGE ISSUE DETECTED (keyword: %s) ===\n " , keyword )
131
+ klog .Error ("Response contains privilege-related content\n " )
132
+ klog .Error ("==================================================" )
133
+ break
134
+ }
135
+ }
136
+ fmt .Println ("=== End SOAP Response ===\n " )
137
+ }
138
+
139
+ // Create a new response with the body
140
+ resp .Body = io .NopCloser (strings .NewReader (string (body )))
141
+ return resp , nil
142
+ }
143
+
144
+ // #### End: This section was added by cursor
145
+
60
146
func newClientWithTimeout (ctx context.Context , u * url.URL , insecure bool , timeout time.Duration ) (* govmomi.Client , error ) {
61
147
clientCreateCtx , clientCreateCtxCancel := context .WithTimeout (ctx , timeout )
62
148
defer clientCreateCtxCancel ()
@@ -65,6 +151,14 @@ func newClientWithTimeout(ctx context.Context, u *url.URL, insecure bool, timeou
65
151
if err != nil {
66
152
return nil , err
67
153
}
154
+
155
+ customTransport := & CustomTransport {
156
+ RoundTripper : http .DefaultTransport ,
157
+ }
158
+
159
+ // Create SOAP client with custom transport
160
+ client .Transport = customTransport
161
+
68
162
client .Timeout = timeout
69
163
return client , nil
70
164
}
0 commit comments