Files

75 lines
2.6 KiB
Go

package model
import (
"errors"
"regexp"
"strings"
"k8s.io/client-go/tools/clientcmd"
)
var kubeName = regexp.MustCompile(`^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$`)
var kubeNamespace = regexp.MustCompile(`^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$`)
const MaxKubeConfigContentBytes = 512 << 10
var (
ErrKubeConfigExternalFiles = errors.New("uploaded Kubeconfig must embed certificate, key and token data instead of external file paths")
ErrKubeConfigLoginPlugin = errors.New("uploaded Kubeconfig cannot use exec or auth-provider login plugins")
)
func (o Outbound) ValidateKubernetes() error {
if o.LocalPort < 0 || o.LocalPort > 65535 {
return errors.New("Kubernetes local port must be 0 or 1024-65535")
}
if o.LocalPort > 0 && o.LocalPort < 1024 {
return errors.New("Kubernetes local port must be 0 or 1024-65535")
}
if o.KubeConfigAssetID != "" && !accountIDPattern.MatchString(o.KubeConfigAssetID) {
return errors.New("invalid Kubeconfig asset id")
}
if len(o.KubeConfigContent) > MaxKubeConfigContentBytes {
return errors.New("Kubeconfig file must not exceed 512 KiB")
}
if o.KubeConfigContent != "" {
config, err := clientcmd.Load([]byte(o.KubeConfigContent))
if err != nil {
return errors.New("invalid Kubeconfig file")
}
for _, cluster := range config.Clusters {
if cluster != nil && cluster.CertificateAuthority != "" {
return ErrKubeConfigExternalFiles
}
}
for _, auth := range config.AuthInfos {
if auth == nil {
continue
}
if auth.Exec != nil || auth.AuthProvider != nil {
return ErrKubeConfigLoginPlugin
}
if auth.ClientCertificate != "" || auth.ClientKey != "" || auth.TokenFile != "" {
return ErrKubeConfigExternalFiles
}
}
context := o.KubeContext
if context == "" {
context = config.CurrentContext
}
if err := clientcmd.ConfirmUsable(*config, context); err != nil {
return errors.New("Kubeconfig file has no usable selected context, cluster or user")
}
}
kind, name, ok := strings.Cut(o.Resource, "/")
if !ok || (kind != "pod" && kind != "service" && kind != "deployment" && kind != "statefulset") || len(name) > 253 || !kubeName.MatchString(name) || strings.Contains(name, "..") {
return errors.New("Kubernetes resource must be pod/name, service/name, deployment/name or statefulset/name")
}
if len(o.Namespace) > 63 || (o.Namespace != "" && !kubeNamespace.MatchString(o.Namespace)) {
return errors.New("invalid Kubernetes namespace")
}
if len(o.KubeConfig) > 4096 || len(o.KubeContext) > 253 || strings.ContainsAny(o.KubeConfig+o.KubeContext, "\x00\r\n") {
return errors.New("invalid Kubernetes config path or context")
}
return nil
}