Skip to content

Commit 8f5a4d7

Browse files
committed
Added certificate flash support for plugins
1 parent 37cd1e7 commit 8f5a4d7

File tree

2 files changed

+111
-4
lines changed

2 files changed

+111
-4
lines changed

cli/certificates/flash.go

+73-4
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ package certificates
2020

2121
import (
2222
"bytes"
23+
"crypto/x509"
2324
"fmt"
2425
"io"
2526
"os"
2627
"strings"
2728
"time"
2829

30+
"github.com/arduino/arduino-fwuploader/certificates"
2931
"github.com/arduino/arduino-fwuploader/cli/arguments"
3032
"github.com/arduino/arduino-fwuploader/cli/common"
3133
"github.com/arduino/arduino-fwuploader/cli/feedback"
@@ -80,19 +82,86 @@ func runFlash(certificateURLs, certificatePaths []string) {
8082
uploadToolDir := common.DownloadRequiredToolsForBoard(packageIndex, board)
8183

8284
var res *flasher.FlashResult
83-
var err error
85+
var flashErr error
8486
if !board.IsPlugin() {
85-
res, err = flashCertificates(board, uploadToolDir, certificateURLs, certificatePaths)
87+
res, flashErr = flashCertificates(board, uploadToolDir, certificateURLs, certificatePaths)
8688
} else {
87-
// TODO
89+
uploader, err := plugin.NewFWUploaderPlugin(uploadToolDir)
90+
if err != nil {
91+
feedback.Fatal(fmt.Sprintf("Could not open uploader plugin: %s", err), feedback.ErrGeneric)
92+
}
93+
res, flashErr = flashCertificatesWithPlugin(uploader, certificateURLs, certificatePaths)
8894
}
8995

9096
feedback.PrintResult(res)
91-
if err != nil {
97+
if flashErr != nil {
9298
os.Exit(int(feedback.ErrGeneric))
9399
}
94100
}
95101

102+
func flashCertificatesWithPlugin(uploader *plugin.FwUploader, certificateURLs, certificatePaths []string) (*flasher.FlashResult, error) {
103+
tmp, err := paths.MkTempDir("", "")
104+
if err != nil {
105+
return nil, err
106+
}
107+
defer tmp.RemoveAll()
108+
certsBundle := tmp.Join("certs.pem")
109+
110+
stdoutBuffer := &bytes.Buffer{}
111+
stderrBuffer := &bytes.Buffer{}
112+
var stdout io.Writer = stdoutBuffer
113+
var stderr io.Writer = stdoutBuffer
114+
if feedback.GetFormat() == feedback.Text {
115+
stdout = io.MultiWriter(os.Stdout, stdoutBuffer)
116+
stderr = io.MultiWriter(os.Stderr, stderrBuffer)
117+
}
118+
119+
var allCerts []*x509.Certificate
120+
for _, certPath := range certificatePaths {
121+
logrus.Infof("Converting and flashing certificate %s", certPath)
122+
stdout.Write([]byte(fmt.Sprintf("Converting and flashing certificate %s\n", certPath)))
123+
124+
certs, err := certificates.LoadCertificatesFromFile(paths.New(certPath))
125+
if err != nil {
126+
return nil, err
127+
}
128+
allCerts = append(allCerts, certs...)
129+
}
130+
131+
for _, URL := range certificateURLs {
132+
logrus.Infof("Converting and flashing certificate from %s", URL)
133+
stdout.Write([]byte(fmt.Sprintf("Converting and flashing certificate from %s\n", URL)))
134+
rootCert, err := certificates.ScrapeRootCertificatesFromURL(URL)
135+
if err != nil {
136+
return nil, err
137+
}
138+
allCerts = append(allCerts, rootCert)
139+
}
140+
141+
f, err := certsBundle.Create()
142+
if err != nil {
143+
return nil, err
144+
}
145+
defer f.Close() // Defer close if an error occurs while writing file
146+
for _, cert := range allCerts {
147+
_, err := f.Write(certificates.EncodeCertificateAsPEM(cert))
148+
if err != nil {
149+
return nil, err
150+
}
151+
}
152+
if err := f.Close(); err != nil {
153+
return nil, err
154+
}
155+
156+
_, err = uploader.FlashCertificates(commonFlags.Address, commonFlags.Fqbn, certsBundle, stdout, stderr)
157+
return &flasher.FlashResult{
158+
Flasher: &flasher.ExecOutput{
159+
Stdout: stdoutBuffer.String(),
160+
Stderr: stderrBuffer.String(),
161+
},
162+
}, err
163+
}
164+
96165
func flashCertificates(board *firmwareindex.IndexBoard, uploadToolDir *paths.Path, certificateURLs, certificatePaths []string) (*flasher.FlashResult, error) {
97166
loaderSketchPath, err := download.DownloadSketch(board.LoaderSketch)
98167
if err != nil {

plugin/plugin.go

+38
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,41 @@ func (uploader *FwUploader) exec(stdout, stderr io.Writer, args ...string) (*byt
190190
execErr := proc.RunWithinContext(context.Background())
191191
return stdoutBuffer, stderrBuffer, execErr
192192
}
193+
194+
// FlashCertificates writes the given certificates bundle in PEM format.
195+
func (uploader *FwUploader) FlashCertificates(portAddress, fqbn string, certsPath *paths.Path, stdout, stderr io.Writer) (*FlashCertificatesResult, error) {
196+
args := []string{"cert", "flash", certsPath.String()}
197+
if portAddress != "" {
198+
args = append(args, "-p", portAddress)
199+
}
200+
if fqbn != "" {
201+
args = append(args, "-b", fqbn)
202+
}
203+
execStdout, execStderr, execErr := uploader.exec(stdout, stderr, args...)
204+
205+
res := &FlashCertificatesResult{
206+
Stdout: execStdout.Bytes(),
207+
Stderr: execStderr.Bytes(),
208+
}
209+
fwErrorPrefix := "FLASH-CERTIFICATES-ERROR: "
210+
for _, line := range strings.Split(execStdout.String(), "\n") {
211+
if strings.HasPrefix(line, fwErrorPrefix) {
212+
res.Error = strings.TrimPrefix(line, fwErrorPrefix)
213+
}
214+
}
215+
if res.Error != "" {
216+
if execErr != nil {
217+
execErr = fmt.Errorf("%s: %w", res.Error, execErr)
218+
} else {
219+
execErr = errors.New(res.Error)
220+
}
221+
}
222+
return res, execErr
223+
}
224+
225+
// FlashCertificatesResult contains the result of GetFirmwareVersion command
226+
type FlashCertificatesResult struct {
227+
Error string
228+
Stdout []byte
229+
Stderr []byte
230+
}

0 commit comments

Comments
 (0)