Skip to content
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

Feature: http retry #463

Merged
merged 7 commits into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The process goes something like this:
* [F5APM](pkg/provider/f5apm/README.md)
* [Akamai](pkg/provider/akamai/README.md)
* OneLogin
* NetIQ
* AWS SAML Provider configured

## Caveats
Expand Down Expand Up @@ -486,7 +487,28 @@ aws iam list-groups
}
}
```
## Advanced Configuration - additional parameters
There are few additional parameters allowing to customise saml2aws configuration.
Use following parameters in `~/.saml2aws` file:
- `http_attempts_count` - configures the number of attempts to send http requests in order to authorise with saml provider. Defaults to 1
- `http_retry_delay` - configures the duration (in seconds) of timeout between attempts to send http requests to saml provider. Defaults to 1

Example: typical configuration with such parameters would look like follows:
```
[default]
url = https://id.customer.cloud
username = user@versent.com.au
provider = Ping
mfa = Auto
skip_verify = false
timeout = 0
aws_urn = urn:amazon:webservices
aws_session_duration = 28800
aws_profile = customer-dev
role_arn = arn:aws:iam::121234567890:role/customer-admin-role
http_attempts_count = 3
http_retry_delay = 1
```
## Building

To build this software on osx clone to the repo to `$GOPATH/src/github.com/versent/saml2aws` and ensure you have `$GOPATH/bin` in your `$PATH`.
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ require (
github.com/alecthomas/units v0.0.0-20190910110746-680d30ca3117 // indirect
github.com/andybalholm/cascadia v1.0.0 // indirect
github.com/aulanov/go.dbus v0.0.0-20150729231527-25c3068a42a0 // indirect
github.com/avast/retry-go v2.6.0+incompatible
github.com/aws/aws-sdk-go v1.23.15
github.com/axw/gocov v1.0.0 // indirect
github.com/beevik/etree v1.0.1
github.com/briandowns/spinner v0.0.0-20170614154858-48dbb65d7bd5
github.com/buildkite/github-release v0.0.0-20200205104344-c0a6db85594d // indirect
github.com/danieljoos/wincred v1.0.1
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae // indirect
github.com/fatih/color v1.7.0 // indirect
Expand All @@ -30,7 +29,6 @@ require (
github.com/marshallbrekka/go-u2fhost v0.0.0-20200107013215-ad5fdc1986ac
github.com/mattn/go-isatty v0.0.8
github.com/mitchellh/go-homedir v1.0.0
github.com/mitchellh/gox v1.0.1 // indirect
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/pkg/errors v0.8.1
Expand Down
24 changes: 2 additions & 22 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@ github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRy
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/aulanov/go.dbus v0.0.0-20150729231527-25c3068a42a0 h1:EEDvbomAQ+MFWqJ9FM6RXyJTkc4lckyWsbc5CGQkG1Y=
github.com/aulanov/go.dbus v0.0.0-20150729231527-25c3068a42a0/go.mod h1:VHvUx+4lTCaJ8zUnEXF4cWEc9c8lnDt4PGLwlZ+3yaM=
github.com/avast/retry-go v2.6.0+incompatible h1:FelcMrm7Bxacr1/RM8+/eqkDkmVN7tjlsy51dOzB3LI=
github.com/avast/retry-go v2.6.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.23.15 h1:ut2ZzO0A34Ds18NXvvkWWKyO4aZqQ9uZquslWzCQvGU=
github.com/aws/aws-sdk-go v1.23.15/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/axw/gocov v1.0.0 h1:YsqYR66hUmilVr23tu8USgnJIJvnwh3n7j5zRn7x4LU=
github.com/axw/gocov v1.0.0/go.mod h1:LvQpEYiwwIb2nYkXY2fDWhg9/AsYqkhmrCshjlUJECE=
github.com/beevik/etree v1.0.1 h1:lWzdj5v/Pj1X360EV7bUudox5SRipy4qZLjY0rhb0ck=
github.com/beevik/etree v1.0.1/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/briandowns/spinner v0.0.0-20170614154858-48dbb65d7bd5 h1:osZyZB7J4kE1tKLeaUjV6+uZVBfS835T0I/RxmwWw1w=
github.com/briandowns/spinner v0.0.0-20170614154858-48dbb65d7bd5/go.mod h1:hw/JEQBIE+c/BLI4aKM8UU8v+ZqrD3h7HC27kKt8JQU=
github.com/buildkite/github-release v0.0.0-20200205104344-c0a6db85594d h1:dSMX9iqIZScLmKhyJ+xQcn+gTU2RS5sKpNpRELYod0g=
github.com/buildkite/github-release v0.0.0-20200205104344-c0a6db85594d/go.mod h1:Hd/sX79FgO4Y8/8nczoszTudx5egMjvbUxQgUZ6W2jc=
github.com/danieljoos/wincred v1.0.1 h1:fcRTaj17zzROVqni2FiToKUVg3MmJ4NtMSGCySPIr/g=
github.com/danieljoos/wincred v1.0.1/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
Expand All @@ -46,18 +44,12 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-github v8.0.1-0.20170604030111-7a51fb928f52+incompatible h1:XfCpf6Ak5XPaZpv2rlCqfBuKoFQH5SvXvpQIiV1H7H4=
github.com/google/go-github v8.0.1-0.20170604030111-7a51fb928f52+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
Expand Down Expand Up @@ -89,12 +81,6 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4=
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/oleiade/reflections v0.0.0-20160817071559-0e86b3c98b2f h1:I6mXuorHlvwNDFelz7a+j0HaGYSzX7+Gq60DqLVypfc=
github.com/oleiade/reflections v0.0.0-20160817071559-0e86b3c98b2f/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down Expand Up @@ -128,19 +114,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20170218080159-6b27048ae5e6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190916140828-c8589233b77d h1:mCMDWKhNO37A7GAhOpHPbIw1cjd0V86kX1/WA9c7FZ8=
golang.org/x/net v0.0.0-20190916140828-c8589233b77d/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20170517174439-f047394b6d14 h1:5fvqvN1Glau4dT9f9CReJ/5DQdgl50EfDOzX7jBecZg=
golang.org/x/oauth2 v0.0.0-20170517174439-f047394b6d14/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -155,8 +137,6 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774 h1:CQVOmarCBFzTx0kbOU0ru54Cvot8SdSrNYjZPhQl+gk=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
2 changes: 2 additions & 0 deletions pkg/cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type IDPAccount struct {
ResourceID string `ini:"resource_id"` // used by F5APM
Subdomain string `ini:"subdomain"` // used by OneLogin
RoleARN string `ini:"role_arn"`
HttpAttemptsCount string `ini:"http_attempts_count"`
HttpRetryDelay string `ini:"http_retry_delay"`
}

func (ia IDPAccount) String() string {
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/aad/aad.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {
TLSClientConfig: &tls.Config{InsecureSkipVerify: idpAccount.SkipVerify, Renegotiation: tls.RenegotiateFreelyAsClient},
}

client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "error building http client")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/adfs/adfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {
TLSClientConfig: &tls.Config{InsecureSkipVerify: idpAccount.SkipVerify, Renegotiation: tls.RenegotiateFreelyAsClient},
}

client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "error building http client")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/akamai/akamai.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {

tr := provider.NewDefaultTransport(idpAccount.SkipVerify)

client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "error building http client")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/f5apm/f5apm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Client struct {
func New(idpAccount *cfg.IDPAccount) (*Client, error) {

tr := provider.NewDefaultTransport(idpAccount.SkipVerify)
client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "Error building HTTP client")
}
Expand Down
6 changes: 4 additions & 2 deletions pkg/provider/f5apm/f5apm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func TestClient_getLoginForm(t *testing.T) {

jar, err := cookiejar.New(nil)
require.Nil(t, err)
ac := Client{client: &provider.HTTPClient{Client: http.Client{Jar: jar}}}
opts := &provider.HTTPClientOptions{IsWithRetries: false}
ac := Client{client: &provider.HTTPClient{Client: http.Client{Jar: jar}, Options: opts}}
t.Log(ac)
loginDetails := &creds.LoginDetails{URL: ts.URL, Username: "groundcontrol", Password: "majortom"}
t.Log(loginDetails)
Expand All @@ -52,7 +53,8 @@ func TestClient_postLoginForm_user_pass(t *testing.T) {

jar, err := cookiejar.New(nil)
require.Nil(t, err)
ac := Client{client: &provider.HTTPClient{Client: http.Client{Jar: jar}}}
opts := &provider.HTTPClientOptions{IsWithRetries: false}
ac := Client{client: &provider.HTTPClient{Client: http.Client{Jar: jar}, Options: opts}}
t.Log(ac)
loginDetails := &creds.LoginDetails{URL: ts.URL, Username: "groundcontrol", Password: "majortom"}
t.Log(loginDetails)
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/googleapps/googleapps.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {

tr := provider.NewDefaultTransport(idpAccount.SkipVerify)

client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "error building http client")
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/provider/googleapps/googleapps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ func TestExtractInputsByFormQuery(t *testing.T) {

doc.Url = &url.URL{
Scheme: "https",
Host: "google.com",
Path: "foobar",
Host: "google.com",
Path: "foobar",
}

form, actionURL, err := extractInputsByFormQuery(doc, "#dev")
Expand Down Expand Up @@ -87,7 +87,8 @@ func TestChallengePage(t *testing.T) {
}))
defer ts.Close()

kc := Client{client: &provider.HTTPClient{Client: http.Client{}}}
opts := &provider.HTTPClientOptions{IsWithRetries: false}
kc := Client{client: &provider.HTTPClient{Client: http.Client{}, Options: opts}}
loginDetails := &creds.LoginDetails{URL: ts.URL, Username: "test", Password: "test123"}
authForm := url.Values{}

Expand Down
74 changes: 70 additions & 4 deletions pkg/provider/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package provider
import (
"crypto/tls"
"fmt"
"github.com/avast/retry-go"
"github.com/versent/saml2aws/pkg/cfg"
"net"
"net/http"
"os"
"runtime"
"strconv"
"time"

"github.com/sirupsen/logrus"
Expand All @@ -23,6 +26,18 @@ import (
type HTTPClient struct {
http.Client
CheckResponseStatus func(*http.Request, *http.Response) error
Options *HTTPClientOptions
}

const (
DefaultAttemptsCount = 1
DefaultRetryDelay = time.Duration(1) * time.Second
)

type HTTPClientOptions struct {
IsWithRetries bool //http retry feature switch
AttemptsCount uint
RetryDelay time.Duration
}

// NewDefaultTransport configure a transport with the TLS skip verify option
Expand All @@ -42,8 +57,27 @@ func NewDefaultTransport(skipVerify bool) *http.Transport {
}
}

func BuildHttpClientOpts(account *cfg.IDPAccount) *HTTPClientOptions {
opts := &HTTPClientOptions{}
atmt, atmtErr := strconv.ParseUint(account.HttpAttemptsCount, 10, 0)
if opts.IsWithRetries = atmtErr == nil; opts.IsWithRetries {
opts.AttemptsCount = uint(atmt)
} else {
opts.AttemptsCount = DefaultAttemptsCount
}

delay, delayErr := strconv.ParseUint(account.HttpRetryDelay, 10, 0)
if delayErr != nil {
opts.RetryDelay = DefaultRetryDelay
} else {
opts.RetryDelay = time.Duration(delay) * time.Second
}

return opts
}

// NewHTTPClient configure the default http client used by the providers
func NewHTTPClient(tr http.RoundTripper) (*HTTPClient, error) {
func NewHTTPClient(tr http.RoundTripper, opts *HTTPClientOptions) (*HTTPClient, error) {

options := &cookiejar.Options{
PublicSuffixList: publicsuffix.List,
Expand All @@ -56,7 +90,7 @@ func NewHTTPClient(tr http.RoundTripper) (*HTTPClient, error) {

client := http.Client{Transport: tr, Jar: jar}

return &HTTPClient{client, nil}, nil
return &HTTPClient{client, nil, opts}, nil
}

// Do do the request
Expand All @@ -81,9 +115,15 @@ func (hc *HTTPClient) Do(req *http.Request) (*http.Response, error) {

req.Header.Set("User-Agent", fmt.Sprintf("saml2aws/1.0 (%s %s) Versent", runtime.GOOS, runtime.GOARCH))

hc.logHTTPRequest(req)
var resp *http.Response
var err error

resp, err := hc.Client.Do(req)
if hc.Options.IsWithRetries {
resp, err = hc.doWithRetry(req)
} else {
hc.logHTTPRequest(req)
resp, err = hc.Client.Do(req)
}
if err != nil {
return resp, err
}
Expand All @@ -101,6 +141,32 @@ func (hc *HTTPClient) Do(req *http.Request) (*http.Response, error) {
return resp, err
}

func (hc *HTTPClient) doWithRetry(req *http.Request) (*http.Response, error) {
var resp *http.Response
err := retry.Do(
func() error {
hc.logHTTPRequest(req)
clientResp, err := hc.Client.Do(req)
if err != nil {
return err
}
resp = clientResp
return nil
},
retry.Attempts(hc.Options.AttemptsCount),
retry.Delay(hc.Options.RetryDelay),
retry.OnRetry(
func(n uint, err error) {
logrus.
WithField("Attempt #", n).
WithField("Caused by", fmt.Errorf("%v", err)).
Debug("Retry")
}),
)
return resp, err

}

// DisableFollowRedirect disable redirects
func (hc *HTTPClient) DisableFollowRedirect() {
hc.CheckRedirect = func(req *http.Request, via []*http.Request) error {
Expand Down
10 changes: 6 additions & 4 deletions pkg/provider/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ func TestClientDoGetOK(t *testing.T) {
defer ts.Close()

rt := NewDefaultTransport(false)

hc, err := NewHTTPClient(rt)
opts := &HTTPClientOptions{IsWithRetries: false}
hc, err := NewHTTPClient(rt, opts)
require.Nil(t, err)

// hc := &HTTPClient{Client: http.Client{}}
Expand All @@ -39,7 +39,8 @@ func TestClientDisableRedirect(t *testing.T) {

rt := NewDefaultTransport(false)

hc, err := NewHTTPClient(rt)
opts := &HTTPClientOptions{IsWithRetries: false}
hc, err := NewHTTPClient(rt, opts)
require.Nil(t, err)

hc.DisableFollowRedirect()
Expand All @@ -59,7 +60,8 @@ func TestClientDoResponseCheck(t *testing.T) {
}))
defer ts.Close()

hc := &HTTPClient{Client: http.Client{}}
opts := &HTTPClientOptions{IsWithRetries: false}
hc := &HTTPClient{Client: http.Client{}, Options: opts}

hc.CheckResponseStatus = SuccessOrRedirectResponseValidator

Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/jumpcloud/jumpcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {

tr := provider.NewDefaultTransport(idpAccount.SkipVerify)

client, err := provider.NewHTTPClient(tr)
client, err := provider.NewHTTPClient(tr, provider.BuildHttpClientOpts(idpAccount))
if err != nil {
return nil, errors.Wrap(err, "error building http client")
}
Expand Down
Loading