Compare commits

...

17 Commits
9.2.2 ... 9.1.0

Author SHA1 Message Date
Robert Parker
d131a325da Security fixes, Nov 2018 2018-11-07 14:58:52 +00:00
Robert Parker
cbdd80118b update apparmor 2018-10-09 09:53:48 +01:00
Stephen Marshall
2ddb7322d7 Fix RTC ppcle_linux build (#209) 2018-09-19 17:11:16 +01:00
Stephen Marshall
4ca342251d Fix lint error - 9.1.0 (#187)
* Fix lint error

* Remove incorrect import
2018-08-13 12:33:33 +01:00
Rob Parker
741ed9451f Merge pull request #185 from arthurbarr/9.1.0
Port latest fixes to 9.1.0
2018-08-08 08:41:02 +01:00
Arthur Barr
48e9001416 Remove unused variable in Dockerfiles 2018-08-07 17:05:12 +01:00
Arthur Barr
4dc843a569 Remove debug statements 2018-08-07 17:05:04 +01:00
Arthur Barr
bbbd305654 Enable only app user to do REST messaging 2018-08-07 17:04:56 +01:00
Arthur Barr
739a01a83d Fix Mac incompatibility of image creation date 2018-08-07 17:04:49 +01:00
Arthur Barr
0c9338b7d6 Enable admin and app users to do REST messaging 2018-08-07 17:04:40 +01:00
Arthur Barr
5dc5d2f3a5 Merge commit 'b8f96d0148a4743807f7493c2f818b907192c615' into 9.1.0 2018-08-07 17:04:29 +01:00
Robert Parker
e8f8655408 make sure to use -aG not -G 2018-08-07 17:04:06 +01:00
Rob Parker
3a1db1a04e force string output in chkmqhealthy (#174) 2018-08-07 17:03:58 +01:00
Rob Parker
acbde18921 check explicitly for /mnt/mqm (#175) 2018-08-07 17:03:50 +01:00
Arthur Barr
1f8bb5fe05 Merge commit '29dfe38d32f50ecbb43cc02c3c482d5c610cc9c7' into 9.1.0 2018-08-07 17:03:31 +01:00
Robert Parker
8afcb56ea8 only download the sdk image if we need to 2018-08-07 17:02:46 +01:00
Robert Parker
0caf879a70 Update license to 9.1 2018-07-25 12:37:01 +01:00
11 changed files with 140 additions and 25 deletions

View File

@@ -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

View File

@@ -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 \
@@ -256,7 +253,7 @@ build-devserver: MQ_SDK_ARCHIVE=$(MQ_ARCHIVE_DEV)
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

View File

@@ -23,8 +23,11 @@ import (
)
var (
// ImageCreated is the date the image was built
ImageCreated = "Not specified"
// ImageRevision is the source control revision identifier
ImageRevision = "Not specified"
// ImageSource is the URL to get source code for building the image
ImageSource = "Not specified"
)

View File

@@ -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

View File

@@ -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/...

View File

@@ -16,13 +16,23 @@
<security-role name="MQWebAdmin">
<group name="MQWebUI" realm="defaultRealm"/>
</security-role>
<security-role name="MQWebUser">
<group name="MQWebMessaging" realm="defaultRealm"/>
</security-role>
</application-bnd>
</enterpriseApplication>
<basicRegistry id="basic" realm="defaultRealm">
<user name="admin" password="${env.MQ_ADMIN_PASSWORD}"/>
<!-- The app user will always get a default password of "passw0rd",
even if you don't set the environment variable.
See `webserver.go` -->
<user name="app" password="${env.MQ_APP_PASSWORD}"/>
<group name="MQWebUI">
<member name="admin"/>
</group>
<group name="MQWebMessaging">
<member name="app"/>
</group>
</basicRegistry>
<variable name="httpHost" value="*"/>
<include location="tls.xml"/>

View File

@@ -139,7 +139,7 @@ rm -rf ${DIR_EXTRACT}
# Apply any bug fixes not included in base Ubuntu or MQ image.
# Don't upgrade everything based on Docker best practices https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#run
$UBUNTU && apt-get install -y gcc-5-base gnupg gpgv libgcrypt20 libstdc++6 perl-base --only-upgrade
$UBUNTU && apt-get install -y libapparmor1 libsystemd0 systemd systemd-sysv libudev1 --only-upgrade
# End of bug fixes
# Clean up cached files

View File

@@ -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)

View File

@@ -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)
}
}

View File

@@ -30,7 +30,7 @@ RUN find /usr/src/mymaven
###############################################################################
# Application runtime (JRE only, no build environment)
###############################################################################
FROM ibmjava:sfj
FROM ibmjava:8-jre
COPY --from=builder /usr/src/mymaven/target/*.jar /opt/app/
COPY --from=builder /usr/src/mymaven/target/lib/*.jar /opt/app/
ENTRYPOINT ["java", "-classpath", "/opt/app/*", "org.junit.platform.console.ConsoleLauncher", "-p", "com.ibm.mqcontainer.test", "--details", "verbose"]

View File

@@ -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");