...

Source file src/github.com/google/go-containerregistry/pkg/authn/authn.go

Documentation: github.com/google/go-containerregistry/pkg/authn

     1  // Copyright 2018 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package authn
    16  
    17  import (
    18  	"encoding/base64"
    19  	"encoding/json"
    20  	"fmt"
    21  	"strings"
    22  )
    23  
    24  // Authenticator is used to authenticate Docker transports.
    25  type Authenticator interface {
    26  	// Authorization returns the value to use in an http transport's Authorization header.
    27  	Authorization() (*AuthConfig, error)
    28  }
    29  
    30  // AuthConfig contains authorization information for connecting to a Registry
    31  // Inlined what we use from github.com/docker/cli/cli/config/types
    32  type AuthConfig struct {
    33  	Username string `json:"username,omitempty"`
    34  	Password string `json:"password,omitempty"`
    35  	Auth     string `json:"auth,omitempty"`
    36  
    37  	// IdentityToken is used to authenticate the user and get
    38  	// an access token for the registry.
    39  	IdentityToken string `json:"identitytoken,omitempty"`
    40  
    41  	// RegistryToken is a bearer token to be sent to a registry
    42  	RegistryToken string `json:"registrytoken,omitempty"`
    43  }
    44  
    45  // This is effectively a copy of the type AuthConfig. This simplifies
    46  // JSON unmarshalling since AuthConfig methods are not inherited
    47  type authConfig AuthConfig
    48  
    49  // UnmarshalJSON implements json.Unmarshaler
    50  func (a *AuthConfig) UnmarshalJSON(data []byte) error {
    51  	var shadow authConfig
    52  	err := json.Unmarshal(data, &shadow)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	*a = (AuthConfig)(shadow)
    58  
    59  	if len(shadow.Auth) != 0 {
    60  		var derr error
    61  		a.Username, a.Password, derr = decodeDockerConfigFieldAuth(shadow.Auth)
    62  		if derr != nil {
    63  			err = fmt.Errorf("unable to decode auth field: %w", derr)
    64  		}
    65  	} else if len(a.Username) != 0 && len(a.Password) != 0 {
    66  		a.Auth = encodeDockerConfigFieldAuth(shadow.Username, shadow.Password)
    67  	}
    68  
    69  	return err
    70  }
    71  
    72  // MarshalJSON implements json.Marshaler
    73  func (a AuthConfig) MarshalJSON() ([]byte, error) {
    74  	shadow := (authConfig)(a)
    75  	shadow.Auth = encodeDockerConfigFieldAuth(shadow.Username, shadow.Password)
    76  	return json.Marshal(shadow)
    77  }
    78  
    79  // decodeDockerConfigFieldAuth deserializes the "auth" field from dockercfg into a
    80  // username and a password. The format of the auth field is base64(<username>:<password>).
    81  //
    82  // From https://github.com/kubernetes/kubernetes/blob/75e49ec824b183288e1dbaccfd7dbe77d89db381/pkg/credentialprovider/config.go
    83  // Copyright 2014 The Kubernetes Authors.
    84  // SPDX-License-Identifier: Apache-2.0
    85  func decodeDockerConfigFieldAuth(field string) (username, password string, err error) {
    86  	var decoded []byte
    87  	// StdEncoding can only decode padded string
    88  	// RawStdEncoding can only decode unpadded string
    89  	if strings.HasSuffix(strings.TrimSpace(field), "=") {
    90  		// decode padded data
    91  		decoded, err = base64.StdEncoding.DecodeString(field)
    92  	} else {
    93  		// decode unpadded data
    94  		decoded, err = base64.RawStdEncoding.DecodeString(field)
    95  	}
    96  
    97  	if err != nil {
    98  		return
    99  	}
   100  
   101  	parts := strings.SplitN(string(decoded), ":", 2)
   102  	if len(parts) != 2 {
   103  		err = fmt.Errorf("must be formatted as base64(username:password)")
   104  		return
   105  	}
   106  
   107  	username = parts[0]
   108  	password = parts[1]
   109  
   110  	return
   111  }
   112  
   113  func encodeDockerConfigFieldAuth(username, password string) string {
   114  	return base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
   115  }
   116  

View as plain text