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

mendersoftware / iot-manager / 1401702106

05 Aug 2024 08:32PM UTC coverage: 87.577%. Remained the same
1401702106

push

gitlab-ci

web-flow
Merge pull request #295 from mendersoftware/dependabot/docker/docker-dependencies-03b04ac819

chore: bump golang from 1.22.4-alpine3.19 to 1.22.5-alpine3.19 in the docker-dependencies group

3264 of 3727 relevant lines covered (87.58%)

11.44 hits per line

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

100.0
/client/client.go
1
// Copyright 2022 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 client
16

17
import (
18
        "bytes"
19
        "context"
20
        "crypto/hmac"
21
        "crypto/sha256"
22
        "crypto/tls"
23
        "encoding/hex"
24
        "encoding/json"
25
        "errors"
26
        "net"
27
        "net/http"
28
        "syscall"
29
        "time"
30

31
        inet "github.com/mendersoftware/iot-manager/internal/net"
32
        "github.com/mendersoftware/iot-manager/model"
33
)
34

35
const (
36
        ParamAlgorithmType = "X-Men-Algorithm"
37
        ParamSignature     = "X-Men-Signature"
38

39
        HdrKeyContentType    = "Content-Type"
40
        AlgorithmTypeHMAC256 = "MEN-HMAC-SHA256-Payload"
41
)
42

43
func New() *http.Client {
5✔
44
        return &http.Client{
5✔
45
                Transport: NewTransport(),
5✔
46
                CheckRedirect: func(req *http.Request, via []*http.Request) error {
7✔
47
                        return http.ErrUseLastResponse
2✔
48
                },
2✔
49
        }
50
}
51

52
func addrIsGlobalUnicast(network, address string, _ syscall.RawConn) error {
17✔
53
        ipAddr, _, err := net.SplitHostPort(address)
17✔
54
        if err != nil {
29✔
55
                ipAddr = address
12✔
56
        }
12✔
57
        ip := net.ParseIP(ipAddr)
17✔
58
        if ip == nil {
19✔
59
                return &net.ParseError{
2✔
60
                        Type: "IP address",
2✔
61
                        Text: address,
2✔
62
                }
2✔
63
        } else if !inet.IsGlobalUnicast(ip) {
23✔
64
                return net.InvalidAddrError("destination address is in reserved address range")
6✔
65
        }
6✔
66
        return nil
9✔
67
}
68

69
func NewTransport() http.RoundTripper {
5✔
70
        dialer := &net.Dialer{
5✔
71
                Control: addrIsGlobalUnicast,
5✔
72
        }
5✔
73
        tlsDialer := &tls.Dialer{
5✔
74
                NetDialer: dialer,
5✔
75
        }
5✔
76
        return &http.Transport{
5✔
77
                Proxy:                 nil,
5✔
78
                DialContext:           dialer.DialContext,
5✔
79
                DialTLSContext:        tlsDialer.DialContext,
5✔
80
                ForceAttemptHTTP2:     true,
5✔
81
                MaxIdleConns:          100,
5✔
82
                IdleConnTimeout:       90 * time.Second,
5✔
83
                TLSHandshakeTimeout:   10 * time.Second,
5✔
84
                ExpectContinueTimeout: 1 * time.Second,
5✔
85
        }
5✔
86
}
5✔
87

88
// NewSignedRequest appends header X-Men-Signature with value:
89
// HMAC256(Request.Body, secret)
90
func NewSignedRequest(
91
        ctx context.Context,
92
        secret []byte,
93
        method string,
94
        url string,
95
        body []byte,
96
) (*http.Request, error) {
7✔
97
        req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewReader(body))
7✔
98
        if err != nil {
9✔
99
                return nil, err
2✔
100
        }
2✔
101
        req.Header.Set(ParamAlgorithmType, AlgorithmTypeHMAC256)
5✔
102

5✔
103
        sign := hmac.New(sha256.New, secret)
5✔
104
        _, _ = sign.Write(body) // Writer cannot error
5✔
105

5✔
106
        req.Header.Set(ParamSignature, hex.EncodeToString(sign.Sum(nil)))
5✔
107

5✔
108
        return req, nil
5✔
109
}
110

111
func NewWebhookRequest(
112
        ctx context.Context,
113
        creds *model.Credentials,
114
        event model.WebhookEvent,
115
) (*http.Request, error) {
15✔
116
        err := creds.Validate()
15✔
117
        if err != nil {
17✔
118
                return nil, err
2✔
119
        } else if creds.Type != model.CredentialTypeHTTP {
17✔
120
                return nil, errors.New("invalid credentials for webhooks")
2✔
121
        }
2✔
122

123
        b, err := json.Marshal(event)
11✔
124
        if err != nil {
13✔
125
                return nil, err
2✔
126
        }
2✔
127
        var req *http.Request
9✔
128
        if creds.HTTP.Secret != nil {
16✔
129
                req, err = NewSignedRequest(
7✔
130
                        ctx,
7✔
131
                        []byte(*creds.HTTP.Secret),
7✔
132
                        http.MethodPost,
7✔
133
                        creds.HTTP.URL,
7✔
134
                        b,
7✔
135
                )
7✔
136
        } else {
9✔
137
                req, err = http.NewRequestWithContext(
2✔
138
                        ctx, http.MethodPost,
2✔
139
                        creds.HTTP.URL, bytes.NewReader(b),
2✔
140
                )
2✔
141
        }
2✔
142
        if err == nil {
16✔
143
                req.Header.Set(HdrKeyContentType, "application/json")
7✔
144
        }
7✔
145
        return req, err
9✔
146
}
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