mirror of
https://github.com/openshift/image-registry.git
synced 2026-02-05 09:45:55 +01:00
Add code from the origin repository
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/logs"
|
||||
|
||||
"github.com/openshift/image-registry/pkg/cmd/dockerregistry"
|
||||
cmdutil "github.com/openshift/origin/pkg/cmd/util"
|
||||
"github.com/openshift/origin/pkg/cmd/util/serviceability"
|
||||
)
|
||||
|
||||
@@ -53,12 +52,20 @@ func main() {
|
||||
dockerregistry.Execute(configFile)
|
||||
}
|
||||
|
||||
func env(key string, defaultValue string) string {
|
||||
val := os.Getenv(key)
|
||||
if len(val) == 0 {
|
||||
return defaultValue
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func startProfiler() {
|
||||
if cmdutil.Env("OPENSHIFT_PROFILE", "") == "web" {
|
||||
if env("OPENSHIFT_PROFILE", "") == "web" {
|
||||
go func() {
|
||||
runtime.SetBlockProfileRate(1)
|
||||
profilePort := cmdutil.Env("OPENSHIFT_PROFILE_PORT", "6060")
|
||||
profileHost := cmdutil.Env("OPENSHIFT_PROFILE_HOST", "127.0.0.1")
|
||||
profilePort := env("OPENSHIFT_PROFILE_PORT", "6060")
|
||||
profileHost := env("OPENSHIFT_PROFILE_HOST", "127.0.0.1")
|
||||
log.Infof(fmt.Sprintf("Starting profiling endpoint at http://%s:%s/debug/pprof/", profileHost, profilePort))
|
||||
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", profileHost, profilePort), nil))
|
||||
}()
|
||||
|
||||
@@ -40,16 +40,16 @@ import (
|
||||
|
||||
kubeversion "k8s.io/kubernetes/pkg/version"
|
||||
|
||||
"github.com/openshift/origin/pkg/cmd/server/crypto"
|
||||
"github.com/openshift/origin/pkg/version"
|
||||
|
||||
"github.com/openshift/image-registry/pkg/clientcmd"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/audit"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/client"
|
||||
registryconfig "github.com/openshift/image-registry/pkg/dockerregistry/server/configuration"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/maxconnections"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/prune"
|
||||
"github.com/openshift/image-registry/pkg/origin-common/clientcmd"
|
||||
"github.com/openshift/image-registry/pkg/origin-common/crypto"
|
||||
)
|
||||
|
||||
var pruneMode = flag.String("prune", "", "prune blobs from the storage and exit (check, delete)")
|
||||
|
||||
@@ -22,10 +22,10 @@ import (
|
||||
userapi "github.com/openshift/origin/pkg/user/apis/user"
|
||||
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization/v1"
|
||||
|
||||
"github.com/openshift/image-registry/pkg/clientcmd"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/client"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/server/configuration"
|
||||
"github.com/openshift/image-registry/pkg/dockerregistry/testutil"
|
||||
"github.com/openshift/image-registry/pkg/origin-common/clientcmd"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
authclientv1 "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authorization/v1"
|
||||
kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
|
||||
"github.com/openshift/image-registry/pkg/clientcmd"
|
||||
"github.com/openshift/image-registry/pkg/origin-common/clientcmd"
|
||||
imageclientv1 "github.com/openshift/origin/pkg/image/generated/clientset/typed/image/v1"
|
||||
userclientv1 "github.com/openshift/origin/pkg/user/generated/clientset/typed/user/v1"
|
||||
)
|
||||
|
||||
17
pkg/origin-common/README.md
Normal file
17
pkg/origin-common/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
## Packages based on the code from the OpenShift Origin repository
|
||||
|
||||
### clientcmd
|
||||
|
||||
The clientcmd package is a redacted copy of [github.com/openshift/origin/pkg/cmd/util/clientcmd](https://godoc.org/github.com/openshift/origin/pkg/cmd/util/clientcmd).
|
||||
|
||||
The code is almost untouched, but there are some differences:
|
||||
|
||||
* some depedencies was merged into this package (getEnv, Addr, recommendedHomeFile, etc.),
|
||||
* it doesn't support migrations for `KUBECONFIG` (i.e. the old default is ignored, which is `.kube/.config`),
|
||||
* it uses the field `openshift.kubeconfig` from our config instead of the `--config` flag.
|
||||
|
||||
### crypto
|
||||
|
||||
The crypto package is a reduced copy of [github.com/openshift/origin/pkg/cmd/server/crypto](https://godoc.org/github.com/openshift/origin/pkg/cmd/server/crypto).
|
||||
|
||||
We keep only functions that are required by the image registry.
|
||||
169
pkg/origin-common/clientcmd/addr.go
Normal file
169
pkg/origin-common/clientcmd/addr.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package clientcmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// urlPrefixes is the list of string prefix values that may indicate a URL
|
||||
// is present.
|
||||
var urlPrefixes = []string{"http://", "https://", "tcp://", "unix://"}
|
||||
|
||||
// isIPv6Host returns true if the value appears to be an IPv6 host string (that does
|
||||
// not include a port).
|
||||
func isIPv6Host(value string) bool {
|
||||
if strings.HasPrefix(value, "[") {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(value, "%") || strings.Count(value, ":") > 1
|
||||
}
|
||||
|
||||
// Addr is a flag type that attempts to load a host, IP, host:port, or
|
||||
// URL value from a string argument. It tracks whether the value was set
|
||||
// and allows the caller to provide defaults for the scheme and port.
|
||||
type Addr struct {
|
||||
// Specified by the caller
|
||||
DefaultScheme string
|
||||
DefaultPort int
|
||||
AllowPrefix bool
|
||||
|
||||
// Provided will be true if Set is invoked
|
||||
Provided bool
|
||||
// Value is the exact value provided on the flag
|
||||
Value string
|
||||
|
||||
// URL represents the user input. The Host field is guaranteed
|
||||
// to be set if Provided is true
|
||||
URL *url.URL
|
||||
// Host is the hostname or IP portion of the user input
|
||||
Host string
|
||||
// IPv6Host is true if the hostname appears to be an IPv6 input
|
||||
IPv6Host bool
|
||||
// Port is the port portion of the user input. Will be 0 if no port was found
|
||||
// and no default port could be established.
|
||||
Port int
|
||||
}
|
||||
|
||||
// Default creates a new Address with the value set
|
||||
func (a Addr) Default() Addr {
|
||||
if err := a.Set(a.Value); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
a.Provided = false
|
||||
return a
|
||||
}
|
||||
|
||||
// Set attempts to set a string value to an address
|
||||
func (a *Addr) Set(value string) error {
|
||||
scheme := a.DefaultScheme
|
||||
if len(scheme) == 0 {
|
||||
scheme = "tcp"
|
||||
}
|
||||
addr := &url.URL{
|
||||
Scheme: scheme,
|
||||
}
|
||||
|
||||
switch {
|
||||
case a.isURL(value):
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a valid URL: %v", err)
|
||||
}
|
||||
if !a.AllowPrefix {
|
||||
parsed.Path = ""
|
||||
}
|
||||
parsed.RawQuery = ""
|
||||
parsed.Fragment = ""
|
||||
|
||||
if parsed.Scheme != "unix" && strings.Contains(parsed.Host, ":") {
|
||||
host, port, err := net.SplitHostPort(parsed.Host)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a valid host:port: %v", err)
|
||||
}
|
||||
portNum, err := strconv.ParseUint(port, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a valid port: %v", err)
|
||||
}
|
||||
a.Host = host
|
||||
a.Port = int(portNum)
|
||||
|
||||
} else {
|
||||
port := 0
|
||||
switch parsed.Scheme {
|
||||
case "http":
|
||||
port = 80
|
||||
case "https":
|
||||
port = 443
|
||||
case "unix":
|
||||
port = 0
|
||||
default:
|
||||
return fmt.Errorf("no port specified")
|
||||
}
|
||||
a.Host = parsed.Host
|
||||
a.Port = port
|
||||
}
|
||||
addr = parsed
|
||||
|
||||
case isIPv6Host(value):
|
||||
a.Host = value
|
||||
a.Port = a.DefaultPort
|
||||
|
||||
case strings.Contains(value, ":"):
|
||||
host, port, err := net.SplitHostPort(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a valid host:port: %v", err)
|
||||
}
|
||||
portNum, err := strconv.ParseUint(port, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a valid port: %v", err)
|
||||
}
|
||||
a.Host = host
|
||||
a.Port = int(portNum)
|
||||
|
||||
default:
|
||||
port := a.DefaultPort
|
||||
if port == 0 {
|
||||
switch a.DefaultScheme {
|
||||
case "http":
|
||||
port = 80
|
||||
case "https":
|
||||
port = 443
|
||||
default:
|
||||
return fmt.Errorf("no port specified")
|
||||
}
|
||||
}
|
||||
a.Host = value
|
||||
a.Port = port
|
||||
}
|
||||
if a.Port > 0 {
|
||||
addr.Host = net.JoinHostPort(a.Host, strconv.FormatInt(int64(a.Port), 10))
|
||||
} else {
|
||||
addr.Host = a.Host
|
||||
}
|
||||
|
||||
if value != a.Value {
|
||||
a.Provided = true
|
||||
}
|
||||
a.URL = addr
|
||||
a.IPv6Host = isIPv6Host(a.Host)
|
||||
a.Value = value
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isURL returns true if the provided value appears to be a valid URL.
|
||||
func (a *Addr) isURL(value string) bool {
|
||||
prefixes := urlPrefixes
|
||||
if a.DefaultScheme != "" {
|
||||
prefixes = append(prefixes, fmt.Sprintf("%s://", a.DefaultScheme))
|
||||
}
|
||||
for _, p := range prefixes {
|
||||
if strings.HasPrefix(value, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -13,19 +14,25 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
kclientcmd "k8s.io/client-go/tools/clientcmd"
|
||||
kclientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
|
||||
"github.com/openshift/origin/pkg/cmd/flagtypes"
|
||||
"github.com/openshift/origin/pkg/cmd/util"
|
||||
"github.com/openshift/origin/pkg/oc/cli/config"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
// getEnv returns an environment value if specified.
|
||||
func getEnv(key string) (string, bool) {
|
||||
val := os.Getenv(key)
|
||||
if len(val) == 0 {
|
||||
return "", false
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
|
||||
// Config contains all the necessary bits for client configuration
|
||||
type Config struct {
|
||||
// MasterAddr is the address the master can be reached on (host, host:port, or URL).
|
||||
MasterAddr flagtypes.Addr
|
||||
MasterAddr Addr
|
||||
// KubernetesAddr is the address of the Kubernetes server (host, host:port, or URL).
|
||||
// If omitted defaults to the master.
|
||||
KubernetesAddr flagtypes.Addr
|
||||
KubernetesAddr Addr
|
||||
// CommonConfig is the shared base config for both the OpenShift config and Kubernetes config
|
||||
CommonConfig restclient.Config
|
||||
// Namespace is the namespace to act in
|
||||
@@ -40,12 +47,22 @@ type Config struct {
|
||||
// NewConfig returns a new configuration
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
MasterAddr: flagtypes.Addr{Value: "localhost:8080", DefaultScheme: "http", DefaultPort: 8080, AllowPrefix: true}.Default(),
|
||||
KubernetesAddr: flagtypes.Addr{Value: "localhost:8080", DefaultScheme: "http", DefaultPort: 8080}.Default(),
|
||||
MasterAddr: Addr{Value: "localhost:8080", DefaultScheme: "http", DefaultPort: 8080, AllowPrefix: true}.Default(),
|
||||
KubernetesAddr: Addr{Value: "localhost:8080", DefaultScheme: "http", DefaultPort: 8080}.Default(),
|
||||
CommonConfig: restclient.Config{},
|
||||
}
|
||||
}
|
||||
|
||||
// github.com/openshift/origin/pkg/oc/cli/config
|
||||
const (
|
||||
openShiftConfigPathEnvVar = "KUBECONFIG"
|
||||
openShiftConfigHomeDir = ".kube"
|
||||
openShiftConfigHomeFileName = "config"
|
||||
openShiftConfigHomeDirFileName = openShiftConfigHomeDir + "/" + openShiftConfigHomeFileName
|
||||
)
|
||||
|
||||
var recommendedHomeFile = path.Join(homedir.HomeDir(), openShiftConfigHomeDirFileName)
|
||||
|
||||
func (cfg *Config) BindToFile(configPath string) *Config {
|
||||
defaultOverrides := &kclientcmd.ConfigOverrides{
|
||||
ClusterDefaults: kclientcmdapi.Cluster{
|
||||
@@ -54,12 +71,12 @@ func (cfg *Config) BindToFile(configPath string) *Config {
|
||||
}
|
||||
|
||||
chain := []string{}
|
||||
if envVarFile := os.Getenv(config.OpenShiftConfigPathEnvVar); len(envVarFile) != 0 {
|
||||
if envVarFile := os.Getenv(openShiftConfigPathEnvVar); len(envVarFile) != 0 {
|
||||
chain = append(chain, filepath.SplitList(envVarFile)...)
|
||||
} else if len(configPath) != 0 {
|
||||
chain = append(chain, configPath)
|
||||
} else {
|
||||
chain = append(chain, config.RecommendedHomeFile)
|
||||
chain = append(chain, recommendedHomeFile)
|
||||
}
|
||||
|
||||
defaultClientConfig := kclientcmd.NewDefaultClientConfig(kclientcmdapi.Config{}, defaultOverrides)
|
||||
@@ -87,7 +104,7 @@ func (cfg *Config) bindEnv() error {
|
||||
// callers may not use the config file if they have specified a master directly, for backwards
|
||||
// compatibility with components that used to use env, switch to service account token, and have
|
||||
// config defined in env.
|
||||
_, masterSet := util.GetEnv("OPENSHIFT_MASTER")
|
||||
_, masterSet := getEnv("OPENSHIFT_MASTER")
|
||||
specifiedMaster := masterSet || cfg.MasterAddr.Provided
|
||||
|
||||
if cfg.clientConfig != nil && !specifiedMaster {
|
||||
@@ -111,16 +128,16 @@ func (cfg *Config) bindEnv() error {
|
||||
}
|
||||
|
||||
// Legacy path - preserve env vars set on pods that previously were honored.
|
||||
if value, ok := util.GetEnv("KUBERNETES_MASTER"); ok && !cfg.KubernetesAddr.Provided {
|
||||
if value, ok := getEnv("KUBERNETES_MASTER"); ok && !cfg.KubernetesAddr.Provided {
|
||||
cfg.KubernetesAddr.Set(value)
|
||||
}
|
||||
if value, ok := util.GetEnv("OPENSHIFT_MASTER"); ok && !cfg.MasterAddr.Provided {
|
||||
if value, ok := getEnv("OPENSHIFT_MASTER"); ok && !cfg.MasterAddr.Provided {
|
||||
cfg.MasterAddr.Set(value)
|
||||
}
|
||||
if value, ok := util.GetEnv("BEARER_TOKEN"); ok && len(cfg.CommonConfig.BearerToken) == 0 {
|
||||
if value, ok := getEnv("BEARER_TOKEN"); ok && len(cfg.CommonConfig.BearerToken) == 0 {
|
||||
cfg.CommonConfig.BearerToken = value
|
||||
}
|
||||
if value, ok := util.GetEnv("BEARER_TOKEN_FILE"); ok && len(cfg.CommonConfig.BearerToken) == 0 {
|
||||
if value, ok := getEnv("BEARER_TOKEN_FILE"); ok && len(cfg.CommonConfig.BearerToken) == 0 {
|
||||
if tokenData, tokenErr := ioutil.ReadFile(value); tokenErr == nil {
|
||||
cfg.CommonConfig.BearerToken = strings.TrimSpace(string(tokenData))
|
||||
if len(cfg.CommonConfig.BearerToken) == 0 {
|
||||
@@ -131,25 +148,25 @@ func (cfg *Config) bindEnv() error {
|
||||
}
|
||||
}
|
||||
|
||||
if value, ok := util.GetEnv("OPENSHIFT_CA_FILE"); ok && len(cfg.CommonConfig.CAFile) == 0 {
|
||||
if value, ok := getEnv("OPENSHIFT_CA_FILE"); ok && len(cfg.CommonConfig.CAFile) == 0 {
|
||||
cfg.CommonConfig.CAFile = value
|
||||
} else if value, ok := util.GetEnv("OPENSHIFT_CA_DATA"); ok && len(cfg.CommonConfig.CAData) == 0 {
|
||||
} else if value, ok := getEnv("OPENSHIFT_CA_DATA"); ok && len(cfg.CommonConfig.CAData) == 0 {
|
||||
cfg.CommonConfig.CAData = []byte(value)
|
||||
}
|
||||
|
||||
if value, ok := util.GetEnv("OPENSHIFT_CERT_FILE"); ok && len(cfg.CommonConfig.CertFile) == 0 {
|
||||
if value, ok := getEnv("OPENSHIFT_CERT_FILE"); ok && len(cfg.CommonConfig.CertFile) == 0 {
|
||||
cfg.CommonConfig.CertFile = value
|
||||
} else if value, ok := util.GetEnv("OPENSHIFT_CERT_DATA"); ok && len(cfg.CommonConfig.CertData) == 0 {
|
||||
} else if value, ok := getEnv("OPENSHIFT_CERT_DATA"); ok && len(cfg.CommonConfig.CertData) == 0 {
|
||||
cfg.CommonConfig.CertData = []byte(value)
|
||||
}
|
||||
|
||||
if value, ok := util.GetEnv("OPENSHIFT_KEY_FILE"); ok && len(cfg.CommonConfig.KeyFile) == 0 {
|
||||
if value, ok := getEnv("OPENSHIFT_KEY_FILE"); ok && len(cfg.CommonConfig.KeyFile) == 0 {
|
||||
cfg.CommonConfig.KeyFile = value
|
||||
} else if value, ok := util.GetEnv("OPENSHIFT_KEY_DATA"); ok && len(cfg.CommonConfig.KeyData) == 0 {
|
||||
} else if value, ok := getEnv("OPENSHIFT_KEY_DATA"); ok && len(cfg.CommonConfig.KeyData) == 0 {
|
||||
cfg.CommonConfig.KeyData = []byte(value)
|
||||
}
|
||||
|
||||
if value, ok := util.GetEnv("OPENSHIFT_INSECURE"); ok && len(value) != 0 {
|
||||
if value, ok := getEnv("OPENSHIFT_INSECURE"); ok && len(value) != 0 {
|
||||
cfg.CommonConfig.Insecure = value == "true"
|
||||
}
|
||||
|
||||
125
pkg/origin-common/crypto/crypto.go
Normal file
125
pkg/origin-common/crypto/crypto.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var versions = map[string]uint16{
|
||||
"VersionTLS10": tls.VersionTLS10,
|
||||
"VersionTLS11": tls.VersionTLS11,
|
||||
"VersionTLS12": tls.VersionTLS12,
|
||||
}
|
||||
|
||||
func TLSVersion(versionName string) (uint16, error) {
|
||||
if len(versionName) == 0 {
|
||||
return DefaultTLSVersion(), nil
|
||||
}
|
||||
if version, ok := versions[versionName]; ok {
|
||||
return version, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unknown tls version %q", versionName)
|
||||
}
|
||||
|
||||
func ValidTLSVersions() []string {
|
||||
validVersions := []string{}
|
||||
for k := range versions {
|
||||
validVersions = append(validVersions, k)
|
||||
}
|
||||
sort.Strings(validVersions)
|
||||
return validVersions
|
||||
}
|
||||
|
||||
func DefaultTLSVersion() uint16 {
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||
return tls.VersionTLS12
|
||||
}
|
||||
|
||||
var ciphers = map[string]uint16{
|
||||
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
|
||||
func CipherSuite(cipherName string) (uint16, error) {
|
||||
if cipher, ok := ciphers[cipherName]; ok {
|
||||
return cipher, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unknown cipher name %q", cipherName)
|
||||
}
|
||||
|
||||
func ValidCipherSuites() []string {
|
||||
validCipherSuites := []string{}
|
||||
for k := range ciphers {
|
||||
validCipherSuites = append(validCipherSuites, k)
|
||||
}
|
||||
sort.Strings(validCipherSuites)
|
||||
return validCipherSuites
|
||||
}
|
||||
|
||||
func DefaultCiphers() []uint16 {
|
||||
// HTTP/2 mandates TLS 1.2 or higher with an AEAD cipher
|
||||
// suite (GCM, Poly1305) and ephemeral key exchange (ECDHE, DHE) for
|
||||
// perfect forward secrecy. Servers may provide additional cipher
|
||||
// suites for backwards compatibility with HTTP/1.1 clients.
|
||||
// See RFC7540, section 9.2 (Use of TLS Features) and Appendix A
|
||||
// (TLS 1.2 Cipher Suite Black List).
|
||||
return []uint16{
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // required by http/2
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // forbidden by http/2
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384, // forbidden by http/2
|
||||
// the next one is in the intermediate suite, but go1.8 http2isBadCipher() complains when it is included at the recommended index
|
||||
// because it comes after ciphers forbidden by the http/2 spec
|
||||
// tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
// tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
|
||||
// tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
|
||||
}
|
||||
}
|
||||
|
||||
// SecureTLSConfig enforces the default minimum security settings for the cluster.
|
||||
func SecureTLSConfig(config *tls.Config) *tls.Config {
|
||||
if config.MinVersion == 0 {
|
||||
config.MinVersion = DefaultTLSVersion()
|
||||
}
|
||||
|
||||
config.PreferServerCipherSuites = true
|
||||
if len(config.CipherSuites) == 0 {
|
||||
config.CipherSuites = DefaultCiphers()
|
||||
}
|
||||
return config
|
||||
}
|
||||
48
pkg/origin-common/crypto/crypto_test.go
Normal file
48
pkg/origin-common/crypto/crypto_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/importer"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConstantMaps(t *testing.T) {
|
||||
pkg, err := importer.Default().Import("crypto/tls")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
discoveredVersions := map[string]bool{}
|
||||
discoveredCiphers := map[string]bool{}
|
||||
for _, declName := range pkg.Scope().Names() {
|
||||
if strings.HasPrefix(declName, "VersionTLS") {
|
||||
discoveredVersions[declName] = true
|
||||
}
|
||||
if strings.HasPrefix(declName, "TLS_RSA_") || strings.HasPrefix(declName, "TLS_ECDHE_") {
|
||||
discoveredCiphers[declName] = true
|
||||
}
|
||||
}
|
||||
|
||||
for k := range discoveredCiphers {
|
||||
if _, ok := ciphers[k]; !ok {
|
||||
t.Errorf("discovered cipher tls.%s not in ciphers map", k)
|
||||
}
|
||||
}
|
||||
for k := range ciphers {
|
||||
if _, ok := discoveredCiphers[k]; !ok {
|
||||
t.Errorf("ciphers map has %s not in tls package", k)
|
||||
}
|
||||
}
|
||||
|
||||
for k := range discoveredVersions {
|
||||
if _, ok := versions[k]; !ok {
|
||||
t.Errorf("discovered version tls.%s not in version map", k)
|
||||
}
|
||||
}
|
||||
for k := range versions {
|
||||
if _, ok := discoveredVersions[k]; !ok {
|
||||
t.Errorf("versions map has %s not in tls package", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user