Open lelvisl opened 3 years ago
As long as you using *govcd.VCDClient for a long time, its auth expires in accordance with auth timeout settings in vcd.
*govcd.VCDClient
State now: handle 401 error and reauth, after this repeat request. And you need have this logic near of every govcd call.
Example of solution with http transport:
package vcdreauth import ( "fmt" "net/http" "strings" "github.com/vmware/go-vcloud-director/v2/govcd" ) type Transport struct { cli *govcd.VCDClient user string password string org string next http.RoundTripper maxAttempts uint } func NewReAuthTransport(cli *govcd.VCDClient, user, password, org string, maxAttempts uint) *Transport { if maxAttempts < 1 { maxAttempts = DefaultReAuthMaxAttempts } return &Transport{ cli: cli, user: user, password: password, org: org, next: cli.Client.Http.Transport, maxAttempts: maxAttempts, } } const DefaultReAuthMaxAttempts = 1 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { for count := 0; count < DefaultReAuthMaxAttempts+1; count++ { // Perform request resp, err := t.next.RoundTrip(req) // don't try to retry auth enpoints if req.URL.Path == "/api/sessions" || strings.Contains(req.URL.Path, "/cloudapi/1.0.0/sessions/provider") { return resp, err } // if status not 401 - don't try to retry if resp.StatusCode != http.StatusUnauthorized { return resp, err } // close the response body when we wont use it anymore if resp != nil { _ = resp.Body.Close() } authResp, err := t.cli.GetAuthResponse(t.user, t.password, t.org) if err != nil { return nil, fmt.Errorf("unable to authenticate: %w", err) } // re-setup auth headers if t.cli.Client.VCDAuthHeader != "" && t.cli.Client.VCDToken != "" { // Add the authorization header req.Header.Set(t.cli.Client.VCDAuthHeader, t.cli.Client.VCDToken) } if len(t.cli.Client.VCDToken) > 32 { req.Header.Set("X-Vmware-Vcloud-Token-Type", "Bearer") req.Header.Set("Authorization", "bearer "+t.cli.Client.VCDToken) } if authResp != nil { _ = authResp.Body.Close() } } return nil, fmt.Errorf("unauthorized - max attempts (%d)", t.maxAttempts) }
Example of usage:
vcdclient := govcd.NewVCDClient(*u, Insecure, govcd.WithHttpUserAgent(userAgent)) vcdclient.Client.Http.Transport = vcdreauth.NewReAuthTransport(vcdclient, User, Password, systemOrg, 1) _, err := vcdclient.GetAuthResponse(User, Password, systemOrg)
if you ok with this solution, i can add it as PR.
P.S. I'm already using this code in my project and its working well.
@dataclouder is it correct flow for reauth?
As long as you using
*govcd.VCDClient
for a long time, its auth expires in accordance with auth timeout settings in vcd.State now: handle 401 error and reauth, after this repeat request. And you need have this logic near of every govcd call.
Example of solution with http transport:
Example of usage:
if you ok with this solution, i can add it as PR.
P.S. I'm already using this code in my project and its working well.