woodpecker/server/plugins/registry/filesystem.go
qwerty287 bed3ef104c
Support Docker credential helpers (#1075)
* support docker credential and add docker-credential-ecr-login into alpine image

* Remove ecr from docker and add docs

* Update docs/docs/30-administration/22-backends/10-docker.md

Co-authored-by: WeStone <xuecanlong@qq.com>
Co-authored-by: Anbraten <anton@ju60.de>
2022-08-14 10:46:18 +02:00

104 lines
2.3 KiB
Go

package registry
import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
"github.com/woodpecker-ci/woodpecker/server/model"
)
type filesystem struct {
path string
}
func Filesystem(path string) model.ReadOnlyRegistryService {
return &filesystem{path}
}
func parseDockerConfig(path string) ([]*model.Registry, error) {
if path == "" {
return nil, nil
}
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
configFile := configfile.ConfigFile{
AuthConfigs: make(map[string]types.AuthConfig),
}
if err := json.NewDecoder(f).Decode(&configFile); err != nil {
return nil, err
}
for registryHostname := range configFile.CredentialHelpers {
newAuth, err := configFile.GetAuthConfig(registryHostname)
if err == nil {
configFile.AuthConfigs[registryHostname] = newAuth
}
}
for addr, ac := range configFile.AuthConfigs {
if ac.Auth != "" {
ac.Username, ac.Password, err = decodeAuth(ac.Auth)
if err != nil {
return nil, err
}
ac.Auth = ""
ac.ServerAddress = addr
configFile.AuthConfigs[addr] = ac
}
}
var auths []*model.Registry
for key, auth := range configFile.AuthConfigs {
auths = append(auths, &model.Registry{
Address: key,
Username: auth.Username,
Password: auth.Password,
})
}
return auths, nil
}
func (b *filesystem) RegistryFind(*model.Repo, string) (*model.Registry, error) {
return nil, nil
}
func (b *filesystem) RegistryList(*model.Repo) ([]*model.Registry, error) {
return parseDockerConfig(b.path)
}
// decodeAuth decodes a base64 encoded string and returns username and password
func decodeAuth(authStr string) (string, string, error) {
if authStr == "" {
return "", "", nil
}
decLen := base64.StdEncoding.DecodedLen(len(authStr))
decoded := make([]byte, decLen)
authByte := []byte(authStr)
n, err := base64.StdEncoding.Decode(decoded, authByte)
if err != nil {
return "", "", err
}
if n > decLen {
return "", "", fmt.Errorf("Something went wrong decoding auth config")
}
arr := strings.SplitN(string(decoded), ":", 2)
if len(arr) != 2 {
return "", "", fmt.Errorf("Invalid auth configuration file")
}
password := strings.Trim(arr[1], "\x00")
return arr[0], password, nil
}