Skip to content

Commit

Permalink
Merge pull request #502 from uyuni-project/Uyuni-2024.10
Browse files Browse the repository at this point in the history
Uyuni 2024.10 patch
  • Loading branch information
deneb-alpha authored Nov 19, 2024
2 parents d5dbed5 + d9c0329 commit a39327f
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .tito/packages/uyuni-tools
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.1.1-0 ./
5.1.2-0 ./
2 changes: 2 additions & 0 deletions mgradm/cmd/install/podman/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ NOTE: installing on a remote podman is not supported yet!
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var flags podmanInstallFlags
flags.Coco.IsChanged = cmd.Flags().Changed("coco-replicas")
flags.HubXmlrpc.IsChanged = cmd.Flags().Changed("hubxmlrpc-replicas")
return utils.CommandHelper(globalFlags, cmd, args, &flags, installForPodman)
},
}
Expand Down
6 changes: 5 additions & 1 deletion mgradm/cmd/install/podman/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,13 @@ func installForPodman(
}

if flags.Coco.Replicas > 0 {
// This may need to be moved up later once more containers require DB access
if err := shared_podman.CreateDbSecrets(flags.Db.User, flags.Db.Password); err != nil {
return err
}
if err := coco.SetupCocoContainer(
authFile, flags.Image.Registry, flags.Coco, flags.Image,
flags.Db.Name, flags.Db.Port, flags.Db.User, flags.Db.Password,
flags.Db.Name, flags.Db.Port,
); err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions mgradm/cmd/uninstall/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func uninstallForPodman(

podman.DeleteNetwork(!flags.Force)

podman.DeleteSecret(podman.DbUserSecret, !flags.Force)
podman.DeleteSecret(podman.DbPassSecret, !flags.Force)

err := podman.ReloadDaemon(!flags.Force)

if !flags.Force {
Expand Down
17 changes: 7 additions & 10 deletions mgradm/shared/coco/coco.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ func Upgrade(
dbUser string,
dbPassword string,
) error {
if err := writeCocoServiceFiles(
authFile, registry, cocoFlags, baseImage, dbName, dbPort, dbUser, dbPassword,
); err != nil {
if err := podman.CreateDbSecrets(dbUser, dbPassword); err != nil {
return err
}

if err := writeCocoServiceFiles(authFile, registry, cocoFlags, baseImage, dbName, dbPort); err != nil {

Check failure on line 35 in mgradm/shared/coco/coco.go

View workflow job for this annotation

GitHub Actions / lint

not enough arguments in call to writeCocoServiceFiles
return err
}

Expand All @@ -48,8 +50,6 @@ func writeCocoServiceFiles(
baseImage types.ImageFlags,
dbName string,
dbPort int,
dbUser string,
dbPassword string,
) error {
image := cocoFlags.Image
currentReplicas := systemd.CurrentReplicaCount(podman.ServerAttestationService)
Expand Down Expand Up @@ -95,8 +95,7 @@ func writeCocoServiceFiles(

environment := fmt.Sprintf(`Environment=UYUNI_IMAGE=%s
Environment=database_connection=jdbc:postgresql://uyuni-server.mgr.internal:%d/%s
Environment=database_user=%s
Environment=database_password=%s`, preparedImage, dbPort, dbName, dbUser, dbPassword)
`, preparedImage, dbPort, dbName)

if err := podman.GenerateSystemdConfFile(
podman.ServerAttestationService+"@", "generated.conf", environment, true,
Expand All @@ -119,11 +118,9 @@ func SetupCocoContainer(
baseImage types.ImageFlags,
dbName string,
dbPort int,
dbUser string,
dbPassword string,
) error {
if err := writeCocoServiceFiles(
authFile, registry, coco, baseImage, dbName, dbPort, dbUser, dbPassword,
authFile, registry, coco, baseImage, dbName, dbPort,
); err != nil {

Check failure on line 124 in mgradm/shared/coco/coco.go

View workflow job for this annotation

GitHub Actions / lint

not enough arguments in call to writeCocoServiceFiles
return err
}
Expand Down
9 changes: 4 additions & 5 deletions mgradm/shared/podman/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package podman

import (
"errors"
"fmt"
"os/exec"
"path"
Expand Down Expand Up @@ -156,19 +155,19 @@ func UpdateSSLCertificate(cnx *shared.Connection, chain *types.CaChain, serverPa
}

// Check and install then using mgr-ssl-cert-setup
if _, err := utils.RunCmdOutput(zerolog.InfoLevel, "podman", args...); err != nil {
return errors.New(L("failed to update SSL certificate"))
if out, err := utils.RunCmdOutput(zerolog.DebugLevel, "podman", args...); err != nil {
return utils.Errorf(err, L("failed to update SSL certificate: %s"), out)
}

// Clean the copied files and the now useless ssl-build
if err := utils.RunCmd("podman", "exec", podman.ServerContainerName, "rm", "-rf", certDir); err != nil {
return errors.New(L("failed to remove copied certificate files in the container"))
return utils.Errorf(err, L("failed to remove copied certificate files in the container"))
}

const sslbuildPath = "/root/ssl-build"
if cnx.TestExistenceInPod(sslbuildPath) {
if err := utils.RunCmd("podman", "exec", podman.ServerContainerName, "rm", "-rf", sslbuildPath); err != nil {
return errors.New(L("failed to remove now useless ssl-build folder in the container"))
return utils.Errorf(err, L("failed to remove now useless ssl-build folder in the container"))
}
}

Expand Down
6 changes: 4 additions & 2 deletions mgradm/shared/templates/attestationServiceTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package templates
import (
"io"
"text/template"

"github.com/uyuni-project/uyuni-tools/shared/podman"

Check failure on line 11 in mgradm/shared/templates/attestationServiceTemplate.go

View workflow job for this annotation

GitHub Actions / lint

could not import github.com/uyuni-project/uyuni-tools/shared/podman (-: # github.com/uyuni-project/uyuni-tools/shared/podman
)

const attestationServiceTemplate = `
Expand All @@ -28,8 +30,8 @@ ExecStart=/bin/sh -c '/usr/bin/podman run \
--sdnotify=conmon \
-d \
-e database_connection \
-e database_user \
-e database_password \
--secret=` + podman.DbUserSecret + `,type=env,target=database_user \
--secret=` + podman.DbPassSecret + `,type=env,target=database_password \
--replace \
--name {{ .NamePrefix }}-server-attestation-%i \
--hostname {{ .NamePrefix }}-server-attestation-%i.mgr.internal \
Expand Down
9 changes: 8 additions & 1 deletion shared/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"io"
"net/http"
"os"
"regexp"
"time"

"github.com/rs/zerolog"
Expand All @@ -32,6 +33,12 @@ func AddAPIFlags(cmd *cobra.Command) {
cmd.PersistentFlags().Bool("api-insecure", false, L("If set, server certificate will not be checked for validity"))
}

var redactRegex = regexp.MustCompile(`(((pxt-session-cookie)|(JSESSIONID))=)[^ ";]+`)

func redactHeaders(header string) string {
return redactRegex.ReplaceAllString(header, "${1}<REDACTED>")
}

func logTraceHeader(v *http.Header) {
// Return early when not in trace loglevel
if log.Logger.GetLevel() != zerolog.TraceLevel {
Expand All @@ -41,7 +48,7 @@ func logTraceHeader(v *http.Header) {
if err != nil {
return
}
log.Trace().Msg(string(b))
log.Trace().Msg(redactHeaders(string(b)))
}

func (c *APIClient) sendRequest(req *http.Request) (*http.Response, error) {
Expand Down
31 changes: 31 additions & 0 deletions shared/api/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2024 SUSE LLC
//
// SPDX-License-Identifier: Apache-2.0

package api

import "testing"

func TestRedactHeaders(t *testing.T) {
data := [][]string{
{
`"JSESSIONID=supersecret; Path=/; Secure; HttpOnly; HttpOnly;HttpOnly;Secure"`,
`"JSESSIONID=<REDACTED>; Path=/; Secure; HttpOnly; HttpOnly;HttpOnly;Secure"`,
},
{
`"pxt-session-cookie=supersecret; Max-Age=0;"`,
`"pxt-session-cookie=<REDACTED>; Max-Age=0;"`,
},
}

for i, testCase := range data {
input := testCase[0]
expected := testCase[1]

actual := redactHeaders(input)

if actual != expected {
t.Errorf("Testcase %d: Expected %s got %s when redacting %s", i, expected, actual, input)
}
}
}
76 changes: 76 additions & 0 deletions shared/podman/secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-FileCopyrightText: 2024 SUSE LLC
//
// SPDX-License-Identifier: Apache-2.0

package podman

import (
"os"
"path"
"strings"

"github.com/rs/zerolog/log"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
"github.com/uyuni-project/uyuni-tools/shared/utils"
)

const (
//DbUserSecret is the name of the podman secret containing the database username.
DbUserSecret = "uyuni-db-user"
//DbUserSecret is the name of the podman secret containing the database password.
DbPassSecret = "uyuni-db-pass"
)

// CreateDbSecrets creates the podman secrets for the database credentials.
func CreateDbSecrets(user string, password string) error {
if err := createSecret(DbUserSecret, user); err != nil {
return err
}
return createSecret(DbPassSecret, password)
}

// createSecret creates a podman secret.
func createSecret(name string, value string) error {
if hasSecret(name) {
return nil
}

tmpDir, err := utils.TempDir()

Check failure on line 38 in shared/podman/secret.go

View workflow job for this annotation

GitHub Actions / lint

assignment mismatch: 2 variables but utils.TempDir returns 3 values) (typecheck)

Check failure on line 38 in shared/podman/secret.go

View workflow job for this annotation

GitHub Actions / lint

assignment mismatch: 2 variables but utils.TempDir returns 3 values) (typecheck)

Check failure on line 38 in shared/podman/secret.go

View workflow job for this annotation

GitHub Actions / lint

assignment mismatch: 2 variables but utils.TempDir returns 3 values) (typecheck)
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)

secretFile := path.Join(tmpDir, "secret")
if err := os.WriteFile(secretFile, []byte(value), 600); err != nil {
return utils.Errorf(err, L("failed to write %s secret to file"), name)
}

if err := utils.RunCmd("podman", "secret", "create", name, secretFile); err != nil {
return utils.Errorf(err, L("failed to create podman secret %s"), name)
}

return nil
}

func hasSecret(name string) bool {
return utils.RunCmd("podman", "secret", "exists", name) == nil
}

// DeleteSecret removes a podman secret.
func DeleteSecret(name string, dryRun bool) {
if !hasSecret(name) {
return
}

args := []string{"secret", "rm", name}
command := "podman " + strings.Join(args, " ")
if dryRun {
log.Info().Msgf(L("Would run %s"), command)
} else {
log.Info().Msgf(L("Run %s"), command)
if err := utils.RunCmd("podman", args...); err != nil {
log.Error().Err(err).Msgf(L("Failed to delete %s secret"), name)
}
}
}
9 changes: 9 additions & 0 deletions uyuni-tools.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
-------------------------------------------------------------------
Mon Nov 18 18:50:59 CET 2024 - [email protected]

- version 5.1.2-0
* CVE-2024-22037: Use podman secret to store the database
credentials (bsc#1231497)
* Redact JSESSIONID and pxt-session-cookie values from logs and
console output (bsc#1231568)

-------------------------------------------------------------------
Mon Oct 14 15:32:26 CEST 2024 - [email protected]

Expand Down
2 changes: 1 addition & 1 deletion uyuni-tools.spec
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
# 0%{?debian} || 0%{?ubuntu}

Name: %{project}
Version: 5.1.1
Version: 5.1.2
Release: 0
Summary: Tools for managing %{productname} container
License: Apache-2.0
Expand Down

0 comments on commit a39327f

Please sign in to comment.