simplify webhook DNS further generalize for gateway (#10448)

continuation of the changes from eaaf05a7cc
this further simplifies, enables this for gateway deployments as well
This commit is contained in:
Harshavardhana 2020-09-10 14:19:32 -07:00 committed by GitHub
parent b7438fe4e6
commit eb2934f0c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 121 additions and 87 deletions

View file

@ -29,7 +29,7 @@ import (
minio "github.com/minio/minio-go/v7" minio "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio-go/v7/pkg/tags"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"

View file

@ -33,7 +33,7 @@ import (
"github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio-go/v7/pkg/tags"
"github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"

View file

@ -33,7 +33,6 @@ import (
"github.com/minio/cli" "github.com/minio/cli"
"github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config"
"github.com/minio/minio/cmd/config/etcd/dns"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/certs" "github.com/minio/minio/pkg/certs"
@ -286,14 +285,6 @@ func handleCommonEnvVars() {
os.Unsetenv(config.EnvAccessKeyOld) os.Unsetenv(config.EnvAccessKeyOld)
os.Unsetenv(config.EnvSecretKeyOld) os.Unsetenv(config.EnvSecretKeyOld)
} }
url, user, pwd, ok := env.LookupEnv(config.EnvDNSWebhook)
if ok {
globalDNSConfig, err = dns.NewOperatorDNS(url, user, pwd)
if err != nil {
logger.Fatal(err, "Unable to fetch the value of "+config.EnvDNSWebhook)
}
}
} }
func logStartupMessage(msg string) { func logStartupMessage(msg string) {

View file

@ -25,8 +25,8 @@ import (
"github.com/minio/minio/cmd/config/api" "github.com/minio/minio/cmd/config/api"
"github.com/minio/minio/cmd/config/cache" "github.com/minio/minio/cmd/config/cache"
"github.com/minio/minio/cmd/config/compress" "github.com/minio/minio/cmd/config/compress"
"github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/config/etcd" "github.com/minio/minio/cmd/config/etcd"
"github.com/minio/minio/cmd/config/etcd/dns"
xldap "github.com/minio/minio/cmd/config/identity/ldap" xldap "github.com/minio/minio/cmd/config/identity/ldap"
"github.com/minio/minio/cmd/config/identity/openid" "github.com/minio/minio/cmd/config/identity/openid"
"github.com/minio/minio/cmd/config/notify" "github.com/minio/minio/cmd/config/notify"
@ -321,6 +321,19 @@ func lookupConfigs(s config.Config, setDriveCount int) {
} }
} }
if dnsURL, dnsUser, dnsPass, ok := env.LookupEnv(config.EnvDNSWebhook); ok {
globalDNSConfig, err = dns.NewOperatorDNS(dnsURL,
dns.Authentication(dnsUser, dnsPass),
dns.RootCAs(globalRootCAs))
if err != nil {
if globalIsGateway {
logger.FatalIf(err, "Unable to initialize remote webhook DNS config")
} else {
logger.LogIf(ctx, fmt.Errorf("Unable to initialize remote webhook DNS config %w", err))
}
}
}
etcdCfg, err := etcd.LookupConfig(s[config.EtcdSubSys][config.Default], globalRootCAs) etcdCfg, err := etcd.LookupConfig(s[config.EtcdSubSys][config.Default], globalRootCAs)
if err != nil { if err != nil {
if globalIsGateway { if globalIsGateway {
@ -342,19 +355,25 @@ func lookupConfigs(s config.Config, setDriveCount int) {
} }
} }
if len(globalDomainNames) != 0 && !globalDomainIPs.IsEmpty() && globalEtcdClient != nil && globalDNSConfig == nil { if len(globalDomainNames) != 0 && !globalDomainIPs.IsEmpty() && globalEtcdClient != nil {
globalDNSConfig, err = dns.NewCoreDNS(etcdCfg.Config, if globalDNSConfig != nil {
dns.DomainNames(globalDomainNames), // if global DNS is already configured, indicate with a warning, incase
dns.DomainIPs(globalDomainIPs), // users are confused.
dns.DomainPort(globalMinioPort), logger.LogIf(ctx, fmt.Errorf("DNS store is already configured with %s, not using etcd for DNS store", globalDNSConfig))
dns.CoreDNSPath(etcdCfg.CoreDNSPath), } else {
) globalDNSConfig, err = dns.NewCoreDNS(etcdCfg.Config,
if err != nil { dns.DomainNames(globalDomainNames),
if globalIsGateway { dns.DomainIPs(globalDomainIPs),
logger.FatalIf(err, "Unable to initialize DNS config") dns.DomainPort(globalMinioPort),
} else { dns.CoreDNSPath(etcdCfg.CoreDNSPath),
logger.LogIf(ctx, fmt.Errorf("Unable to initialize DNS config for %s: %w", )
globalDomainNames, err)) if err != nil {
if globalIsGateway {
logger.FatalIf(err, "Unable to initialize DNS config")
} else {
logger.LogIf(ctx, fmt.Errorf("Unable to initialize DNS config for %s: %w",
globalDomainNames, err))
}
} }
} }
} }

View file

@ -26,9 +26,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/minio/minio-go/v7/pkg/set"
"github.com/coredns/coredns/plugin/etcd/msg" "github.com/coredns/coredns/plugin/etcd/msg"
"github.com/minio/minio-go/v7/pkg/set"
"go.etcd.io/etcd/v3/clientv3" "go.etcd.io/etcd/v3/clientv3"
) )
@ -214,6 +213,11 @@ func (c *CoreDNS) DeleteRecord(record SrvRecord) error {
return nil return nil
} }
// String stringer name for this implementation of dns.Store
func (c *CoreDNS) String() string {
return "etcdDNS"
}
// CoreDNS - represents dns config for coredns server. // CoreDNS - represents dns config for coredns server.
type CoreDNS struct { type CoreDNS struct {
domainNames []string domainNames []string
@ -223,13 +227,13 @@ type CoreDNS struct {
etcdClient *clientv3.Client etcdClient *clientv3.Client
} }
// Option - functional options pattern style // EtcdOption - functional options pattern style
type Option func(*CoreDNS) type EtcdOption func(*CoreDNS)
// DomainNames set a list of domain names used by this CoreDNS // DomainNames set a list of domain names used by this CoreDNS
// client setting, note this will fail if set to empty when // client setting, note this will fail if set to empty when
// constructor initializes. // constructor initializes.
func DomainNames(domainNames []string) Option { func DomainNames(domainNames []string) EtcdOption {
return func(args *CoreDNS) { return func(args *CoreDNS) {
args.domainNames = domainNames args.domainNames = domainNames
} }
@ -237,14 +241,14 @@ func DomainNames(domainNames []string) Option {
// DomainIPs set a list of custom domain IPs, note this will // DomainIPs set a list of custom domain IPs, note this will
// fail if set to empty when constructor initializes. // fail if set to empty when constructor initializes.
func DomainIPs(domainIPs set.StringSet) Option { func DomainIPs(domainIPs set.StringSet) EtcdOption {
return func(args *CoreDNS) { return func(args *CoreDNS) {
args.domainIPs = domainIPs args.domainIPs = domainIPs
} }
} }
// DomainPort - is a string version of server port // DomainPort - is a string version of server port
func DomainPort(domainPort string) Option { func DomainPort(domainPort string) EtcdOption {
return func(args *CoreDNS) { return func(args *CoreDNS) {
args.domainPort = domainPort args.domainPort = domainPort
} }
@ -253,14 +257,14 @@ func DomainPort(domainPort string) Option {
// CoreDNSPath - custom prefix on etcd to populate DNS // CoreDNSPath - custom prefix on etcd to populate DNS
// service records, optional and can be empty. // service records, optional and can be empty.
// if empty then c.prefixPath is used i.e "/skydns" // if empty then c.prefixPath is used i.e "/skydns"
func CoreDNSPath(prefix string) Option { func CoreDNSPath(prefix string) EtcdOption {
return func(args *CoreDNS) { return func(args *CoreDNS) {
args.prefixPath = prefix args.prefixPath = prefix
} }
} }
// NewCoreDNS - initialize a new coreDNS set/unset values. // NewCoreDNS - initialize a new coreDNS set/unset values.
func NewCoreDNS(cfg clientv3.Config, setters ...Option) (Store, error) { func NewCoreDNS(cfg clientv3.Config, setters ...EtcdOption) (Store, error) {
etcdClient, err := clientv3.New(cfg) etcdClient, err := clientv3.New(cfg)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -25,39 +25,39 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"time" "time"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config"
xhttp "github.com/minio/minio/cmd/http"
) )
var ( var (
defaultOperatorContextTimeout = 10 * time.Second defaultOperatorContextTimeout = 10 * time.Second
// ErrNotImplemented - Indicates no entries were found for the given key (directory) // ErrNotImplemented - Indicates the functionality which is not implemented
ErrNotImplemented = errors.New("The method is not implemented") ErrNotImplemented = errors.New("The method is not implemented")
globalRootCAs *x509.CertPool
) )
// RegisterGlobalCAs register the global root CAs func (c *OperatorDNS) addAuthHeader(r *http.Request) error {
func RegisterGlobalCAs(CAs *x509.CertPool) { if c.username == "" || c.password == "" {
globalRootCAs = CAs return nil
} }
func (c *OperatorDNS) addAuthHeader(r *http.Request) (*http.Request, error) {
claims := &jwt.StandardClaims{ claims := &jwt.StandardClaims{
ExpiresAt: int64(15 * time.Minute), ExpiresAt: int64(15 * time.Minute),
Issuer: c.Username, Issuer: c.username,
Subject: config.EnvDNSWebhook, Subject: config.EnvDNSWebhook,
} }
token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims) token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
ss, err := token.SignedString([]byte(c.Password)) ss, err := token.SignedString([]byte(c.password))
if err != nil { if err != nil {
return r, err return err
} }
r.Header.Set("Authorization", "Bearer "+ss) r.Header.Set("Authorization", "Bearer "+ss)
return r, nil return nil
} }
func (c *OperatorDNS) endpoint(bucket string, delete bool) (string, error) { func (c *OperatorDNS) endpoint(bucket string, delete bool) (string, error) {
@ -67,11 +67,7 @@ func (c *OperatorDNS) endpoint(bucket string, delete bool) (string, error) {
} }
q := u.Query() q := u.Query()
q.Add("bucket", bucket) q.Add("bucket", bucket)
if delete { q.Add("delete", strconv.FormatBool(delete))
q.Add("delete", "true")
} else {
q.Add("delete", "false")
}
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
return u.String(), nil return u.String(), nil
} }
@ -88,16 +84,16 @@ func (c *OperatorDNS) Put(bucket string) error {
if err != nil { if err != nil {
return err return err
} }
req, err = c.addAuthHeader(req) if err = c.addAuthHeader(req); err != nil {
if err != nil {
return err return err
} }
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
if err := c.Delete(bucket); err != nil { if derr := c.Delete(bucket); derr != nil {
return err return derr
} }
} }
xhttp.DrainBody(resp.Body)
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return fmt.Errorf("request to create the service for bucket %s, failed with status %s", bucket, resp.Status) return fmt.Errorf("request to create the service for bucket %s, failed with status %s", bucket, resp.Status)
} }
@ -116,14 +112,14 @@ func (c *OperatorDNS) Delete(bucket string) error {
if err != nil { if err != nil {
return err return err
} }
req, err = c.addAuthHeader(req) if err = c.addAuthHeader(req); err != nil {
if err != nil {
return err return err
} }
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
return err return err
} }
xhttp.DrainBody(resp.Body)
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return fmt.Errorf("request to delete the service for bucket %s, failed with status %s", bucket, resp.Status) return fmt.Errorf("request to delete the service for bucket %s, failed with status %s", bucket, resp.Status)
} }
@ -158,43 +154,68 @@ func (c *OperatorDNS) Get(bucket string) (srvRecords []SrvRecord, err error) {
return nil, ErrNotImplemented return nil, ErrNotImplemented
} }
// String stringer name for this implementation of dns.Store
func (c *OperatorDNS) String() string {
return "webhookDNS"
}
// OperatorDNS - represents dns config for MinIO k8s operator. // OperatorDNS - represents dns config for MinIO k8s operator.
type OperatorDNS struct { type OperatorDNS struct {
httpClient *http.Client httpClient *http.Client
Endpoint string Endpoint string
Username string rootCAs *x509.CertPool
Password string username string
password string
}
// OperatorOption - functional options pattern style for OperatorDNS
type OperatorOption func(*OperatorDNS)
// Authentication - custom username and password for authenticating at the endpoint
func Authentication(username, password string) OperatorOption {
return func(args *OperatorDNS) {
args.username = username
args.password = password
}
}
// RootCAs - add custom trust certs pool
func RootCAs(CAs *x509.CertPool) OperatorOption {
return func(args *OperatorDNS) {
args.rootCAs = CAs
}
} }
// NewOperatorDNS - initialize a new K8S Operator DNS set/unset values. // NewOperatorDNS - initialize a new K8S Operator DNS set/unset values.
func NewOperatorDNS(endpoint, user, pwd string) (Store, error) { func NewOperatorDNS(endpoint string, setters ...OperatorOption) (Store, error) {
if endpoint == "" || user == "" || pwd == "" { if endpoint == "" {
return nil, errors.New("invalid argument") return nil, errors.New("invalid argument")
} }
args := &OperatorDNS{ args := &OperatorDNS{
Username: user,
Password: pwd,
Endpoint: endpoint, Endpoint: endpoint,
httpClient: &http.Client{ }
Transport: &http.Transport{ for _, setter := range setters {
Proxy: http.ProxyFromEnvironment, setter(args)
DialContext: (&net.Dialer{ }
Timeout: 3 * time.Second, args.httpClient = &http.Client{
KeepAlive: 5 * time.Second, Transport: &http.Transport{
}).DialContext, Proxy: http.ProxyFromEnvironment,
ResponseHeaderTimeout: 3 * time.Second, DialContext: (&net.Dialer{
TLSHandshakeTimeout: 3 * time.Second, Timeout: 3 * time.Second,
ExpectContinueTimeout: 3 * time.Second, KeepAlive: 5 * time.Second,
TLSClientConfig: &tls.Config{ }).DialContext,
RootCAs: globalRootCAs, ResponseHeaderTimeout: 3 * time.Second,
}, TLSHandshakeTimeout: 3 * time.Second,
// Go net/http automatically unzip if content-type is ExpectContinueTimeout: 3 * time.Second,
// gzip disable this feature, as we are always interested TLSClientConfig: &tls.Config{
// in raw stream. RootCAs: args.rootCAs,
DisableCompression: true,
}, },
// Go net/http automatically unzip if content-type is
// gzip disable this feature, as we are always interested
// in raw stream.
DisableCompression: true,
}, },
} }
return args, nil return args, nil
} }

View file

@ -24,4 +24,5 @@ type Store interface {
List() (map[string][]SrvRecord, error) List() (map[string][]SrvRecord, error)
DeleteRecord(record SrvRecord) error DeleteRecord(record SrvRecord) error
Close() error Close() error
String() string
} }

View file

@ -24,7 +24,7 @@ import (
"github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/set"
humanize "github.com/dustin/go-humanize" humanize "github.com/dustin/go-humanize"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/http/stats" "github.com/minio/minio/cmd/http/stats"

View file

@ -26,7 +26,7 @@ import (
humanize "github.com/dustin/go-humanize" humanize "github.com/dustin/go-humanize"
"github.com/minio/minio/cmd/config/cache" "github.com/minio/minio/cmd/config/cache"
"github.com/minio/minio/cmd/config/compress" "github.com/minio/minio/cmd/config/compress"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
xldap "github.com/minio/minio/cmd/config/identity/ldap" xldap "github.com/minio/minio/cmd/config/identity/ldap"
"github.com/minio/minio/cmd/config/identity/openid" "github.com/minio/minio/cmd/config/identity/openid"
"github.com/minio/minio/cmd/config/policy/opa" "github.com/minio/minio/cmd/config/policy/opa"

View file

@ -38,7 +38,7 @@ import (
"github.com/klauspost/readahead" "github.com/klauspost/readahead"
"github.com/minio/minio-go/v7/pkg/s3utils" "github.com/minio/minio-go/v7/pkg/s3utils"
"github.com/minio/minio/cmd/config/compress" "github.com/minio/minio/cmd/config/compress"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/config/storageclass" "github.com/minio/minio/cmd/config/storageclass"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"

View file

@ -37,7 +37,7 @@ import (
"github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/encrypt" "github.com/minio/minio-go/v7/pkg/encrypt"
"github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio-go/v7/pkg/tags"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/config/storageclass" "github.com/minio/minio/cmd/config/storageclass"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"

View file

@ -32,7 +32,6 @@ import (
"github.com/minio/cli" "github.com/minio/cli"
"github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config"
"github.com/minio/minio/cmd/config/etcd/dns"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
@ -130,7 +129,6 @@ func serverHandleCmdArgs(ctx *cli.Context) {
// Register root CAs for remote ENVs // Register root CAs for remote ENVs
env.RegisterGlobalCAs(globalRootCAs) env.RegisterGlobalCAs(globalRootCAs)
dns.RegisterGlobalCAs(globalRootCAs)
globalMinioAddr = globalCLIContext.Addr globalMinioAddr = globalCLIContext.Addr

View file

@ -40,7 +40,7 @@ import (
miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" miniogopolicy "github.com/minio/minio-go/v7/pkg/policy"
"github.com/minio/minio-go/v7/pkg/s3utils" "github.com/minio/minio-go/v7/pkg/s3utils"
"github.com/minio/minio/browser" "github.com/minio/minio/browser"
"github.com/minio/minio/cmd/config/etcd/dns" "github.com/minio/minio/cmd/config/dns"
"github.com/minio/minio/cmd/config/identity/openid" "github.com/minio/minio/cmd/config/identity/openid"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"