From 9258bbea5b4d6e06f4b771d915f60cd3406ece0b Mon Sep 17 00:00:00 2001 From: wl-chen Date: Wed, 23 Feb 2022 15:48:53 +0800 Subject: [PATCH] build(installer): generate auth, platform, gateway chart custom values (#1772) --- charts/values/customConfig.yaml | 92 ++++++++ charts/values/generateChartValues.go | 321 +++++++++++++++++++++++++++ charts/values/main.go | 13 ++ charts/values/struct.go | 108 +++++++++ 4 files changed, 534 insertions(+) create mode 100644 charts/values/customConfig.yaml create mode 100644 charts/values/generateChartValues.go create mode 100644 charts/values/main.go create mode 100644 charts/values/struct.go diff --git a/charts/values/customConfig.yaml b/charts/values/customConfig.yaml new file mode 100644 index 000000000..d35489507 --- /dev/null +++ b/charts/values/customConfig.yaml @@ -0,0 +1,92 @@ +# 必填,etcd访问地址,形式如https://172.19.0.2:2379 +etcd: + host: +# 必填,服务器ip,数组形式 +serverIPs: +# 访问的域名,数组形式 +dnsNames: +# 必填,集群front-proxy-ca.crt文件地址,默认位置为/etc/kubernetes/pki/front-proxy-ca.crt +frontProxyCaCrtAbsPath: +# 必填,集群etcd的ca.crt文件地址,默认位置为/etc/kubernetes/pki/etcd/ca.crt +etcdCrtAbsPath: +# 必填,集群etcd的ca.key文件地址,默认位置为/etc/kubernetes/pki/etcd/ca.key +etcdKeyAbsPath: +tke-auth: + api: + # 必填 + replicas: + # 必填 + image: + # 必填,数组形式,auth的重定向访问地址,包括集群服务器ip地址(必填)、tke-gateway的域名(可选)、集群高可用的VIP地址(可选)和集群的公共可访问域名(可选) + redirectHosts: + enableAudit: + # tke-auth-api组件在node上的对外暴露端口,默认31138 + nodePort: + # tke集群的租户id,默认default + tenantID: + # OIDC认证方式的secret,默认自动生成 + oIDCClientSecret: + # authentication用户名,默认为admin + adminUsername: + controller: + # 必填 + replicas: + # 必填 + image: + # tke集群的用户名,默认为admin + adminUsername: + # tke集群的密码,默认自动生成 + adminPassword: +tke-gateway: + api: + # 必填 + replicas: + # 必填 + image: + enableAuth: true + enableAudit: + # OIDC认证方式客户端id,默认为default + oIDCClientID: + # OIDC认证方式的issuer_url,默认为https://tke-auth-api/oidc + oIDCIssuerURL: + # 是否开启OIDC认证,默认不开启,值为空 + useOIDCCA: + controller: + # 必填 + replicas: + # 必填 + providerResImage: + # 必填 + image: + # 默认为registry.tke.com + registryDomain: + # 默认为library + registryNamespace: + # 监控存储类型,默认为influxdb + monitorStorageType: + # 监控存储地址,为tke集群master ip地址加8086端口 + monitorStorageAddresses: +tke-gateway: + # 必填 + image: + # 默认为registry.tke.com + registryDomainSuffix: + # tke集群的租户id,默认default + tenantID: + # OIDC认证方式的secret,默认自动生成 + oIDCClientSecret: + # 是否开启自签名,默认为true + selfSigned: true + # 第三方cert证书,在selfSigned为false时需要填值 + serverCrt: + # 第三方certKey,在selfSigned为false时需要填值 + serverKey: + enableRegistry: + enableAuth: true + enableBusiness: + enableMonitor: + enableRegistry: + enableLogagent: + enableAudit: + enableApplication: + enableMesh: diff --git a/charts/values/generateChartValues.go b/charts/values/generateChartValues.go new file mode 100644 index 000000000..d1ff1f03e --- /dev/null +++ b/charts/values/generateChartValues.go @@ -0,0 +1,321 @@ +package main + +import ( + "errors" + "fmt" + "io/ioutil" + "net" + "os" + + "github.com/segmentio/ksuid" + "gopkg.in/yaml.v2" + + // platformv1 "tkestack.io/tke/api/platform/v1" + "tkestack.io/tke/cmd/tke-installer/app/installer/certs" + "tkestack.io/tke/cmd/tke-installer/app/installer/constants" + + // v1 "tkestack.io/tke/pkg/platform/types/v1" + "tkestack.io/tke/pkg/util/pkiutil" +) + +const ( + DataDir = "data/" + + AuthChartValuePath = "auth-chart-values.yaml" + PlatformChartValuePath = "platform-chart-values.yaml" + GatewayChartValuePath = "gateway-chart-values.yaml" +) + +func GenerateValueChart() error { + customConfig := CustomConfig{} + data, err := ioutil.ReadFile("customConfig.yaml") + if err != nil { + return err + } + if err := yaml.Unmarshal(data, &customConfig); err != nil { + return err + } + + if isExist, _ := PathExists(DataDir); !isExist { + os.Mkdir(DataDir, 0777) + } + + if err := customConfig.GenerateCertificates(); err != nil { + return err + } + oIDCClientSecret := ksuid.New().String() + if err := customConfig.GenerateAuthChartValuesYaml(oIDCClientSecret); err != nil { + return err + } + if err := customConfig.GeneratePlatformChartValuesYaml(); err != nil { + return err + } + if err := customConfig.GenerateGatewayChartValuesYaml(oIDCClientSecret); err != nil { + return err + } + return nil +} + +func PathExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func (customConfig *CustomConfig) GenerateCertificates() error { + serverIPs := customConfig.ServerIPs + dnsNames := customConfig.DNSNames + frontProxyCaCrtAbsPath := customConfig.FrontProxyCaCrtAbsPath + etcdCrtAbsPath := customConfig.EtcdCrtAbsPath + etcdKeyAbsPath := customConfig.EtcdKeyAbsPath + + ips := []net.IP{net.ParseIP("127.0.0.1")} + if len(serverIPs) != 0 { + for _, serverIPStr := range serverIPs { + certIP := net.ParseIP(serverIPStr) + if certIP == nil { + return fmt.Errorf(fmt.Sprintf("SERVER IP: %s FORMAT error", serverIPStr)) + } + ips = append(ips, certIP) + } + } else { + return errors.New("SERVER_IPs should not be null") + } + if err := certs.Generate(dnsNames, ips, DataDir); err != nil { + return err + } + + frontProxyCaCrt, err := ioutil.ReadFile(frontProxyCaCrtAbsPath) + if err != nil { + return err + } + if err := ioutil.WriteFile(constants.FrontProxyCACrtFile, frontProxyCaCrt, 0644); err != nil { + return err + } + + etcdCrt, err := ioutil.ReadFile(etcdCrtAbsPath) + if err != nil { + return err + } + etcdKey, err := ioutil.ReadFile(etcdKeyAbsPath) + if err != nil { + return err + } + if err := ioutil.WriteFile(DataDir+"etcd-ca.crt", etcdCrt, 0644); err != nil { + return err + } + etcdClientCertData, etcdClientKeyData, err := pkiutil.GenerateClientCertAndKey("tke", nil, etcdCrt, etcdKey) + if err != nil { + return err + } + if err := ioutil.WriteFile(DataDir+"etcd.crt", etcdClientCertData, 0644); err != nil { + return err + } + if err := ioutil.WriteFile(DataDir+"etcd.key", etcdClientKeyData, 0644); err != nil { + return err + } + + passwordCsv := fmt.Sprintf("%s,admin,1,administrator", ksuid.New().String()) + tokenCsv := fmt.Sprintf("%s,admin,1,administrator", ksuid.New().String()) + if err := ioutil.WriteFile(DataDir+"password.csv", []byte(passwordCsv), 0644); err != nil { + return err + } + if err := ioutil.WriteFile(DataDir+"token.csv", []byte(tokenCsv), 0644); err != nil { + return err + } + return nil +} + +func (customConfig *CustomConfig) GenerateAuthChartValuesYaml(oIDCClientSecret string) error { + cacrt, err := ioutil.ReadFile(DataDir + "ca.crt") + if err != nil { + return err + } + caKey, err := ioutil.ReadFile(DataDir + "ca.key") + if err != nil { + return err + } + adminCrt, err := ioutil.ReadFile(DataDir + "admin.crt") + if err != nil { + return err + } + adminKey, err := ioutil.ReadFile(DataDir + "admin.key") + if err != nil { + return err + } + serverCrt, err := ioutil.ReadFile(DataDir + "server.crt") + if err != nil { + return err + } + serverKey, err := ioutil.ReadFile(DataDir + "server.key") + if err != nil { + return err + } + webhookCrt, err := ioutil.ReadFile(DataDir + "webhook.crt") + if err != nil { + return err + } + webhookKey, err := ioutil.ReadFile(DataDir + "webhook.key") + if err != nil { + return err + } + etcdCaCrt, err := ioutil.ReadFile(DataDir + "etcd-ca.crt") + if err != nil { + return err + } + etcdCrt, err := ioutil.ReadFile(DataDir + "etcd.crt") + if err != nil { + return err + } + etcdKey, err := ioutil.ReadFile(DataDir + "etcd.key") + if err != nil { + return err + } + frontProxyCaCrt, err := ioutil.ReadFile(DataDir + "front-proxy-ca.crt") + if err != nil { + return err + } + tokenCsv, err := ioutil.ReadFile(DataDir + "token.csv") + if err != nil { + return err + } + passwordCsv, err := ioutil.ReadFile(DataDir + "password.csv") + if err != nil { + return err + } + obj := AuthChartValue{ + Etcd: customConfig.Etcd, + Cacrt: string(cacrt), + CaKey: string(caKey), + AdminCrt: string(adminCrt), + AdminKey: string(adminKey), + ServerCrt: string(serverCrt), + ServerKey: string(serverKey), + WebhookCrt: string(webhookCrt), + WebHookKey: string(webhookKey), + EtcdCaCrt: string(etcdCaCrt), + EtcdCrt: string(etcdCrt), + EtcdKey: string(etcdKey), + FrontProxyCaCrt: string(frontProxyCaCrt), + PasswordCsv: string(passwordCsv), + TokenCsv: string(tokenCsv), + } + + originAuthCustomConfig := customConfig.TkeAuth + if originAuthCustomConfig == nil { + return errors.New("auth custom config content error") + } + + if originAuthCustomConfig.API.Replicas <= 0 { + return errors.New("auth custom config api replicas le 0") + } + if len(originAuthCustomConfig.API.Image) == 0 { + return errors.New("auth custom config api image nil") + } + if originAuthCustomConfig.API.RedirectHosts == nil { + originAuthCustomConfig.API.RedirectHosts = make([]string, len(customConfig.ServerIPs)) + } + originAuthCustomConfig.API.RedirectHosts = append(originAuthCustomConfig.API.RedirectHosts, customConfig.ServerIPs...) + originAuthCustomConfig.API.OIDCClientSecret = oIDCClientSecret + + if originAuthCustomConfig.Controller.Replicas <= 0 { + return errors.New("auth custom config api replicas le 0") + } + if len(originAuthCustomConfig.Controller.Image) == 0 { + return errors.New("auth custom config api image nil") + } + if len(originAuthCustomConfig.Controller.AdminUsername) == 0 { + originAuthCustomConfig.Controller.AdminUsername = "admin" + } + originAuthCustomConfig.Controller.AdminPassword = []byte(originAuthCustomConfig.Controller.AdminUsername) + obj.TkeAuth = originAuthCustomConfig + + bytes, errMarshal := yaml.Marshal(obj) + if errMarshal != nil { + return errMarshal + } + if err := ioutil.WriteFile(AuthChartValuePath, bytes, 0644); err != nil { + return err + } + return nil +} + +func (customConfig *CustomConfig) GeneratePlatformChartValuesYaml() error { + cacrt, err := ioutil.ReadFile(DataDir + "ca.crt") + if err != nil { + return err + } + + obj := PlatformChartValue{ + Etcd: customConfig.Etcd, + Cacrt: string(cacrt), + } + + originPlatformCustomConfig := customConfig.TkePlatform + if originPlatformCustomConfig == nil { + return errors.New("platform custom config content error") + } + + if originPlatformCustomConfig.API.Replicas <= 0 { + return errors.New("platform custom config api replicas le 0") + } + if len(originPlatformCustomConfig.API.Image) == 0 { + return errors.New("platform custom config api image nil") + } + + if originPlatformCustomConfig.Controller.Replicas <= 0 { + return errors.New("platform custom config controller replicas le 0") + } + if len(originPlatformCustomConfig.Controller.Image) == 0 { + return errors.New("platform custom config controller image nil") + } + if len(originPlatformCustomConfig.Controller.ProviderResImage) == 0 { + return errors.New("platform custom config controller provider res image nil") + } + if len(originPlatformCustomConfig.Controller.MonitorStorageAddresses) == 0 { + originPlatformCustomConfig.Controller.MonitorStorageAddresses = fmt.Sprintf("http://%s:8086", customConfig.ServerIPs[0]) + } + obj.TKEPlatform = originPlatformCustomConfig + + bytes, errMarshal := yaml.Marshal(obj) + if errMarshal != nil { + return errMarshal + } + if err := ioutil.WriteFile(PlatformChartValuePath, bytes, 0644); err != nil { + return err + } + return nil +} + +func (customConfig *CustomConfig) GenerateGatewayChartValuesYaml(oIDCClientSecret string) error { + obj := GatewayChartValue{ + Etcd: customConfig.Etcd, + } + + originGatewayCustomConfig := customConfig.TkeGateway + if originGatewayCustomConfig == nil { + return errors.New("gateway custom config content error") + } + + if len(originGatewayCustomConfig.Image) == 0 { + return errors.New("gateway custom config image nil") + } + if len(originGatewayCustomConfig.OIDCClientSecret) == 0 { + originGatewayCustomConfig.OIDCClientSecret = oIDCClientSecret + } + obj.TKEGateway = originGatewayCustomConfig + + bytes, errMarshal := yaml.Marshal(obj) + if errMarshal != nil { + return errMarshal + } + if err := ioutil.WriteFile(GatewayChartValuePath, bytes, 0644); err != nil { + return err + } + return nil +} diff --git a/charts/values/main.go b/charts/values/main.go new file mode 100644 index 000000000..cdaeb0f9d --- /dev/null +++ b/charts/values/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + "log" +) + +func main() { + if err := GenerateValueChart(); err != nil { + log.Fatalf("generate chart value yaml fail, error: %s", err.Error()) + } + fmt.Printf("generate chart value yaml success!") +} diff --git a/charts/values/struct.go b/charts/values/struct.go new file mode 100644 index 000000000..344553edb --- /dev/null +++ b/charts/values/struct.go @@ -0,0 +1,108 @@ +package main + +type EtcdConfig struct { + Host string `yaml:"host"` +} + +type AuthChartValue struct { + Cacrt string `yaml:"caCrt"` + CaKey string `yaml:"caKey"` + AdminCrt string `yaml:"adminCrt"` + AdminKey string `yaml:"adminKey"` + ServerCrt string `yaml:"serverCrt"` + ServerKey string `yaml:"serverKey"` + WebhookCrt string `yaml:"webhookCrt"` + WebHookKey string `yaml:"webhookKey"` + EtcdCaCrt string `yaml:"etcdCaCrt"` + EtcdCrt string `yaml:"etcdCrt"` + EtcdKey string `yaml:"etcdKey"` + FrontProxyCaCrt string `yaml:"frontProxyCaCrt"` + PasswordCsv string `yaml:"passwordCsv"` + TokenCsv string `yaml:"tokenCsv"` + Etcd *EtcdConfig `yaml:"etcd"` + TkeAuth *AuthCustomConfig `yaml:"inline"` +} + +type PlatformChartValue struct { + Cacrt string `yaml:"caCrt"` + Etcd *EtcdConfig `yaml:"etcd"` + TKEPlatform *PlatformCustomConfig `yaml:",inline"` +} + +type GatewayChartValue struct { + Etcd *EtcdConfig `yaml:"etcd"` + TKEGateway *GatewayCustomConfig `yaml:",inline"` +} + +type CustomConfig struct { + // TODO 目前只允许namespace为tke,后续开放支持配置namespace + // ChartNamespace string `yaml:"chartNamespace"` + ServerIPs []string `yaml:"serverIPs,flow"` + DNSNames []string `yaml:"dnsNames,flow"` + FrontProxyCaCrtAbsPath string `yaml:"frontProxyCaCrtAbsPath"` + EtcdCrtAbsPath string `yaml:"etcdCrtAbsPath"` + EtcdKeyAbsPath string `yaml:"etcdKeyAbsPath"` + Etcd *EtcdConfig `yaml:"etcd"` + TkeAuth *AuthCustomConfig `yaml:"tke-auth"` + TkePlatform *PlatformCustomConfig `yaml:"tke-platform"` + TkeGateway *GatewayCustomConfig `yaml:"tke-gateway"` +} + +type BaseCustomConfig struct { + Replicas int `yaml:"replicas"` + Image string `yaml:"image"` +} + +type AuthCustomConfig struct { + API struct { + BaseCustomConfig + RedirectHosts []string `yaml:"redirectHosts,flow"` + NodePort string `yaml:"nodePort,omitempty"` + EnableAudit string `yaml:"enableAudit,omitempty"` + TenantID string `yaml:"tenantID,omitempty"` + OIDCClientSecret string `yaml:"oIDCClientSecret,omitempty"` + AdminUsername string `yaml:"adminUsername,omitempty"` + } + Controller struct { + BaseCustomConfig + AdminUsername string `yaml:"adminUsername,omitempty"` + AdminPassword []byte `yaml:"adminPassword,omitempty"` + } +} + +type PlatformCustomConfig struct { + API struct { + BaseCustomConfig + EnableAuth string `yaml:"enableAuth,omitempty"` + EnableAudit string `yaml:"enableAudit,omitempty"` + OIDCClientID string `yaml:"oIDCClientID,omitempty"` + OIDCIssuerURL string `yaml:"oIDCIssuerURL,omitempty"` + UseOIDCCA string `yaml:"useOIDCCA,omitempty"` + } + Controller struct { + BaseCustomConfig + ProviderResImage string `yaml:"providerResImage"` + RegistryDomain string `yaml:"registryDomain,omitempty"` + RegistryNamespace string `yaml:"registryNamespace,omitempty"` + MonitorStorageType string `yaml:"monitorStorageType,omitempty"` + MonitorStorageAddresses string `yaml:"monitorStorageAddresses,omitempty"` + } +} + +type GatewayCustomConfig struct { + Image string `yaml:"image"` + RegistryDomainSuffix string `yaml:"registryDomainSuffix,omitempty"` + TenantID string `yaml:"tenantID,omitempty"` + OIDCClientSecret string `yaml:"oIDCClientSecret,omitempty"` + SelfSigned string `yaml:"selfSigned,omitempty"` + EnableAuth string `yaml:"enableAuth,omitempty"` + EnableRegistry string `yaml:"enableRegistry,omitempty"` + EnableBusiness string `yaml:"enableBusiness,omitempty"` + EnableMonitor string `yaml:"enableMonitor,omitempty"` + EnableLogagent string `yaml:"enableLogagent,omitempty"` + EnableAudit string `yaml:"enableAudit,omitempty"` + EnableApplication string `yaml:"enableApplication,omitempty"` + EnableMesh string `yaml:"enableMesh,omitempty"` + ServerKey string `yaml:"serverKey,omitempty"` + ServerCrt string `yaml:"serverCrt,omitempty"` +}