• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / deployments / 920043239

pending completion
920043239

Pull #872

gitlab-ci

alfrunes
chore: Restrict tag character set

Changelog: None
Signed-off-by: Alf-Rune Siqveland <alf.rune@northern.tech>
Pull Request #872: MEN-6348: Add tags to releases

220 of 229 new or added lines in 7 files covered. (96.07%)

223 existing lines in 7 files now uncovered.

7560 of 9480 relevant lines covered (79.75%)

34.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.47
/config/config.go
1
// Copyright 2023 Northern.tech AS
2
//
3
//        Licensed under the Apache License, Version 2.0 (the "License");
4
//        you may not use this file except in compliance with the License.
5
//        You may obtain a copy of the License at
6
//
7
//            http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//        Unless required by applicable law or agreed to in writing, software
10
//        distributed under the License is distributed on an "AS IS" BASIS,
11
//        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//        See the License for the specific language governing permissions and
13
//        limitations under the License.
14
package config
15

16
import (
17
        "crypto/rand"
18
        "encoding/base64"
19
        "fmt"
20
        "io"
21
        "os"
22
        "strings"
23

24
        "github.com/mendersoftware/go-lib-micro/config"
25
        "github.com/mendersoftware/go-lib-micro/log"
26
        "github.com/pkg/errors"
27
)
28

29
const (
30
        EnvProd = "prod"
31
        EnvDev  = "dev"
32

33
        SettingHttps            = "https"
34
        SettingHttpsCertificate = SettingHttps + ".certificate"
35
        SettingHttpsKey         = SettingHttps + ".key"
36

37
        SettingListen        = "listen"
38
        SettingListenDefault = ":8080"
39

40
        SettingStorage = "storage"
41

42
        SettingDefaultStorage             = SettingStorage + ".default"
43
        SettingDefaultStorageDefault      = "aws"
44
        SettingStorageBucket              = SettingStorage + ".bucket"
45
        SettingStorageBucketDefault       = "mender-artifact-storage"
46
        SettingStorageMaxImageSize        = SettingStorage + ".max_image_size"
47
        SettingStorageMaxImageSizeDefault = 10 * 1024 * 1024 * 1024 // 10 GiB
48

49
        SettingStorageEnableDirectUpload        = SettingStorage + ".enable_direct_upload"
50
        SettingStorageEnableDirectUploadDefault = false
51

52
        SettingStorageDirectUploadSkipVerify        = SettingStorage + ".direct_upload_skip_verify"
53
        SettingStorageDirectUploadSkipVerifyDefault = false
54

55
        SettingsStorageDownloadExpireSeconds        = SettingStorage + ".download_expire_seconds"
56
        SettingsStorageDownloadExpireSecondsDefault = 900
57
        SettingsStorageUploadExpireSeconds          = SettingStorage + ".upload_expire_seconds"
58
        SettingsStorageUploadExpireSecondsDefault   = 3600
59

60
        SettingsAws                       = "aws"
61
        SettingAwsS3Region                = SettingsAws + ".region"
62
        SettingAwsS3RegionDefault         = "us-east-1"
63
        SettingAwsS3ForcePathStyle        = SettingsAws + ".force_path_style"
64
        SettingAwsS3ForcePathStyleDefault = true
65
        SettingAwsS3UseAccelerate         = SettingsAws + ".use_accelerate"
66
        SettingAwsS3UseAccelerateDefault  = false
67
        SettingAwsURI                     = SettingsAws + ".uri"
68
        SettingAwsExternalURI             = SettingsAws + ".external_uri"
69
        SettingAwsUnsignedHeaders         = SettingsAws + ".unsigned_headers"
70
        SettingAwsUnsignedHeadersDefault  = "Accept-Encoding"
71

72
        SettingsAwsTagArtifact        = SettingsAws + ".tag_artifact"
73
        SettingsAwsTagArtifactDefault = false
74

75
        SettingsAwsAuth      = SettingsAws + ".auth"
76
        SettingAwsAuthKeyId  = SettingsAwsAuth + ".key"
77
        SettingAwsAuthSecret = SettingsAwsAuth + ".secret"
78
        SettingAwsAuthToken  = SettingsAwsAuth + ".token"
79

80
        SettingAzure                    = "azure"
81
        SettingAzureAuth                = SettingAzure + ".auth"
82
        SettingAzureConnectionString    = SettingAzureAuth + ".connection_string"
83
        SettingAzureSharedKey           = SettingAzureAuth + ".shared_key"
84
        SettingAzureSharedKeyAccount    = SettingAzureSharedKey + ".account_name"
85
        SettingAzureSharedKeyAccountKey = SettingAzureSharedKey + ".account_key"
86
        SettingAzureSharedKeyURI        = SettingAzureSharedKey + ".uri"
87

88
        SettingMongo        = "mongo-url"
89
        SettingMongoDefault = "mongodb://mongo-deployments:27017"
90

91
        SettingDbSSL        = "mongo_ssl"
92
        SettingDbSSLDefault = false
93

94
        SettingDbSSLSkipVerify        = "mongo_ssl_skipverify"
95
        SettingDbSSLSkipVerifyDefault = false
96

97
        SettingDbUsername = "mongo_username"
98
        SettingDbPassword = "mongo_password"
99

100
        SettingWorkflows        = "mender-workflows"
101
        SettingWorkflowsDefault = "http://mender-workflows-server:8080"
102

103
        SettingMiddleware        = "middleware"
104
        SettingMiddlewareDefault = EnvProd
105

106
        SettingInventoryAddr        = "inventory_addr"
107
        SettingInventoryAddrDefault = "http://mender-inventory:8080"
108

109
        SettingReportingAddr        = "reporting_addr"
110
        SettingReportingAddrDefault = ""
111

112
        SettingInventoryTimeout        = "inventory_timeout"
113
        SettingInventoryTimeoutDefault = 10
114

115
        // SettingPresignAlgorithm sets the algorithm used for signing
116
        // downloadable URLs. This option is currently ignored.
117
        SettingPresignAlgorithm        = "presign.algorithm"
118
        SettingPresignAlgorithmDefault = "HMAC256"
119

120
        // SettingPresignSecret sets the secret for generating signed url.
121
        // For HMAC type of algorithms the value must be a base64 encoded
122
        // secret. For public key signatures, the value must be a path to
123
        // the private key (not yet supported).
124
        SettingPresignSecret        = "presign.secret"
125
        SettingPresignSecretDefault = ""
126

127
        // SettingPresignExpireSeconds sets the amount of seconds it takes for
128
        // the signed URL to expire.
129
        SettingPresignExpireSeconds        = "presign.expire_seconds"
130
        SettingPresignExpireSecondsDefault = 900
131

132
        // SettingPresignHost sets the URL hostname (pointing to the gateway)
133
        // for the generated URL. If the configuration option is left blank
134
        // (default), it will try to use the X-Forwarded-Host header forwarded
135
        // by the proxy.
136
        SettingPresignHost        = "presign.url_hostname"
137
        SettingPresignHostDefault = ""
138

139
        // SettingPresignURLScheme sets the URL scheme used for generating the
140
        // pre-signed url.
141
        SettingPresignScheme        = "presign.url_scheme"
142
        SettingPresignSchemeDefault = "https"
143
)
144

145
const (
146
        StorageTypeAWS   = "aws"
147
        StorageTypeAzure = "azure"
148
)
149

150
const (
151
        deprecatedSettingAwsS3Bucket               = SettingsAws + ".bucket"
152
        deprecatedSettingAwsS3MaxImageSize         = SettingsAws + ".max_image_size"
153
        deprecatedSettingsAwsDownloadExpireSeconds = SettingsAws + ".download_expire_seconds"
154
        deprecatedSettingsAwsUploadExpireSeconds   = SettingsAws + ".upload_expire_seconds"
155
)
156

157
// ValidateAwsAuth validates configuration of SettingsAwsAuth section if provided.
158
func ValidateAwsAuth(c config.Reader) error {
1✔
159

1✔
160
        if c.IsSet(SettingsAwsAuth) {
1✔
UNCOV
161
                required := []string{SettingAwsAuthKeyId, SettingAwsAuthSecret}
×
UNCOV
162
                for _, key := range required {
×
163
                        if !c.IsSet(key) {
×
164
                                return MissingOptionError(key)
×
165
                        }
×
166

167
                        if c.GetString(key) == "" {
×
UNCOV
168
                                return MissingOptionError(key)
×
169
                        }
×
170
                }
171
        }
172

173
        return nil
1✔
174
}
175

176
// ValidateHttps validates configuration of SettingHttps section if provided.
177
func ValidateHttps(c config.Reader) error {
1✔
178

1✔
179
        if c.IsSet(SettingHttps) {
1✔
UNCOV
180
                required := []string{SettingHttpsCertificate, SettingHttpsKey}
×
UNCOV
181
                for _, key := range required {
×
182
                        if !c.IsSet(key) {
×
183
                                return MissingOptionError(key)
×
184
                        }
×
185

186
                        value := c.GetString(key)
×
UNCOV
187
                        if value == "" {
×
188
                                return MissingOptionError(key)
×
189
                        }
×
190

191
                        if _, err := os.Stat(value); err != nil {
×
UNCOV
192
                                return err
×
193
                        }
×
194
                }
195
        }
196

197
        return nil
1✔
198
}
199

200
func ValidateStorage(c config.Reader) error {
1✔
201
        svc := c.GetString(SettingDefaultStorage)
1✔
202
        if svc != StorageTypeAWS && svc != StorageTypeAzure {
1✔
UNCOV
203
                return fmt.Errorf(
×
UNCOV
204
                        `setting "%s" (%s) must be one of "aws" or "azure"`,
×
205
                        SettingDefaultStorage, svc,
×
206
                )
×
207
        }
×
208
        return nil
1✔
209
}
210

211
// Generate error with missing required option message.
UNCOV
212
func MissingOptionError(option string) error {
×
UNCOV
213
        return fmt.Errorf("Required option: '%s'", option)
×
214
}
×
215

216
func applyAliases() {
1✔
217
        for _, alias := range Aliases {
2✔
218
                if config.Config.IsSet(alias.Alias) {
1✔
UNCOV
219
                        config.Config.Set(alias.Key, config.Config.Get(alias.Alias))
×
UNCOV
220
                }
×
221
        }
222
}
223

224
func Setup(configPath string) error {
1✔
225
        err := config.FromConfigFile(configPath, Defaults)
1✔
226
        if err != nil {
1✔
UNCOV
227
                return fmt.Errorf("error loading configuration: %s", err)
×
UNCOV
228
        }
×
229

230
        // Enable setting config values by environment variables
231
        config.Config.SetEnvPrefix("DEPLOYMENTS")
1✔
232
        config.Config.AutomaticEnv()
1✔
233
        config.Config.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
1✔
234
        if err := config.ValidateConfig(config.Config, Validators...); err != nil {
1✔
UNCOV
235
                return errors.WithMessage(err, "config: error validating configuration")
×
UNCOV
236
        }
×
237
        if config.Config.Get(SettingPresignSecret) == "" {
1✔
238
                log.NewEmpty().Warnf("'%s' not configured. Generating a random secret.",
×
UNCOV
239
                        SettingPresignSecret,
×
240
                )
×
241
                var buf [32]byte
×
242
                n, err := io.ReadFull(rand.Reader, buf[:])
×
243
                if err != nil {
×
244
                        return errors.WithMessagef(err,
×
245
                                "failed to generate '%s'",
×
246
                                SettingPresignSecret,
×
247
                        )
×
248
                } else if n == 0 {
×
249
                        return errors.Errorf(
×
250
                                "failed to generate '%s'",
×
251
                                SettingPresignSecret,
×
252
                        )
×
253
                }
×
254
                secret := base64.StdEncoding.EncodeToString(buf[:n])
×
255
                config.Config.Set(SettingPresignSecret, secret)
×
256
        }
257
        applyAliases()
1✔
258
        return nil
1✔
259
}
260

261
var (
262
        Validators = []config.Validator{ValidateAwsAuth, ValidateHttps, ValidateStorage}
263
        // Aliases for deprecated configuration names to preserve backward compatibility.
264
        Aliases = []struct {
265
                Key   string
266
                Alias string
267
        }{
268
                {Key: SettingStorageBucket, Alias: deprecatedSettingAwsS3Bucket},
269
                {Key: SettingsStorageDownloadExpireSeconds,
270
                        Alias: deprecatedSettingsAwsDownloadExpireSeconds},
271
                {Key: SettingsStorageUploadExpireSeconds, Alias: deprecatedSettingsAwsUploadExpireSeconds},
272
                {Key: SettingStorageMaxImageSize, Alias: deprecatedSettingAwsS3MaxImageSize},
273
        }
274

275
        Defaults = []config.Default{
276
                {Key: SettingListen, Value: SettingListenDefault},
277
                {Key: SettingDefaultStorage, Value: SettingDefaultStorageDefault},
278
                {Key: SettingAwsS3Region, Value: SettingAwsS3RegionDefault},
279
                {Key: SettingStorageBucket, Value: SettingStorageBucketDefault},
280
                {Key: SettingStorageDirectUploadSkipVerify,
281
                        Value: SettingStorageDirectUploadSkipVerifyDefault},
282
                {Key: SettingStorageEnableDirectUpload, Value: SettingStorageEnableDirectUploadDefault},
283
                {Key: SettingAwsS3ForcePathStyle, Value: SettingAwsS3ForcePathStyleDefault},
284
                {Key: SettingAwsS3UseAccelerate, Value: SettingAwsS3UseAccelerateDefault},
285
                {Key: SettingAwsUnsignedHeaders, Value: SettingAwsUnsignedHeadersDefault},
286
                {Key: SettingStorageMaxImageSize, Value: SettingStorageMaxImageSizeDefault},
287
                {Key: SettingsStorageDownloadExpireSeconds,
288
                        Value: SettingsStorageDownloadExpireSecondsDefault},
289
                {Key: SettingsStorageUploadExpireSeconds, Value: SettingsStorageUploadExpireSecondsDefault},
290
                {Key: SettingMongo, Value: SettingMongoDefault},
291
                {Key: SettingDbSSL, Value: SettingDbSSLDefault},
292
                {Key: SettingDbSSLSkipVerify, Value: SettingDbSSLSkipVerifyDefault},
293
                {Key: SettingWorkflows, Value: SettingWorkflowsDefault},
294
                {Key: SettingsAwsTagArtifact, Value: SettingsAwsTagArtifactDefault},
295
                {Key: SettingInventoryAddr, Value: SettingInventoryAddrDefault},
296
                {Key: SettingReportingAddr, Value: SettingReportingAddrDefault},
297
                {Key: SettingInventoryTimeout, Value: SettingInventoryTimeoutDefault},
298
                {Key: SettingPresignAlgorithm, Value: SettingPresignAlgorithmDefault},
299
                {Key: SettingPresignSecret, Value: SettingPresignSecretDefault},
300
                {Key: SettingPresignExpireSeconds, Value: SettingPresignExpireSecondsDefault},
301
                {Key: SettingPresignHost, Value: SettingPresignHostDefault},
302
                {Key: SettingPresignScheme, Value: SettingPresignSchemeDefault},
303
        }
304
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc