// Copyright (c) 2021 Gitpod GmbH. All rights reserved. // Licensed under the GNU Affero General Public License (AGPL). // See License.AGPL.txt in the project root for license information. package proxy import ( "bytes" _ "embed" "encoding/base64" "fmt" "text/template" "github.com/gitpod-io/gitpod/installer/pkg/common" ideProxyComponent "github.com/gitpod-io/gitpod/installer/pkg/components/ide-proxy" minioComponent "github.com/gitpod-io/gitpod/installer/pkg/components/minio" openvsxproxy "github.com/gitpod-io/gitpod/installer/pkg/components/openvsx-proxy" "golang.org/x/crypto/bcrypt" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/pointer" ) //go:embed templates/configmap/vhost.docker-registry.tpl var vhostDockerRegistry []byte //go:embed templates/configmap/vhost.empty.tpl var vhostEmptyTmpl []byte //go:embed templates/configmap/vhost.minio.tpl var vhostMinioTmpl []byte //go:embed templates/configmap/vhost.open-vsx.tpl var vhostOpenVSXTmpl []byte //go:embed templates/configmap/vhost.ide-proxy.tpl var ideProxyTmpl []byte //go:embed templates/configmap/vhost.payment-endpoint.tpl var vhostPaymentEndpointTmpl []byte type commonTpl struct { Domain string ReverseProxy string } type dockerRegistryTpl struct { Domain string ReverseProxy string Username string Password string } type openVSXTpl struct { Domain string RepoURL string } func renderTemplate(tpl []byte, values interface{}) (*string, error) { t, err := template.New("template").Parse(string(tpl)) if err != nil { return nil, err } var parsed bytes.Buffer err = t.Execute(&parsed, values) if err != nil { return nil, err } rendered := parsed.String() return &rendered, nil } const kubeDomain = "svc.cluster.local" func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { empty, err := renderTemplate(vhostEmptyTmpl, nil) if err != nil { return nil, err } openVSX, err := renderTemplate(vhostOpenVSXTmpl, openVSXTpl{ Domain: ctx.Config.Domain, RepoURL: fmt.Sprintf("openvsx-proxy.%s.%s:%d", ctx.Namespace, kubeDomain, openvsxproxy.ServicePort), }) if err != nil { return nil, err } ideProxy, err := renderTemplate(ideProxyTmpl, commonTpl{ Domain: ctx.Config.Domain, ReverseProxy: fmt.Sprintf("ide-proxy.%s.%s:%d", ctx.Namespace, kubeDomain, ideProxyComponent.ServicePort), }) if err != nil { return nil, err } paymentEndpoint, err := renderTemplate(vhostPaymentEndpointTmpl, commonTpl{ Domain: ctx.Config.Domain, ReverseProxy: fmt.Sprintf("payment-endpoint.%s.%s:%d", ctx.Namespace, kubeDomain, 3002), // todo(sje): get port from (future) config }) if err != nil { return nil, err } data := map[string]string{ "vhost.empty": *empty, "vhost.open-vsx": *openVSX, "vhost.payment-endpoint": *paymentEndpoint, "vhost.ide-proxy": *ideProxy, } if ctx.Config.ObjectStorage.CloudStorage == nil { // Don't expose Minio if using cloud storage minio, err := renderTemplate(vhostMinioTmpl, commonTpl{ Domain: ctx.Config.Domain, ReverseProxy: fmt.Sprintf("minio.%s.%s:%d", ctx.Namespace, kubeDomain, minioComponent.ServiceConsolePort), }) if err != nil { return nil, err } data["vhost.minio"] = *minio } if pointer.BoolDeref(ctx.Config.ContainerRegistry.InCluster, false) { username := ctx.Values.InternalRegistryUsername if username == "" { return nil, fmt.Errorf("unknown value: internal registry username") } password := ctx.Values.InternalRegistryPassword if password == "" { return nil, fmt.Errorf("unknown value: internal registry password") } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return nil, err } dockerRegistry, err := renderTemplate(vhostDockerRegistry, dockerRegistryTpl{ Domain: ctx.Config.Domain, ReverseProxy: fmt.Sprintf("https://%s.%s.%s", common.DockerRegistryName, ctx.Namespace, kubeDomain), Username: username, Password: base64.StdEncoding.EncodeToString(hashedPassword), }) if err != nil { return nil, err } data["vhost.docker-registry"] = *dockerRegistry } return []runtime.Object{ &corev1.ConfigMap{ TypeMeta: common.TypeMetaConfigmap, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-config", Component), Namespace: ctx.Namespace, Labels: common.CustomizeLabel(ctx, Component, common.TypeMetaConfigmap), Annotations: common.CustomizeAnnotation(ctx, Component, common.TypeMetaConfigmap), }, Data: data, }, }, nil }