Skip to content

Commit 97bf204

Browse files
committed
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č <[email protected]>
1 parent e6f8896 commit 97bf204

File tree

2 files changed

+41
-36
lines changed

2 files changed

+41
-36
lines changed

docker/docker_client.go

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ const (
141141
noAuth
142142
)
143143

144-
func newBearerTokenFromJSONBlob(blob []byte) (*bearerToken, error) {
144+
// readFromJSONBlob sets token data in dest from the provided JSON.
145+
func (bt *bearerToken) readFromJSONBlob(blob []byte) error {
145146
var token struct {
146147
Token string `json:"token"`
147148
AccessToken string `json:"access_token"`
@@ -150,14 +151,12 @@ func newBearerTokenFromJSONBlob(blob []byte) (*bearerToken, error) {
150151
expirationTime time.Time
151152
}
152153
if err := json.Unmarshal(blob, &token); err != nil {
153-
return nil, err
154+
return err
154155
}
155156

156-
res := &bearerToken{
157-
token: token.Token,
158-
}
159-
if res.token == "" {
160-
res.token = token.AccessToken
157+
bt.token = token.Token
158+
if bt.token == "" {
159+
bt.token = token.AccessToken
161160
}
162161

163162
if token.ExpiresIn < minimumTokenLifetimeSeconds {
@@ -167,8 +166,8 @@ func newBearerTokenFromJSONBlob(blob []byte) (*bearerToken, error) {
167166
if token.IssuedAt.IsZero() {
168167
token.IssuedAt = time.Now().UTC()
169168
}
170-
res.expirationTime = token.IssuedAt.Add(time.Duration(token.ExpiresIn) * time.Second)
171-
return res, nil
169+
bt.expirationTime = token.IssuedAt.Add(time.Duration(token.ExpiresIn) * time.Second)
170+
return nil
172171
}
173172

174173
// this is cloned from docker/go-connections because upstream docker has changed
@@ -712,20 +711,18 @@ func (c *dockerClient) obtainBearerToken(ctx context.Context, challenge challeng
712711
token, inCache = c.tokenCache[cacheKey]
713712
}()
714713
if !inCache || time.Now().After(token.expirationTime) {
715-
var (
716-
t *bearerToken
717-
err error
718-
)
714+
token = &bearerToken{}
715+
716+
var err error
719717
if c.auth.IdentityToken != "" {
720-
t, err = c.getBearerTokenOAuth2(ctx, challenge, scopes)
718+
err = c.getBearerTokenOAuth2(ctx, token, challenge, scopes)
721719
} else {
722-
t, err = c.getBearerToken(ctx, challenge, scopes)
720+
err = c.getBearerToken(ctx, token, challenge, scopes)
723721
}
724722
if err != nil {
725723
return "", err
726724
}
727725

728-
token = t
729726
func() { // A scope for defer
730727
c.tokenCacheLock.Lock()
731728
defer c.tokenCacheLock.Unlock()
@@ -735,16 +732,19 @@ func (c *dockerClient) obtainBearerToken(ctx context.Context, challenge challeng
735732
return token.token, nil
736733
}
737734

738-
func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, challenge challenge,
739-
scopes []authScope) (*bearerToken, error) {
735+
// getBearerTokenOAuth2 obtains an "Authorization: Bearer" token using a pre-existing identity token per
736+
// https://github.com/distribution/distribution/blob/main/docs/spec/auth/oauth.md for challenge and scopes,
737+
// and writes it into dest.
738+
func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, dest *bearerToken, challenge challenge,
739+
scopes []authScope) error {
740740
realm, ok := challenge.Parameters["realm"]
741741
if !ok {
742-
return nil, errors.New("missing realm in bearer auth challenge")
742+
return errors.New("missing realm in bearer auth challenge")
743743
}
744744

745745
authReq, err := http.NewRequestWithContext(ctx, http.MethodPost, realm, nil)
746746
if err != nil {
747-
return nil, err
747+
return err
748748
}
749749

750750
// Make the form data required against the oauth2 authentication
@@ -769,31 +769,34 @@ func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, challenge chall
769769
logrus.Debugf("%s %s", authReq.Method, authReq.URL.Redacted())
770770
res, err := c.client.Do(authReq)
771771
if err != nil {
772-
return nil, err
772+
return err
773773
}
774774
defer res.Body.Close()
775775
if err := httpResponseToError(res, "Trying to obtain access token"); err != nil {
776-
return nil, err
776+
return err
777777
}
778778

779779
tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
780780
if err != nil {
781-
return nil, err
781+
return err
782782
}
783783

784-
return newBearerTokenFromJSONBlob(tokenBlob)
784+
return dest.readFromJSONBlob(tokenBlob)
785785
}
786786

787-
func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
788-
scopes []authScope) (*bearerToken, error) {
787+
// getBearerToken obtains an "Authorization: Bearer" token using a GET request, per
788+
// https://github.com/distribution/distribution/blob/main/docs/spec/auth/token.md for challenge and scopes,
789+
// and writes it into dest.
790+
func (c *dockerClient) getBearerToken(ctx context.Context, dest *bearerToken, challenge challenge,
791+
scopes []authScope) error {
789792
realm, ok := challenge.Parameters["realm"]
790793
if !ok {
791-
return nil, errors.New("missing realm in bearer auth challenge")
794+
return errors.New("missing realm in bearer auth challenge")
792795
}
793796

794797
authReq, err := http.NewRequestWithContext(ctx, http.MethodGet, realm, nil)
795798
if err != nil {
796-
return nil, err
799+
return err
797800
}
798801

799802
params := authReq.URL.Query()
@@ -821,18 +824,18 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
821824
logrus.Debugf("%s %s", authReq.Method, authReq.URL.Redacted())
822825
res, err := c.client.Do(authReq)
823826
if err != nil {
824-
return nil, err
827+
return err
825828
}
826829
defer res.Body.Close()
827830
if err := httpResponseToError(res, "Requesting bearer token"); err != nil {
828-
return nil, err
831+
return err
829832
}
830833
tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
831834
if err != nil {
832-
return nil, err
835+
return err
833836
}
834837

835-
return newBearerTokenFromJSONBlob(tokenBlob)
838+
return dest.readFromJSONBlob(tokenBlob)
836839
}
837840

838841
// detectPropertiesHelper performs the work of detectProperties which executes

docker/docker_client_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func TestDockerCertDir(t *testing.T) {
9292
}
9393
}
9494

95-
func TestNewBearerTokenFromJSONBlob(t *testing.T) {
95+
func TestBearerTokenReadFromJSONBlob(t *testing.T) {
9696
for _, c := range []struct {
9797
input string
9898
expected *bearerToken // or nil on failure
@@ -111,7 +111,8 @@ func TestNewBearerTokenFromJSONBlob(t *testing.T) {
111111
&bearerToken{token: "IAmAToken", expirationTime: time.Unix(1514800802+60, 0)},
112112
},
113113
} {
114-
token, err := newBearerTokenFromJSONBlob([]byte(c.input))
114+
token := &bearerToken{}
115+
err := token.readFromJSONBlob([]byte(c.input))
115116
if c.expected == nil {
116117
assert.Error(t, err, c.input)
117118
} else {
@@ -123,11 +124,12 @@ func TestNewBearerTokenFromJSONBlob(t *testing.T) {
123124
}
124125
}
125126

126-
func TestNewBearerTokenIssuedAtZeroFromJsonBlob(t *testing.T) {
127+
func TestBearerTokenReadFromJSONBlobIssuedAtZeroFrom(t *testing.T) {
127128
zeroTime := time.Time{}.Format(time.RFC3339)
128129
now := time.Now()
129130
tokenBlob := []byte(fmt.Sprintf(`{"token":"IAmAToken","expires_in":100,"issued_at":"%s"}`, zeroTime))
130-
token, err := newBearerTokenFromJSONBlob(tokenBlob)
131+
token := &bearerToken{}
132+
err := token.readFromJSONBlob(tokenBlob)
131133
require.NoError(t, err)
132134
expectedExpiration := now.Add(time.Duration(100) * time.Second)
133135
require.False(t, token.expirationTime.Before(expectedExpiration),

0 commit comments

Comments
 (0)