Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support insecure Docker registries #58

Merged
merged 2 commits into from
Sep 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import (

"github.com/ivanilves/lstags/auth/basic"
"github.com/ivanilves/lstags/auth/bearer"
"github.com/ivanilves/lstags/auth/none"
)

// WebSchema defines how do we connect to remote web servers
var WebSchema = "https://"

// TokenResponse is an abstraction for aggregated token-related information we get from authentication services
type TokenResponse interface {
Method() string
Expand All @@ -19,7 +23,7 @@ type TokenResponse interface {
func parseAuthHeader(headers http.Header) (string, string, error) {
header, defined := headers["Www-Authenticate"]
if !defined {
return "", "", errors.New("Missing 'Www-Authenticate' header")
return "None", "realm=none", nil
}
fields := strings.SplitN(header[0], " ", 2)
if len(fields) != 2 {
Expand Down Expand Up @@ -63,7 +67,7 @@ func validateParams(method string, params map[string]string) (map[string]string,
// * detects authentication type (e.g. Bearer or Basic)
// * delegates actual authentication to type-specific implementation
func NewToken(registry, repository, username, password string) (TokenResponse, error) {
url := "https://" + registry + "/v2"
url := WebSchema + registry + "/v2"

resp, err := http.Get(url)
if err != nil {
Expand All @@ -80,6 +84,8 @@ func NewToken(registry, repository, username, password string) (TokenResponse, e
}

switch method {
case "None":
return none.RequestToken()
case "Basic":
return basic.RequestToken(url, username, password)
case "Bearer":
Expand Down
2 changes: 1 addition & 1 deletion auth/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// TokenResponse implementation for Basic authentication
type TokenResponse struct {
T string `json:"token"`
T string
}

// Method is set to "Basic"
Expand Down
25 changes: 25 additions & 0 deletions auth/none/none.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package none

// TokenResponse implementation for None authentication
type TokenResponse struct {
}

// Method is set to "None"
func (tr TokenResponse) Method() string {
return "None"
}

// Token is set to a dummy string
func (tr TokenResponse) Token() string {
return ""
}

// ExpiresIn is set to 0 for None authentication
func (tr TokenResponse) ExpiresIn() int {
return 0
}

// RequestToken does pretty little here...
func RequestToken() (*TokenResponse, error) {
return &TokenResponse{}, nil
}
22 changes: 14 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ import (
)

type options struct {
DefaultRegistry string `short:"r" long:"default-registry" default:"registry.hub.docker.com" description:"Docker registry to use by default" env:"DEFAULT_REGISTRY"`
Username string `short:"u" long:"username" default:"" description:"Docker registry username" env:"USERNAME"`
Password string `short:"p" long:"password" default:"" description:"Docker registry password" env:"PASSWORD"`
DockerJSON string `shord:"j" long:"docker-json" default:"~/.docker/config.json" env:"DOCKER_JSON"`
Concurrency int `short:"c" long:"concurrency" default:"32" description:"Concurrent request limit while querying registry" env:"CONCURRENCY"`
TraceRequests bool `short:"T" long:"trace-requests" description:"Trace registry HTTP requests" env:"TRACE_REQUESTS"`
Version bool `short:"V" long:"version" description:"Show version and exit"`
Positional struct {
DefaultRegistry string `short:"r" long:"default-registry" default:"registry.hub.docker.com" description:"Docker registry to use by default" env:"DEFAULT_REGISTRY"`
Username string `short:"u" long:"username" default:"" description:"Docker registry username" env:"USERNAME"`
Password string `short:"p" long:"password" default:"" description:"Docker registry password" env:"PASSWORD"`
DockerJSON string `shord:"j" long:"docker-json" default:"~/.docker/config.json" env:"DOCKER_JSON"`
Concurrency int `short:"c" long:"concurrency" default:"32" description:"Concurrent request limit while querying registry" env:"CONCURRENCY"`
InsecureRegistry bool `short:"i" long:"insecure-registry" description:"Use insecure plain-HTTP registriy" env:"INSECURE_REGISTRY"`
TraceRequests bool `short:"T" long:"trace-requests" description:"Trace registry HTTP requests" env:"TRACE_REQUESTS"`
Version bool `short:"V" long:"version" description:"Show version and exit"`
Positional struct {
Repository string `positional-arg-name:"REPOSITORY" description:"Docker repository to list tags from"`
} `positional-args:"yes"`
}
Expand Down Expand Up @@ -137,6 +138,11 @@ func main() {
suicide(errors.New("You should provide a repository name, e.g. 'nginx' or 'mesosphere/chronos'"))
}

if o.InsecureRegistry {
auth.WebSchema = "http://"
registry.WebSchema = "http://"
}

registry.TraceRequests = o.TraceRequests

repository, filter, err := trimFilter(o.Positional.Repository)
Expand Down
7 changes: 5 additions & 2 deletions tag/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/ivanilves/lstags/tag"
)

// WebSchema defines how do we connect to remote web servers
var WebSchema = "https://"

// TraceRequests defines if we should print out HTTP request URLs and response headers/bodies
var TraceRequests = false

Expand Down Expand Up @@ -101,7 +104,7 @@ func parseTagNamesJSON(data io.ReadCloser) ([]string, error) {
}

func fetchTagNames(registry, repo, authorization string) ([]string, error) {
url := "https://" + registry + "/v2/" + repo + "/tags/list"
url := WebSchema + registry + "/v2/" + repo + "/tags/list"

resp, err := httpRequest(url, authorization, "v2")
if err != nil {
Expand Down Expand Up @@ -173,7 +176,7 @@ func fetchDigest(url, authorization string) (string, error) {
}

func fetchDetails(registry, repo, tagName, authorization string) (string, int64, error) {
url := "https://" + registry + "/v2/" + repo + "/manifests/" + tagName
url := WebSchema + registry + "/v2/" + repo + "/manifests/" + tagName

dc := make(chan string, 0)
cc := make(chan int64, 0)
Expand Down