Path: blob/main/components/image-builder-bob/pkg/builder/config.go
2499 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package builder56import (7"crypto/aes"8"crypto/cipher"9"encoding/base64"10"os"11"path/filepath"12"strings"1314"golang.org/x/xerrors"15)1617// Config configures a builder18type Config struct {19TargetRef string20BaseRef string21BaseContext string22BuildBase bool23BaseLayerAuth string24WorkspaceLayerAuth string25Dockerfile string26ContextDir string27ExternalBuildkitd string28localCacheImport string29}3031var DockerfilePathNotExists = xerrors.Errorf("BOB_DOCKERFILE_PATH does not exist or isn't a file")3233// GetConfigFromEnv extracts configuration from environment variables34func GetConfigFromEnv() (*Config, error) {35cfg := &Config{36TargetRef: os.Getenv("BOB_TARGET_REF"),37BaseRef: os.Getenv("BOB_BASE_REF"),38BaseContext: os.Getenv("THEIA_WORKSPACE_ROOT"),39BuildBase: os.Getenv("BOB_BUILD_BASE") == "true",40BaseLayerAuth: os.Getenv("BOB_BASELAYER_AUTH"),41WorkspaceLayerAuth: os.Getenv("BOB_WSLAYER_AUTH"),42Dockerfile: os.Getenv("BOB_DOCKERFILE_PATH"),43ContextDir: os.Getenv("BOB_CONTEXT_DIR"),44ExternalBuildkitd: os.Getenv("BOB_EXTERNAL_BUILDKITD"),45localCacheImport: os.Getenv("BOB_LOCAL_CACHE_IMPORT"),46}4748if cfg.BaseRef == "" {49cfg.BaseRef = "localhost:8080/base:latest"50}51if cfg.TargetRef == "" {52cfg.TargetRef = "localhost:8080/target:latest"53}54if cfg.BuildBase {55if cfg.Dockerfile == "" {56return nil, xerrors.Errorf("When building the base image BOB_DOCKERFILE_PATH is mandatory")57}58var err error59cfg.Dockerfile, err = filepath.Abs(cfg.Dockerfile)60if err != nil {61return nil, xerrors.Errorf("cannot make BOB_DOCKERFILE_PATH absolute: %w", err)62}63if !strings.HasPrefix(cfg.Dockerfile, "/workspace") {64return nil, xerrors.Errorf("BOB_DOCKERFILE_PATH must begin with /workspace")65}66if stat, err := os.Stat(cfg.Dockerfile); err != nil || stat.IsDir() {67return nil, DockerfilePathNotExists68}69}7071var authKey = os.Getenv("BOB_AUTH_KEY")72if authKey != "" {73if len(authKey) != 32 {74return nil, xerrors.Errorf("BOB_AUTH_KEY must be exactly 32 bytes long")75}7677// we have an authkey, hence assume that the auth fields are base64 encoded and encrypted78if cfg.BaseLayerAuth != "" {79dec, err := base64.RawStdEncoding.DecodeString(cfg.BaseLayerAuth)80if err != nil {81return nil, xerrors.Errorf("BOB_BASELAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present")82}83cfg.BaseLayerAuth, err = decrypt(dec, authKey)84if err != nil {85return nil, xerrors.Errorf("cannot decrypt BOB_BASELAYER_AUTH: %w", err)86}87}88if cfg.WorkspaceLayerAuth != "" {89dec, err := base64.RawStdEncoding.DecodeString(cfg.WorkspaceLayerAuth)90if err != nil {91return nil, xerrors.Errorf("BOB_WSLAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present")92}93cfg.WorkspaceLayerAuth, err = decrypt(dec, authKey)94if err != nil {95return nil, xerrors.Errorf("cannot decrypt BOB_WSLAYER_AUTH: %w", err)96}97}98}99100return cfg, nil101}102103// source: https://astaxie.gitbooks.io/build-web-application-with-golang/en/09.6.html104func decrypt(ciphertext []byte, key string) (string, error) {105c, err := aes.NewCipher([]byte(key))106if err != nil {107return "", err108}109110gcm, err := cipher.NewGCM(c)111if err != nil {112return "", err113}114115nonceSize := gcm.NonceSize()116if len(ciphertext) < nonceSize {117return "", xerrors.Errorf("ciphertext too short")118}119120nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]121res, err := gcm.Open(nil, nonce, ciphertext, nil)122if err != nil {123return "", err124}125126return string(res), nil127}128129130