Skip to content

Commit

Permalink
add gpg command (#216)
Browse files Browse the repository at this point in the history
* add import gpg command

Co-authored-by: Cedric Bosdonnat <[email protected]>

* import-minimal gpg key

* restart uyuni-update-config to update gpg key

* add localization

---------

Co-authored-by: Cedric Bosdonnat <[email protected]>
  • Loading branch information
mbussolotto and cbosdo authored Apr 17, 2024
1 parent c4b7142 commit ddc64bf
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
2 changes: 2 additions & 0 deletions mgradm/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/uyuni-project/uyuni-tools/shared/utils"

"github.com/uyuni-project/uyuni-tools/mgradm/cmd/distro"
"github.com/uyuni-project/uyuni-tools/mgradm/cmd/gpg"
"github.com/uyuni-project/uyuni-tools/mgradm/cmd/hub"
"github.com/uyuni-project/uyuni-tools/mgradm/cmd/inspect"
"github.com/uyuni-project/uyuni-tools/mgradm/cmd/install"
Expand Down Expand Up @@ -78,6 +79,7 @@ func NewUyuniadmCommand() (*cobra.Command, error) {
rootCmd.AddCommand(status.NewCommand(globalFlags))
rootCmd.AddCommand(inspect.NewCommand(globalFlags))
rootCmd.AddCommand(upgrade.NewCommand(globalFlags))
rootCmd.AddCommand(gpg.NewCommand(globalFlags))

rootCmd.AddCommand(utils.GetConfigHelpCommand())

Expand Down
119 changes: 119 additions & 0 deletions mgradm/cmd/gpg/add/gpg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: 2024 SUSE LLC
//
// SPDX-License-Identifier: Apache-2.0

package gpgadd

import (
"fmt"
"net/url"
"os"
"path"
"path/filepath"
"strings"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
adm_utils "github.com/uyuni-project/uyuni-tools/mgradm/shared/utils"
"github.com/uyuni-project/uyuni-tools/shared"
"github.com/uyuni-project/uyuni-tools/shared/kubernetes"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
"github.com/uyuni-project/uyuni-tools/shared/podman"
"github.com/uyuni-project/uyuni-tools/shared/types"
"github.com/uyuni-project/uyuni-tools/shared/utils"
)

const customKeyringPath = "/var/spacewalk/gpg/customer-build-keys.gpg"

type gpgAddFlags struct {
Backend string
Force bool
}

// NewCommand import gpg keys from 3rd party repository.
func NewCommand(globalFlags *types.GlobalFlags) *cobra.Command {
gpgAddKeyCmd := &cobra.Command{
Use: "add",
Short: "Add gpg keys for 3rd party repositories",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var flags gpgAddFlags
return utils.CommandHelper(globalFlags, cmd, args, &flags, gpgAddKeys)
},
}

gpgAddKeyCmd.Flags().BoolP("force", "f", false, "Run the import")
utils.AddBackendFlag(gpgAddKeyCmd)
return gpgAddKeyCmd
}

func gpgAddKeys(globalFlags *types.GlobalFlags, flags *gpgAddFlags, cmd *cobra.Command, args []string) error {
cnx := shared.NewConnection(flags.Backend, podman.ServerContainerName, kubernetes.ServerFilter)
if !utils.FileExists(customKeyringPath) {
if err := adm_utils.ExecCommand(zerolog.InfoLevel, cnx, "mkdir", "-m", "700", "-p", filepath.Dir(customKeyringPath)); err != nil {
return fmt.Errorf(L("failed to create folder %s: %s"), filepath.Dir(customKeyringPath), err)
}
if err := adm_utils.ExecCommand(zerolog.InfoLevel, cnx, "gpg", "--no-default-keyring", "--keyring", customKeyringPath, "--fingerprint"); err != nil {
return fmt.Errorf(L("failed to create keyring %s: %s"), customKeyringPath, err)
}
}
gpgAddCmd := []string{"gpg", "--no-default-keyring", "--import", "--import-options", "import-minimal"}

if !flags.Force {
gpgAddCmd = append(gpgAddCmd, "--dry-run")
}
gpgAddCmd = append(gpgAddCmd, "--keyring", customKeyringPath)

scriptDir, err := os.MkdirTemp("", "mgradm-*")
defer os.RemoveAll(scriptDir)
if err != nil {
return fmt.Errorf(L("failed to create temporary directory %s"), err)
}

for _, keyURL := range args {
// Parse the URL
parsedURL, err := url.Parse(keyURL)
if err != nil {
log.Error().Err(err).Msgf(L("failed to parse %s"), keyURL)
continue
}

keyname := path.Base(parsedURL.Path)
hostKeyPath := filepath.Join(scriptDir, keyname)
if err := utils.DownloadFile(hostKeyPath, keyURL); err != nil {
log.Error().Err(err).Msgf(L("failed to download %s"), keyURL)
continue
}

if err := utils.RunCmdStdMapping(zerolog.InfoLevel, "gpg", "--show-key", hostKeyPath); err != nil {
log.Error().Err(err).Msgf(L("failed to show key %s"), hostKeyPath)
continue
}

containerKeyPath := filepath.Join(filepath.Dir(customKeyringPath), keyname)

if err := cnx.Copy(hostKeyPath, "server:"+containerKeyPath, "", ""); err != nil {
log.Error().Err(err).Msgf(L("failed to cp %s to %s"), hostKeyPath, containerKeyPath)
continue
}
defer func() {
_ = adm_utils.ExecCommand(zerolog.Disabled, cnx, "rm", containerKeyPath)
}()

gpgAddCmd = append(gpgAddCmd, containerKeyPath)
}

log.Info().Msgf("Running: %s", strings.Join(gpgAddCmd, " "))
if err := adm_utils.ExecCommand(zerolog.InfoLevel, cnx, gpgAddCmd...); err != nil {
return fmt.Errorf(L("failed to run import key: %s"), err)
}

//this is for running import-suma-build-keys, who import customer-build-keys.gpg
uyuniUpdateCmd := []string{"systemctl", "restart", "uyuni-update-config"}
log.Info().Msgf("Running: %s", strings.Join(uyuniUpdateCmd, " "))
if err := adm_utils.ExecCommand(zerolog.InfoLevel, cnx, uyuniUpdateCmd...); err != nil {
return fmt.Errorf(L("failed to restart uyuni-update-config: %s"), err)
}
return err
}
24 changes: 24 additions & 0 deletions mgradm/cmd/gpg/gpg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: 2024 SUSE LLC
//
// SPDX-License-Identifier: Apache-2.0

package gpg

import (
"github.com/spf13/cobra"
gpgadd "github.com/uyuni-project/uyuni-tools/mgradm/cmd/gpg/add"
"github.com/uyuni-project/uyuni-tools/shared/types"
)

// NewCommand import gpg keys from 3rd party repository.
func NewCommand(globalFlags *types.GlobalFlags) *cobra.Command {
gpgKeyCmd := &cobra.Command{
Use: "gpg",
Short: "Manage gpg keys for 3rd party repositories",
Args: cobra.ExactArgs(1),
}

gpgKeyCmd.AddCommand(gpgadd.NewCommand(globalFlags))

return gpgKeyCmd
}
45 changes: 45 additions & 0 deletions shared/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ package utils

import (
"bufio"
"bytes"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"net/http"
"os"
"regexp"
"strings"
Expand Down Expand Up @@ -166,3 +169,45 @@ func GetRandomBase64(size int) string {
}
return base64.StdEncoding.EncodeToString(data)
}

// GetURLBody provide the body content of an GET HTTP request.
func GetURLBody(URL string) ([]byte, error) {
// Download the key from the URL
log.Debug().Msgf("Downloading %s", URL)
resp, err := http.Get(URL)
if err != nil {
return nil, fmt.Errorf(L("error downloading from %s: %s"), URL, err)
}
defer resp.Body.Close()

// Check server response
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf(L("bad status: %s"), resp.Status)
}

var buf bytes.Buffer

if _, err = io.Copy(&buf, resp.Body); err != nil {
return nil, err
}

// Extract the byte slice from the buffer
data := buf.Bytes()
return data, nil
}

// DownloadFile downloads from a remote path to a local file.
func DownloadFile(filepath string, URL string) (err error) {
data, err := GetURLBody(URL)
if err != nil {
return err
}

// Writer the body to file
log.Debug().Msgf("Saving %s to %s", URL, filepath)
if err := os.WriteFile(filepath, data, 0644); err != nil {
return err
}

return nil
}
1 change: 1 addition & 0 deletions uyuni-tools.changes.mbussolotto.gpg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- add gpg command to mgradm

0 comments on commit ddc64bf

Please sign in to comment.