Configure Single-Sign-On for the web server

This commit is contained in:
Stephen Marshall
2018-10-03 13:19:09 +01:00
committed by Robert Parker
parent 9b3b1f7b9e
commit 4c1d124484
4 changed files with 171 additions and 3 deletions

View File

@@ -20,18 +20,26 @@ import (
)
// postInit is run after /var/mqm is set up
// This version of postInit is only included as part of the MQ Advanced for Developers build
func postInit(name string) error {
disable := os.Getenv("MQ_DISABLE_WEB_CONSOLE")
if disable != "true" && disable != "1" {
// Configure Single-Sign-On for the web server (if enabled)
enableSSO := os.Getenv("MQ_ENABLE_SSO")
if enableSSO == "true" || enableSSO == "1" {
err := configureSSO()
if err != nil {
return err
}
}
// Configure the web server (if installed)
err := configureWebServer()
if err != nil {
return err
}
// Start the web server, in the background (if installed)
// WARNING: No error handling or health checking available for the web server,
// which is why it's limited to use with MQ Advanced for Developers only
// WARNING: No error handling or health checking available for the web server
go func() {
startWebServer()
}()

View File

@@ -23,9 +23,12 @@ import (
"os/user"
"path/filepath"
"strconv"
"strings"
"syscall"
"github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/internal/keystore"
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
)
func startWebServer() error {
@@ -88,6 +91,101 @@ func CopyFile(src, dest string) error {
return err
}
func configureSSO() error {
// Ensure all required environment variables are set for SSO
requiredEnvVars := []string{
"MQ_WEB_ADMIN_USERS",
"MQ_OIDC_CLIENT_ID",
"MQ_OIDC_CLIENT_SECRET",
"MQ_OIDC_AUTHORIZATION_ENDPOINT",
"MQ_OIDC_TOKEN_ENDPOINT",
"MQ_OIDC_JWK_ENDPOINT",
"MQ_OIDC_ISSUER_IDENTIFIER",
"MQ_OIDC_CERTIFICATE",
}
for _, envVar := range requiredEnvVars {
if len(os.Getenv(envVar)) == 0 {
return fmt.Errorf("%v must be set when MQ_ENABLE_SSO=true", envVar)
}
}
// Check mqweb directory exists
const mqwebDir string = "/etc/mqm/web/installations/Installation1/servers/mqweb"
_, err := os.Stat(mqwebDir)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
// Process SSO template for generating file mqwebuser.xml
adminUsers := strings.Split(os.Getenv("MQ_WEB_ADMIN_USERS"), ",")
err = mqtemplate.ProcessTemplateFile(mqwebDir+"/mqwebuser.xml.tpl", mqwebDir+"/mqwebuser.xml", map[string][]string{"AdminUser": adminUsers}, log)
if err != nil {
return err
}
// Configure SSO TLS
return configureSSO_TLS()
}
func configureSSO_TLS() error {
// Create tls directory
dir := "/run/tls"
_, err := os.Stat(dir)
if err != nil {
if os.IsNotExist(err) {
err = os.MkdirAll(dir, 0770)
if err != nil {
return err
}
mqmUID, mqmGID, err := command.LookupMQM()
if err != nil {
log.Error(err)
return err
}
err = os.Chown(dir, mqmUID, mqmGID)
if err != nil {
log.Error(err)
return err
}
} else {
return err
}
}
// Setup key store & trust store
ks := keystore.NewJKSKeyStore(filepath.Join(dir, "key.jks"), "password")
ts := keystore.NewJKSKeyStore(filepath.Join(dir, "trust.jks"), "password")
log.Debug("Creating key store")
err = ks.Create(log)
if err != nil {
return err
}
log.Debug("Creating trust store")
err = ts.Create(log)
if err != nil {
return err
}
log.Debug("Creating self-signed certificate in key store")
err = ks.CreateSelfSignedCertificate("default", "CN=IBMMQWeb,O=IBM,OU=Platform,C=GB")
if err != nil {
return err
}
log.Debug("Importing self-signed certificate into trust store")
err = ts.Import(ks.Filename, ks.Password)
if err != nil {
return err
}
log.Debug("Adding OIDC CA certificate to trust store")
err = ts.Add(os.Getenv("MQ_OIDC_CERTIFICATE"), "OIDC")
return err
}
func configureWebServer() error {
_, err := os.Stat("/opt/mqm/bin/strmqweb")
if err != nil {

View File

@@ -150,6 +150,24 @@ func (ks *KeyStore) Import(inputFile, password string) error {
return nil
}
// CreateSelfSignedCertificate creates a self-signed certificate in the keystore
func (ks *KeyStore) CreateSelfSignedCertificate(label, dn string) error {
out, _, err := command.Run(ks.command, "-cert", "-create", "-db", ks.Filename, "-pw", ks.Password, "-label", label, "-dn", dn)
if err != nil {
return fmt.Errorf("error running \"%v -cert -create\": %v %s", ks.command, err, out)
}
return nil
}
// Add adds a CA certificate to the keystore
func (ks *KeyStore) Add(inputFile, label string) error {
out, _, err := command.Run(ks.command, "-cert", "-add", "-db", ks.Filename, "-type", ks.keyStoreType, "-pw", ks.Password, "-file", inputFile, "-label", label)
if err != nil {
return fmt.Errorf("error running \"%v -cert -add\": %v %s", ks.command, err, out)
}
return nil
}
// GetCertificateLabels returns the labels of all certificates in the key store
func (ks *KeyStore) GetCertificateLabels() ([]string, error) {
out, _, err := command.Run(ks.command, "-cert", "-list", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<server>
<featureManager>
<feature>openidConnectClient-1.0</feature>
<feature>ssl-1.0</feature>
</featureManager>
<enterpriseApplication id="com.ibm.mq.console">
<application-bnd>
<security-role name="MQWebAdmin">
<group name="MQWebUI" realm="defaultRealm"/>
{{- range $index, $element := .AdminUser}}
<user name="admin{{$index}}" access-id="{{.}}"/>
{{- end}}
</security-role>
</application-bnd>
</enterpriseApplication>
<enterpriseApplication id="com.ibm.mq.rest">
<application-bnd>
<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>
<openidConnectClient id="mqclient"
clientId="${env.MQ_OIDC_CLIENT_ID}"
clientSecret="${env.MQ_OIDC_CLIENT_SECRET}"
authorizationEndpointUrl="${env.MQ_OIDC_AUTHORIZATION_ENDPOINT}"
tokenEndpointUrl="${env.MQ_OIDC_TOKEN_ENDPOINT}"
scope="openid profile email"
inboundPropagation="supported"
jwkEndpointUrl="${env.MQ_OIDC_JWK_ENDPOINT}"
signatureAlgorithm="RS256"
issuerIdentifier="${env.MQ_OIDC_ISSUER_IDENTIFIER}">
</openidConnectClient>
<variable name="httpHost" value="*"/>
<keyStore id="MQWebKeyStore" location="/run/tls/key.jks" type="JKS" password="password"/>
<keyStore id="MQWebTrustStore" location="/run/tls/trust.jks" type="JKS" password="password"/>
<ssl id="thisSSLConfig" clientAuthenticationSupported="true" keyStoreRef="MQWebKeyStore" trustStoreRef="MQWebTrustStore" sslProtocol="TLSv1.2" serverKeyAlias="default"/>
<sslDefault sslRef="thisSSLConfig"/>
<httpDispatcher enableWelcomePage="false" appOrContextRootMissingMessage='&lt;script&gt;document.location.href="/ibmmq/console";&lt;/script&gt;' />
</server>