blob: d231db709f7175b55004dd813bc84058dbffdfc9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package egress
import (
"crypto/tls"
"errors"
"fmt"
"regexp"
"strings"
gochassisconfig "github.com/go-chassis/go-chassis/core/config"
"github.com/go-chassis/go-chassis/core/lager"
chassisTLS "github.com/go-chassis/go-chassis/core/tls"
"github.com/go-chassis/go-chassis/pkg/util/iputil"
"github.com/go-mesh/mesher/config"
)
const (
dns1123LabelMaxLength int = 63
dns1123LabelFmt string = "[a-zA-Z0-9]([-a-z-A-Z0-9]*[a-zA-Z0-9])?"
wildcardPrefix string = "\\*|(\\*)?" + dns1123LabelFmt
DefaultEgressType = "cse"
// EgressTLS defines tls prefix
EgressTLS = "egress"
)
var (
dns1123LabelRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$")
wildcardPrefixRegexp = regexp.MustCompile("^" + wildcardPrefix + "$")
)
// Init initialize Egress config
func Init() error {
// init dests
egressConfigFromFile := config.GetEgressConfig()
BuildEgress(GetEgressType(egressConfigFromFile.Egress))
op, err := getSpecifiedOptions()
if err != nil {
return fmt.Errorf("Egress options error: %v", err)
}
DefaultEgress.Init(op)
lager.Logger.Info("Egress init success")
return nil
}
//ValidateEgressRule validate the Egress rules of each service
func ValidateEgressRule(rules map[string][]*config.EgressRule) (bool, error) {
for _, rule := range rules {
for _, egressrule := range rule {
if len(egressrule.Hosts) == 0 {
return false, errors.New("Egress rule should have atleast one host")
}
for _, host := range egressrule.Hosts {
err := ValidateHostName(host)
if err != nil {
return false, err
}
}
}
}
return true, nil
}
//ValidateHostName validates the host
func ValidateHostName(host string) error {
if len(host) > 255 {
return fmt.Errorf("host name %q too long (max 255)", host)
}
if len(host) == 0 {
return fmt.Errorf("empty host name not allowed")
}
parts := strings.SplitN(host, ".", 2)
if !IsWildcardDNS1123Label(parts[0]) {
return fmt.Errorf("host name %q invalid (label %q invalid)", host, parts[0])
} else if len(parts) > 1 {
err := validateDNS1123Labels(parts[1])
return err
}
return nil
}
//IsWildcardDNS1123Label validate wild card label
func IsWildcardDNS1123Label(value string) bool {
return len(value) <= dns1123LabelMaxLength && wildcardPrefixRegexp.MatchString(value)
}
//validateDNS1123Labels validate host
func validateDNS1123Labels(host string) error {
for _, label := range strings.Split(host, ".") {
if !IsDNS1123Label(label) {
return fmt.Errorf("host name %q invalid (label %q invalid)", host, label)
}
}
return nil
}
//IsDNS1123Label validate label
func IsDNS1123Label(value string) bool {
return len(value) <= dns1123LabelMaxLength && dns1123LabelRegexp.MatchString(value)
}
// Options defines how to init Egress and its fetcher
type Options struct {
Endpoints []string
EnableSSL bool
TLSConfig *tls.Config
Version string
ConfigPath string
//TODO: need timeout for client
// TimeOut time.Duration
}
/*
// ToPilotOptions translate options to client options
func (o Options) ToPilotOptions() *client.PilotOptions {
return &client.PilotOptions{Endpoints: o.Endpoints}
}
*/
func getSpecifiedOptions() (opts Options, err error) {
hosts, scheme, err := iputil.URIs2Hosts(strings.Split(config.GetEgressEndpoints(), ","))
if err != nil {
return
}
opts.Endpoints = hosts
// TODO: envoy api v1 or v2
opts.TLSConfig, err = chassisTLS.GetTLSConfig(scheme, EgressTLS)
if err != nil {
return
}
if opts.TLSConfig != nil {
opts.EnableSSL = true
}
opts.ConfigPath = gochassisconfig.GetServiceDiscoveryConfigPath()
return
}
// GetEgressType returns the type of egress
func GetEgressType(egress config.Egress) string {
if egress.Infra != "" {
return egress.Infra
}
return DefaultEgressType
}