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

Use retryable http client in Azure authz provider #372

Merged

Conversation

bingosummer
Copy link
Contributor

@bingosummer bingosummer commented Aug 7, 2023

We see the timeout error in the checkaccess requrests sometimes.

Error occured during authorization check. Please retry again. Error: Checkaccess requests have timed out.: context deadline exceeded

This PR moves withRetryableHttpClient from Azure authn provider to utils, and leverage it in Azure authz provider's RefreshToken and CheckAccess.

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from 68962f3 to 1cbc986 Compare August 7, 2023 06:31
@bingosummer bingosummer marked this pull request as ready for review August 7, 2023 06:43
@bingosummer bingosummer requested review from a team as code owners August 7, 2023 06:43
@bingosummer bingosummer changed the title Use retrable http client in Azure authz provider Use retryable http client in Azure authz provider Aug 7, 2023
@bingosummer
Copy link
Contributor Author

@weinong @AzureMarker could you please have a review? Thanks!

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from 1cbc986 to ad88d63 Compare August 7, 2023 07:20
@@ -120,6 +124,8 @@ func (s Authorizer) Check(ctx context.Context, request *authzv1.SubjectAccessRev
return &authzv1.SubjectAccessReviewStatus{Allowed: true, Reason: rbac.AccessAllowedVerdict}, nil
}

ctx = azureutils.WithRetryableHttpClient(ctx, s.HttpClientRetryCount)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. why do we save the http client in the context?
  2. as far as I can tell, it still uses AccessInfo.client, no?

Copy link
Contributor Author

@bingosummer bingosummer Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed the comment of WithRetryableHttpClient.

// WithRetryableHttpClient sets the oauth2.HTTPClient key of the context to an
// *http.Client made from makeRetryableHttpClient.
// Some of the libraries we use will take the client out of the context via
// oauth2.HTTPClient and use it, so this way we can add retries to external code.

Both RefreshToken and sendCheckAccessRequest are using the library "net/http".

@AzureMarker to confirm whether "net/http" respects the http client in the context?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net/http is a standard library, it doesn't reference third party code so there's no way it uses that context key.

This key is used in go-oidc:

if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {

The other HTTP client usages hard-code to go.kubeguard.dev/guard/util/httpclient's DefaultHTTPClient, which is just a normal HTTP client.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this change 57e588e. Could you please review it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AzureMarker gentle ping

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from ad88d63 to bc5f06a Compare August 9, 2023 02:34
@@ -74,6 +75,9 @@ func (u *oboTokenProvider) Acquire(ctx context.Context, token string) (AuthRespo
klog.V(10).Infoln(cmd)
}

if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
u.client = c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't modify the token provider (u.client). Store a reference to the HTTP client in a variable and modify it there.

The issue is if this is called twice (first with a context that holds an HTTP client, then with a context that has no HTTP client), the second call will use the HTTP client of the first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed this part to make the pr focus on authz.

@@ -374,6 +375,10 @@ func (a *AccessInfo) CheckAccess(request *authzv1.SubjectAccessReviewSpec) (*aut
}

func (a *AccessInfo) sendCheckAccessRequest(ctx context.Context, checkAccessURL url.URL, checkAccessBody *CheckAccessRequest, ch chan *authzv1.SubjectAccessReviewStatus) error {
if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
a.client = c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here, don't modify a.client, store it in a local variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed. Could you please check whether the fix meets the requirement? Thanks

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from 57e588e to 656a1ec Compare November 7, 2023 02:51
@bingosummer
Copy link
Contributor Author

@AzureMarker Could you please have a review again? Thanks

@bingosummer
Copy link
Contributor Author

@weinong could you please have a review? Thanks

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from fd7361f to f30b13d Compare March 7, 2024 02:19
@bingosummer
Copy link
Contributor Author

The PR is rebased. @weinong could you please have a review? Please let me know if anything is missing. Thanks!

@@ -373,6 +377,11 @@ func (a *AccessInfo) CheckAccess(request *authzv1.SubjectAccessReviewSpec) (*aut
}

func (a *AccessInfo) sendCheckAccessRequest(ctx context.Context, checkAccessUsername string, checkAccessURL url.URL, checkAccessBody *CheckAccessRequest, ch chan *authzv1.SubjectAccessReviewStatus) error {
var clientInCtx *http.Client
if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we move this client loader to util/azure so we can hide the context key from caller?

@@ -37,7 +37,8 @@ import (
)

const (
loginResp = `{ "token_type": "Bearer", "expires_in": 8459, "access_token": "%v"}`
loginResp = `{ "token_type": "Bearer", "expires_in": 8459, "access_token": "%v"}`
httpClientRetryCount = 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a unit test for covering the retry behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

ClientID: "client_id",
ClientSecret: "client_secret",
TenantID: "tenant_id",
HttpClientRetryCount: httpClientRetryCount,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we assert that it try 2 times ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch 6 times, most recently from da82048 to 685ade4 Compare April 1, 2024 16:04
Signed-off-by: Bin Xia <binxi@microsoft.com>
@bingosummer bingosummer force-pushed the azure-authz-retrable-http-client branch from 685ade4 to 3e9b748 Compare April 1, 2024 16:13
@@ -171,6 +174,7 @@ func TestCheck(t *testing.T) {
assert.Nilf(t, resp, "response should be nil")
assert.NotNilf(t, err, "should get error")
assert.Contains(t, err.Error(), "Error occured during authorization check")
assert.Contains(t, err.Error(), fmt.Sprintf("giving up after %d attempt", httpClientRetryCount+1))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bcho @julienstroheker this line can assert that it gives up after 3 attempts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please have another round of review? Thanks

Copy link
Contributor

@bcho bcho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bingosummer
Copy link
Contributor Author

@weinong could you please have another round of review? Thanks

@weinong
Copy link
Contributor

weinong commented Apr 2, 2024

@julienstroheker PTAL

Copy link
Contributor

@weinong weinong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved

@weinong weinong merged commit a74230a into kubeguard:master Apr 3, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants