Merge pull request #46 from pterodactyl/feature/docker-repo-auth
Add Docker registry authentication
This commit is contained in:
		
						commit
						cecc72110c
					
				| 
						 | 
				
			
			@ -1,5 +1,12 @@
 | 
			
		|||
package config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dockerNetworkInterfaces struct {
 | 
			
		||||
	V4 struct {
 | 
			
		||||
		Subnet  string `default:"172.18.0.0/16"`
 | 
			
		||||
| 
						 | 
				
			
			@ -53,4 +60,28 @@ type DockerConfiguration struct {
 | 
			
		|||
	// Defines the location of the timezone file on the host system that should
 | 
			
		||||
	// be mounted into the created containers so that they all use the same time.
 | 
			
		||||
	TimezonePath string `default:"/etc/timezone" json:"timezone_path" yaml:"timezone_path"`
 | 
			
		||||
 | 
			
		||||
	// Registries .
 | 
			
		||||
	Registries map[string]RegistryConfiguration `json:"registries" yaml:"registries"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegistryConfiguration .
 | 
			
		||||
type RegistryConfiguration struct {
 | 
			
		||||
	Username string `yaml:"username"`
 | 
			
		||||
	Password string `yaml:"password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Base64 .
 | 
			
		||||
func (c RegistryConfiguration) Base64() (string, error) {
 | 
			
		||||
	authConfig := types.AuthConfig{
 | 
			
		||||
		Username: c.Username,
 | 
			
		||||
		Password: c.Password,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := json.Marshal(authConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", errors.WithStack(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return base64.URLEncoding.EncodeToString(b), nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -654,7 +654,33 @@ func (d *DockerEnvironment) ensureImageExists() error {
 | 
			
		|||
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*15)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	out, err := d.Client.ImagePull(ctx, d.Image(), types.ImagePullOptions{All: false})
 | 
			
		||||
	image := d.Image()
 | 
			
		||||
 | 
			
		||||
	// Get a registry auth configuration from the config.
 | 
			
		||||
	var registryAuth *config.RegistryConfiguration
 | 
			
		||||
	for registry, c := range config.Get().Docker.Registries {
 | 
			
		||||
		if !strings.HasPrefix(image, registry) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log.WithField("registry", registry).Debug("using authentication for repository")
 | 
			
		||||
		registryAuth = &c
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get the ImagePullOptions.
 | 
			
		||||
	imagePullOptions := types.ImagePullOptions{All: false}
 | 
			
		||||
	if registryAuth != nil {
 | 
			
		||||
		b64, err := registryAuth.Base64()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.WithError(err).Error("failed to get registry auth credentials")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// b64 is a string so if there is an error it will just be empty, not nil.
 | 
			
		||||
		imagePullOptions.RegistryAuth = b64
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out, err := d.Client.ImagePull(ctx, image, imagePullOptions)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		images, ierr := d.Client.ImageList(ctx, types.ImageListOptions{})
 | 
			
		||||
		if ierr != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,10 +114,10 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Generate a path to the file by cleaning it up and appending the root server path to it. This
 | 
			
		||||
// DOES NOT gaurantee that the file resolves within the server data directory. You'll want to use
 | 
			
		||||
// DOES NOT guarantee that the file resolves within the server data directory. You'll want to use
 | 
			
		||||
// the fs.unsafeIsInDataDirectory(p) function to confirm.
 | 
			
		||||
func (fs *Filesystem) unsafeFilePath(p string) string {
 | 
			
		||||
	// Calling filpath.Clean on the joined directory will resolve it to the absolute path,
 | 
			
		||||
	// Calling filepath.Clean on the joined directory will resolve it to the absolute path,
 | 
			
		||||
	// removing any ../ type of resolution arguments, and leaving us with a direct path link.
 | 
			
		||||
	//
 | 
			
		||||
	// This will also trim the existing root path off the beginning of the path passed to
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user