Skip to content

Cleanup directories handling #765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 87 additions & 46 deletions certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
"math/big"
"net"
"os"
"strings"
"text/template"
"time"

"github.com/arduino/go-paths-helper"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -133,12 +133,38 @@ func generateSingleCertificate(isCa bool) (*x509.Certificate, error) {
return &template, nil
}

func generateCertificates() {
// migrateCertificatesGeneratedWithOldAgentVersions checks if certificates generated
// with an old version of the Agent needs to be migrated to the current certificates
// directory, and performs the migration if needed.
func migrateCertificatesGeneratedWithOldAgentVersions(certsDir *paths.Path) {
if certsDir.Join("ca.cert.pem").Exist() {
// The new certificates are already set-up, nothing to do
return
}

fileList := []string{
"ca.key.pem",
"ca.cert.pem",
"ca.cert.cer",
"key.pem",
"cert.pem",
"cert.cer",
}
oldCertsDirPath, _ := os.Executable()
oldCertsDir := paths.New(oldCertsDirPath)
for _, fileName := range fileList {
oldCert := oldCertsDir.Join(fileName)
if oldCert.Exist() {
oldCert.CopyTo(certsDir.Join(fileName))
}
}
}

os.Remove("ca.cert.pem")
os.Remove("ca.key.pem")
os.Remove("cert.pem")
os.Remove("key.pem")
func generateCertificates(certsDir *paths.Path) {
certsDir.Join("ca.cert.pem").Remove()
certsDir.Join("ca.key.pem").Remove()
certsDir.Join("cert.pem").Remove()
certsDir.Join("key.pem").Remove()

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

keyOut, err := os.OpenFile("ca.key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Error(err.Error())
os.Exit(1)
{
keyOutPath := certsDir.Join("ca.key.pem").String()
keyOut, err := os.OpenFile(keyOutPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) // Save key with user-only permission 0600
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
pem.Encode(keyOut, pemBlockForKey(caKey))
keyOut.Close()
log.Printf("written %s", keyOutPath)
}
pem.Encode(keyOut, pemBlockForKey(caKey))
keyOut.Close()
log.Println("written ca.key.pem")

// Create the certification authority
caTemplate, err := generateSingleCertificate(true)

if err != nil {
log.Error(err.Error())
os.Exit(1)
}

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

certOut, err := os.Create("ca.cert.pem")
if err != nil {
log.Error(err.Error())
os.Exit(1)
{
caCertOutPath := certsDir.Join("ca.cert.pem")
caCertOut, err := caCertOutPath.Create()
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
pem.Encode(caCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
caCertOut.Close()
log.Printf("written %s", caCertOutPath)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Print("written ca.cert.pem")

ioutil.WriteFile("ca.cert.cer", derBytes, 0644)
log.Print("written ca.cert.cer")
{
caCertPath := certsDir.Join("ca.cert.cer")
caCertPath.WriteFile(derBytes)
log.Printf("written %s", caCertPath)
}

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

keyOut, err = os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Error(err.Error())
os.Exit(1)
{
keyOutPath := certsDir.Join("key.pem").String()
keyOut, err := os.OpenFile(keyOutPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) // Save key with user-only permission 0600
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
pem.Encode(keyOut, pemBlockForKey(key))
keyOut.Close()
log.Printf("written %s", keyOutPath)
}
pem.Encode(keyOut, pemBlockForKey(key))
keyOut.Close()
log.Println("written key.pem")

// Create the final certificate
template, err := generateSingleCertificate(false)

if err != nil {
log.Error(err.Error())
os.Exit(1)
}

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

certOut, err = os.Create("cert.pem")
if err != nil {
log.Error(err.Error())
os.Exit(1)
{
certOutPath := certsDir.Join("cert.pem").String()
certOut, err := os.Create(certOutPath)
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Printf("written %s", certOutPath)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Print("written cert.pem")

ioutil.WriteFile("cert.cer", derBytes, 0644)
log.Print("written cert.cer")

{
certPath := certsDir.Join("cert.cer")
certPath.WriteFile(derBytes)
log.Printf("written %s", certPath)
}
}

func certHandler(c *gin.Context) {
Expand All @@ -230,14 +271,14 @@ func certHandler(c *gin.Context) {
}

func deleteCertHandler(c *gin.Context) {
DeleteCertificates()
DeleteCertificates(getCertificatesDir())
}

// DeleteCertificates will delete the certificates
func DeleteCertificates() {
os.Remove("ca.cert.pem")
os.Remove("ca.cert.cer")
os.Remove("ca.key.pem")
func DeleteCertificates(certDir *paths.Path) {
certDir.Join("ca.cert.pem").Remove()
certDir.Join("ca.cert.cer").Remove()
certDir.Join("ca.key.pem").Remove()
}

const noFirefoxTemplateHTML = `<!DOCTYPE html>
Expand Down
38 changes: 32 additions & 6 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,41 @@ package main

import (
_ "embed"
"fmt"
"os"

"github.com/arduino/go-paths-helper"
log "github.com/sirupsen/logrus"
)

// getDefaultArduinoCreateConfigDir returns the full path to the default arduino create agent data directory
func getDefaultArduinoCreateConfigDir() (*paths.Path, error) {
// getCertificatesDir return the directory where SSL certificates are saved
func getCertificatesDir() *paths.Path {
return getDataDir()
}

// getDataDir returns the full path to the default Arduino Create Agent data directory.
func getDataDir() *paths.Path {
userDir, err := os.UserHomeDir()
if err != nil {
log.Panicf("Could not get user dir: %s", err)
}
dataDir := paths.New(userDir, ".arduino-create")
if err := dataDir.MkdirAll(); err != nil {
log.Panicf("Could not create data dir: %s", err)
}
return dataDir
}

// getLogsDir return the directory where logs are saved
func getLogsDir() *paths.Path {
logsDir := getDataDir().Join("logs")
if err := logsDir.MkdirAll(); err != nil {
log.Panicf("Can't create logs dir: %s", err)
}
return logsDir
}

// getDefaultConfigDir returns the full path to the default Arduino Create Agent configuration directory.
func getDefaultConfigDir() *paths.Path {
// UserConfigDir returns the default root directory to use
// for user-specific configuration data. Users should create
// their own application-specific subdirectory within this
Expand All @@ -43,14 +69,14 @@ func getDefaultArduinoCreateConfigDir() (*paths.Path, error) {
// is not defined), then it will return an error.
configDir, err := os.UserConfigDir()
if err != nil {
return nil, err
log.Panicf("Can't get user home dir: %s", err)
}

agentConfigDir := paths.New(configDir, "ArduinoCreateAgent")
if err := agentConfigDir.MkdirAll(); err != nil {
return nil, fmt.Errorf("cannot create config dir: %s", err)
log.Panicf("Can't create config dir: %s", err)
}
return agentConfigDir, nil
return agentConfigDir
}

//go:embed config.ini
Expand Down
2 changes: 1 addition & 1 deletion hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func checkCmd(m []byte) {
} else if strings.HasPrefix(sl, "downloadtool") {
// Always delete root certificates when we receive a downloadtool command
// Useful if the install procedure was not followed strictly (eg. manually)
DeleteCertificates()
DeleteCertificates(getCertificatesDir())
go func() {
args := strings.Split(s, " ")
var tool, toolVersion, pack, behaviour string
Expand Down
Loading