diff --git a/Dockerfile-server b/Dockerfile-server
index aa46d76..4324555 100644
--- a/Dockerfile-server
+++ b/Dockerfile-server
@@ -21,12 +21,11 @@ ARG BUILDER_IMAGE=mq-golang-sdk:9.0.5.0-x86_64-ubuntu-16.04
FROM $BUILDER_IMAGE as builder
WORKDIR /go/src/github.com/ibm-messaging/mq-container/
ARG IMAGE_REVISION="Not specified"
-ARG IMAGE_CREATED="Not specified"
ARG IMAGE_SOURCE="Not specified"
COPY cmd/ ./cmd
COPY internal/ ./internal
COPY vendor/ ./vendor
-RUN go build -ldflags "-X \"main.ImageCreated=$IMAGE_CREATED\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" ./cmd/runmqserver/
+RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" ./cmd/runmqserver/
RUN go build ./cmd/chkmqready/
RUN go build ./cmd/chkmqhealthy/
# Run all unit tests
diff --git a/Makefile b/Makefile
index eb63076..4250d73 100644
--- a/Makefile
+++ b/Makefile
@@ -62,8 +62,6 @@ DEV_JMS_IMAGE=mq-dev-jms-test
# Variables for versioning
IMAGE_REVISION=$(shell git rev-parse HEAD)
IMAGE_SOURCE=$(shell git config --get remote.origin.url)
-IMAGE_CREATED=$(shell date -u +%Y-%m-%dT%H:%M:%S%:z)
-
ifneq (,$(findstring Microsoft,$(shell uname -r)))
DOWNLOADS_DIR=$(patsubst /mnt/c%,C:%,$(realpath ./downloads/))
@@ -223,7 +221,6 @@ define docker-build-mq
--build-arg BASE_IMAGE=$(BASE_IMAGE) \
--build-arg BUILDER_IMAGE=$(MQ_IMAGE_GOLANG_SDK) \
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
- --build-arg IMAGE_CREATED="$(IMAGE_CREATED)" \
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
--label IBM_PRODUCT_ID=$4 \
--label IBM_PRODUCT_NAME=$5 \
@@ -241,7 +238,7 @@ docker-version:
.PHONY: build-advancedserver
build-advancedserver: MQ_SDK_ARCHIVE=$(MQ_ARCHIVE)
-build-advancedserver: downloads/$(MQ_ARCHIVE) docker-version build-golang-sdk
+build-advancedserver: downloads/$(MQ_ARCHIVE) docker-version build-golang-sdk-ex
$(info $(SPACER)$(shell printf $(TITLE)"Build $(MQ_IMAGE_ADVANCEDSERVER)"$(END)))
$(call docker-build-mq,$(MQ_IMAGE_ADVANCEDSERVER),Dockerfile-server,$(MQ_ARCHIVE),"4486e8c4cc9146fd9b3ce1f14a2dfc5b","IBM MQ Advanced",$(MQ_VERSION))
@@ -253,10 +250,10 @@ else
build-devserver: MQ_PACKAGES=MQSeriesRuntime-*.rpm MQSeriesServer-*.rpm MQSeriesJava*.rpm MQSeriesJRE*.rpm MQSeriesGSKit*.rpm MQSeriesMsg*.rpm MQSeriesSamples*.rpm MQSeriesAMS-*.rpm MQSeriesWeb-*.rpm
endif
build-devserver: MQ_SDK_ARCHIVE=$(MQ_ARCHIVE_DEV)
-build-devserver: downloads/$(MQ_ARCHIVE_DEV) docker-version build-golang-sdk
+build-devserver: downloads/$(MQ_ARCHIVE_DEV) docker-version build-golang-sdk-ex
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER_BASE)"$(END)))
$(call docker-build-mq,$(MQ_IMAGE_DEVSERVER_BASE),Dockerfile-server,$(MQ_ARCHIVE_DEV),"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers (Non-Warranted)",$(MQ_VERSION))
- $(DOCKER) build --tag $(MQ_IMAGE_DEVSERVER) --build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" --build-arg IMAGE_REVISION="$(IMAGE_REVISION)" --build-arg IMAGE_CREATED="$(IMAGE_CREATED)" --build-arg BASE_IMAGE=$(MQ_IMAGE_DEVSERVER_BASE) --build-arg BUILDER_IMAGE=$(MQ_IMAGE_GOLANG_SDK) --file incubating/mqadvanced-server-dev/Dockerfile .
+ $(DOCKER) build --tag $(MQ_IMAGE_DEVSERVER) --build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" --build-arg IMAGE_REVISION="$(IMAGE_REVISION)" --build-arg BASE_IMAGE=$(MQ_IMAGE_DEVSERVER_BASE) --build-arg BUILDER_IMAGE=$(MQ_IMAGE_GOLANG_SDK) --file incubating/mqadvanced-server-dev/Dockerfile .
.PHONY: build-advancedserver-cover
build-advancedserver-cover: docker-version
@@ -266,15 +263,23 @@ build-advancedserver-cover: docker-version
build-explorer: downloads/$(MQ_ARCHIVE_DEV)
$(call docker-build-mq,mq-explorer:latest-$(ARCH),incubating/mq-explorer/Dockerfile-mq-explorer,$(MQ_ARCHIVE_DEV),"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers (Non-Warranted)",$(MQ_VERSION))
+.PHONY: build-sdk
+build-sdk: downloads/$(MQ_SDK_ARCHIVE) build-sdk-ex
+
+.PHONY: build-sdk-ex
ifeq "$(findstring ubuntu,$(BASE_IMAGE))" "ubuntu"
-build-sdk: MQ_PACKAGES=ibmmq-sdk ibmmq-samples build-essential
+build-sdk-ex: MQ_PACKAGES=ibmmq-sdk ibmmq-samples build-essential
else
-build-sdk: MQ_PACKAGES=MQSeriesRuntime-*.rpm MQSeriesSDK-*.rpm MQSeriesSamples*.rpm
+build-sdk-ex: MQ_PACKAGES=MQSeriesRuntime-*.rpm MQSeriesSDK-*.rpm MQSeriesSamples*.rpm
endif
-build-sdk: downloads/$(MQ_SDK_ARCHIVE) docker-version docker-pull
+build-sdk-ex: docker-version docker-pull
$(call docker-build-mq,$(MQ_IMAGE_SDK),incubating/mq-sdk/Dockerfile,$(MQ_SDK_ARCHIVE),"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers SDK (Non-Warranted)",$(MQ_VERSION))
-build-golang-sdk: downloads/$(MQ_SDK_ARCHIVE) docker-version build-sdk
+.PHONY: build-golang-sdk
+build-golang-sdk: downloads/$(MQ_SDK_ARCHIVE) build-golang-sdk-ex
+
+.PHONY: build-golang-sdk-ex
+build-golang-sdk-ex: docker-version build-sdk-ex
$(DOCKER) build --build-arg BASE_IMAGE=$(MQ_IMAGE_SDK) -t $(MQ_IMAGE_GOLANG_SDK) -f incubating/mq-golang-sdk/Dockerfile .
# $(call docker-build-mq,$(MQ_IMAGE_GOLANG_SDK),incubating/mq-golang-sdk/Dockerfile,$(MQ_IMAGE_SDK),"98102d16795c4263ad9ca075190a2d4d","IBM MQ Advanced for Developers SDK (Non-Warranted)",$(MQ_VERSION))
diff --git a/cmd/chkmqhealthy/main.go b/cmd/chkmqhealthy/main.go
index ff62e93..b26bea8 100644
--- a/cmd/chkmqhealthy/main.go
+++ b/cmd/chkmqhealthy/main.go
@@ -39,7 +39,7 @@ func queueManagerHealthy() (bool, error) {
fmt.Println(err)
return false, err
}
- fmt.Println(out)
+ fmt.Printf("%s", out)
if !strings.Contains(string(out), "(RUNNING)") {
return false, nil
}
diff --git a/cmd/runmqserver/mqconfig.go b/cmd/runmqserver/mqconfig.go
index 51c9179..a653ce1 100644
--- a/cmd/runmqserver/mqconfig.go
+++ b/cmd/runmqserver/mqconfig.go
@@ -131,7 +131,7 @@ func readMounts() error {
//dev := parts[0]
mountPoint := parts[1]
fsType := parts[2]
- if strings.Contains(mountPoint, "/mnt") {
+ if strings.Contains(mountPoint, "/mnt/mqm") {
log.Printf("Detected '%v' volume mounted to %v", fsType, mountPoint)
detected = true
}
diff --git a/cmd/runmqserver/webserver.go b/cmd/runmqserver/webserver.go
index 4852288..a88786a 100644
--- a/cmd/runmqserver/webserver.go
+++ b/cmd/runmqserver/webserver.go
@@ -21,7 +21,9 @@ import (
"fmt"
"io"
"os"
+ "os/exec"
"path/filepath"
+ "syscall"
"github.com/ibm-messaging/mq-container/internal/command"
)
@@ -33,7 +35,20 @@ func startWebServer() error {
return nil
}
log.Println("Starting web server")
- out, rc, err := command.RunAsMQM("strmqweb")
+ cmd := exec.Command("strmqweb")
+ // Set a default app password for the web server, if one isn't already set
+ _, set := os.LookupEnv("MQ_APP_PASSWORD")
+ if !set {
+ // Take all current environment variables, and add the app password
+ cmd.Env = append(os.Environ(), "MQ_APP_PASSWORD=passw0rd")
+ }
+ cmd.SysProcAttr = &syscall.SysProcAttr{}
+ uid, gid, err := command.LookupMQM()
+ if err != nil {
+ return err
+ }
+ cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
+ out, rc, err := command.RunCmd(cmd)
if err != nil {
log.Printf("Error %v starting web server: %v", rc, string(out))
return err
diff --git a/incubating/mqadvanced-server-dev/Dockerfile b/incubating/mqadvanced-server-dev/Dockerfile
index 208ee52..f022258 100644
--- a/incubating/mqadvanced-server-dev/Dockerfile
+++ b/incubating/mqadvanced-server-dev/Dockerfile
@@ -20,14 +20,13 @@ ARG BUILDER_IMAGE=mq-golang-sdk:9.0.5.0-x86_64-ubuntu-16.04
###############################################################################
FROM $BUILDER_IMAGE as builder
ARG IMAGE_REVISION="Not specified"
-ARG IMAGE_CREATED="Not specified"
ARG IMAGE_SOURCE="Not specified"
WORKDIR /go/src/github.com/ibm-messaging/mq-container/
COPY cmd/ ./cmd
COPY internal/ ./internal
COPY vendor/ ./vendor
# Re-build runmqserver, with code tagged with 'mqdev' enabled
-RUN go build -ldflags "-X \"main.ImageCreated=$IMAGE_CREATED\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" --tags 'mqdev' ./cmd/runmqserver
+RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\"" --tags 'mqdev' ./cmd/runmqserver
RUN go build ./cmd/runmqdevserver/
# Run all unit tests
RUN go test -v ./cmd/runmqdevserver/...
diff --git a/incubating/mqadvanced-server-dev/web/installations/Installation1/servers/mqweb/mqwebuser.xml b/incubating/mqadvanced-server-dev/web/installations/Installation1/servers/mqweb/mqwebuser.xml
index f0e5ada..fb1f855 100644
--- a/incubating/mqadvanced-server-dev/web/installations/Installation1/servers/mqweb/mqwebuser.xml
+++ b/incubating/mqadvanced-server-dev/web/installations/Installation1/servers/mqweb/mqwebuser.xml
@@ -16,13 +16,23 @@
+
+
+
+
+
+
+
+
diff --git a/install-mq.sh b/install-mq.sh
index 143f16e..6273628 100644
--- a/install-mq.sh
+++ b/install-mq.sh
@@ -106,7 +106,7 @@ $UBUNTU && groupadd --system --gid 999 mqm
$UBUNTU && useradd --system --uid 999 --gid mqm mqm
$RHEL && groupadd --system --gid 888 mqm
$RHEL && useradd --system --uid 888 --gid mqm mqm
-usermod -G mqm root
+usermod -aG mqm root
# Find directory containing .deb files
$UBUNTU && DIR_DEB=$(find ${DIR_EXTRACT} -name "*.deb" -printf "%h\n" | sort -u | head -1)
diff --git a/test/docker/devconfig_test.go b/test/docker/devconfig_test.go
index da172d3..933100e 100644
--- a/test/docker/devconfig_test.go
+++ b/test/docker/devconfig_test.go
@@ -37,10 +37,11 @@ func TestDevGoldenPath(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ qm := "qm1"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
- "MQ_QMGR_NAME=qm1",
+ "MQ_QMGR_NAME=" + qm,
},
}
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
@@ -49,7 +50,13 @@ func TestDevGoldenPath(t *testing.T) {
waitForWebReady(t, cli, id, insecureTLSConfig)
t.Run("JMS", func(t *testing.T) {
// Run the JMS tests, with no password specified
- runJMSTests(t, cli, id, false, "app", "")
+ runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS)
+ })
+ t.Run("REST admin", func(t *testing.T) {
+ testRESTAdmin(t, cli, id, insecureTLSConfig)
+ })
+ t.Run("REST messaging", func(t *testing.T) {
+ testRESTMessaging(t, cli, id, insecureTLSConfig, qm, "app", defaultAppPasswordWeb)
})
// Stop the container cleanly
stopContainer(t, cli, id)
@@ -64,11 +71,13 @@ func TestDevSecure(t *testing.T) {
t.Fatal(err)
}
const tlsPassPhrase string = "passw0rd"
+ qm := "qm1"
+ appPassword := "differentPassw0rd"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
- "MQ_QMGR_NAME=qm1",
- "MQ_APP_PASSWORD=" + devAppPassword,
+ "MQ_QMGR_NAME=" + qm,
+ "MQ_APP_PASSWORD=" + appPassword,
"MQ_TLS_KEYSTORE=/var/tls/server.p12",
"MQ_TLS_PASSPHRASE=" + tlsPassPhrase,
"DEBUG=1",
@@ -100,7 +109,17 @@ func TestDevSecure(t *testing.T) {
waitForReady(t, cli, ctr.ID)
cert := filepath.Join(tlsDir(t, true), "server.crt")
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
- runJMSTests(t, cli, ctr.ID, true, "app", devAppPassword)
+
+ t.Run("JMS", func(t *testing.T) {
+ runJMSTests(t, cli, ctr.ID, true, "app", appPassword)
+ })
+ t.Run("REST admin", func(t *testing.T) {
+ testRESTAdmin(t, cli, ctr.ID, insecureTLSConfig)
+ })
+ t.Run("REST messaging", func(t *testing.T) {
+ testRESTMessaging(t, cli, ctr.ID, insecureTLSConfig, qm, "app", appPassword)
+ })
+
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
@@ -129,7 +148,7 @@ func TestDevWebDisabled(t *testing.T) {
})
t.Run("JMS", func(t *testing.T) {
// Run the JMS tests, with no password specified
- runJMSTests(t, cli, id, false, "app", "")
+ runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS)
})
// Stop the container cleanly
stopContainer(t, cli, id)
diff --git a/test/docker/devconfig_test_util.go b/test/docker/devconfig_test_util.go
index c89e458..1ca662a 100644
--- a/test/docker/devconfig_test_util.go
+++ b/test/docker/devconfig_test_util.go
@@ -18,12 +18,14 @@ limitations under the License.
package main
import (
+ "bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
+ "net/http/httputil"
"path/filepath"
"strings"
"testing"
@@ -34,8 +36,9 @@ import (
"github.com/docker/docker/client"
)
-const devAdminPassword string = "passw0rd"
-const devAppPassword string = "passw0rd"
+const defaultAdminPassword string = "passw0rd"
+const defaultAppPasswordOS string = ""
+const defaultAppPasswordWeb string = "passw0rd"
// Disable TLS verification (server uses a self-signed certificate by default,
// so verification isn't useful anyway)
@@ -58,7 +61,7 @@ func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls
select {
case <-time.After(1 * time.Second):
req, err := http.NewRequest("GET", url, nil)
- req.SetBasicAuth("admin", devAdminPassword)
+ req.SetBasicAuth("admin", defaultAdminPassword)
resp, err := httpClient.Do(req.WithContext(ctx))
if err == nil && resp.StatusCode == http.StatusOK {
t.Log("MQ web server is ready")
@@ -140,17 +143,16 @@ func createTLSConfig(t *testing.T, certFile, password string) *tls.Config {
}
}
-func testREST(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
+func testRESTAdmin(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
httpClient := http.Client{
Timeout: time.Duration(30 * time.Second),
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}
-
url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getPort(t, cli, ID, 9443))
req, err := http.NewRequest("GET", url, nil)
- req.SetBasicAuth("admin", devAdminPassword)
+ req.SetBasicAuth("admin", defaultAdminPassword)
resp, err := httpClient.Do(req)
if err != nil {
t.Fatal(err)
@@ -159,3 +161,70 @@ func testREST(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config
t.Errorf("Expected HTTP status code %v from 'GET installation'; got %v", http.StatusOK, resp.StatusCode)
}
}
+
+// curl -i -k https://localhost:1234/ibmmq/rest/v1/messaging/qmgr/qm1/queue/DEV.QUEUE.1/message -X POST -u app -H “ibm-mq-rest-csrf-token: N/A” -H “Content-Type: text/plain;charset=utf-8" -d “Hello World”
+
+func logHTTPRequest(t *testing.T, req *http.Request) {
+ d, err := httputil.DumpRequestOut(req, true)
+ if err != nil {
+ t.Error(err)
+ }
+ t.Logf("HTTP request: %v", string(d))
+}
+
+func logHTTPResponse(t *testing.T, resp *http.Response) {
+ d, err := httputil.DumpResponse(resp, true)
+ if err != nil {
+ t.Error(err)
+ }
+ t.Logf("HTTP response: %v", string(d))
+}
+
+func testRESTMessaging(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config, qmName string, user string, password string) {
+ httpClient := http.Client{
+ Timeout: time.Duration(30 * time.Second),
+ Transport: &http.Transport{
+ TLSClientConfig: tlsConfig,
+ },
+ }
+ q := "DEV.QUEUE.1"
+ url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/messaging/qmgr/%s/queue/%s/message", getPort(t, cli, ID, 9443), qmName, q)
+ putMessage := []byte("Hello")
+ req, err := http.NewRequest("POST", url, bytes.NewBuffer(putMessage))
+ req.SetBasicAuth(user, password)
+ req.Header.Add("ibm-mq-rest-csrf-token", "n/a")
+ req.Header.Add("Content-Type", "text/plain;charset=utf-8")
+ logHTTPRequest(t, req)
+ resp, err := httpClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logHTTPResponse(t, resp)
+ if resp.StatusCode != http.StatusCreated {
+ t.Errorf("Expected HTTP status code %v from 'POST to queue'; got %v", http.StatusOK, resp.StatusCode)
+ t.Logf("HTTP response: %+v", resp)
+ t.Fail()
+ }
+
+ req, err = http.NewRequest("DELETE", url, nil)
+ req.Header.Add("ibm-mq-rest-csrf-token", "n/a")
+ req.SetBasicAuth(user, password)
+ logHTTPRequest(t, req)
+ resp, err = httpClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logHTTPResponse(t, resp)
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ t.Errorf("Expected HTTP status code %v from 'DELETE from queue'; got %v", http.StatusOK, resp.StatusCode)
+ t.Logf("HTTP response: %+v", resp)
+ t.Fail()
+ }
+ gotMessage, err := ioutil.ReadAll(resp.Body)
+ //gotMessage := string(b)
+ if string(gotMessage) != string(putMessage) {
+ t.Errorf("Expected payload to be \"%s\"; got \"%s\"", putMessage, gotMessage)
+ }
+}
diff --git a/test/messaging/src/main/java/com/ibm/mqcontainer/test/JMSTests.java b/test/messaging/src/main/java/com/ibm/mqcontainer/test/JMSTests.java
index 44f5d4e..df0575d 100644
--- a/test/messaging/src/main/java/com/ibm/mqcontainer/test/JMSTests.java
+++ b/test/messaging/src/main/java/com/ibm/mqcontainer/test/JMSTests.java
@@ -73,6 +73,10 @@ class JMSTests {
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
factory.setChannel(channel);
factory.setConnectionNameList(String.format("%s(1414)", addr));
+ // If a password is set, make sure it gets sent to the queue manager for authentication
+ if (password != null) {
+ factory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
+ }
// factory.setClientReconnectOptions(WMQConstants.WMQ_CLIENT_RECONNECT);
if (TRUSTSTORE == null) {
LOGGER.info("Not using TLS");