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

mendersoftware / mender-server / 1897784243

30 Jun 2025 11:50AM UTC coverage: 65.64% (-0.09%) from 65.731%
1897784243

Pull #769

gitlab-ci

alfrunes
chore(deviceauth): Add missing config env key replacer

The replacer did not exist because there were no prior configuration
settings with a period or dash in the key name.

Signed-off-by: Alf-Rune Siqveland <alf.rune@northern.tech>
Pull Request #769: MEN-7744: Rate limits for authenticated requests

181 of 332 new or added lines in 9 files covered. (54.52%)

1 existing line in 1 file now uncovered.

32539 of 49572 relevant lines covered (65.64%)

1.39 hits per line

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

59.52
/backend/services/deviceauth/server.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

15
package main
16

17
import (
18
        "context"
19
        "fmt"
20
        "net/http"
21
        "os"
22
        "os/signal"
23
        "time"
24

25
        "github.com/pkg/errors"
26
        "golang.org/x/sys/unix"
27

28
        "github.com/mendersoftware/mender-server/pkg/config"
29
        "github.com/mendersoftware/mender-server/pkg/config/ratelimits"
30
        "github.com/mendersoftware/mender-server/pkg/log"
31
        "github.com/mendersoftware/mender-server/pkg/redis"
32

33
        api_http "github.com/mendersoftware/mender-server/services/deviceauth/api/http"
34
        "github.com/mendersoftware/mender-server/services/deviceauth/cache"
35
        "github.com/mendersoftware/mender-server/services/deviceauth/client/orchestrator"
36
        "github.com/mendersoftware/mender-server/services/deviceauth/client/tenant"
37
        dconfig "github.com/mendersoftware/mender-server/services/deviceauth/config"
38
        "github.com/mendersoftware/mender-server/services/deviceauth/devauth"
39
        "github.com/mendersoftware/mender-server/services/deviceauth/jwt"
40
        "github.com/mendersoftware/mender-server/services/deviceauth/store/mongo"
41
)
42

43
func RunServer(c config.Reader) error {
2✔
44
        tenantadmAddr := c.GetString(dconfig.SettingTenantAdmAddr)
2✔
45

2✔
46
        l := log.New(log.Ctx{})
2✔
47

2✔
48
        db, err := mongo.NewDataStoreMongo(
2✔
49
                mongo.DataStoreMongoConfig{
2✔
50
                        ConnectionString: c.GetString(dconfig.SettingDb),
2✔
51

2✔
52
                        SSL:           c.GetBool(dconfig.SettingDbSSL),
2✔
53
                        SSLSkipVerify: c.GetBool(dconfig.SettingDbSSLSkipVerify),
2✔
54

2✔
55
                        Username: c.GetString(dconfig.SettingDbUsername),
2✔
56
                        Password: c.GetString(dconfig.SettingDbPassword),
2✔
57
                })
2✔
58
        if err != nil {
2✔
59
                return errors.Wrap(err, "database connection failed")
×
60
        }
×
61

62
        jwtHandler, err := jwt.NewJWTHandler(
2✔
63
                c.GetString(dconfig.SettingServerPrivKeyPath),
2✔
64
        )
2✔
65
        var jwtFallbackHandler jwt.Handler
2✔
66
        fallback := c.GetString(dconfig.SettingServerFallbackPrivKeyPath)
2✔
67
        if err == nil && fallback != "" {
2✔
68
                jwtFallbackHandler, err = jwt.NewJWTHandler(
×
69
                        fallback,
×
70
                )
×
71
        }
×
72
        if err != nil {
2✔
73
                return err
×
74
        }
×
75

76
        orchClientConf := orchestrator.Config{
2✔
77
                OrchestratorAddr: c.GetString(dconfig.SettingOrchestratorAddr),
2✔
78
                Timeout:          time.Duration(30) * time.Second,
2✔
79
        }
2✔
80

2✔
81
        devauth := devauth.NewDevAuth(db,
2✔
82
                orchestrator.NewClient(orchClientConf),
2✔
83
                jwtHandler,
2✔
84
                devauth.Config{
2✔
85
                        Issuer:             c.GetString(dconfig.SettingJWTIssuer),
2✔
86
                        ExpirationTime:     int64(c.GetInt(dconfig.SettingJWTExpirationTimeout)),
2✔
87
                        DefaultTenantToken: c.GetString(dconfig.SettingDefaultTenantToken),
2✔
88
                        InventoryAddr:      config.Config.GetString(dconfig.SettingInventoryAddr),
2✔
89

2✔
90
                        EnableReporting: config.Config.GetBool(dconfig.SettingEnableReporting),
2✔
91
                        HaveAddons: config.Config.GetBool(dconfig.SettingHaveAddons) &&
2✔
92
                                tenantadmAddr != "",
2✔
93
                })
2✔
94

2✔
95
        if jwtFallbackHandler != nil {
2✔
96
                devauth = devauth.WithJWTFallbackHandler(jwtFallbackHandler)
×
97
        }
×
98

99
        if tenantadmAddr != "" {
2✔
100
                tc := tenant.NewClient(tenant.Config{
×
101
                        TenantAdmAddr: tenantadmAddr,
×
102
                })
×
103
                devauth = devauth.WithTenantVerification(tc)
×
104
        }
×
105

106
        var apiOptions []api_http.Option
2✔
107

2✔
108
        cacheConnStr := c.GetString(dconfig.SettingRedisConnectionString)
2✔
109
        if cacheConnStr == "" {
4✔
110
                // for backward compatibility check old redis_addr setting
2✔
111
                cacheConnStr = c.GetString(dconfig.SettingRedisAddr)
2✔
112
        }
2✔
113
        if cacheConnStr != "" {
2✔
114
                l.Infof("setting up redis cache")
×
115

×
116
                ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
×
117
                redisClient, err := redis.ClientFromConnectionString(ctx, cacheConnStr)
×
118
                cancel()
×
119
                if err != nil {
×
120
                        return fmt.Errorf("failed to initialize redis client: %w", err)
×
121
                }
×
122

123
                redisKeyPrefix := c.GetString(dconfig.SettingRedisKeyPrefix)
×
124
                cache := cache.NewRedisCache(
×
125
                        redisClient,
×
126
                        redisKeyPrefix,
×
127
                        c.GetInt(dconfig.SettingRedisLimitsExpSec),
×
128
                )
×
129
                devauth = devauth.WithCache(cache)
×
NEW
130

×
NEW
131
                rateLimiter, err := ratelimits.SetupRedisRateLimits(
×
NEW
132
                        redisClient, c.GetString(dconfig.SettingRedisKeyPrefix), c,
×
NEW
133
                )
×
134
                if err != nil {
×
135
                        return fmt.Errorf("error configuring rate limits: %w", err)
×
136
                }
×
NEW
137
                if rateLimiter != nil {
×
NEW
138
                        apiOptions = append(apiOptions,
×
NEW
139
                                api_http.ConfigAuthVerifyMiddleware(
×
NEW
140
                                        rateLimiter.WithRewriteRequests(true).MiddlewareGin,
×
NEW
141
                                ),
×
NEW
142
                        )
×
NEW
143
                }
×
144
        }
145

146
        apiHandler := api_http.NewRouter(devauth, db, apiOptions...)
2✔
147

2✔
148
        addr := c.GetString(dconfig.SettingListen)
2✔
149
        l.Printf("listening on %s", addr)
2✔
150

2✔
151
        srv := &http.Server{
2✔
152
                Addr:    addr,
2✔
153
                Handler: apiHandler,
2✔
154
        }
2✔
155

2✔
156
        errChan := make(chan error, 1)
2✔
157
        go func() {
4✔
158
                if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
2✔
159
                        errChan <- err
×
160
                }
×
161
        }()
162
        quit := make(chan os.Signal, 1)
2✔
163
        signal.Notify(quit, unix.SIGINT, unix.SIGTERM)
2✔
164
        select {
2✔
165
        case sig := <-quit:
2✔
166
                l.Infof("received signal %s: terminating", sig)
2✔
167
        case err = <-errChan:
×
168
                l.Errorf("server terminated unexpectedly: %s", err.Error())
×
169
                return err
×
170
        }
171

172
        l.Info("server shutdown")
2✔
173
        ctxWithTimeout, cancel := context.WithTimeout(context.Background(), 5*time.Second)
2✔
174
        defer cancel()
2✔
175
        if err := srv.Shutdown(ctxWithTimeout); err != nil {
2✔
176
                l.Error("error when shutting down the server ", err)
×
177
        }
×
178
        return nil
2✔
179
}
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