mirror of
https://github.com/containers/skopeo.git
synced 2025-08-28 02:52:41 +00:00
Merge pull request #264 from runcom/split-flags
cmd: per command tls flags
This commit is contained in:
commit
a515fefda9
@ -13,12 +13,12 @@ import (
|
|||||||
|
|
||||||
// contextsFromGlobalOptions returns source and destionation types.SystemContext depending on c.
|
// contextsFromGlobalOptions returns source and destionation types.SystemContext depending on c.
|
||||||
func contextsFromGlobalOptions(c *cli.Context) (*types.SystemContext, *types.SystemContext, error) {
|
func contextsFromGlobalOptions(c *cli.Context) (*types.SystemContext, *types.SystemContext, error) {
|
||||||
sourceCtx, err := contextFromGlobalOptions(c, "src-creds")
|
sourceCtx, err := contextFromGlobalOptions(c, "src-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
destinationCtx, err := contextFromGlobalOptions(c, "dest-creds")
|
destinationCtx, err := contextFromGlobalOptions(c, "dest-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -87,5 +87,23 @@ var copyCmd = cli.Command{
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use `USERNAME[:PASSWORD]` for accessing the destination registry",
|
Usage: "Use `USERNAME[:PASSWORD]` for accessing the destination registry",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "src-cert-dir",
|
||||||
|
Value: "",
|
||||||
|
Usage: "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the source registry",
|
||||||
|
},
|
||||||
|
cli.BoolTFlag{
|
||||||
|
Name: "src-tls-verify",
|
||||||
|
Usage: "require HTTPS and verify certificates when talking to the docker source registry (defaults to true)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "dest-cert-dir",
|
||||||
|
Value: "",
|
||||||
|
Usage: "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the destination registry",
|
||||||
|
},
|
||||||
|
cli.BoolTFlag{
|
||||||
|
Name: "dest-tls-verify",
|
||||||
|
Usage: "require HTTPS and verify certificates when talking to the docker destination registry (defaults to true)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ func deleteHandler(context *cli.Context) error {
|
|||||||
return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err)
|
return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, err := contextFromGlobalOptions(context, "creds")
|
ctx, err := contextFromGlobalOptions(context, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -39,5 +39,14 @@ var deleteCmd = cli.Command{
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use `USERNAME[:PASSWORD]` for accessing the registry",
|
Usage: "Use `USERNAME[:PASSWORD]` for accessing the registry",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "cert-dir",
|
||||||
|
Value: "",
|
||||||
|
Usage: "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the registry",
|
||||||
|
},
|
||||||
|
cli.BoolTFlag{
|
||||||
|
Name: "tls-verify",
|
||||||
|
Usage: "require HTTPS and verify certificates when talking to docker registries (defaults to true)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,15 @@ var inspectCmd = cli.Command{
|
|||||||
Usage: "Inspect image IMAGE-NAME",
|
Usage: "Inspect image IMAGE-NAME",
|
||||||
ArgsUsage: "IMAGE-NAME",
|
ArgsUsage: "IMAGE-NAME",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "cert-path",
|
||||||
|
Value: "",
|
||||||
|
Usage: "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the registry",
|
||||||
|
},
|
||||||
|
cli.BoolTFlag{
|
||||||
|
Name: "tls-verify",
|
||||||
|
Usage: "require HTTPS and verify certificates when talking to docker registries (defaults to true)",
|
||||||
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "raw",
|
Name: "raw",
|
||||||
Usage: "output raw manifest",
|
Usage: "output raw manifest",
|
||||||
|
@ -19,6 +19,7 @@ var layersCmd = cli.Command{
|
|||||||
Name: "layers",
|
Name: "layers",
|
||||||
Usage: "Get layers of IMAGE-NAME",
|
Usage: "Get layers of IMAGE-NAME",
|
||||||
ArgsUsage: "IMAGE-NAME [LAYER...]",
|
ArgsUsage: "IMAGE-NAME [LAYER...]",
|
||||||
|
Hidden: true,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
fmt.Fprintln(os.Stderr, `DEPRECATED: skopeo layers is deprecated in favor of skopeo copy`)
|
fmt.Fprintln(os.Stderr, `DEPRECATED: skopeo layers is deprecated in favor of skopeo copy`)
|
||||||
if c.NArg() == 0 {
|
if c.NArg() == 0 {
|
||||||
|
@ -30,14 +30,10 @@ func createApp() *cli.App {
|
|||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "enable debug output",
|
Usage: "enable debug output",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cert-path",
|
|
||||||
Value: "",
|
|
||||||
Usage: "use certificates at `PATH` (cert.pem, key.pem) to connect to the registry",
|
|
||||||
},
|
|
||||||
cli.BoolTFlag{
|
cli.BoolTFlag{
|
||||||
Name: "tls-verify",
|
Name: "tls-verify",
|
||||||
Usage: "require HTTPS and verify certificates when talking to docker registries (defaults to true)",
|
Usage: "require HTTPS and verify certificates when talking to docker registries (defaults to true)",
|
||||||
|
Hidden: true,
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "policy",
|
Name: "policy",
|
||||||
@ -54,6 +50,9 @@ func createApp() *cli.App {
|
|||||||
if c.GlobalBool("debug") {
|
if c.GlobalBool("debug") {
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
}
|
}
|
||||||
|
if c.GlobalIsSet("tls-verify") {
|
||||||
|
logrus.Warn("'--tls-verify' is deprecated, please set this on the specific subcommand")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
|
@ -9,15 +9,20 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func contextFromGlobalOptions(c *cli.Context, credsFlag string) (*types.SystemContext, error) {
|
func contextFromGlobalOptions(c *cli.Context, flagPrefix string) (*types.SystemContext, error) {
|
||||||
ctx := &types.SystemContext{
|
ctx := &types.SystemContext{
|
||||||
RegistriesDirPath: c.GlobalString("registries.d"),
|
RegistriesDirPath: c.GlobalString("registries.d"),
|
||||||
DockerCertPath: c.GlobalString("cert-path"),
|
DockerCertPath: c.String(flagPrefix + "cert-dir"),
|
||||||
|
// DEPRECATED: keep this here for backward compatibility, but override
|
||||||
|
// them if per subcommand flags are provided (see below).
|
||||||
DockerInsecureSkipTLSVerify: !c.GlobalBoolT("tls-verify"),
|
DockerInsecureSkipTLSVerify: !c.GlobalBoolT("tls-verify"),
|
||||||
}
|
}
|
||||||
if c.IsSet(credsFlag) {
|
if c.IsSet(flagPrefix + "tls-verify") {
|
||||||
|
ctx.DockerInsecureSkipTLSVerify = !c.BoolT(flagPrefix + "tls-verify")
|
||||||
|
}
|
||||||
|
if c.IsSet(flagPrefix + "creds") {
|
||||||
var err error
|
var err error
|
||||||
ctx.DockerAuthConfig, err = getDockerAuth(c.String(credsFlag))
|
ctx.DockerAuthConfig, err = getDockerAuth(c.String(flagPrefix + "creds"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -58,7 +63,7 @@ func parseImage(c *cli.Context) (types.Image, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctx, err := contextFromGlobalOptions(c, "creds")
|
ctx, err := contextFromGlobalOptions(c, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -73,7 +78,7 @@ func parseImageSource(c *cli.Context, name string, requestedManifestMIMETypes []
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctx, err := contextFromGlobalOptions(c, "creds")
|
ctx, err := contextFromGlobalOptions(c, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,11 @@ _skopeo_copy() {
|
|||||||
local options_with_args="
|
local options_with_args="
|
||||||
--sign-by
|
--sign-by
|
||||||
--src-creds --screds
|
--src-creds --screds
|
||||||
|
--src-cert-path
|
||||||
|
--src-tls-verify
|
||||||
--dest-creds --dcreds
|
--dest-creds --dcreds
|
||||||
|
--dest-cert-path
|
||||||
|
--dest-tls-verify
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--remove-signatures
|
--remove-signatures
|
||||||
@ -34,9 +38,11 @@ _skopeo_copy() {
|
|||||||
_skopeo_inspect() {
|
_skopeo_inspect() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--creds
|
--creds
|
||||||
|
--cert-path
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--raw
|
--raw
|
||||||
|
--tls-verify
|
||||||
"
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
@ -68,30 +74,33 @@ _skopeo_manifest_digest() {
|
|||||||
|
|
||||||
_skopeo_delete() {
|
_skopeo_delete() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--creds
|
--creds
|
||||||
|
--cert-path
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
|
--tls-verify
|
||||||
"
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
_skopeo_layers() {
|
_skopeo_layers() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
|
--creds
|
||||||
|
--cert-path
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
|
--tls-verify
|
||||||
"
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
_skopeo_skopeo() {
|
_skopeo_skopeo() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--cert-path
|
|
||||||
--policy
|
--policy
|
||||||
--registries.d
|
--registries.d
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--debug
|
--debug
|
||||||
--tls-verify
|
|
||||||
--version -v
|
--version -v
|
||||||
--help -h
|
--help -h
|
||||||
"
|
"
|
||||||
|
@ -37,14 +37,10 @@ Most commands refer to container images, using a _transport_`:`_details_ format.
|
|||||||
|
|
||||||
**--debug** enable debug output
|
**--debug** enable debug output
|
||||||
|
|
||||||
**--cert-path** _path_ Use certificates at _path_ (cert.pem, key.pem) to connect to the registry
|
|
||||||
|
|
||||||
**--policy** _path-to-policy_ Path to a policy.json file to use for verifying signatures and deciding whether an image is trusted, overriding the default trust policy file.
|
**--policy** _path-to-policy_ Path to a policy.json file to use for verifying signatures and deciding whether an image is trusted, overriding the default trust policy file.
|
||||||
|
|
||||||
**--registries.d** _dir_ use registry configuration files in _dir_ (e.g. for docker signature storage), overriding the default path.
|
**--registries.d** _dir_ use registry configuration files in _dir_ (e.g. for docker signature storage), overriding the default path.
|
||||||
|
|
||||||
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to docker registries (defaults to true)
|
|
||||||
|
|
||||||
**--help**|**-h** Show help
|
**--help**|**-h** Show help
|
||||||
|
|
||||||
**--version**|**-v** print the version number
|
**--version**|**-v** print the version number
|
||||||
@ -70,6 +66,14 @@ Uses the system's trust policy to validate images, rejects images not trusted by
|
|||||||
|
|
||||||
**--dest-creds** _username[:password]_ for accessing the destination registry
|
**--dest-creds** _username[:password]_ for accessing the destination registry
|
||||||
|
|
||||||
|
**--src-cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the source registry
|
||||||
|
|
||||||
|
**--src-tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to docker source registry (defaults to true)
|
||||||
|
|
||||||
|
**--dest-cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the destination registry
|
||||||
|
|
||||||
|
**--dest-tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to docker destination registry (defaults to true)
|
||||||
|
|
||||||
Existing signatures, if any, are preserved as well.
|
Existing signatures, if any, are preserved as well.
|
||||||
|
|
||||||
## skopeo delete
|
## skopeo delete
|
||||||
@ -83,6 +87,10 @@ $ docker exec -it registry bin/registry garbage-collect /etc/docker/registry/con
|
|||||||
|
|
||||||
**--creds** _username[:password]_ for accessing the registry
|
**--creds** _username[:password]_ for accessing the registry
|
||||||
|
|
||||||
|
**--cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the registry
|
||||||
|
|
||||||
|
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to docker registries (defaults to true)
|
||||||
|
|
||||||
Additionally, the registry must allow deletions by setting `REGISTRY_STORAGE_DELETE_ENABLED=true` for the registry daemon.
|
Additionally, the registry must allow deletions by setting `REGISTRY_STORAGE_DELETE_ENABLED=true` for the registry daemon.
|
||||||
|
|
||||||
## skopeo inspect
|
## skopeo inspect
|
||||||
@ -96,12 +104,9 @@ Return low-level information about _image-name_ in a registry
|
|||||||
|
|
||||||
**--creds** _username[:password]_ for accessing the registry
|
**--creds** _username[:password]_ for accessing the registry
|
||||||
|
|
||||||
## skopeo layers
|
**--cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the registry
|
||||||
**skopeo layers** _image-name_
|
|
||||||
|
|
||||||
Get image layers of _image-name_
|
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to docker registries (defaults to true)
|
||||||
|
|
||||||
_image-name_ name of the image to retrieve layers
|
|
||||||
|
|
||||||
## skopeo manifest-digest
|
## skopeo manifest-digest
|
||||||
**skopeo manifest-digest** _manifest-file_
|
**skopeo manifest-digest** _manifest-file_
|
||||||
|
@ -16,7 +16,7 @@ clone git github.com/pmezard/go-difflib master
|
|||||||
# docker deps from https://github.com/docker/docker/blob/v1.11.2/hack/vendor.sh
|
# docker deps from https://github.com/docker/docker/blob/v1.11.2/hack/vendor.sh
|
||||||
clone git github.com/docker/docker v1.12.1
|
clone git github.com/docker/docker v1.12.1
|
||||||
clone git github.com/docker/engine-api 4eca04ae18f4f93f40196a17b9aa6e11262a7269
|
clone git github.com/docker/engine-api 4eca04ae18f4f93f40196a17b9aa6e11262a7269
|
||||||
clone git github.com/docker/go-connections v0.2.0
|
clone git github.com/docker/go-connections 4ccf312bf1d35e5dbda654e57a9be4c3f3cd0366
|
||||||
clone git github.com/vbatts/tar-split v0.9.11
|
clone git github.com/vbatts/tar-split v0.9.11
|
||||||
clone git github.com/gorilla/context 14f550f51a
|
clone git github.com/gorilla/context 14f550f51a
|
||||||
clone git github.com/gorilla/mux e444e69cbd
|
clone git github.com/gorilla/mux e444e69cbd
|
||||||
|
67
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
67
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
@ -87,6 +87,64 @@ func newTransport() *http.Transport {
|
|||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupCertificates(dir string, tlsc *tls.Config) error {
|
||||||
|
if dir == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fs, err := ioutil.ReadDir(dir)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range fs {
|
||||||
|
fullPath := filepath.Join(dir, f.Name())
|
||||||
|
if strings.HasSuffix(f.Name(), ".crt") {
|
||||||
|
systemPool, err := tlsconfig.SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get system cert pool: %v", err)
|
||||||
|
}
|
||||||
|
tlsc.RootCAs = systemPool
|
||||||
|
logrus.Debugf("crt: %s", fullPath)
|
||||||
|
data, err := ioutil.ReadFile(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tlsc.RootCAs.AppendCertsFromPEM(data)
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(f.Name(), ".cert") {
|
||||||
|
certName := f.Name()
|
||||||
|
keyName := certName[:len(certName)-5] + ".key"
|
||||||
|
logrus.Debugf("cert: %s", fullPath)
|
||||||
|
if !hasFile(fs, keyName) {
|
||||||
|
return fmt.Errorf("missing key %s for client certificate %s. Note that CA certificates should use the extension .crt", keyName, certName)
|
||||||
|
}
|
||||||
|
cert, err := tls.LoadX509KeyPair(filepath.Join(dir, certName), filepath.Join(dir, keyName))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tlsc.Certificates = append(tlsc.Certificates, cert)
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(f.Name(), ".key") {
|
||||||
|
keyName := f.Name()
|
||||||
|
certName := keyName[:len(keyName)-4] + ".cert"
|
||||||
|
logrus.Debugf("key: %s", fullPath)
|
||||||
|
if !hasFile(fs, certName) {
|
||||||
|
return fmt.Errorf("missing client certificate %s for key %s", certName, keyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasFile(files []os.FileInfo, name string) bool {
|
||||||
|
for _, f := range files {
|
||||||
|
if f.Name() == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// newDockerClient returns a new dockerClient instance for refHostname (a host a specified in the Docker image reference, not canonicalized to dockerRegistry)
|
// newDockerClient returns a new dockerClient instance for refHostname (a host a specified in the Docker image reference, not canonicalized to dockerRegistry)
|
||||||
// “write” specifies whether the client will be used for "write" access (in particular passed to lookaside.go:toplevelFromSection)
|
// “write” specifies whether the client will be used for "write" access (in particular passed to lookaside.go:toplevelFromSection)
|
||||||
func newDockerClient(ctx *types.SystemContext, ref dockerReference, write bool) (*dockerClient, error) {
|
func newDockerClient(ctx *types.SystemContext, ref dockerReference, write bool) (*dockerClient, error) {
|
||||||
@ -102,13 +160,10 @@ func newDockerClient(ctx *types.SystemContext, ref dockerReference, write bool)
|
|||||||
if ctx != nil && (ctx.DockerCertPath != "" || ctx.DockerInsecureSkipTLSVerify) {
|
if ctx != nil && (ctx.DockerCertPath != "" || ctx.DockerInsecureSkipTLSVerify) {
|
||||||
tlsc := &tls.Config{}
|
tlsc := &tls.Config{}
|
||||||
|
|
||||||
if ctx.DockerCertPath != "" {
|
if err := setupCertificates(ctx.DockerCertPath, tlsc); err != nil {
|
||||||
cert, err := tls.LoadX509KeyPair(filepath.Join(ctx.DockerCertPath, "cert.pem"), filepath.Join(ctx.DockerCertPath, "key.pem"))
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error loading x509 key pair: %s", err)
|
|
||||||
}
|
|
||||||
tlsc.Certificates = append(tlsc.Certificates, cert)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsc.InsecureSkipVerify = ctx.DockerInsecureSkipTLSVerify
|
tlsc.InsecureSkipVerify = ctx.DockerInsecureSkipTLSVerify
|
||||||
tr.TLSClientConfig = tlsc
|
tr.TLSClientConfig = tlsc
|
||||||
}
|
}
|
||||||
|
7
vendor/github.com/containers/image/types/types.go
generated
vendored
7
vendor/github.com/containers/image/types/types.go
generated
vendored
@ -270,8 +270,11 @@ type SystemContext struct {
|
|||||||
RegistriesDirPath string
|
RegistriesDirPath string
|
||||||
|
|
||||||
// === docker.Transport overrides ===
|
// === docker.Transport overrides ===
|
||||||
DockerCertPath string // If not "", a directory containing "cert.pem" and "key.pem" used when talking to a Docker Registry
|
// If not "", a directory containing a CA certificate (ending with ".crt"),
|
||||||
DockerInsecureSkipTLSVerify bool // Allow contacting docker registries over HTTP, or HTTPS with failed TLS verification. Note that this does not affect other TLS connections.
|
// a client certificate (ending with ".cert") and a client ceritificate key
|
||||||
|
// (ending with ".key") used when talking to a Docker Registry.
|
||||||
|
DockerCertPath string
|
||||||
|
DockerInsecureSkipTLSVerify bool // Allow contacting docker registries over HTTP, or HTTPS with failed TLS verification. Note that this does not affect other TLS connections.
|
||||||
// if nil, the library tries to parse ~/.docker/config.json to retrieve credentials
|
// if nil, the library tries to parse ~/.docker/config.json to retrieve credentials
|
||||||
DockerAuthConfig *DockerAuthConfig
|
DockerAuthConfig *DockerAuthConfig
|
||||||
// if not "", an User-Agent header is added to each request when contacting a registry.
|
// if not "", an User-Agent header is added to each request when contacting a registry.
|
||||||
|
177
vendor/github.com/docker/go-connections/nat/nat.go
generated
vendored
177
vendor/github.com/docker/go-connections/nat/nat.go
generated
vendored
@ -85,14 +85,10 @@ func (p Port) Port() string {
|
|||||||
// Int returns the port number of a Port as an int
|
// Int returns the port number of a Port as an int
|
||||||
func (p Port) Int() int {
|
func (p Port) Int() int {
|
||||||
portStr := p.Port()
|
portStr := p.Port()
|
||||||
if len(portStr) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't need to check for an error because we're going to
|
// We don't need to check for an error because we're going to
|
||||||
// assume that any error would have been found, and reported, in NewPort()
|
// assume that any error would have been found, and reported, in NewPort()
|
||||||
port, _ := strconv.ParseUint(portStr, 10, 16)
|
port, _ := ParsePort(portStr)
|
||||||
return int(port)
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
// Range returns the start/end port numbers of a Port range as ints
|
// Range returns the start/end port numbers of a Port range as ints
|
||||||
@ -132,92 +128,115 @@ func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding,
|
|||||||
exposedPorts = make(map[Port]struct{}, len(ports))
|
exposedPorts = make(map[Port]struct{}, len(ports))
|
||||||
bindings = make(map[Port][]PortBinding)
|
bindings = make(map[Port][]PortBinding)
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, rawPort := range ports {
|
for _, rawPort := range ports {
|
||||||
proto := "tcp"
|
portMappings, err := ParsePortSpec(rawPort)
|
||||||
|
|
||||||
if i := strings.LastIndex(rawPort, "/"); i != -1 {
|
|
||||||
proto = rawPort[i+1:]
|
|
||||||
rawPort = rawPort[:i]
|
|
||||||
}
|
|
||||||
if !strings.Contains(rawPort, ":") {
|
|
||||||
rawPort = fmt.Sprintf("::%s", rawPort)
|
|
||||||
} else if len(strings.Split(rawPort, ":")) == 2 {
|
|
||||||
rawPort = fmt.Sprintf(":%s", rawPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
parts, err := PartParser(portSpecTemplate, rawPort)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
for _, portMapping := range portMappings {
|
||||||
containerPort = parts["containerPort"]
|
port := portMapping.Port
|
||||||
rawIP = parts["ip"]
|
|
||||||
hostPort = parts["hostPort"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if rawIP != "" && net.ParseIP(rawIP) == nil {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid ip address: %s", rawIP)
|
|
||||||
}
|
|
||||||
if containerPort == "" {
|
|
||||||
return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
startPort, endPort, err := ParsePortRange(containerPort)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
var startHostPort, endHostPort uint64 = 0, 0
|
|
||||||
if len(hostPort) > 0 {
|
|
||||||
startHostPort, endHostPort, err = ParsePortRange(hostPort)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
|
|
||||||
// Allow host port range iff containerPort is not a range.
|
|
||||||
// In this case, use the host port range as the dynamic
|
|
||||||
// host port range to allocate into.
|
|
||||||
if endPort != startPort {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validateProto(strings.ToLower(proto)) {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid proto: %s", proto)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := uint64(0); i <= (endPort - startPort); i++ {
|
|
||||||
containerPort = strconv.FormatUint(startPort+i, 10)
|
|
||||||
if len(hostPort) > 0 {
|
|
||||||
hostPort = strconv.FormatUint(startHostPort+i, 10)
|
|
||||||
}
|
|
||||||
// Set hostPort to a range only if there is a single container port
|
|
||||||
// and a dynamic host port.
|
|
||||||
if startPort == endPort && startHostPort != endHostPort {
|
|
||||||
hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
|
|
||||||
}
|
|
||||||
port, err := NewPort(strings.ToLower(proto), containerPort)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if _, exists := exposedPorts[port]; !exists {
|
if _, exists := exposedPorts[port]; !exists {
|
||||||
exposedPorts[port] = struct{}{}
|
exposedPorts[port] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding := PortBinding{
|
|
||||||
HostIP: rawIP,
|
|
||||||
HostPort: hostPort,
|
|
||||||
}
|
|
||||||
bslice, exists := bindings[port]
|
bslice, exists := bindings[port]
|
||||||
if !exists {
|
if !exists {
|
||||||
bslice = []PortBinding{}
|
bslice = []PortBinding{}
|
||||||
}
|
}
|
||||||
bindings[port] = append(bslice, binding)
|
bindings[port] = append(bslice, portMapping.Binding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return exposedPorts, bindings, nil
|
return exposedPorts, bindings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortMapping is a data object mapping a Port to a PortBinding
|
||||||
|
type PortMapping struct {
|
||||||
|
Port Port
|
||||||
|
Binding PortBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitParts(rawport string) (string, string, string) {
|
||||||
|
parts := strings.Split(rawport, ":")
|
||||||
|
n := len(parts)
|
||||||
|
containerport := parts[n-1]
|
||||||
|
|
||||||
|
switch n {
|
||||||
|
case 1:
|
||||||
|
return "", "", containerport
|
||||||
|
case 2:
|
||||||
|
return "", parts[0], containerport
|
||||||
|
case 3:
|
||||||
|
return parts[0], parts[1], containerport
|
||||||
|
default:
|
||||||
|
return strings.Join(parts[:n-2], ":"), parts[n-2], containerport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParsePortSpec parses a port specification string into a slice of PortMappings
|
||||||
|
func ParsePortSpec(rawPort string) ([]PortMapping, error) {
|
||||||
|
var proto string
|
||||||
|
rawIP, hostPort, containerPort := splitParts(rawPort)
|
||||||
|
proto, containerPort = SplitProtoPort(containerPort)
|
||||||
|
|
||||||
|
// Strip [] from IPV6 addresses
|
||||||
|
ip, _, err := net.SplitHostPort(rawIP + ":")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid ip address %v: %s", rawIP, err)
|
||||||
|
}
|
||||||
|
if ip != "" && net.ParseIP(ip) == nil {
|
||||||
|
return nil, fmt.Errorf("Invalid ip address: %s", ip)
|
||||||
|
}
|
||||||
|
if containerPort == "" {
|
||||||
|
return nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
startPort, endPort, err := ParsePortRange(containerPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
var startHostPort, endHostPort uint64 = 0, 0
|
||||||
|
if len(hostPort) > 0 {
|
||||||
|
startHostPort, endHostPort, err = ParsePortRange(hostPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
|
||||||
|
// Allow host port range iff containerPort is not a range.
|
||||||
|
// In this case, use the host port range as the dynamic
|
||||||
|
// host port range to allocate into.
|
||||||
|
if endPort != startPort {
|
||||||
|
return nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validateProto(strings.ToLower(proto)) {
|
||||||
|
return nil, fmt.Errorf("Invalid proto: %s", proto)
|
||||||
|
}
|
||||||
|
|
||||||
|
ports := []PortMapping{}
|
||||||
|
for i := uint64(0); i <= (endPort - startPort); i++ {
|
||||||
|
containerPort = strconv.FormatUint(startPort+i, 10)
|
||||||
|
if len(hostPort) > 0 {
|
||||||
|
hostPort = strconv.FormatUint(startHostPort+i, 10)
|
||||||
|
}
|
||||||
|
// Set hostPort to a range only if there is a single container port
|
||||||
|
// and a dynamic host port.
|
||||||
|
if startPort == endPort && startHostPort != endHostPort {
|
||||||
|
hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
|
||||||
|
}
|
||||||
|
port, err := NewPort(strings.ToLower(proto), containerPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
binding := PortBinding{
|
||||||
|
HostIP: ip,
|
||||||
|
HostPort: hostPort,
|
||||||
|
}
|
||||||
|
ports = append(ports, PortMapping{Port: port, Binding: binding})
|
||||||
|
}
|
||||||
|
return ports, nil
|
||||||
|
}
|
||||||
|
1
vendor/github.com/docker/go-connections/nat/parse.go
generated
vendored
1
vendor/github.com/docker/go-connections/nat/parse.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
// PartParser parses and validates the specified string (data) using the specified template
|
// PartParser parses and validates the specified string (data) using the specified template
|
||||||
// e.g. ip:public:private -> 192.168.0.1:80:8000
|
// e.g. ip:public:private -> 192.168.0.1:80:8000
|
||||||
|
// DEPRECATED: do not use, this function may be removed in a future version
|
||||||
func PartParser(template, data string) (map[string]string, error) {
|
func PartParser(template, data string) (map[string]string, error) {
|
||||||
// ip:public:private
|
// ip:public:private
|
||||||
var (
|
var (
|
||||||
|
8
vendor/github.com/docker/go-connections/sockets/inmem_socket.go
generated
vendored
8
vendor/github.com/docker/go-connections/sockets/inmem_socket.go
generated
vendored
@ -79,11 +79,3 @@ func (a dummyAddr) Network() string {
|
|||||||
func (a dummyAddr) String() string {
|
func (a dummyAddr) String() string {
|
||||||
return string(a)
|
return string(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeoutError is used when there is a timeout with a connection
|
|
||||||
// this implements the net.Error interface
|
|
||||||
type timeoutError struct{}
|
|
||||||
|
|
||||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
|
||||||
func (e *timeoutError) Timeout() bool { return true }
|
|
||||||
func (e *timeoutError) Temporary() bool { return true }
|
|
||||||
|
16
vendor/github.com/docker/go-connections/sockets/sockets.go
generated
vendored
16
vendor/github.com/docker/go-connections/sockets/sockets.go
generated
vendored
@ -2,6 +2,7 @@
|
|||||||
package sockets
|
package sockets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@ -10,6 +11,9 @@ import (
|
|||||||
// Why 32? See https://github.com/docker/docker/pull/8035.
|
// Why 32? See https://github.com/docker/docker/pull/8035.
|
||||||
const defaultTimeout = 32 * time.Second
|
const defaultTimeout = 32 * time.Second
|
||||||
|
|
||||||
|
// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system.
|
||||||
|
var ErrProtocolNotAvailable = errors.New("protocol not available")
|
||||||
|
|
||||||
// ConfigureTransport configures the specified Transport according to the
|
// ConfigureTransport configures the specified Transport according to the
|
||||||
// specified proto and addr.
|
// specified proto and addr.
|
||||||
// If the proto is unix (using a unix socket to communicate) or npipe the
|
// If the proto is unix (using a unix socket to communicate) or npipe the
|
||||||
@ -17,17 +21,9 @@ const defaultTimeout = 32 * time.Second
|
|||||||
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
|
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
|
||||||
switch proto {
|
switch proto {
|
||||||
case "unix":
|
case "unix":
|
||||||
// No need for compression in local communications.
|
return configureUnixTransport(tr, proto, addr)
|
||||||
tr.DisableCompression = true
|
|
||||||
tr.Dial = func(_, _ string) (net.Conn, error) {
|
|
||||||
return net.DialTimeout(proto, addr, defaultTimeout)
|
|
||||||
}
|
|
||||||
case "npipe":
|
case "npipe":
|
||||||
// No need for compression in local communications.
|
return configureNpipeTransport(tr, proto, addr)
|
||||||
tr.DisableCompression = true
|
|
||||||
tr.Dial = func(_, _ string) (net.Conn, error) {
|
|
||||||
return DialPipe(addr, defaultTimeout)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
tr.Proxy = http.ProxyFromEnvironment
|
tr.Proxy = http.ProxyFromEnvironment
|
||||||
dialer, err := DialerFromEnvironment(&net.Dialer{
|
dialer, err := DialerFromEnvironment(&net.Dialer{
|
||||||
|
20
vendor/github.com/docker/go-connections/sockets/sockets_unix.go
generated
vendored
20
vendor/github.com/docker/go-connections/sockets/sockets_unix.go
generated
vendored
@ -3,11 +3,31 @@
|
|||||||
package sockets
|
package sockets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
|
||||||
|
|
||||||
|
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||||||
|
if len(addr) > maxUnixSocketPathSize {
|
||||||
|
return fmt.Errorf("Unix socket path %q is too long", addr)
|
||||||
|
}
|
||||||
|
// No need for compression in local communications.
|
||||||
|
tr.DisableCompression = true
|
||||||
|
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||||||
|
return net.DialTimeout(proto, addr, defaultTimeout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
|
||||||
|
return ErrProtocolNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
// DialPipe connects to a Windows named pipe.
|
// DialPipe connects to a Windows named pipe.
|
||||||
// This is not supported on other OSes.
|
// This is not supported on other OSes.
|
||||||
func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
|
func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
|
||||||
|
14
vendor/github.com/docker/go-connections/sockets/sockets_windows.go
generated
vendored
14
vendor/github.com/docker/go-connections/sockets/sockets_windows.go
generated
vendored
@ -2,11 +2,25 @@ package sockets
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio"
|
"github.com/Microsoft/go-winio"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||||||
|
return ErrProtocolNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
|
||||||
|
// No need for compression in local communications.
|
||||||
|
tr.DisableCompression = true
|
||||||
|
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||||||
|
return DialPipe(addr, defaultTimeout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DialPipe connects to a Windows named pipe.
|
// DialPipe connects to a Windows named pipe.
|
||||||
func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
|
func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
|
||||||
return winio.DialPipe(addr, &timeout)
|
return winio.DialPipe(addr, &timeout)
|
||||||
|
2
vendor/github.com/docker/go-connections/sockets/tcp_socket.go
generated
vendored
2
vendor/github.com/docker/go-connections/sockets/tcp_socket.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewTCPSocket creates a TCP socket listener with the specified address and
|
// NewTCPSocket creates a TCP socket listener with the specified address and
|
||||||
// and the specified tls configuration. If TLSConfig is set, will encapsulate the
|
// the specified tls configuration. If TLSConfig is set, will encapsulate the
|
||||||
// TCP listener inside a TLS one.
|
// TCP listener inside a TLS one.
|
||||||
func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
|
func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
|
21
vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go
generated
vendored
Normal file
21
vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package tlsconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SystemCertPool returns a copy of the system cert pool,
|
||||||
|
// returns an error if failed to load or empty pool on windows.
|
||||||
|
func SystemCertPool() (*x509.CertPool, error) {
|
||||||
|
certpool, err := x509.SystemCertPool()
|
||||||
|
if err != nil && runtime.GOOS == "windows" {
|
||||||
|
logrus.Warnf("Unable to use system certificate pool: %v", err)
|
||||||
|
return x509.NewCertPool(), nil
|
||||||
|
}
|
||||||
|
return certpool, err
|
||||||
|
}
|
16
vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go
generated
vendored
Normal file
16
vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package tlsconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SystemCertPool returns an new empty cert pool,
|
||||||
|
// accessing system cert pool is supported in go 1.7
|
||||||
|
func SystemCertPool() (*x509.CertPool, error) {
|
||||||
|
logrus.Warn("Unable to use system certificate pool: requires building with go 1.7 or later")
|
||||||
|
return x509.NewCertPool(), nil
|
||||||
|
}
|
48
vendor/github.com/docker/go-connections/tlsconfig/config.go
generated
vendored
48
vendor/github.com/docker/go-connections/tlsconfig/config.go
generated
vendored
@ -46,44 +46,46 @@ var acceptedCBCCiphers = []uint16{
|
|||||||
// known weak algorithms removed.
|
// known weak algorithms removed.
|
||||||
var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
|
var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
|
||||||
|
|
||||||
// ServerDefault is a secure-enough TLS configuration for the server TLS configuration.
|
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
|
||||||
var ServerDefault = tls.Config{
|
func ServerDefault() *tls.Config {
|
||||||
// Avoid fallback to SSL protocols < TLS1.0
|
return &tls.Config{
|
||||||
MinVersion: tls.VersionTLS10,
|
// Avoid fallback to SSL protocols < TLS1.0
|
||||||
PreferServerCipherSuites: true,
|
MinVersion: tls.VersionTLS10,
|
||||||
CipherSuites: DefaultServerAcceptedCiphers,
|
PreferServerCipherSuites: true,
|
||||||
|
CipherSuites: DefaultServerAcceptedCiphers,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientDefault is a secure-enough TLS configuration for the client TLS configuration.
|
// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
|
||||||
var ClientDefault = tls.Config{
|
func ClientDefault() *tls.Config {
|
||||||
// Prefer TLS1.2 as the client minimum
|
return &tls.Config{
|
||||||
MinVersion: tls.VersionTLS12,
|
// Prefer TLS1.2 as the client minimum
|
||||||
CipherSuites: clientCipherSuites,
|
MinVersion: tls.VersionTLS12,
|
||||||
|
CipherSuites: clientCipherSuites,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
|
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
|
||||||
func certPool(caFile string) (*x509.CertPool, error) {
|
func certPool(caFile string) (*x509.CertPool, error) {
|
||||||
// If we should verify the server, we need to load a trusted ca
|
// If we should verify the server, we need to load a trusted ca
|
||||||
certPool := x509.NewCertPool()
|
certPool, err := SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read system certificates: %v", err)
|
||||||
|
}
|
||||||
pem, err := ioutil.ReadFile(caFile)
|
pem, err := ioutil.ReadFile(caFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not read CA certificate %q: %v", caFile, err)
|
return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
|
||||||
}
|
}
|
||||||
if !certPool.AppendCertsFromPEM(pem) {
|
if !certPool.AppendCertsFromPEM(pem) {
|
||||||
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
|
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
|
||||||
}
|
}
|
||||||
s := certPool.Subjects()
|
logrus.Debugf("Trusting %d certs", len(certPool.Subjects()))
|
||||||
subjects := make([]string, len(s))
|
|
||||||
for i, subject := range s {
|
|
||||||
subjects[i] = string(subject)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Trusting certs with subjects: %v", subjects)
|
|
||||||
return certPool, nil
|
return certPool, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client returns a TLS configuration meant to be used by a client.
|
// Client returns a TLS configuration meant to be used by a client.
|
||||||
func Client(options Options) (*tls.Config, error) {
|
func Client(options Options) (*tls.Config, error) {
|
||||||
tlsConfig := ClientDefault
|
tlsConfig := ClientDefault()
|
||||||
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
|
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
|
||||||
if !options.InsecureSkipVerify && options.CAFile != "" {
|
if !options.InsecureSkipVerify && options.CAFile != "" {
|
||||||
CAs, err := certPool(options.CAFile)
|
CAs, err := certPool(options.CAFile)
|
||||||
@ -101,12 +103,12 @@ func Client(options Options) (*tls.Config, error) {
|
|||||||
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server returns a TLS configuration meant to be used by a server.
|
// Server returns a TLS configuration meant to be used by a server.
|
||||||
func Server(options Options) (*tls.Config, error) {
|
func Server(options Options) (*tls.Config, error) {
|
||||||
tlsConfig := ServerDefault
|
tlsConfig := ServerDefault()
|
||||||
tlsConfig.ClientAuth = options.ClientAuth
|
tlsConfig.ClientAuth = options.ClientAuth
|
||||||
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
|
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -123,5 +125,5 @@ func Server(options Options) (*tls.Config, error) {
|
|||||||
}
|
}
|
||||||
tlsConfig.ClientCAs = CAs
|
tlsConfig.ClientCAs = CAs
|
||||||
}
|
}
|
||||||
return &tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user