Enable admin and app users to do REST messaging
This commit is contained in:
@@ -16,13 +16,21 @@
|
|||||||
<security-role name="MQWebAdmin">
|
<security-role name="MQWebAdmin">
|
||||||
<group name="MQWebUI" realm="defaultRealm"/>
|
<group name="MQWebUI" realm="defaultRealm"/>
|
||||||
</security-role>
|
</security-role>
|
||||||
|
<security-role name="MQWebUser">
|
||||||
|
<group name="MQWebMessaging" realm="defaultRealm"/>
|
||||||
|
</security-role>
|
||||||
</application-bnd>
|
</application-bnd>
|
||||||
</enterpriseApplication>
|
</enterpriseApplication>
|
||||||
<basicRegistry id="basic" realm="defaultRealm">
|
<basicRegistry id="basic" realm="defaultRealm">
|
||||||
<user name="admin" password="${env.MQ_ADMIN_PASSWORD}"/>
|
<user name="admin" password="${env.MQ_ADMIN_PASSWORD}"/>
|
||||||
|
<user name="app" password="${env.MQ_APP_PASSWORD}"/>
|
||||||
<group name="MQWebUI">
|
<group name="MQWebUI">
|
||||||
<member name="admin"/>
|
<member name="admin"/>
|
||||||
</group>
|
</group>
|
||||||
|
<group name="MQWebMessaging">
|
||||||
|
<member name="app"/>
|
||||||
|
<member name="admin"/>
|
||||||
|
</group>
|
||||||
</basicRegistry>
|
</basicRegistry>
|
||||||
<variable name="httpHost" value="*"/>
|
<variable name="httpHost" value="*"/>
|
||||||
<include location="tls.xml"/>
|
<include location="tls.xml"/>
|
||||||
|
|||||||
@@ -37,10 +37,11 @@ func TestDevGoldenPath(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
qm := "qm1"
|
||||||
containerConfig := container.Config{
|
containerConfig := container.Config{
|
||||||
Env: []string{
|
Env: []string{
|
||||||
"LICENSE=accept",
|
"LICENSE=accept",
|
||||||
"MQ_QMGR_NAME=qm1",
|
"MQ_QMGR_NAME=" + qm,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
|
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
|
||||||
@@ -51,6 +52,13 @@ func TestDevGoldenPath(t *testing.T) {
|
|||||||
// Run the JMS tests, with no password specified
|
// Run the JMS tests, with no password specified
|
||||||
runJMSTests(t, cli, id, false, "app", "")
|
runJMSTests(t, cli, id, false, "app", "")
|
||||||
})
|
})
|
||||||
|
t.Run("REST admin", func(t *testing.T) {
|
||||||
|
testRESTAdmin(t, cli, id, insecureTLSConfig)
|
||||||
|
})
|
||||||
|
t.Run("REST messaging as admin", func(t *testing.T) {
|
||||||
|
testRESTMessaging(t, cli, id, insecureTLSConfig, qm, "admin", devAdminPassword)
|
||||||
|
})
|
||||||
|
// Can't run the messaging tests as "app" with the defaults, because you can't have an empty password
|
||||||
// Stop the container cleanly
|
// Stop the container cleanly
|
||||||
stopContainer(t, cli, id)
|
stopContainer(t, cli, id)
|
||||||
}
|
}
|
||||||
@@ -64,10 +72,11 @@ func TestDevSecure(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
const tlsPassPhrase string = "passw0rd"
|
const tlsPassPhrase string = "passw0rd"
|
||||||
|
qm := "qm1"
|
||||||
containerConfig := container.Config{
|
containerConfig := container.Config{
|
||||||
Env: []string{
|
Env: []string{
|
||||||
"LICENSE=accept",
|
"LICENSE=accept",
|
||||||
"MQ_QMGR_NAME=qm1",
|
"MQ_QMGR_NAME=", qm,
|
||||||
"MQ_APP_PASSWORD=" + devAppPassword,
|
"MQ_APP_PASSWORD=" + devAppPassword,
|
||||||
"MQ_TLS_KEYSTORE=/var/tls/server.p12",
|
"MQ_TLS_KEYSTORE=/var/tls/server.p12",
|
||||||
"MQ_TLS_PASSPHRASE=" + tlsPassPhrase,
|
"MQ_TLS_PASSPHRASE=" + tlsPassPhrase,
|
||||||
@@ -100,7 +109,21 @@ func TestDevSecure(t *testing.T) {
|
|||||||
waitForReady(t, cli, ctr.ID)
|
waitForReady(t, cli, ctr.ID)
|
||||||
cert := filepath.Join(tlsDir(t, true), "server.crt")
|
cert := filepath.Join(tlsDir(t, true), "server.crt")
|
||||||
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
|
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
|
||||||
runJMSTests(t, cli, ctr.ID, true, "app", devAppPassword)
|
|
||||||
|
t.Run("JMS", func(t *testing.T) {
|
||||||
|
// Run the JMS tests, with no password specified
|
||||||
|
runJMSTests(t, cli, ctr.ID, true, "app", devAppPassword)
|
||||||
|
})
|
||||||
|
t.Run("REST admin", func(t *testing.T) {
|
||||||
|
testRESTAdmin(t, cli, ctr.ID, insecureTLSConfig)
|
||||||
|
})
|
||||||
|
t.Run("REST messaging as admin", func(t *testing.T) {
|
||||||
|
testRESTMessaging(t, cli, ctr.ID, insecureTLSConfig, qm, "admin", devAdminPassword)
|
||||||
|
})
|
||||||
|
t.Run("REST messaging as app", func(t *testing.T) {
|
||||||
|
testRESTMessaging(t, cli, ctr.ID, insecureTLSConfig, qm, "app", devAppPassword)
|
||||||
|
})
|
||||||
|
|
||||||
// Stop the container cleanly
|
// Stop the container cleanly
|
||||||
stopContainer(t, cli, ctr.ID)
|
stopContainer(t, cli, ctr.ID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -140,14 +142,13 @@ 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{
|
httpClient := http.Client{
|
||||||
Timeout: time.Duration(30 * time.Second),
|
Timeout: time.Duration(30 * time.Second),
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: tlsConfig,
|
TLSClientConfig: tlsConfig,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getPort(t, cli, ID, 9443))
|
url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getPort(t, cli, ID, 9443))
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
req.SetBasicAuth("admin", devAdminPassword)
|
req.SetBasicAuth("admin", devAdminPassword)
|
||||||
@@ -159,3 +160,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)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user