-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.go
106 lines (91 loc) · 3.12 KB
/
index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// This file is part of arduino-cloud-cli.
//
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package binary
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"compress/gzip"
"github.com/arduino/arduino-cloud-cli/internal/binary/gpgkey"
"golang.org/x/crypto/openpgp"
)
const (
// URL of cloud-team binary index.
IndexGZURL = "https://cloud-downloads.arduino.cc/binaries/index.json.gz"
IndexSigURL = "https://cloud-downloads.arduino.cc/binaries/index.json.sig"
)
// Index contains details about all the binaries
// loaded in 'cloud-downloads'.
type Index struct {
Boards []IndexBoard `json:"boards"`
}
// IndexBoard describes all the binaries available for a specific board.
type IndexBoard struct {
Fqbn string `json:"fqbn"`
Provision *IndexBin `json:"provision"`
}
// IndexBin contains the details needed to retrieve a binary file from the cloud.
type IndexBin struct {
URL string `json:"url"`
Checksum string `json:"checksum"`
Size json.Number `json:"size"`
}
// LoadIndex downloads and verifies the index of binaries
// contained in 'cloud-downloads'.
func LoadIndex() (*Index, error) {
indexGZ, err := download(IndexGZURL)
if err != nil {
return nil, fmt.Errorf("cannot download index: %w", err)
}
indexReader, err := gzip.NewReader(bytes.NewReader(indexGZ))
if err != nil {
return nil, fmt.Errorf("cannot decompress index: %w", err)
}
index, err := ioutil.ReadAll(indexReader)
if err != nil {
return nil, fmt.Errorf("cannot read downloaded index: %w", err)
}
sig, err := download(IndexSigURL)
if err != nil {
return nil, fmt.Errorf("cannot download index signature: %w", err)
}
keyRing, err := openpgp.ReadKeyRing(bytes.NewReader(gpgkey.IndexPublicKey))
if err != nil {
return nil, fmt.Errorf("cannot retrieve Arduino public GPG key: %w", err)
}
signer, err := openpgp.CheckDetachedSignature(keyRing, bytes.NewReader(index), bytes.NewReader(sig))
if signer == nil || err != nil {
return nil, fmt.Errorf("invalid signature for index downloaded from %s", IndexGZURL)
}
i := &Index{}
if err = json.Unmarshal(index, &i); err != nil {
return nil, fmt.Errorf("cannot unmarshal index json: %w", err)
}
return i, nil
}
// FindProvisionBin looks for the provisioning binary corresponding
// to the passed fqbn in the index.
// Returns nil if the binary is not found.
func (i *Index) FindProvisionBin(fqbn string) *IndexBin {
for _, b := range i.Boards {
if b.Fqbn == fqbn {
return b.Provision
}
}
return nil
}