From b82cab4cd462fd2c60c1e4380aac39c8970c9739 Mon Sep 17 00:00:00 2001 From: Ryan Doherty Date: Tue, 2 Jul 2024 13:54:21 -0400 Subject: [PATCH 1/5] Upgrade servlet spec --- EuPathDB/src/main/webapp/WEB-INF/web.xml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/EuPathDB/src/main/webapp/WEB-INF/web.xml b/EuPathDB/src/main/webapp/WEB-INF/web.xml index d79a7a1..3f75026 100644 --- a/EuPathDB/src/main/webapp/WEB-INF/web.xml +++ b/EuPathDB/src/main/webapp/WEB-INF/web.xml @@ -1,10 +1,8 @@ - + From 0ac26ce14ebc9c5db9829c91880eaf63a1dd16b2 Mon Sep 17 00:00:00 2001 From: Ryan Doherty Date: Tue, 2 Jul 2024 15:17:26 -0400 Subject: [PATCH 2/5] Adjust log location --- EuPathDB/src/main/resources/log4j2.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EuPathDB/src/main/resources/log4j2.json b/EuPathDB/src/main/resources/log4j2.json index 106635e..97f7010 100644 --- a/EuPathDB/src/main/resources/log4j2.json +++ b/EuPathDB/src/main/resources/log4j2.json @@ -4,8 +4,8 @@ "appender": [{ "type": "RollingFile", "name": "oauth-log", - "fileName": "${sys:catalina.base}/logs/oauth/oauth.log", - "filePattern": "${sys:catalina.base}/logs/oauth/oauth.log.%i", + "fileName": "/opt/logs/tomcat/oauth/oauth.log", + "filePattern": "/opt/logs/tomcat/oauth/oauth.log.%i", "append": "true", "PatternLayout": { "pattern": "%-9r [%-5p] [%d{yyyy/MM/dd|HH:mm:ss}] - %C:%L - %m%n" }, "Policies": { @@ -15,8 +15,8 @@ },{ "type": "RollingFile", "name": "login-log", - "fileName": "${sys:catalina.base}/logs/oauth/logins.log", - "filePattern": "${sys:catalina.base}/logs/oauth/logins.log.%i", + "fileName": "/opt/logs/tomcat/oauth/logins.log", + "filePattern": "/opt/logs/tomcat/oauth/logins.log.%i", "append": "true", "PatternLayout": { "pattern": "%d{yyyy-MM-dd|HH:mm:ss} %m%n" }, "Policies": { From 5c79f8249ce672c1da80cfeb4ceee51c9eaddec5 Mon Sep 17 00:00:00 2001 From: Ryan Doherty Date: Wed, 10 Jul 2024 06:22:42 -0400 Subject: [PATCH 3/5] Always use https in redirects to the local server --- .../java/org/gusdb/oauth2/service/OAuthService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Server/src/main/java/org/gusdb/oauth2/service/OAuthService.java b/Server/src/main/java/org/gusdb/oauth2/service/OAuthService.java index 522fb3f..c05248d 100644 --- a/Server/src/main/java/org/gusdb/oauth2/service/OAuthService.java +++ b/Server/src/main/java/org/gusdb/oauth2/service/OAuthService.java @@ -45,6 +45,7 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Variant; import org.apache.logging.log4j.LogManager; @@ -99,6 +100,9 @@ private static enum LoginFormStatus { failed, error, accessdenied; } @Context private HttpHeaders _headers; + @Context + private UriInfo _uriInfo; + @GET @Path(Endpoints.ASSETS + "{name:.+}") public Response getStaticFile(@PathParam("name") String name) { @@ -140,8 +144,8 @@ public Response attemptLogin( AuthzRequest originalRequest = (formId == null ? null : session.clearFormId(formId)); if (originalRequest == null) { // formId doesn't exist on this session; give user generic success page - return Response.seeOther(new URI(RESOURCE_PREFIX + - config.getLoginSuccessPage())).build(); + String baseUri = _uriInfo.getBaseUri().toString().replace("http://", "https://"); + return Response.seeOther(new URI(baseUri + RESOURCE_PREFIX + config.getLoginSuccessPage())).build(); } authenticator.logSuccessfulLogin(loginName, validUserId.get(), originalRequest.getClientId(), originalRequest.getRedirectUri(), _request.getRemoteAddr()); return OAuthRequestHandler.handleAuthorizationRequest(originalRequest, loginName, validUserId.get(), config.getTokenExpirationSecs()); @@ -255,7 +259,8 @@ private URI getLoginUri(String formId, String redirectUri, LoginFormStatus statu if (status != null) { queryString += (queryString.isEmpty() ? "" : "&") + "status=" + status.name(); } - return new URI(RESOURCE_PREFIX + OAuthServlet.getApplicationConfig(_context).getLoginFormPage() + + String baseUri = _uriInfo.getBaseUri().toString().replace("http://", "https://"); + return new URI(baseUri + RESOURCE_PREFIX + OAuthServlet.getApplicationConfig(_context).getLoginFormPage() + (queryString.isEmpty() ? "" : "?" + queryString)); } From 4ab140b9588e7f3785378ee24b9dc24cbc138bd2 Mon Sep 17 00:00:00 2001 From: Dan Galdi Date: Fri, 9 Aug 2024 11:31:31 -0400 Subject: [PATCH 4/5] Postgres support --- EuPathDB/pom.xml | 1 - .../gusdb/oauth2/eupathdb/AccountDbAuthenticator.java | 2 +- .../gusdb/oauth2/eupathdb/BearerTokenGenerator.java | 11 +++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/EuPathDB/pom.xml b/EuPathDB/pom.xml index 3e08267..74d82a6 100644 --- a/EuPathDB/pom.xml +++ b/EuPathDB/pom.xml @@ -79,7 +79,6 @@ org.apache.logging.log4j log4j-core - diff --git a/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/AccountDbAuthenticator.java b/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/AccountDbAuthenticator.java index 19f9f45..b81b4f9 100644 --- a/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/AccountDbAuthenticator.java +++ b/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/AccountDbAuthenticator.java @@ -208,7 +208,7 @@ public String getNextGuestId() { String id = new AccountManager(_accountDb, _schema, USER_PROPERTY_DEFS).createGuestAccount("guest_").getUserId().toString(); // FIXME: since this code directly accesses the DB, it should live in AccountManager; // however that complicates FgpUtil releases prior to move to bearer tokens, so adding it here. - String sql = "insert into useraccounts.guest_ids (user_id, creation_time) values (?, TO_DATE(SYSDATE))"; + String sql = "insert into useraccounts.guest_ids (user_id, creation_time) values (?, current_date)"; int inserted = new SQLRunner(_accountDb.getDataSource(), sql, "insert-guest-id") .executeUpdate(new Object[]{ Long.valueOf(id) }, new Integer[]{ Types.BIGINT }); if (inserted != 1) throw new IllegalStateException("Tried to insert duplicate guest ID " + id + ". Check ID sequence to make sure it is big enough."); diff --git a/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/BearerTokenGenerator.java b/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/BearerTokenGenerator.java index d74fc82..c79bc13 100644 --- a/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/BearerTokenGenerator.java +++ b/EuPathDB/src/main/java/org/gusdb/oauth2/eupathdb/BearerTokenGenerator.java @@ -28,13 +28,14 @@ public class BearerTokenGenerator extends ToolBase { private static final String PROP_ACCOUNTDB_LOGIN = "accountDbLogin"; private static final String PROP_ACCOUNTDB_PASSWORD = "accountDbPassword"; private static final String PROP_LOGIN_NAME = "loginName"; + private static final String PROP_DB_PLATFORM = "dbPlatform"; public static void main(String[] args) throws Exception { new BearerTokenGenerator(args).execute(); } public BearerTokenGenerator(String[] args) { - super(args, new String[] { PROP_KEYSTORE_FILE, PROP_KEYSTORE_PASSPHRASE, PROP_ACCOUNTDB_LOGIN, PROP_ACCOUNTDB_PASSWORD, PROP_LOGIN_NAME }); + super(args, new String[] { PROP_KEYSTORE_FILE, PROP_KEYSTORE_PASSPHRASE, PROP_ACCOUNTDB_LOGIN, PROP_ACCOUNTDB_PASSWORD, PROP_LOGIN_NAME, PROP_DB_PLATFORM }); } public void execute() throws Exception { @@ -44,13 +45,15 @@ public void execute() throws Exception { String accountDbLogin = findProp(PROP_ACCOUNTDB_LOGIN); String accountDbPassword = findProp(PROP_ACCOUNTDB_PASSWORD); String loginName = findProp(PROP_LOGIN_NAME); + String platform = findProp(PROP_DB_PLATFORM); SigningKeyStore keyStore = new SigningKeyStore(new KeyPairReader().readKeyPair(Paths.get(keyStoreFile), keyStorePassPhrase)); + // dummy up a client; SigningKeyStore requires >0 but will not be used here keyStore.setClientSigningKeys("abc", Set.of("mug2kfCI8qhXzrnuE/nh1gK9JbSFaXaih+zdsfD8io25MWH4b3V5u+U8E7SW4x7iBAHdq6yWWrF/TP9p098lfQ==")); // generate a new token for this account - String token = generateToken(keyStore, accountDbLogin, accountDbPassword, loginName); + String token = generateToken(keyStore, accountDbLogin, accountDbPassword, loginName, platform); System.out.println("Bearer Token\n\n" + token + "\n"); // verify token using same method as the client @@ -71,13 +74,13 @@ public void execute() throws Exception { System.out.println("Subject after parsing token: " + claims.getSubject()); } - private static String generateToken(SigningKeyStore keyStore, String accountDbLogin, String accountDbPassword, String loginName) throws Exception { + private static String generateToken(SigningKeyStore keyStore, String accountDbLogin, String accountDbPassword, String loginName, String dbPlatform) throws Exception { JsonObject authenticatorConfig = Json.createObjectBuilder() .add("login", accountDbLogin) .add("password", accountDbPassword) .add("connectionUrl", "jdbc:oracle:thin:@localhost:5011/acctdb.upenn.edu") - .add("platform", "Oracle") + .add("platform", dbPlatform) .add("poolSize", 1) .add("schema", "useraccounts.") .build(); From 37c4d752cdbc40a8041ad1459b7f12d8f7c296d5 Mon Sep 17 00:00:00 2001 From: Ryan Doherty Date: Thu, 22 Aug 2024 01:18:58 -0400 Subject: [PATCH 5/5] Move shared logic into common file and download settings.xml for build in case user does not have it in ~/.m2 --- bin/createHmacSecretValue.sh | 28 +++++------------------ bin/createPrivateKeyFile.sh | 28 ++++++++--------------- bin/shared.sh | 44 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 41 deletions(-) create mode 100644 bin/shared.sh diff --git a/bin/createHmacSecretValue.sh b/bin/createHmacSecretValue.sh index ed10f03..e49e5e4 100755 --- a/bin/createHmacSecretValue.sh +++ b/bin/createHmacSecretValue.sh @@ -1,28 +1,12 @@ #!/bin/bash -# record the current directory for output -RUN_DIR=$(pwd) - # get to the parent directory of the bin dir -PROJECT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/.. -cd $PROJECT_DIR - -# only build uber-jar if necessary -if [ ! -e Server/target/uber-jar.jar ]; then - - # tell the user what we're doing - echo "Project not built; this will take a few moments..." - echo - - # build the entire project to cache snapshot deps in local mvn repo - mvn clean install &> /dev/null +cd $( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/.. - # package the server component into an uber jar - cd Server - mvn clean package assembly:single &> /dev/null - cd .. +source bin/shared.sh -fi +buildUberJar -# generate a random value of sufficient length -java -classpath Server/target/uber-jar.jar org.gusdb.oauth2.tools.KeyGenerator HmacSHA512 +echo +createHmacValue +echo diff --git a/bin/createPrivateKeyFile.sh b/bin/createPrivateKeyFile.sh index afe31cc..b9c4c6b 100755 --- a/bin/createPrivateKeyFile.sh +++ b/bin/createPrivateKeyFile.sh @@ -9,30 +9,20 @@ if [ "$#" != "1" ]; then fi passPhrase=$1 -outputFile=ecKeys.$( date +%s%3N ).pkcs12 - -# record the current directory for output -RUN_DIR=$(pwd) +outputFilename=ecKeys.$( date +%s%3N ).pkcs12 +outputFile=$(pwd)/$outputFilename # get to the parent directory of the bin dir -PROJECT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/.. -cd $PROJECT_DIR - -# only build uber-jar if necessary -if [ ! -e Server/target/uber-jar.jar ]; then +cd $( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/.. - # build the entire project to cache snapshot deps in local mvn repo - mvn clean install +source bin/shared.sh - # package the server component into an uber jar - cd Server - mvn clean package assembly:single - cd .. - -fi +buildUberJar # generate a random seed of sufficient length -seed=$( java -classpath Server/target/uber-jar.jar org.gusdb.oauth2.tools.KeyGenerator HmacSHA512 ) +seed=$(createHmacValue) # generate the key and write to file -java -classpath Server/target/uber-jar.jar org.gusdb.oauth2.tools.KeyPairWriter $outputFile "$passPhrase" $seed && echo "Wrote key file to $outputFile" +echo +java -classpath Server/target/uber-jar.jar org.gusdb.oauth2.tools.KeyPairWriter $outputFile "$passPhrase" $seed \ + && echo && echo "Wrote key file to $outputFilename" && echo diff --git a/bin/shared.sh b/bin/shared.sh new file mode 100644 index 0000000..19583c8 --- /dev/null +++ b/bin/shared.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +fetchSettings() { + if [ "$GITHUB_USERNAME" == "" ]; then + echo 'Environment variable $GITHUB_USERNAME must be set' + exit 1 + fi + if [ "$GITHUB_TOKEN" == "" ]; then + echo 'Environment variable $GITHUB_TOKEN must be set' + exit 1 + fi + echo "Github credentials for $GITHUB_USERNAME found in environment" + + echo "Fetching settings.xml" \ + && curl --no-progress-meter -O https://raw.githubusercontent.com/VEuPathDB/maven-release-tools/main/settings.xml +} + +buildUberJar() { + # only build uber-jar if necessary + if [ ! -e Server/target/uber-jar.jar ]; then + + # tell the user what we're doing + echo "Project not built; this will take a few moments (script will be faster next time)..." + + fetchSettings + + # build the entire project to cache snapshot deps in local mvn repo + echo "Building code..." + mvn --settings ./settings.xml clean install &> /dev/null + + # package the server component into an uber jar + cd Server + echo "Building uber jar..." + mvn --settings ../settings.xml clean package assembly:single &> /dev/null + cd .. + + rm settings.xml + fi +} + +createHmacValue() { + # generate a random value of sufficient length + java -classpath Server/target/uber-jar.jar org.gusdb.oauth2.tools.KeyGenerator HmacSHA512 +}