Skip to content

Commit a3e7ecc

Browse files
cmaglieumbynos
andauthored
Cleanup directories handling (#765)
* Sligltly simplified getDefaultConfigDir * Some code make-up * Added method to directly get data-dir * Added method to directly get logs dir * Removed now useless local variable * certs are now created in `.arduino-create` folder * Better use of go-paths library * Perform certificates migration if needed --------- Co-authored-by: Umberto Baldi <[email protected]>
1 parent 8b9ab21 commit a3e7ecc

File tree

4 files changed

+142
-88
lines changed

4 files changed

+142
-88
lines changed

certificates.go

+87-46
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ import (
1616
"crypto/x509/pkix"
1717
"encoding/pem"
1818
"fmt"
19-
"io/ioutil"
2019
"math/big"
2120
"net"
2221
"os"
2322
"strings"
2423
"text/template"
2524
"time"
2625

26+
"github.com/arduino/go-paths-helper"
2727
"github.com/gin-gonic/gin"
2828
log "github.com/sirupsen/logrus"
2929
)
@@ -133,12 +133,38 @@ func generateSingleCertificate(isCa bool) (*x509.Certificate, error) {
133133
return &template, nil
134134
}
135135

136-
func generateCertificates() {
136+
// migrateCertificatesGeneratedWithOldAgentVersions checks if certificates generated
137+
// with an old version of the Agent needs to be migrated to the current certificates
138+
// directory, and performs the migration if needed.
139+
func migrateCertificatesGeneratedWithOldAgentVersions(certsDir *paths.Path) {
140+
if certsDir.Join("ca.cert.pem").Exist() {
141+
// The new certificates are already set-up, nothing to do
142+
return
143+
}
144+
145+
fileList := []string{
146+
"ca.key.pem",
147+
"ca.cert.pem",
148+
"ca.cert.cer",
149+
"key.pem",
150+
"cert.pem",
151+
"cert.cer",
152+
}
153+
oldCertsDirPath, _ := os.Executable()
154+
oldCertsDir := paths.New(oldCertsDirPath)
155+
for _, fileName := range fileList {
156+
oldCert := oldCertsDir.Join(fileName)
157+
if oldCert.Exist() {
158+
oldCert.CopyTo(certsDir.Join(fileName))
159+
}
160+
}
161+
}
137162

138-
os.Remove("ca.cert.pem")
139-
os.Remove("ca.key.pem")
140-
os.Remove("cert.pem")
141-
os.Remove("key.pem")
163+
func generateCertificates(certsDir *paths.Path) {
164+
certsDir.Join("ca.cert.pem").Remove()
165+
certsDir.Join("ca.key.pem").Remove()
166+
certsDir.Join("cert.pem").Remove()
167+
certsDir.Join("key.pem").Remove()
142168

143169
// Create the key for the certification authority
144170
caKey, err := generateKey("P256")
@@ -147,36 +173,44 @@ func generateCertificates() {
147173
os.Exit(1)
148174
}
149175

150-
keyOut, err := os.OpenFile("ca.key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
151-
if err != nil {
152-
log.Error(err.Error())
153-
os.Exit(1)
176+
{
177+
keyOutPath := certsDir.Join("ca.key.pem").String()
178+
keyOut, err := os.OpenFile(keyOutPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) // Save key with user-only permission 0600
179+
if err != nil {
180+
log.Error(err.Error())
181+
os.Exit(1)
182+
}
183+
pem.Encode(keyOut, pemBlockForKey(caKey))
184+
keyOut.Close()
185+
log.Printf("written %s", keyOutPath)
154186
}
155-
pem.Encode(keyOut, pemBlockForKey(caKey))
156-
keyOut.Close()
157-
log.Println("written ca.key.pem")
158187

159188
// Create the certification authority
160189
caTemplate, err := generateSingleCertificate(true)
161-
162190
if err != nil {
163191
log.Error(err.Error())
164192
os.Exit(1)
165193
}
166194

167195
derBytes, _ := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, publicKey(caKey), caKey)
168196

169-
certOut, err := os.Create("ca.cert.pem")
170-
if err != nil {
171-
log.Error(err.Error())
172-
os.Exit(1)
197+
{
198+
caCertOutPath := certsDir.Join("ca.cert.pem")
199+
caCertOut, err := caCertOutPath.Create()
200+
if err != nil {
201+
log.Error(err.Error())
202+
os.Exit(1)
203+
}
204+
pem.Encode(caCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
205+
caCertOut.Close()
206+
log.Printf("written %s", caCertOutPath)
173207
}
174-
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
175-
certOut.Close()
176-
log.Print("written ca.cert.pem")
177208

178-
ioutil.WriteFile("ca.cert.cer", derBytes, 0644)
179-
log.Print("written ca.cert.cer")
209+
{
210+
caCertPath := certsDir.Join("ca.cert.cer")
211+
caCertPath.WriteFile(derBytes)
212+
log.Printf("written %s", caCertPath)
213+
}
180214

181215
// Create the key for the final certificate
182216
key, err := generateKey("P256")
@@ -185,37 +219,44 @@ func generateCertificates() {
185219
os.Exit(1)
186220
}
187221

188-
keyOut, err = os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
189-
if err != nil {
190-
log.Error(err.Error())
191-
os.Exit(1)
222+
{
223+
keyOutPath := certsDir.Join("key.pem").String()
224+
keyOut, err := os.OpenFile(keyOutPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) // Save key with user-only permission 0600
225+
if err != nil {
226+
log.Error(err.Error())
227+
os.Exit(1)
228+
}
229+
pem.Encode(keyOut, pemBlockForKey(key))
230+
keyOut.Close()
231+
log.Printf("written %s", keyOutPath)
192232
}
193-
pem.Encode(keyOut, pemBlockForKey(key))
194-
keyOut.Close()
195-
log.Println("written key.pem")
196233

197234
// Create the final certificate
198235
template, err := generateSingleCertificate(false)
199-
200236
if err != nil {
201237
log.Error(err.Error())
202238
os.Exit(1)
203239
}
204240

205241
derBytes, _ = x509.CreateCertificate(rand.Reader, template, caTemplate, publicKey(key), caKey)
206242

207-
certOut, err = os.Create("cert.pem")
208-
if err != nil {
209-
log.Error(err.Error())
210-
os.Exit(1)
243+
{
244+
certOutPath := certsDir.Join("cert.pem").String()
245+
certOut, err := os.Create(certOutPath)
246+
if err != nil {
247+
log.Error(err.Error())
248+
os.Exit(1)
249+
}
250+
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
251+
certOut.Close()
252+
log.Printf("written %s", certOutPath)
211253
}
212-
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
213-
certOut.Close()
214-
log.Print("written cert.pem")
215-
216-
ioutil.WriteFile("cert.cer", derBytes, 0644)
217-
log.Print("written cert.cer")
218254

255+
{
256+
certPath := certsDir.Join("cert.cer")
257+
certPath.WriteFile(derBytes)
258+
log.Printf("written %s", certPath)
259+
}
219260
}
220261

221262
func certHandler(c *gin.Context) {
@@ -230,14 +271,14 @@ func certHandler(c *gin.Context) {
230271
}
231272

232273
func deleteCertHandler(c *gin.Context) {
233-
DeleteCertificates()
274+
DeleteCertificates(getCertificatesDir())
234275
}
235276

236277
// DeleteCertificates will delete the certificates
237-
func DeleteCertificates() {
238-
os.Remove("ca.cert.pem")
239-
os.Remove("ca.cert.cer")
240-
os.Remove("ca.key.pem")
278+
func DeleteCertificates(certDir *paths.Path) {
279+
certDir.Join("ca.cert.pem").Remove()
280+
certDir.Join("ca.cert.cer").Remove()
281+
certDir.Join("ca.key.pem").Remove()
241282
}
242283

243284
const noFirefoxTemplateHTML = `<!DOCTYPE html>

config.go

+32-6
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,41 @@ package main
1717

1818
import (
1919
_ "embed"
20-
"fmt"
2120
"os"
2221

2322
"github.com/arduino/go-paths-helper"
2423
log "github.com/sirupsen/logrus"
2524
)
2625

27-
// getDefaultArduinoCreateConfigDir returns the full path to the default arduino create agent data directory
28-
func getDefaultArduinoCreateConfigDir() (*paths.Path, error) {
26+
// getCertificatesDir return the directory where SSL certificates are saved
27+
func getCertificatesDir() *paths.Path {
28+
return getDataDir()
29+
}
30+
31+
// getDataDir returns the full path to the default Arduino Create Agent data directory.
32+
func getDataDir() *paths.Path {
33+
userDir, err := os.UserHomeDir()
34+
if err != nil {
35+
log.Panicf("Could not get user dir: %s", err)
36+
}
37+
dataDir := paths.New(userDir, ".arduino-create")
38+
if err := dataDir.MkdirAll(); err != nil {
39+
log.Panicf("Could not create data dir: %s", err)
40+
}
41+
return dataDir
42+
}
43+
44+
// getLogsDir return the directory where logs are saved
45+
func getLogsDir() *paths.Path {
46+
logsDir := getDataDir().Join("logs")
47+
if err := logsDir.MkdirAll(); err != nil {
48+
log.Panicf("Can't create logs dir: %s", err)
49+
}
50+
return logsDir
51+
}
52+
53+
// getDefaultConfigDir returns the full path to the default Arduino Create Agent configuration directory.
54+
func getDefaultConfigDir() *paths.Path {
2955
// UserConfigDir returns the default root directory to use
3056
// for user-specific configuration data. Users should create
3157
// their own application-specific subdirectory within this
@@ -43,14 +69,14 @@ func getDefaultArduinoCreateConfigDir() (*paths.Path, error) {
4369
// is not defined), then it will return an error.
4470
configDir, err := os.UserConfigDir()
4571
if err != nil {
46-
return nil, err
72+
log.Panicf("Can't get user home dir: %s", err)
4773
}
4874

4975
agentConfigDir := paths.New(configDir, "ArduinoCreateAgent")
5076
if err := agentConfigDir.MkdirAll(); err != nil {
51-
return nil, fmt.Errorf("cannot create config dir: %s", err)
77+
log.Panicf("Can't create config dir: %s", err)
5278
}
53-
return agentConfigDir, nil
79+
return agentConfigDir
5480
}
5581

5682
//go:embed config.ini

hub.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func checkCmd(m []byte) {
182182
} else if strings.HasPrefix(sl, "downloadtool") {
183183
// Always delete root certificates when we receive a downloadtool command
184184
// Useful if the install procedure was not followed strictly (eg. manually)
185-
DeleteCertificates()
185+
DeleteCertificates(getCertificatesDir())
186186
go func() {
187187
args := strings.Split(s, " ")
188188
var tool, toolVersion, pack, behaviour string

0 commit comments

Comments
 (0)