diff --git a/cmd/runmqserver/qmgr.go b/cmd/runmqserver/qmgr.go index 821bd66..236d36d 100644 --- a/cmd/runmqserver/qmgr.go +++ b/cmd/runmqserver/qmgr.go @@ -21,6 +21,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "github.com/ibm-messaging/mq-container/internal/command" @@ -109,11 +110,11 @@ func configureQueueManager() error { // Run runmqsc command out, err := cmd.CombinedOutput() if err != nil { - log.Errorf("Error running MQSC file %v (%v):\n\t%v", file.Name(), err, strings.Replace(string(out), "\n", "\n\t", -1)) + log.Errorf("Error running MQSC file %v (%v):\n\t%v", file.Name(), err, formatMQSCOutput(string(out))) continue } else { // Print the runmqsc output, adding tab characters to make it more readable as part of the log - log.Printf("Output for \"runmqsc\" with %v:\n\t%v", abs, strings.Replace(string(out), "\n", "\n\t", -1)) + log.Printf("Output for \"runmqsc\" with %v:\n\t%v", abs, formatMQSCOutput(string(out))) } } } @@ -130,3 +131,16 @@ func stopQueueManager(name string) error { log.Println("Stopped queue manager") return nil } + +func formatMQSCOutput(out string) string { + // redact sensitive information + pattern, _ := regexp.Compile("(?i)LDAPPWD\\s?\\((.*?)\\)") + out = pattern.ReplaceAllString(out, "LDAPPWD(*********)") + pattern, _ = regexp.Compile("(?i)PASSWORD\\s?\\((.*?)\\)") + out = pattern.ReplaceAllString(out, "PASSWORD(*********)") + pattern, _ = regexp.Compile("(?i)SSLCRYP\\s?\\((.*?)\\)") + out = pattern.ReplaceAllString(out, "SSLCRYP(*********)") + + // add tab characters to make it more readable as part of the log + return strings.Replace(string(out), "\n", "\n\t", -1) +} diff --git a/test/docker/docker_api_test.go b/test/docker/docker_api_test.go index f540639..cd662fa 100644 --- a/test/docker/docker_api_test.go +++ b/test/docker/docker_api_test.go @@ -558,6 +558,7 @@ func TestMQSC(t *testing.T) { // on that image, and checks that the MQSC has been applied correctly. func TestLargeMQSC(t *testing.T) { t.Parallel() + cli, err := client.NewEnvClient() if err != nil { t.Fatal(err) @@ -597,6 +598,57 @@ func TestLargeMQSC(t *testing.T) { } } +// TestRedactMQSC creates a new image with a MQSC file that contains sensitive information, starts a container based +// on that image, and checks that the MQSC has been redacted in the logs. +func TestRedactMQSC(t *testing.T) { + t.Parallel() + + cli, err := client.NewEnvClient() + if err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + sslcryp := "GSK_PKCS11=/usr/lib/pkcs11/PKCS11_API.so;token-label;token-password;SYMMETRIC_CIPHER_ON;" + fmt.Fprintf(&buf, "*TEST-REDACT-MQSC: A(1) LDAPPWD(abcdefgh) B(2) PASSWORD(abcdefgh) C(3) SSLCRYP(%v) D(4)\n", sslcryp) + fmt.Fprintf(&buf, "*TEST-REDACT-MQSC: A(1) ldappwd(12345678) B(2) password(12345678) C(3) sslcryp(%v) D(4)\n", sslcryp) + fmt.Fprintf(&buf, "*TEST-REDACT-MQSC: A(1) LDAPPWD (12?@!$gh) B(2) PASSWORD (12?@!$gh) C(3) SSLCRYP (%v) D(4)", sslcryp) + var files = []struct { + Name, Body string + }{ + {"Dockerfile", fmt.Sprintf(` + FROM %v + USER root + RUN rm -f /etc/mqm/*.mqsc + ADD test.mqsc /etc/mqm/ + RUN chmod 0660 /etc/mqm/test.mqsc + USER mqm`, imageName())}, + {"test.mqsc", buf.String()}, + } + tag := createImage(t, cli, files) + defer deleteImage(t, cli, tag) + + containerConfig := container.Config{ + Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"}, + Image: tag, + } + id := runContainer(t, cli, &containerConfig) + defer cleanContainer(t, cli, id) + waitForReady(t, cli, id) + stopContainer(t, cli, id) + scanner := bufio.NewScanner(strings.NewReader(inspectLogs(t, cli, id))) + expectedOutput := "*TEST-REDACT-MQSC: A(1) LDAPPWD(*********) B(2) PASSWORD(*********) C(3) SSLCRYP(*********) D(4)" + for scanner.Scan() { + s := scanner.Text() + if strings.Contains(s, "*TEST-REDACT-MQSC:") && !strings.Contains(s, expectedOutput) { + t.Fatalf("Expected redacted MQSC output, got: %v", s) + } + } + err = scanner.Err() + if err != nil { + t.Fatal(err) + } +} + // TestInvalidMQSC creates a new image with an MQSC file containing invalid MQSC, // tries to start a container based on that image, and checks that container terminates // func TestInvalidMQSC(t *testing.T) {