Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 15fe891

Browse files
committedJul 9, 2024
Move creation of bearerToken to obtainBearerToken
Instead of having getBearerToken* construct a new bearerToken object, have the caller provide one. This will allow us to record that a token is being obtained, so that others can wait for it. Should not change behavior. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
1 parent c06c69d commit 15fe891

File tree

2 files changed

+37
-33
lines changed

2 files changed

+37
-33
lines changed
 

‎docker/docker_client.go

+31-29
Original file line numberDiff line numberDiff line change
@@ -760,20 +760,18 @@ func (c *dockerClient) obtainBearerToken(ctx context.Context, challenge challeng
760760
token, inCache = c.tokenCache[cacheKey]
761761
}()
762762
if !inCache || time.Now().After(token.expirationTime) {
763-
var (
764-
t *bearerToken
765-
err error
766-
)
763+
token = &bearerToken{}
764+
765+
var err error
767766
if c.auth.IdentityToken != "" {
768-
t, err = c.getBearerTokenOAuth2(ctx, challenge, scopes)
767+
err = c.getBearerTokenOAuth2(ctx, token, challenge, scopes)
769768
} else {
770-
t, err = c.getBearerToken(ctx, challenge, scopes)
769+
err = c.getBearerToken(ctx, token, challenge, scopes)
771770
}
772771
if err != nil {
773772
return "", err
774773
}
775774

776-
token = t
777775
func() { // A scope for defer
778776
c.tokenCacheLock.Lock()
779777
defer c.tokenCacheLock.Unlock()
@@ -783,16 +781,19 @@ func (c *dockerClient) obtainBearerToken(ctx context.Context, challenge challeng
783781
return token.token, nil
784782
}
785783

786-
func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, challenge challenge,
787-
scopes []authScope) (*bearerToken, error) {
784+
// getBearerTokenOAuth2 obtains an "Authorization: Bearer" token using a pre-existing identity token per
785+
// https://github.com/distribution/distribution/blob/main/docs/spec/auth/oauth.md for challenge and scopes,
786+
// and writes it into dest.
787+
func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, dest *bearerToken, challenge challenge,
788+
scopes []authScope) error {
788789
realm, ok := challenge.Parameters["realm"]
789790
if !ok {
790-
return nil, errors.New("missing realm in bearer auth challenge")
791+
return errors.New("missing realm in bearer auth challenge")
791792
}
792793

793794
authReq, err := http.NewRequestWithContext(ctx, http.MethodPost, realm, nil)
794795
if err != nil {
795-
return nil, err
796+
return err
796797
}
797798

798799
// Make the form data required against the oauth2 authentication
@@ -817,26 +818,29 @@ func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, challenge chall
817818
logrus.Debugf("%s %s", authReq.Method, authReq.URL.Redacted())
818819
res, err := c.client.Do(authReq)
819820
if err != nil {
820-
return nil, err
821+
return err
821822
}
822823
defer res.Body.Close()
823824
if err := httpResponseToError(res, "Trying to obtain access token"); err != nil {
824-
return nil, err
825+
return err
825826
}
826827

827-
return newBearerTokenFromHTTPResponseBody(res)
828+
return dest.readFromHTTPResponseBody(res)
828829
}
829830

830-
func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
831-
scopes []authScope) (*bearerToken, error) {
831+
// getBearerToken obtains an "Authorization: Bearer" token using a GET request, per
832+
// https://github.com/distribution/distribution/blob/main/docs/spec/auth/token.md for challenge and scopes,
833+
// and writes it into dest.
834+
func (c *dockerClient) getBearerToken(ctx context.Context, dest *bearerToken, challenge challenge,
835+
scopes []authScope) error {
832836
realm, ok := challenge.Parameters["realm"]
833837
if !ok {
834-
return nil, errors.New("missing realm in bearer auth challenge")
838+
return errors.New("missing realm in bearer auth challenge")
835839
}
836840

837841
authReq, err := http.NewRequestWithContext(ctx, http.MethodGet, realm, nil)
838842
if err != nil {
839-
return nil, err
843+
return err
840844
}
841845

842846
params := authReq.URL.Query()
@@ -864,22 +868,22 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
864868
logrus.Debugf("%s %s", authReq.Method, authReq.URL.Redacted())
865869
res, err := c.client.Do(authReq)
866870
if err != nil {
867-
return nil, err
871+
return err
868872
}
869873
defer res.Body.Close()
870874
if err := httpResponseToError(res, "Requesting bearer token"); err != nil {
871-
return nil, err
875+
return err
872876
}
873877

874-
return newBearerTokenFromHTTPResponseBody(res)
878+
return dest.readFromHTTPResponseBody(res)
875879
}
876880

877-
// newBearerTokenFromHTTPResponseBody parses a http.Response to obtain a bearerToken.
881+
// readFromHTTPResponseBody sets token data by parsing a http.Response.
878882
// The caller is still responsible for ensuring res.Body is closed.
879-
func newBearerTokenFromHTTPResponseBody(res *http.Response) (*bearerToken, error) {
883+
func (bt *bearerToken) readFromHTTPResponseBody(res *http.Response) error {
880884
blob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
881885
if err != nil {
882-
return nil, err
886+
return err
883887
}
884888

885889
var token struct {
@@ -895,12 +899,10 @@ func newBearerTokenFromHTTPResponseBody(res *http.Response) (*bearerToken, error
895899
if len(bodySample) > bodySampleLength {
896900
bodySample = bodySample[:bodySampleLength]
897901
}
898-
return nil, fmt.Errorf("decoding bearer token (last URL %q, body start %q): %w", res.Request.URL.Redacted(), string(bodySample), err)
902+
return fmt.Errorf("decoding bearer token (last URL %q, body start %q): %w", res.Request.URL.Redacted(), string(bodySample), err)
899903
}
900904

901-
bt := &bearerToken{
902-
token: token.Token,
903-
}
905+
bt.token = token.Token
904906
if bt.token == "" {
905907
bt.token = token.AccessToken
906908
}
@@ -913,7 +915,7 @@ func newBearerTokenFromHTTPResponseBody(res *http.Response) (*bearerToken, error
913915
token.IssuedAt = time.Now().UTC()
914916
}
915917
bt.expirationTime = token.IssuedAt.Add(time.Duration(token.ExpiresIn) * time.Second)
916-
return bt, nil
918+
return nil
917919
}
918920

919921
// detectPropertiesHelper performs the work of detectProperties which executes

‎docker/docker_client_test.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func testTokenHTTPResponse(t *testing.T, body string) *http.Response {
106106
}
107107
}
108108

109-
func TestNewBearerTokenFromHTTPResponseBody(t *testing.T) {
109+
func TestBearerTokenReadFromHTTPResponseBody(t *testing.T) {
110110
for _, c := range []struct {
111111
input string
112112
expected *bearerToken // or nil if a failure is expected
@@ -128,7 +128,8 @@ func TestNewBearerTokenFromHTTPResponseBody(t *testing.T) {
128128
expected: &bearerToken{token: "IAmAToken", expirationTime: time.Unix(1514800802+60, 0)},
129129
},
130130
} {
131-
token, err := newBearerTokenFromHTTPResponseBody(testTokenHTTPResponse(t, c.input))
131+
token := &bearerToken{}
132+
err := token.readFromHTTPResponseBody(testTokenHTTPResponse(t, c.input))
132133
if c.expected == nil {
133134
assert.Error(t, err, c.input)
134135
} else {
@@ -140,11 +141,12 @@ func TestNewBearerTokenFromHTTPResponseBody(t *testing.T) {
140141
}
141142
}
142143

143-
func TestNewBearerTokenFromHTTPResponseBodyIssuedAtZero(t *testing.T) {
144+
func TestBearerTokenReadFromHTTPResponseBodyIssuedAtZero(t *testing.T) {
144145
zeroTime := time.Time{}.Format(time.RFC3339)
145146
now := time.Now()
146147
tokenBlob := fmt.Sprintf(`{"token":"IAmAToken","expires_in":100,"issued_at":"%s"}`, zeroTime)
147-
token, err := newBearerTokenFromHTTPResponseBody(testTokenHTTPResponse(t, tokenBlob))
148+
token := &bearerToken{}
149+
err := token.readFromHTTPResponseBody(testTokenHTTPResponse(t, tokenBlob))
148150
require.NoError(t, err)
149151
expectedExpiration := now.Add(time.Duration(100) * time.Second)
150152
require.False(t, token.expirationTime.Before(expectedExpiration),

0 commit comments

Comments
 (0)
Please sign in to comment.