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

mendersoftware / useradm / 1088469980

28 Nov 2023 09:52PM UTC coverage: 87.17%. First build
1088469980

Pull #394

gitlab-ci

merlin-northern
chore: private keys and key ids: tests

Changelog: Title
Ticket: MEN-6804
Signed-off-by: Peter Grzybowski <peter@northern.tech>
Pull Request #394: Men 6804 key rotation support

166 of 232 new or added lines in 9 files covered. (71.55%)

2874 of 3297 relevant lines covered (87.17%)

130.99 hits per line

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

79.63
/jwt/jwt.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 jwt
15

16
import (
17
        "crypto/ed25519"
18
        "crypto/rsa"
19
        "crypto/x509"
20
        "encoding/pem"
21
        "os"
22

23
        "github.com/pkg/errors"
24

25
        jwtv4 "github.com/golang-jwt/jwt/v4"
26

27
        "github.com/mendersoftware/useradm/common"
28
)
29

30
var (
31
        ErrTokenExpired = errors.New("jwt: token expired")
32
        ErrTokenInvalid = errors.New("jwt: token invalid")
33
)
34

35
const (
36
        pemHeaderPKCS1 = "RSA PRIVATE KEY"
37
        pemHeaderPKCS8 = "PRIVATE KEY"
38
)
39

40
// Handler jwt generator/verifier
41
//
42
//go:generate ../utils/mockgen.sh
43
type Handler interface {
44
        ToJWT(t *Token) (string, error)
45
        // FromJWT parses the token and does basic validity checks (Claims.Valid()).
46
        // returns:
47
        // ErrTokenExpired when the token is valid but expired
48
        // ErrTokenInvalid when the token is invalid (malformed, missing required claims, etc.)
49
        FromJWT(string) (*Token, error)
50
}
51

52
func NewJWTHandler(privateKeyPath string, privateKeyFilenamePattern string) (Handler, error) {
7✔
53
        priv, err := os.ReadFile(privateKeyPath)
7✔
54
        block, _ := pem.Decode(priv)
7✔
55
        if block == nil {
8✔
56
                return nil, errors.Wrap(err, "failed to read private key")
1✔
57
        }
1✔
58
        switch block.Type {
6✔
59
        case pemHeaderPKCS1:
3✔
60
                privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
3✔
61
                if err != nil {
3✔
62
                        return nil, errors.Wrap(err, "failed to read rsa private key")
×
63
                }
×
64
                return NewJWTHandlerRS256(
3✔
65
                                privKey,
3✔
66
                                common.KeyIdFromPath(privateKeyPath, privateKeyFilenamePattern),
3✔
67
                        ),
3✔
68
                        nil
3✔
69
        case pemHeaderPKCS8:
2✔
70
                key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
2✔
71
                if err != nil {
2✔
72
                        return nil, errors.Wrap(err, "failed to read private key")
×
73
                }
×
74
                switch v := key.(type) {
2✔
75
                case *rsa.PrivateKey:
1✔
76
                        return NewJWTHandlerRS256(
1✔
77
                                        v,
1✔
78
                                        common.KeyIdFromPath(privateKeyPath, privateKeyFilenamePattern),
1✔
79
                                ),
1✔
80
                                nil
1✔
81
                case ed25519.PrivateKey:
1✔
82
                        return NewJWTHandlerEd25519(
1✔
83
                                        &v,
1✔
84
                                        common.KeyIdFromPath(privateKeyPath, privateKeyFilenamePattern),
1✔
85
                                ),
1✔
86
                                nil
1✔
87
                }
88
        }
89
        return nil, errors.Errorf("unsupported server private key type")
1✔
90
}
91

92
func GetKeyId(tokenString string) int {
157✔
93
        token, _, err := jwtv4.NewParser().ParseUnverified(tokenString, &Claims{})
157✔
94

157✔
95
        if err != nil {
165✔
96
                return common.KeyIdZero
8✔
97
        }
8✔
98

99
        if _, ok := token.Header["kid"]; ok {
298✔
100
                if _, ok := token.Header["kid"]; ok {
298✔
101
                        if _, isFloat := token.Header["kid"].(float64); isFloat {
298✔
102
                                return int(token.Header["kid"].(float64))
149✔
103
                        }
149✔
NEW
104
                        if _, isInt := token.Header["kid"].(int64); isInt {
×
NEW
105
                                return int(token.Header["kid"].(int64))
×
NEW
106
                        }
×
NEW
107
                        if _, isInt := token.Header["kid"].(int); isInt {
×
NEW
108
                                return token.Header["kid"].(int)
×
NEW
109
                        }
×
110
                }
111
        }
112

NEW
113
        return common.KeyIdZero
×
114
}
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