Merge pull request #301 from ibm-messaging/master
Backport fixes to 9.1.2
This commit is contained in:
@@ -16,11 +16,12 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ibm-messaging/mq-container/internal/command"
|
"github.com/ibm-messaging/mq-container/internal/command"
|
||||||
@@ -86,43 +87,35 @@ func configureQueueManager() error {
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if strings.HasSuffix(file.Name(), ".mqsc") {
|
if strings.HasSuffix(file.Name(), ".mqsc") {
|
||||||
abs := filepath.Join(configDir, file.Name())
|
abs := filepath.Join(configDir, file.Name())
|
||||||
// #nosec G204
|
// #nosec G204
|
||||||
cmd := exec.Command("runmqsc")
|
cmd := exec.Command("runmqsc")
|
||||||
stdin, err := cmd.StdinPipe()
|
// Read mqsc file into variable
|
||||||
|
mqsc, err := ioutil.ReadFile(abs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Printf("Error reading file %v: %v", abs, err)
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
// Open the MQSC file for reading
|
// Write mqsc to buffer
|
||||||
// #nosec G304
|
var buffer bytes.Buffer
|
||||||
f, err := os.Open(abs)
|
_, err = buffer.Write(mqsc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error opening %v: %v", abs, err)
|
log.Printf("Error writing MQSC file %v to buffer: %v", abs, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// Copy the contents to stdin of the runmqsc process
|
// Buffer mqsc to stdin of runmqsc
|
||||||
_, err = io.Copy(stdin, f)
|
cmd.Stdin = &buffer
|
||||||
if err != nil {
|
// Run runmqsc command
|
||||||
log.Errorf("Error reading %v: %v", abs, err)
|
|
||||||
}
|
|
||||||
err = f.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Failed to close MQSC file handle: %v", err)
|
|
||||||
}
|
|
||||||
err = stdin.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Failed to close MQSC stdin: %v", err)
|
|
||||||
}
|
|
||||||
// Run the command and wait for completion
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
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, formatMQSCOutput(string(out)))
|
||||||
}
|
}
|
||||||
// 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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -138,3 +131,16 @@ func stopQueueManager(name string) error {
|
|||||||
log.Println("Stopped queue manager")
|
log.Println("Stopped queue manager")
|
||||||
return nil
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -554,6 +554,102 @@ func TestMQSC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestLargeMQSC creates a new image with a large MQSC file in, starts a container based
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
const numQueues = 1000
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i := 1; i <= numQueues; i++ {
|
||||||
|
fmt.Fprintf(&buf, "* Test processing of a large MQSC file, defining queue test%v\nDEFINE QLOCAL(test%v)\n", i, i)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
|
||||||
|
rc, mqscOutput := execContainer(t, cli, id, "mqm", []string{"bash", "-c", "echo 'DISPLAY QLOCAL(test" + strconv.Itoa(numQueues) + ")' | runmqsc"})
|
||||||
|
if rc != 0 {
|
||||||
|
r := regexp.MustCompile("AMQ[0-9][0-9][0-9][0-9]E")
|
||||||
|
t.Fatalf("Expected runmqsc to exit with rc=0, got %v with error %v", rc, r.FindString(mqscOutput))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)\n", sslcryp)
|
||||||
|
fmt.Fprintf(&buf, "*TEST-REDACT-MQSC: A(1) LDAPPWD (abcdefgh) B(2) PASSWORD\t(abcdefgh) C(3) SSLCRYP \t (%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,
|
// 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
|
// tries to start a container based on that image, and checks that container terminates
|
||||||
// func TestInvalidMQSC(t *testing.T) {
|
// func TestInvalidMQSC(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user