Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/image-builder-bob/pkg/builder/config.go
2499 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package builder
6
7
import (
8
"crypto/aes"
9
"crypto/cipher"
10
"encoding/base64"
11
"os"
12
"path/filepath"
13
"strings"
14
15
"golang.org/x/xerrors"
16
)
17
18
// Config configures a builder
19
type Config struct {
20
TargetRef string
21
BaseRef string
22
BaseContext string
23
BuildBase bool
24
BaseLayerAuth string
25
WorkspaceLayerAuth string
26
Dockerfile string
27
ContextDir string
28
ExternalBuildkitd string
29
localCacheImport string
30
}
31
32
var DockerfilePathNotExists = xerrors.Errorf("BOB_DOCKERFILE_PATH does not exist or isn't a file")
33
34
// GetConfigFromEnv extracts configuration from environment variables
35
func GetConfigFromEnv() (*Config, error) {
36
cfg := &Config{
37
TargetRef: os.Getenv("BOB_TARGET_REF"),
38
BaseRef: os.Getenv("BOB_BASE_REF"),
39
BaseContext: os.Getenv("THEIA_WORKSPACE_ROOT"),
40
BuildBase: os.Getenv("BOB_BUILD_BASE") == "true",
41
BaseLayerAuth: os.Getenv("BOB_BASELAYER_AUTH"),
42
WorkspaceLayerAuth: os.Getenv("BOB_WSLAYER_AUTH"),
43
Dockerfile: os.Getenv("BOB_DOCKERFILE_PATH"),
44
ContextDir: os.Getenv("BOB_CONTEXT_DIR"),
45
ExternalBuildkitd: os.Getenv("BOB_EXTERNAL_BUILDKITD"),
46
localCacheImport: os.Getenv("BOB_LOCAL_CACHE_IMPORT"),
47
}
48
49
if cfg.BaseRef == "" {
50
cfg.BaseRef = "localhost:8080/base:latest"
51
}
52
if cfg.TargetRef == "" {
53
cfg.TargetRef = "localhost:8080/target:latest"
54
}
55
if cfg.BuildBase {
56
if cfg.Dockerfile == "" {
57
return nil, xerrors.Errorf("When building the base image BOB_DOCKERFILE_PATH is mandatory")
58
}
59
var err error
60
cfg.Dockerfile, err = filepath.Abs(cfg.Dockerfile)
61
if err != nil {
62
return nil, xerrors.Errorf("cannot make BOB_DOCKERFILE_PATH absolute: %w", err)
63
}
64
if !strings.HasPrefix(cfg.Dockerfile, "/workspace") {
65
return nil, xerrors.Errorf("BOB_DOCKERFILE_PATH must begin with /workspace")
66
}
67
if stat, err := os.Stat(cfg.Dockerfile); err != nil || stat.IsDir() {
68
return nil, DockerfilePathNotExists
69
}
70
}
71
72
var authKey = os.Getenv("BOB_AUTH_KEY")
73
if authKey != "" {
74
if len(authKey) != 32 {
75
return nil, xerrors.Errorf("BOB_AUTH_KEY must be exactly 32 bytes long")
76
}
77
78
// we have an authkey, hence assume that the auth fields are base64 encoded and encrypted
79
if cfg.BaseLayerAuth != "" {
80
dec, err := base64.RawStdEncoding.DecodeString(cfg.BaseLayerAuth)
81
if err != nil {
82
return nil, xerrors.Errorf("BOB_BASELAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present")
83
}
84
cfg.BaseLayerAuth, err = decrypt(dec, authKey)
85
if err != nil {
86
return nil, xerrors.Errorf("cannot decrypt BOB_BASELAYER_AUTH: %w", err)
87
}
88
}
89
if cfg.WorkspaceLayerAuth != "" {
90
dec, err := base64.RawStdEncoding.DecodeString(cfg.WorkspaceLayerAuth)
91
if err != nil {
92
return nil, xerrors.Errorf("BOB_WSLAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present")
93
}
94
cfg.WorkspaceLayerAuth, err = decrypt(dec, authKey)
95
if err != nil {
96
return nil, xerrors.Errorf("cannot decrypt BOB_WSLAYER_AUTH: %w", err)
97
}
98
}
99
}
100
101
return cfg, nil
102
}
103
104
// source: https://astaxie.gitbooks.io/build-web-application-with-golang/en/09.6.html
105
func decrypt(ciphertext []byte, key string) (string, error) {
106
c, err := aes.NewCipher([]byte(key))
107
if err != nil {
108
return "", err
109
}
110
111
gcm, err := cipher.NewGCM(c)
112
if err != nil {
113
return "", err
114
}
115
116
nonceSize := gcm.NonceSize()
117
if len(ciphertext) < nonceSize {
118
return "", xerrors.Errorf("ciphertext too short")
119
}
120
121
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
122
res, err := gcm.Open(nil, nonce, ciphertext, nil)
123
if err != nil {
124
return "", err
125
}
126
127
return string(res), nil
128
}
129
130