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

mendersoftware / deviceauth / 1029905495

09 Oct 2023 04:24AM UTC coverage: 83.929% (-3.9%) from 87.856%
1029905495

Pull #674

gitlab-ci

tranchitella
feat: support for ED25519 server keys for signing the JWT tokens

Ticket: MEN-6775
Changelog: Title

Signed-off-by: Fabio Tranchitella <fabio.tranchitella@northern.tech>
Pull Request #674: feat: support for ED25519 server keys for signing the JWT tokens

139 of 148 new or added lines in 4 files covered. (93.92%)

88 existing lines in 3 files now uncovered.

4721 of 5625 relevant lines covered (83.93%)

46.83 hits per line

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

81.36
/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
        "crypto/ed25519"
19
        "crypto/rsa"
20
        "net/http"
21
        "time"
22

23
        "github.com/ant0ine/go-json-rest/rest"
24
        "github.com/mendersoftware/go-lib-micro/config"
25
        "github.com/mendersoftware/go-lib-micro/log"
26
        "github.com/pkg/errors"
27

28
        api_http "github.com/mendersoftware/deviceauth/api/http"
29
        "github.com/mendersoftware/deviceauth/cache"
30
        "github.com/mendersoftware/deviceauth/client/orchestrator"
31
        "github.com/mendersoftware/deviceauth/client/tenant"
32
        dconfig "github.com/mendersoftware/deviceauth/config"
33
        "github.com/mendersoftware/deviceauth/devauth"
34
        "github.com/mendersoftware/deviceauth/jwt"
35
        "github.com/mendersoftware/deviceauth/keys"
36
        "github.com/mendersoftware/deviceauth/store/mongo"
37
)
38

39
func SetupAPI(stacktype string) (*rest.Api, error) {
3✔
40
        api := rest.NewApi()
3✔
41
        if err := SetupMiddleware(api, stacktype); err != nil {
4✔
42
                return nil, errors.Wrap(err, "failed to setup middleware")
1✔
43
        }
1✔
44

45
        //this will override the framework's error resp to the desired one:
46
        // {"error": "msg"}
47
        // instead of:
48
        // {"Error": "msg"}
49
        rest.ErrorFieldName = "error"
2✔
50

2✔
51
        return api, nil
2✔
52
}
53

54
func getJWTHandler(privateKeyType, privateKeyPath,
55
        fallbackPrivateKeyPath string) (jwt.Handler, error) {
10✔
56
        if privateKeyType == dconfig.SettingServerPrivKeyTypeRSA {
15✔
57
                privKey, err := keys.LoadRSAPrivate(privateKeyPath)
5✔
58
                if err != nil {
6✔
59
                        return nil, errors.Wrap(err, "failed to read rsa private key")
1✔
60
                }
1✔
61
                fallbackPrivKeyPath := fallbackPrivateKeyPath
4✔
62
                var fallbackPrivKey *rsa.PrivateKey
4✔
63
                if fallbackPrivKeyPath != "" {
6✔
64
                        fallbackPrivKey, err = keys.LoadRSAPrivate(fallbackPrivKeyPath)
2✔
65
                        if err != nil {
3✔
66
                                return nil, errors.Wrap(err, "failed to read fallback rsa private key")
1✔
67
                        }
1✔
68
                }
69
                return jwt.NewJWTHandlerRS256(privKey, fallbackPrivKey), nil
3✔
70
        } else if privateKeyType == dconfig.SettingServerPrivKeyTypeEd25519 {
9✔
71
                privKey, err := keys.LoadEd25519Private(privateKeyPath)
4✔
72
                if err != nil {
5✔
73
                        return nil, errors.Wrap(err, "failed to read ed25519 private key")
1✔
74
                }
1✔
75
                fallbackPrivKeyPath := fallbackPrivateKeyPath
3✔
76
                var fallbackPrivKey *ed25519.PrivateKey
3✔
77
                if fallbackPrivKeyPath != "" {
5✔
78
                        fallbackPrivKey, err = keys.LoadEd25519Private(fallbackPrivKeyPath)
2✔
79
                        if err != nil {
3✔
80
                                return nil, errors.Wrap(err, "failed to read fallback ed25519 private key")
1✔
81
                        }
1✔
82
                }
83
                return jwt.NewJWTHandlerEd25519(privKey, fallbackPrivKey), nil
2✔
84
        }
85
        return nil, errors.Errorf("unsupported server private key type %v", privateKeyType)
1✔
86
}
87

88
func RunServer(c config.Reader) error {
1✔
89
        var tenantadmAddr = c.GetString(dconfig.SettingTenantAdmAddr)
1✔
90

1✔
91
        l := log.New(log.Ctx{})
1✔
92

1✔
93
        db, err := mongo.NewDataStoreMongo(
1✔
94
                mongo.DataStoreMongoConfig{
1✔
95
                        ConnectionString: c.GetString(dconfig.SettingDb),
1✔
96

1✔
97
                        SSL:           c.GetBool(dconfig.SettingDbSSL),
1✔
98
                        SSLSkipVerify: c.GetBool(dconfig.SettingDbSSLSkipVerify),
1✔
99

1✔
100
                        Username: c.GetString(dconfig.SettingDbUsername),
1✔
101
                        Password: c.GetString(dconfig.SettingDbPassword),
1✔
102
                })
1✔
103
        if err != nil {
1✔
104
                return errors.Wrap(err, "database connection failed")
×
105
        }
×
106

107
        jwtHandler, err := getJWTHandler(
1✔
108
                c.GetString(dconfig.SettingServerPrivKeyType),
1✔
109
                c.GetString(dconfig.SettingServerPrivKeyPath),
1✔
110
                c.GetString(dconfig.SettingServerFallbackPrivKeyPath),
1✔
111
        )
1✔
112
        if err != nil {
1✔
NEW
UNCOV
113
                return err
×
NEW
UNCOV
114
        }
×
115

116
        orchClientConf := orchestrator.Config{
1✔
117
                OrchestratorAddr: c.GetString(dconfig.SettingOrchestratorAddr),
1✔
118
                Timeout:          time.Duration(30) * time.Second,
1✔
119
        }
1✔
120

1✔
121
        devauth := devauth.NewDevAuth(db,
1✔
122
                orchestrator.NewClient(orchClientConf),
1✔
123
                jwtHandler,
1✔
124
                devauth.Config{
1✔
125
                        Issuer:             c.GetString(dconfig.SettingJWTIssuer),
1✔
126
                        ExpirationTime:     int64(c.GetInt(dconfig.SettingJWTExpirationTimeout)),
1✔
127
                        DefaultTenantToken: c.GetString(dconfig.SettingDefaultTenantToken),
1✔
128
                        InventoryAddr:      config.Config.GetString(dconfig.SettingInventoryAddr),
1✔
129

1✔
130
                        EnableReporting: config.Config.GetBool(dconfig.SettingEnableReporting),
1✔
131
                        HaveAddons: config.Config.GetBool(dconfig.SettingHaveAddons) &&
1✔
132
                                tenantadmAddr != "",
1✔
133
                })
1✔
134

1✔
135
        if tenantadmAddr != "" {
2✔
136
                tc := tenant.NewClient(tenant.Config{
1✔
137
                        TenantAdmAddr: tenantadmAddr,
1✔
138
                })
1✔
139
                devauth = devauth.WithTenantVerification(tc)
1✔
140
        }
1✔
141

142
        if cacheAddr := c.GetString(dconfig.SettingRedisAddr); cacheAddr != "" {
1✔
UNCOV
143
                l.Infof("setting up redis cache")
×
UNCOV
144

×
UNCOV
145
                cache, err := cache.NewRedisCache(cacheAddr,
×
UNCOV
146
                        c.GetString(dconfig.SettingRedisUsername),
×
UNCOV
147
                        c.GetString(dconfig.SettingRedisPassword),
×
UNCOV
148
                        c.GetInt(dconfig.SettingRedisDb),
×
UNCOV
149
                        c.GetInt(dconfig.SettingRedisTimeoutSec),
×
UNCOV
150
                        c.GetInt(dconfig.SettingRedisLimitsExpSec),
×
UNCOV
151
                )
×
UNCOV
152

×
UNCOV
153
                if err != nil {
×
UNCOV
154
                        return err
×
UNCOV
155
                }
×
156

UNCOV
157
                devauth = devauth.WithCache(cache)
×
158
        }
159

160
        api, err := SetupAPI(c.GetString(dconfig.SettingMiddleware))
1✔
161
        if err != nil {
1✔
UNCOV
162
                return errors.Wrap(err, "API setup failed")
×
UNCOV
163
        }
×
164

165
        devauthapi := api_http.NewDevAuthApiHandlers(devauth, db)
1✔
166

1✔
167
        apph, err := devauthapi.GetApp()
1✔
168
        if err != nil {
1✔
UNCOV
169
                return errors.Wrap(err, "device authentication API handlers setup failed")
×
UNCOV
170
        }
×
171
        api.SetApp(apph)
1✔
172

1✔
173
        addr := c.GetString(dconfig.SettingListen)
1✔
174
        l.Printf("listening on %s", addr)
1✔
175

1✔
176
        return http.ListenAndServe(addr, api.MakeHandler())
1✔
177
}
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