diff --git a/README.md b/README.md index 2b01aaeec..047cb1252 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ First, [install Gradle](https://gradle.org/install/). Then, in an empty directory, create a file named "build.gradle" with your favorite text editor and enter the following: - plugins { id "com.marklogic.ml-gradle" version "3.4.0" } + plugins { id "com.marklogic.ml-gradle" version "3.6.1" } Then run: - gradle mlNew + gradle mlNewProject This starts a project wizard to stub out files for your new application. You can accept all the defaults, but be sure to enter a valid port number for the "REST API port" question. ml-gradle will then print the following logging: diff --git a/examples/external-security/.gitignore b/examples/external-security/.gitignore new file mode 100644 index 000000000..73e810817 --- /dev/null +++ b/examples/external-security/.gitignore @@ -0,0 +1,2 @@ +gradle-local.properties +.gradle diff --git a/examples/external-security/README.md b/examples/external-security/README.md new file mode 100644 index 000000000..f48c6a543 --- /dev/null +++ b/examples/external-security/README.md @@ -0,0 +1,3 @@ +This project shows how to configure an external security and use it in an application server. + +If you want to deploy using a user with external security you'll need to configure the Admin, App-Services and Manage servers ahead of time. \ No newline at end of file diff --git a/examples/external-security/build.gradle b/examples/external-security/build.gradle new file mode 100644 index 000000000..5753e15fc --- /dev/null +++ b/examples/external-security/build.gradle @@ -0,0 +1,3 @@ +plugins { + id "com.marklogic.ml-gradle" version "3.6.0" +} \ No newline at end of file diff --git a/examples/external-security/gradle.properties b/examples/external-security/gradle.properties new file mode 100644 index 000000000..f925c4cab --- /dev/null +++ b/examples/external-security/gradle.properties @@ -0,0 +1,17 @@ +mlHost=localhost +mlAppName=external-security-example +mlRestPort=8141 +mlUsername=admin +mlPassword=admin + +#leave blank if you do not want an External Security Configuration used for an application server +cpExternalSecurity=example + +#the below is needed if you want to deploy with an external user +#basic is used in this example but kerberos-ticket could also be used +mlRestAuthentication=basic +mlAppServicesAuthentication=basic +mlAdminAuthentication=basic +mlManageAuthentication=basic + + diff --git a/examples/external-security/gradlew b/examples/external-security/gradlew new file mode 100755 index 000000000..4453ccea3 --- /dev/null +++ b/examples/external-security/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/examples/external-security/gradlew.bat b/examples/external-security/gradlew.bat new file mode 100644 index 000000000..f9553162f --- /dev/null +++ b/examples/external-security/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/external-security/src/main/ml-config/security/external-security/example.xml b/examples/external-security/src/main/ml-config/security/external-security/example.xml new file mode 100644 index 000000000..eded99c72 --- /dev/null +++ b/examples/external-security/src/main/ml-config/security/external-security/example.xml @@ -0,0 +1,13 @@ + + example + + ldap + 300 + internal + ldap://localhost:389 + base + ou + guest + password + MD5 + \ No newline at end of file diff --git a/examples/external-security/src/main/ml-config/servers/example.json b/examples/external-security/src/main/ml-config/servers/example.json new file mode 100644 index 000000000..feafcf2b3 --- /dev/null +++ b/examples/external-security/src/main/ml-config/servers/example.json @@ -0,0 +1,6 @@ +{ + "server-type": "http", + "server-name": "%%NAME%%", + "authentication": "basic", + "external-security":["%%cpExternalSecurity%%"] +} \ No newline at end of file diff --git a/examples/ssl-2way-project/README.md b/examples/ssl-2way-project/README.md index 0aa20e475..25126ce4e 100644 --- a/examples/ssl-2way-project/README.md +++ b/examples/ssl-2way-project/README.md @@ -1,90 +1,67 @@ -This project shows how to create an SSLContext to support deploying modules when 2-way SSL is configured -for an app server. +This project shows how to create an SSLContext to support deploying modules when 2-way SSL is configured for an app server. -2-way SSL requires a certificate template to be configured on the MarkLogic app server, -"ssl require client certificate" set to true and one or more "ssl client certificate authorities" -selected indicating which CAs the client certificates must be signed by. +2-way SSL requires a certificate template to be configured on the MarkLogic app server, "ssl require client certificate" set to true and one or more "ssl client certificate authorities" selected indicating which CAs the client certificates must be signed by. -Follow instructions here https://docs.marklogic.com/guide/security/SSL to setup SSL for -the MarkLogic app server. +Follow instructions here to setup SSL for the MarkLogic app server. -To make this work, you will need a certificate authority (CA) that can sign certificates for you. -You can either use a known 3rd party or setup your own CA for testing. The rest of the instructions -assume that the same CA is used to sign both the client and the server certificates. +To make this work, you will need a certificate authority (CA) that can sign certificates for you. You can either use a known 3rd party or setup your own CA for testing. The rest of the instructions assume that the same CA is used to sign both the client and the server certificates. -## Create a server certificate -If the server does not yet have a certificate signed by your CA, you will need to get one and imort -it to the server. If you already have server certificated signed by the CA, you can skip this step. +### Create a server certificate +If the server does not yet have a certificate signed by your CA, you will need to get one and imort it to the server. If you already have server certificated signed by the CA, you can skip this step. -1) Using the certificate template created above, generate and download a certificate request (CSR). Use -that CSR to request a certificate from the CA (or generate one yourself if you have your own CA). +#### Generate and download a certificate request (CSR) -_Important: Your CSR will have the values for country, state/province, city/town, organization, -organizational unit and email address from the certificate template. Your CA will have requirements -for what must be in each of those fields. If using your own CA to sign certificates, you will need -to configure openssl to be able to process CSRs with the values from the template or set the template -values to the values needed for your openssl CA configuration before generating the server CSR._ +Using the certificate template created above, generate and download a certificate request (CSR). Use that CSR to request a certificate from the CA (or generate one yourself if you have your own CA). + +_Important: Your CSR will have the values for country, state/province, city/town, organization, organizational unit and email address from the certificate template. Your CA will have requirements for what must be in each of those fields. If using your own CA to sign certificates, you will need to configure openssl to be able to process CSRs with the values from the template or set the template values to the values needed for your openssl CA configuration before generating the server CSR._ The following are helpful resources if considering setting up your own CA for testing: -* https://www.area536.com/projects/be-your-own-certificate-authority-with-openssl/ -* https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html +* +* -1) Once you have the signed server certificate, import it into the server using the "Import" tab of -the certificate template used to generate the CSR. +#### Import the signed server certificate +Once you have the signed server certificate, import it into the server using the "Import" tab of the certificate template used to generate the CSR. -_Important: The CN in the server cert will be the hostname of the MarkLogic host as seen from the "Hosts" list in -the admin UI. This will need to be the hostname you use to connect to MarkLogic if hostname verification is -being used._ +_Important: The CN in the server cert will be the hostname of the MarkLogic host as seen from the "Hosts" list in the admin UI. This will need to be the hostname you use to connect to MarkLogic if hostname verification is being used._ -## Create a client certificate -Since we are using ml-gradle which uses the MarkLogic Java Client under the covers, we need to use the -Java SSL libraries to setup the client SSL configuration. Java uses a "keystore" to manage client and -CA certificates. We will use the Java _keytool_ commandline tool to setup a keystore for the client. +### Create a client certificate +Since we are using ml-gradle which uses the MarkLogic Java Client under the covers, we need to use the Java SSL libraries to setup the client SSL configuration. Java uses a "keystore" to manage client and CA certificates. We will use the Java _keytool_ commandline tool to setup a keystore for the client. The follow instructions were guided by the following helpful resources: -* https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html -* https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores +* +* -1) Create a keystore +#### Create a keystore ``` keytool -keystore clientkeystore -genkey -alias client ``` -You will be prompted for a password for the keystore. Remember this and use it as the `mlKeystorePassword` -in the `gradle.properties` file. +You will be prompted for a password for the keystore. Remember this and use it as the `mlKeystorePassword` in the `gradle.properties` file. -You will be propted to enter values for your name (CN), country, state/province, city/town, organization and -organizational unit. Enter values as required by your CA but make sure to use the MarkLogic username that will -be using the certificate when propted for "your first and last name". This is the CN stored in the certificate. +You will be propted to enter values for your name (CN), country, state/province, city/town, organization and organizational unit. Enter values as required by your CA but make sure to use the MarkLogic username that will be using the certificate when propted for "your first and last name". This is the CN stored in the certificate. -_Important: The CN in client certificate needs to match the user name that you will use to connect to -MarkLogic or authentication will fail._ +_Important: The CN in client certificate needs to match the user name that you will use to connect to MarkLogic or authentication will fail._ -If you want a different password on the client certificate, enter one when prompted and use this as the -`mlKeystoreCertPassword` in the `gradle.properties` file. Otherwise, hit enter to use the same password as the -keystore. +If you want a different password on the client certificate, enter one when prompted and use this as the `mlKeystoreCertPassword` in the `gradle.properties` file. Otherwise, hit enter to use the same password as the keystore. -When complete, this will create a file called `clientkeystore` (you can name this file whatever you want though). -Use this as the value for `mlKeystore` in the `gradle.properties` file. +When complete, this will create a file called `clientkeystore` (you can name this file whatever you want though). Use this as the value for `mlKeystore` in the `gradle.properties` file. -1) Create a client CSR +#### Create a client CSR ``` keytool -keystore clientkeystore -certreq -alias client -keyalg rsa -file client.csr ``` -1) Use the CSR to have a CA to generate a signed client certificate (or generate one using your own CA) +#### Generate a signed client certificate +Use the CSR to have a CA generate a signed client certificate (or generate one using your own CA) -1) Import the CA certificate +#### Import the CA certificate ``` keytool -import -keystore clientkeystore -file ca.crt -alias theCARoot ``` -1) Import the signed client certificate +#### Import the signed client certificate ``` keytool -import -keystore clientkeystore -file client.crt -alias client ``` - - - -s +Use the client keystore filename as the value for `mlKeystore` in the `gradle.properties` file.