Skip to content

Commit

Permalink
support registry authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
timfeirg authored and CMGS committed Jan 17, 2018
1 parent 7ce89d6 commit 9e1ab88
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 15 deletions.
18 changes: 13 additions & 5 deletions cluster/calcium/build_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ func (c *calcium) BuildImage(ctx context.Context, opts *types.BuildOptions) (cha
lastMessage.Error = err.Error()
break
}
log.Errorf("[BuildImage] Decode build image message failed %v", err)
malformed := []byte{}
_, _ = decoder.Buffered().Read(malformed)
log.Errorf("[BuildImage] Decode build image message failed %v, buffered: %v", err, malformed)
return
}
ch <- message
Expand All @@ -182,9 +184,13 @@ func (c *calcium) BuildImage(ctx context.Context, opts *types.BuildOptions) (cha
log.Errorf("[BuildImage] Build image failed %v", lastMessage.ErrorDetail.Message)
return
}
// About this "Khadgar", https://github.com/docker/docker/issues/10983#issuecomment-85892396
// Just because Ben Schnetzer's cute Khadgar...
rc, err := node.Engine.ImagePush(ctx, tag, enginetypes.ImagePushOptions{RegistryAuth: "Khadgar"})
encodedAuth, err := c.MakeEncodedAuthConfigFromRemote(tag)
if err != nil {
ch <- makeErrorBuildImageMessage(err)
return
}
pushOptions := enginetypes.ImagePushOptions{RegistryAuth: encodedAuth}
rc, err := node.Engine.ImagePush(ctx, tag, pushOptions)
if err != nil {
ch <- makeErrorBuildImageMessage(err)
return
Expand All @@ -199,7 +205,9 @@ func (c *calcium) BuildImage(ctx context.Context, opts *types.BuildOptions) (cha
if err == io.EOF {
break
}
log.Errorf("[BuildImage] Decode push image message failed %v", err)
malformed := []byte{}
_, _ = decoder2.Buffered().Read(malformed)
log.Errorf("[BuildImage] Decode push image message failed %v, buffered: %v", err, malformed)
return
}
ch <- message
Expand Down
38 changes: 38 additions & 0 deletions cluster/calcium/helper.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package calcium

import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"strings"

"github.com/docker/distribution/reference"
enginetypes "github.com/docker/docker/api/types"
enginecontainer "github.com/docker/docker/api/types/container"
engineapi "github.com/docker/docker/client"
"github.com/docker/docker/registry"
"github.com/projecteru2/core/lock"
"github.com/projecteru2/core/types"
"github.com/projecteru2/core/utils"
Expand Down Expand Up @@ -165,3 +169,37 @@ func execuateInside(client *engineapi.Client, ID, cmd, user string, env []string
}
return b, nil
}

// MakeAuthConfigFromRemote Calculate encoded AuthConfig from registry and eru-core config
// See https://github.com/docker/cli/blob/16cccc30f95c8163f0749eba5a2e80b807041342/cli/command/registry.go#L67
func (c *calcium) MakeEncodedAuthConfigFromRemote(remote string) (string, error) {
ref, err := reference.ParseNormalizedNamed(remote)
if err != nil {
return "", err
}

// Resolve the Repository name from fqn to RepositoryInfo
repoInfo, err := registry.ParseRepositoryInfo(ref)
if err != nil {
return "", err
}

serverAddress := repoInfo.Index.Name
if authConfig, exists := c.config.Docker.AuthConfigs[serverAddress]; exists {
if encodedAuth, err := EncodeAuthToBase64(authConfig); err == nil {
return encodedAuth, nil
}
return "", err
}
return "dummy", nil
}

// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
// See https://github.com/docker/cli/blob/master/cli/command/registry.go#L41
func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(buf), nil
}
11 changes: 11 additions & 0 deletions cluster/calcium/helper_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package calcium

import (
"encoding/base64"
"encoding/json"
"testing"

"github.com/projecteru2/core/types"
Expand All @@ -17,3 +19,12 @@ func TestMakeMountPaths(t *testing.T) {
assert.Equal(t, binds, []string{"/foo-data:/foo-data:rw", "/proc/sys:/writable-proc/sys:rw", "/sys/kernel/mm/transparent_hugepage:/writable-sys/kernel/mm/transparent_hugepage:rw"})
assert.Equal(t, volumes, map[string]struct{}{"/foo-data": struct{}{}, "/writable-proc/sys": struct{}{}, "/writable-sys/kernel/mm/transparent_hugepage": struct{}{}})
}

func TestRegistryAuth(t *testing.T) {
tag := "docker.io/projecteru2/core"
encodedAuth, _ := mockc.MakeEncodedAuthConfigFromRemote(tag)
decodedAuth, _ := base64.StdEncoding.DecodeString(encodedAuth)
authConfig := types.AuthConfig{}
json.Unmarshal(decodedAuth, &authConfig)
assert.Equal(t, authConfig.Password, mockc.config.Docker.AuthConfigs["docker.io"].Password)
}
8 changes: 7 additions & 1 deletion cluster/calcium/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@ var (
},
Git: coretypes.GitConfig{SCMType: "gitlab"},
Docker: coretypes.DockerConfig{
Hub: "hub.testhub.com",
Hub: "docker.io",
Namespace: "apps",
AuthConfigs: map[string]coretypes.AuthConfig{
"docker.io": coretypes.AuthConfig{
Username: "timfeirg",
Password: "secret",
},
},
},
Scheduler: coretypes.SchedConfig{
ShareBase: 10,
Expand Down
6 changes: 6 additions & 0 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 20 additions & 9 deletions types/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import "time"
import (
"time"
)

// Config holds eru-core config
type Config struct {
Expand Down Expand Up @@ -37,14 +39,15 @@ type GitConfig struct {

// DockerConfig holds eru-core docker config
type DockerConfig struct {
APIVersion string `yaml:"version"` // docker API version
LogDriver string `yaml:"log_driver"` // docker log driver, can be "json-file", "none"
NetworkMode string `yaml:"network_mode"` // docker network mode
CertPath string `yaml:"cert_path"` // docker cert files path
Hub string `yaml:"hub"` // docker hub address
Namespace string `yaml:"namespace"` // docker hub prefix, will be set to $Hub/$HubPrefix/$appname
BuildPod string `yaml:"build_pod"` // podname used to build
UseLocalDNS bool `yaml:"local_dns"` // use node IP as dns
APIVersion string `yaml:"version"` // docker API version
LogDriver string `yaml:"log_driver"` // docker log driver, can be "json-file", "none"
NetworkMode string `yaml:"network_mode"` // docker network mode
CertPath string `yaml:"cert_path"` // docker cert files path
Hub string `yaml:"hub"` // docker hub address
Namespace string `yaml:"namespace"` // docker hub prefix, will be set to $Hub/$HubPrefix/$appname
BuildPod string `yaml:"build_pod"` // podname used to build
UseLocalDNS bool `yaml:"local_dns"` // use node IP as dns
AuthConfigs map[string]AuthConfig `yaml:"auths"` // docker registry credentials
}

// SchedConfig holds scheduler config
Expand All @@ -59,3 +62,11 @@ type SyslogConfig struct {
Facility string `yaml:"facility"`
Format string `yaml:"format"`
}

// AuthConfig contains authorization information for connecting to a Registry
// Basically copied from https://github.com/moby/moby/blob/16a1736b9b93e44c898f95d670bbaf20a558103d/api/types/auth.go#L4
// But use yaml instead of json
type AuthConfig struct {
Username string `yaml:"username,omitempty" json:"username,omitempty"`
Password string `yaml:"password,omitempty" json:"password,omitempty"`
}

0 comments on commit 9e1ab88

Please sign in to comment.