Skip to content
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

Add upload certificate command to adam #927

Merged
merged 4 commits into from
Mar 5, 2024
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
26 changes: 26 additions & 0 deletions cmd/adam.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"os"

"github.com/lf-edge/eden/pkg/defaults"
"github.com/lf-edge/eden/pkg/eden"
Expand All @@ -24,6 +25,7 @@ func newAdamCmd(configName, verbosity *string) *cobra.Command {
newStartAdamCmd(cfg),
newStopAdamCmd(),
newStatusAdamCmd(),
newChangeCertCmd(),
},
},
}
Expand Down Expand Up @@ -91,3 +93,27 @@ func newStatusAdamCmd() *cobra.Command {

return statusAdamCmd
}

func newChangeCertCmd() *cobra.Command {
var certFile string

var changeCertCmd = &cobra.Command{
Use: "change-signing-cert",
Short: "change signing certificate for adam",
Long: `Set Adam's signing certificate from a file.`,
Run: func(cmd *cobra.Command, args []string) {
certData, err := os.ReadFile(certFile)
if err != nil {
log.Fatalf("Failed to read certificate file: %s", err)
}

if err := openEVEC.ChangeSigningCert(certData); err != nil {
log.Fatalf("Failed to upload certificate to adam: %s", err)
}
},
}

changeCertCmd.Flags().StringVarP(&certFile, "cert-file", "", "", "path to the signing certificate file")

return changeCertCmd
}
27 changes: 27 additions & 0 deletions cmd/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/lf-edge/eden/pkg/defaults"
"github.com/lf-edge/eden/pkg/eden"
"github.com/lf-edge/eden/pkg/openevec"
"github.com/lf-edge/eden/pkg/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -47,3 +48,29 @@ func newCertsCmd(cfg *openevec.EdenSetupArgs) *cobra.Command {

return certsCmd
}

func newGenSigningCertCmd() *cobra.Command {
var certPath string

var certsCmd = &cobra.Command{
Use: "gen-signing-cert",
Short: "generate new signing certificate for controller",
Long: `Generate a new signing certificate for the controller using the same signing key`,
Run: func(cmd *cobra.Command, args []string) {
if err := utils.GenServerCertFromPrevCertAndKey(certPath); err != nil {
log.Errorf("cannot generate signing cert: %s", err)
} else {
log.Info("GenServerCertEllipticFromPrevCertAndKey done")
}
},
}

edenHome, err := utils.DefaultEdenDir()
if err != nil {
log.Fatal(err)
}

certsCmd.Flags().StringVarP(&certPath, "out", "o", filepath.Join(edenHome, defaults.DefaultCertsDist, "signing-new.pem"), "certificate output path")

return certsCmd
}
1 change: 1 addition & 0 deletions cmd/edenUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func newUtilsCmd(configName, verbosity *string) *cobra.Command {
newDownloaderCmd(cfg),
newOciImageCmd(),
newCertsCmd(cfg),
newGenSigningCertCmd(),
newGcpCmd(cfg),
newSdInfoEveCmd(),
newDebugCmd(cfg),
Expand Down
61 changes: 53 additions & 8 deletions pkg/controller/adam/adam.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ import (
"github.com/lf-edge/eden/pkg/defaults"
"github.com/lf-edge/eden/pkg/device"
"github.com/lf-edge/eden/pkg/utils"
"github.com/lf-edge/eve-api/go/auth"
"github.com/lf-edge/eve-api/go/certs"
uuid "github.com/satori/go.uuid"
log "github.com/sirupsen/logrus"
"google.golang.org/protobuf/proto"
)

const (
Expand All @@ -39,11 +42,11 @@ type Ctx struct {
serverCA string
insecureTLS bool
AdamRemote bool
AdamRemoteRedis bool //use redis for obtain logs and info
AdamRedisURLEden string //string with redis url for obtain logs and info
AdamCaching bool //enable caching of adam`s logs/info
AdamCachingRedis bool //caching to redis instead of files
AdamCachingPrefix string //custom prefix for file or stream naming for cache
AdamRemoteRedis bool // use redis for obtain logs and info
AdamRedisURLEden string // string with redis url for obtain logs and info
AdamCaching bool // enable caching of adam`s logs/info
AdamCachingRedis bool // caching to redis instead of files
AdamCachingPrefix string // custom prefix for file or stream naming for cache
}

// parseRedisURL try to use string from config to obtain redis url
Expand Down Expand Up @@ -196,9 +199,26 @@ func (adam *Ctx) ConfigGet(devUUID uuid.UUID) (out string, err error) {
return adam.getObj(path.Join("/admin/device", devUUID.String(), "config"), mimeProto)
}

// CertsGet get attest certs for devID
func (adam *Ctx) CertsGet(devUUID uuid.UUID) (out string, err error) {
return adam.getObj(path.Join("/admin/device", devUUID.String(), "certs"), mimeJSON)
// GetECDHCert get cert for ECDH exchange for devID
func (adam *Ctx) GetECDHCert(devUUID uuid.UUID) ([]byte, error) {
europaul marked this conversation as resolved.
Show resolved Hide resolved
attestData, err := adam.getObj(path.Join("/admin/device", devUUID.String(), "certs"), mimeJSON)
if err != nil {
return nil, fmt.Errorf("cannot get attestation certificates from cloud for %s", devUUID)
}
req := &types.Zcerts{}
if err := json.Unmarshal([]byte(attestData), req); err != nil {
return nil, fmt.Errorf("cannot unmarshal attest: %w", err)
}
var devCert []byte
for _, c := range req.Certs {
if c.Type == certs.ZCertType_CERT_TYPE_DEVICE_ECDH_EXCHANGE {
devCert = c.Cert
}
}
if len(devCert) == 0 {
return nil, fmt.Errorf("no DEVICE_ECDH_EXCHANGE certificate")
}
return devCert, nil
}

// RequestLastCallback check request by pattern from existence files with callback
Expand Down Expand Up @@ -405,3 +425,28 @@ func (adam *Ctx) GetGlobalOptions() (*types.GlobalOptions, error) {
}
return &globalOptions, nil
}

// SigningCertGet gets signing certificate from Adam
func (adam *Ctx) SigningCertGet() (signCert []byte, err error) {
certsData, err := adam.getObj("/api/v2/edgedevice/certs", mimeProto)
if err != nil {
return nil, err
}
zcloudMsg := &auth.AuthContainer{}
err = proto.Unmarshal([]byte(certsData), zcloudMsg)
if err != nil {
return nil, err
}
ctrlCert := &certs.ZControllerCert{}
err = proto.Unmarshal(zcloudMsg.ProtectedPayload.Payload, ctrlCert)
if err != nil {
return nil, err
}
for _, c := range ctrlCert.Certs {
// there should be only one signing certificate, so we return the first one we find
if c.Type == certs.ZCertType_CERT_TYPE_CONTROLLER_SIGNING {
return c.Cert, nil
}
}
return nil, fmt.Errorf("no signing certificate found")
}
9 changes: 5 additions & 4 deletions pkg/controller/application.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package controller

Check failure on line 1 in pkg/controller/application.go

View workflow job for this annotation

GitHub Actions / yetus

golangcilint: 1-47 lines are duplicate of `pkg/controller/networkInstance.go:1-47` (dupl)

import (
"fmt"

"github.com/lf-edge/eden/pkg/utils"
"github.com/lf-edge/eve-api/go/config"
)
Expand All @@ -15,7 +16,7 @@
return -1, fmt.Errorf("not found applicationInstance with ID: %s", id)
}

//GetApplicationInstanceConfig return AppInstanceConfig config from cloud by ID
// GetApplicationInstanceConfig return AppInstanceConfig config from cloud by ID
func (cloud *CloudCtx) GetApplicationInstanceConfig(id string) (applicationInstanceConfig *config.AppInstanceConfig, err error) {
applicationInstanceConfigInd, err := cloud.getApplicationInstanceInd(id)
if err != nil {
Expand All @@ -24,13 +25,13 @@
return cloud.applicationInstances[applicationInstanceConfigInd], nil
}

//AddApplicationInstanceConfig add AppInstanceConfig config to cloud
// AddApplicationInstanceConfig add AppInstanceConfig config to cloud
func (cloud *CloudCtx) AddApplicationInstanceConfig(applicationInstanceConfig *config.AppInstanceConfig) error {
cloud.applicationInstances = append(cloud.applicationInstances, applicationInstanceConfig)
return nil
}

//RemoveApplicationInstanceConfig remove AppInstanceConfig config to cloud
// RemoveApplicationInstanceConfig remove AppInstanceConfig config to cloud
func (cloud *CloudCtx) RemoveApplicationInstanceConfig(id string) error {
applicationInstanceConfigInd, err := cloud.getApplicationInstanceInd(id)
if err != nil {
Expand All @@ -40,7 +41,7 @@
return nil
}

//ListApplicationInstanceConfig return ApplicationInstance configs from cloud
// ListApplicationInstanceConfig return ApplicationInstance configs from cloud
func (cloud *CloudCtx) ListApplicationInstanceConfig() []*config.AppInstanceConfig {
return cloud.applicationInstances
}
5 changes: 3 additions & 2 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import (
uuid "github.com/satori/go.uuid"
)

//Controller is an interface of controller
// Controller is an interface of controller
type Controller interface {
CertsGet(devUUID uuid.UUID) (out string, err error)
GetECDHCert(devUUID uuid.UUID) ([]byte, error)
SigningCertGet() (signCert []byte, err error)
ConfigGet(devUUID uuid.UUID) (out string, err error)
ConfigSet(devUUID uuid.UUID, devConfig []byte) (err error)
LogAppsChecker(devUUID uuid.UUID, appUUID uuid.UUID, q map[string]string, handler eapps.HandlerFunc, mode eapps.LogCheckerMode, timeout time.Duration) (err error)
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ func (cloud *CloudCtx) OnBoardDev(node *device.Ctx) error {
if err = cloud.ConfigSync(node); err != nil {
log.Fatal(err)
}
//wait for certs
if _, err = cloud.CertsGet(node.GetID()); err != nil {
// wait for certs
if _, err = cloud.GetECDHCert(node.GetID()); err != nil {
log.Fatal(err)
}
}
Expand Down
79 changes: 34 additions & 45 deletions pkg/eden/eden.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,53 +130,20 @@ func StartAdam(adamPort int, adamPath string, adamForce bool, adamTag string, ad
return err
}
globalCertsDir := filepath.Join(edenHome, defaults.DefaultCertsDist)
serverCertPath := filepath.Join(globalCertsDir, "server.pem")
serverKeyPath := filepath.Join(globalCertsDir, "server-key.pem")
cert, err := os.ReadFile(serverCertPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", serverCertPath, err)
}
key, err := os.ReadFile(serverKeyPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", serverKeyPath, err)
}
envs := []string{
fmt.Sprintf("SERVER_CERT=%s", cert),
fmt.Sprintf("SERVER_KEY=%s", key),
}
if !apiV1 {
signingCertPath := filepath.Join(globalCertsDir, "signing.pem")
signingKeyPath := filepath.Join(globalCertsDir, "signing-key.pem")
signingCert, err := os.ReadFile(signingCertPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", signingCertPath, err)
}
signingKey, err := os.ReadFile(signingKeyPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", signingKeyPath, err)
}
envs = append(envs, fmt.Sprintf("SIGNING_CERT=%s", signingCert))
envs = append(envs, fmt.Sprintf("SIGNING_KEY=%s", signingKey))

encryptCertPath := filepath.Join(globalCertsDir, "encrypt.pem")
encryptKeyPath := filepath.Join(globalCertsDir, "encrypt-key.pem")
encryptCert, err := os.ReadFile(encryptCertPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", encryptCertPath, err)
}
encryptKey, err := os.ReadFile(encryptKeyPath)
if err != nil {
return fmt.Errorf("StartAdam: cannot load %s: %s", encryptKeyPath, err)
}
envs = append(envs, fmt.Sprintf("ENCRYPT_CERT=%s", encryptCert))
envs = append(envs, fmt.Sprintf("ENCRYPT_KEY=%s", encryptKey))
}
portMap := map[string]string{"8080": strconv.Itoa(adamPort)}
volumeMap := map[string]string{"/adam/run": fmt.Sprintf("%s/run", adamPath)}
adamServerCommand := strings.Fields("server --conf-dir ./run/conf")
volumeMap := map[string]string{
globalCertsDir: globalCertsDir,
}

var adamServerCommand []string

if adamPath == "" {
volumeMap = map[string]string{"/adam/run": ""}
volumeMap["/adam/run"] = ""
adamServerCommand = strings.Fields("server")
} else {
volumeMap["/adam/run"] = fmt.Sprintf("%s/run", adamPath)
adamServerCommand = strings.Fields("server --conf-dir ./run/conf")
}
if adamRemoteRedisURL != "" {
redisPasswordFile := filepath.Join(globalCertsDir, defaults.DefaultRedisPasswordFile)
Expand All @@ -189,10 +156,32 @@ func StartAdam(adamPort int, adamPath string, adamForce bool, adamTag string, ad
}
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--db-url %s", adamRemoteRedisURL))...)
}

serverCertPath := filepath.Join(globalCertsDir, "server.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--server-cert %s", serverCertPath))...)

serverKeyPath := filepath.Join(globalCertsDir, "server-key.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--server-key %s", serverKeyPath))...)

if !apiV1 {
signingCertPath := filepath.Join(globalCertsDir, "signing.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--signing-cert %s", signingCertPath))...)

signingKeyPath := filepath.Join(globalCertsDir, "signing-key.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--signing-key %s", signingKeyPath))...)

encryptCertPath := filepath.Join(globalCertsDir, "encrypt.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--encrypt-cert %s", encryptCertPath))...)

encryptKeyPath := filepath.Join(globalCertsDir, "encrypt-key.pem")
adamServerCommand = append(adamServerCommand, strings.Fields(fmt.Sprintf("--encrypt-key %s", encryptKeyPath))...)
}

adamServerCommand = append(adamServerCommand, opts...)

if adamForce {
_ = utils.StopContainer(defaults.DefaultAdamContainerName, true)
if err := utils.CreateAndRunContainer(defaults.DefaultAdamContainerName, defaults.DefaultAdamContainerRef+":"+adamTag, portMap, volumeMap, adamServerCommand, envs); err != nil {
if err := utils.CreateAndRunContainer(defaults.DefaultAdamContainerName, defaults.DefaultAdamContainerRef+":"+adamTag, portMap, volumeMap, adamServerCommand, nil); err != nil {
return fmt.Errorf("StartAdam: error in create adam container: %s", err)
}
} else {
Expand All @@ -201,7 +190,7 @@ func StartAdam(adamPort int, adamPath string, adamForce bool, adamTag string, ad
return fmt.Errorf("StartAdam: error in get state of adam container: %s", err)
}
if state == "" {
if err := utils.CreateAndRunContainer(defaults.DefaultAdamContainerName, defaults.DefaultAdamContainerRef+":"+adamTag, portMap, volumeMap, adamServerCommand, envs); err != nil {
if err := utils.CreateAndRunContainer(defaults.DefaultAdamContainerName, defaults.DefaultAdamContainerRef+":"+adamTag, portMap, volumeMap, adamServerCommand, nil); err != nil {
return fmt.Errorf("StartAdam: error in create adam container: %s", err)
}
} else if !strings.Contains(state, "running") {
Expand Down
Loading
Loading