Skip to content
21 changes: 21 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,27 @@ allprojects {
force "io.grpc:grpc-stub:${grpcVersion}"
force "io.grpc:grpc-xds:${grpcVersion}"

// Netty - transitive dependency via azure-core-http-netty; force for CVE-2025-67735
force "io.netty:netty-buffer:${nettyVersion}"
force "io.netty:netty-codec:${nettyVersion}"
force "io.netty:netty-codec-dns:${nettyVersion}"
force "io.netty:netty-codec-http:${nettyVersion}"
force "io.netty:netty-codec-http2:${nettyVersion}"
force "io.netty:netty-codec-socks:${nettyVersion}"
force "io.netty:netty-common:${nettyVersion}"
force "io.netty:netty-handler:${nettyVersion}"
force "io.netty:netty-handler-proxy:${nettyVersion}"
force "io.netty:netty-resolver:${nettyVersion}"
force "io.netty:netty-resolver-dns:${nettyVersion}"
force "io.netty:netty-resolver-dns-classes-macos:${nettyVersion}"
force "io.netty:netty-resolver-dns-native-macos:${nettyVersion}"
force "io.netty:netty-transport:${nettyVersion}"
force "io.netty:netty-transport-classes-epoll:${nettyVersion}"
force "io.netty:netty-transport-classes-kqueue:${nettyVersion}"
force "io.netty:netty-transport-native-epoll:${nettyVersion}"
force "io.netty:netty-transport-native-kqueue:${nettyVersion}"
force "io.netty:netty-transport-native-unix-common:${nettyVersion}"

// tcrdb, cloud, SequenceAnalysis, recipe mfa, pipeline, fileTransfer, docker mcc, DiscvrLabKeyModules:Studies and api have differnet versions of these libraries, so we need to force these versions
force "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
force "com.fasterxml.jackson.core:jackson-databind:${jacksonDatabindVersion}"
Expand Down
7 changes: 7 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ npmWorkDirectory=.node
angusActivationVersion=2.0.3
angusMailVersion=2.0.5

# Microsoft libraries for sending OAuth2-authenticated notification emails via the Microsoft Graph API
azureIdentityVersion=1.18.1
microsoftGraphVersion=6.59.0

# Netty - transitive dependency via azure-core-http-netty; force for CVE-2025-67735
nettyVersion=4.2.8.Final

annotationsVersion=15.0

antVersion=1.10.15
Expand Down
8 changes: 7 additions & 1 deletion server/configs/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ context.encryptionKey=@@encryptionKey@@
#server.tomcat.max-part-header-size=512
#server.tomcat.max-connections=250

## SMTP configuration
## SMTP configuration - if using this, comment out Microsoft Graph configuration
mail.smtpHost=@@smtpHost@@
mail.smtpPort=@@smtpPort@@
mail.smtpUser=@@smtpUser@@
Expand All @@ -82,6 +82,12 @@ mail.smtpUser=@@smtpUser@@
#mail.smtpSocketFactoryClass=@@smtpSocketFactoryClass@@
#mail.smtpAuth=@@smtpAuth@@

## Microsoft Graph configuration - if using this, comment out SMTP configuration
#mail.graph.tenantId=@@graphTenantId@@
#mail.graph.fromAddress=@@graphFromAddress@@
#mail.graph.clientId=@@graphClientId@@
#mail.graph.clientSecret=@@graphClientSecret@@

# Optional - JMS configuration for remote ActiveMQ message management for distributed pipeline jobs
# https://www.labkey.org/Documentation/wiki-page.view?name=jmsQueue
#context.resources.jms.ConnectionFactory.type=org.apache.activemq.ActiveMQConnectionFactory
Expand Down
7 changes: 6 additions & 1 deletion server/configs/pg.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ smtpHost=localhost
smtpUser=Anonymous
smtpPort=25

#graphTenantId=
#graphFromAddress=
#graphClientId=
#graphClientSecret=<this should be a client secret value>

databaseDefault=labkey
databaseBootstrap=labkey2
databaseDefaultHost=localhost
Expand All @@ -16,4 +21,4 @@ jdbcUser=postgres
jdbcPassword=sasa

# key for the encrypted property store and other potentially sensitive content
encryptionKey=defaultKey
encryptionKey=defaultKey
56 changes: 56 additions & 0 deletions server/embedded/src/org/labkey/embedded/LabKeyServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ public MailProperties smtpSource()
return new MailProperties();
}

@Bean
public GraphMailProperties graphSource()
{
return new GraphMailProperties();
}

@Bean
public CSPFilterProperties cspSource()
{
Expand Down Expand Up @@ -875,6 +881,56 @@ public void setSmtpAuth(String smtpAuth)
}
}

@Configuration
@ConfigurationProperties("mail.graph")
public static class GraphMailProperties
{
private String tenantId;
private String clientId;
private String clientSecret;
private String fromAddress;

public String getTenantId()
{
return tenantId;
}

public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}

public String getClientId()
{
return clientId;
}

public void setClientId(String clientId)
{
this.clientId = clientId;
}

public String getClientSecret()
{
return clientSecret;
}

public void setClientSecret(String clientSecret)
{
this.clientSecret = clientSecret;
}

public String getFromAddress()
{
return fromAddress;
}

public void setFromAddress(String fromAddress)
{
this.fromAddress = fromAddress;
}
}

@Configuration
@ConfigurationProperties("csp")
public static class CSPFilterProperties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ protected TomcatWebServer getTomcatWebServer(Tomcat tomcat)
// Add extra resources to context (e.g. LDAP, JMS)
addExtraContextResources(contextProperties, context);

// Add the SMTP config
// Add the mail transport config (SMTP or Microsoft Graph)
addSmtpProperties(context);
addGraphProperties(context);

// Add the encryption key(s)
context.addParameter("EncryptionKey", contextProperties.getEncryptionKey());
Expand Down Expand Up @@ -409,10 +410,18 @@ private void addSmtpProperties(StandardContext context)
// Get session/mail properties
LabKeyServer.MailProperties mailProps = _server.smtpSource();

context.addParameter("mail.smtp.host", mailProps.getSmtpHost());
context.addParameter("mail.smtp.user", mailProps.getSmtpUser());
context.addParameter("mail.smtp.port", mailProps.getSmtpPort());

if (mailProps.getSmtpHost() != null)
{
context.addParameter("mail.smtp.host", mailProps.getSmtpHost());
}
if (mailProps.getSmtpUser() != null)
{
context.addParameter("mail.smtp.user", mailProps.getSmtpUser());
}
if (mailProps.getSmtpPort() != null)
{
context.addParameter("mail.smtp.port", mailProps.getSmtpPort());
}
if (mailProps.getSmtpFrom() != null)
{
context.addParameter("mail.smtp.from", mailProps.getSmtpFrom());
Expand All @@ -434,4 +443,27 @@ private void addSmtpProperties(StandardContext context)
context.addParameter("mail.smtp.auth", mailProps.getSmtpAuth());
}
}

private void addGraphProperties(StandardContext context)
{
// Get Microsoft Graph mail properties
LabKeyServer.GraphMailProperties graphProps = _server.graphSource();

if (graphProps.getTenantId() != null)
{
context.addParameter("mail.graph.tenantId", graphProps.getTenantId());
}
if (graphProps.getClientId() != null)
{
context.addParameter("mail.graph.clientId", graphProps.getClientId());
}
if (graphProps.getClientSecret() != null)
{
context.addParameter("mail.graph.clientSecret", graphProps.getClientSecret());
}
if (graphProps.getFromAddress() != null)
{
context.addParameter("mail.graph.fromAddress", graphProps.getFromAddress());
}
}
}