Skip to content

Commit 1c6dd9a

Browse files
umeshwaghodecx-leonelsanchesHussainS12
authored
JDK8 new version uptake in the docker image and other pipeline fixes. (checkmarx-ltd#1019)
*Added support for SendGrid as new BugTracker *Upgraded spring boot 2.7.0 and spring core to 5.3.20 to fix vulnerabilities *Upgraded openjdk8 version inside Dockerfile. * Updated test data to fix failing test cases Co-authored-by: Leonel Sanches <[email protected]> Co-authored-by: HussainS12 <[email protected]>
1 parent 46bfb2b commit 1c6dd9a

File tree

13 files changed

+248
-75
lines changed

13 files changed

+248
-75
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ cx-flow.log*
3131

3232
### VSCode ###
3333
.vscode
34+
.DS_Store

Diff for: Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ WORKDIR app
44
RUN apk update && \
55
apk upgrade && \
66
apk upgrade
7-
RUN apk add openjdk8=8.302.08-r2 --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community
7+
RUN apk add openjdk8=8.322.06-r0 --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community
88
ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk
99
COPY build/libs/*.jar cx-flow.jar
1010
ENTRYPOINT ["java", "-Xms512m", "-Xmx2048m", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=web", "-jar", "cx-flow.jar"]

Diff for: build-11.gradle

+9-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import org.gradle.api.tasks.testing.Test
22

33
buildscript {
44
ext {
5-
CxSBSDK = "0.5.17"
5+
CxSBSDK = "0.5.18"
66
ConfigProviderVersion = "1.0.9"
77
//cxVersion = "8.90.5"
8-
springBootVersion = '2.6.6'
8+
springBootVersion = '2.7.0'
99
sonarqubeVersion = '2.8'
1010
atlassianVersion = "5.2.0"
1111
atlassianFugueVersion = "4.7.2"
@@ -63,7 +63,7 @@ configurations {
6363
ext['tomcat.version'] = '9.0.62'
6464
ext['groovy.version'] = '3.0.9'
6565
ext['logback-classic.version'] = '1.2.10'
66-
ext['spring-core.version'] = '5.3.18'
66+
ext['spring-core.version'] = '5.3.20'
6767

6868
dependencies {
6969
compile group: 'com.beust', name: 'jcommander', version: '1.78'
@@ -113,8 +113,10 @@ dependencies {
113113
compile("com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}")
114114
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}")
115115
compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}")
116-
//compile ("org.thymeleaf:thymeleaf:3.0.11.RELEASE")
116+
117117
compile("org.thymeleaf:thymeleaf-spring5:3.0.15.RELEASE")
118+
implementation 'ognl:ognl:3.3.2'
119+
118120
compile ("org.apache.httpcomponents:httpclient:4.5.13")
119121
compile ("org.codehaus.groovy:groovy-all:3.0.9") {
120122
exclude group: 'org.apache.ant', module: 'ant'
@@ -172,6 +174,9 @@ dependencies {
172174
compile("javax.persistence:javax.persistence-api:2.2")
173175
compile group:'org.apache.tomcat', name:'tomcat-juli', version:property('tomcat.version')
174176
compile group:'org.springframework', name:'spring-core', version:property('spring-core.version')
177+
178+
implementation group: 'com.sendgrid', name: 'sendgrid-java', version: '4.9.0'
179+
175180
}
176181

177182
springBoot {

Diff for: build.gradle

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
buildscript {
22
ext {
3-
CxSBSDK = "0.5.17"
3+
CxSBSDK = "0.5.18"
44
ConfigProviderVersion = "1.0.10"
55
//cxVersion = "8.90.5"
6-
springBootVersion = '2.6.6'
6+
springBootVersion = '2.7.0'
77
sonarqubeVersion = '2.8'
88
atlassianVersion = "5.2.0"
99
atlassianFugueVersion = "4.7.2"
@@ -75,7 +75,7 @@ configurations {
7575
ext['tomcat.version'] = '9.0.62'
7676
ext['groovy.version'] = '3.0.9'
7777
ext['logback-classic.version'] = '1.2.10'
78-
ext['spring-core.version'] = '5.3.18'
78+
ext['spring-core.version'] = '5.3.20'
7979

8080
dependencies {
8181
compile group: 'com.beust', name: 'jcommander', version: '1.78'
@@ -132,8 +132,10 @@ dependencies {
132132
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}")
133133
compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}")
134134
compile("org.apache.httpcomponents:httpclient:4.5.13")
135-
//compile("org.thymeleaf:thymeleaf:3.0.11.RELEASE")
135+
136136
compile("org.thymeleaf:thymeleaf-spring5:3.0.15.RELEASE")
137+
implementation 'ognl:ognl:3.3.2'
138+
137139
compile("org.codehaus.groovy:groovy-all:3.0.9") {
138140
exclude group: 'org.apache.ant', module: 'ant'
139141
exclude group: 'org.webjars', module: 'jquery'
@@ -199,6 +201,7 @@ dependencies {
199201
compile group:'org.apache.tomcat', name:'tomcat-juli', version:property('tomcat.version')
200202
compile group:'org.springframework', name:'spring-core', version:property('spring-core.version')
201203

204+
implementation group: 'com.sendgrid', name: 'sendgrid-java', version: '4.9.0'
202205
}
203206

204207
springBoot {

Diff for: docs/Bug-Trackers-and-Feedback-Channels.md

+42
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* [CxXML](#cxxml)
1919
* [Json](#json)
2020
* [CSV](#csv)
21+
* [Email](#email)
2122
* [NONE|WAIT](#none)
2223

2324
## <a name="data">Understanding the Data</a>
@@ -313,6 +314,7 @@ Valid options for `bug-tracker-impl` are currently the following ones:
313314
* Azure
314315
* CxXML - Only available for SAST 8.x|9.x
315316
* Csv
317+
* Email
316318
* JIRA
317319
* Json
318320
* GitHub
@@ -630,6 +632,46 @@ The file system path and the file naming format are required.
630632

631633
**[TIMESTAMP]** → Current timestamp (yyyyMMdd.HHmmss format)
632634

635+
## <a name="email">Email Notifications</a>
636+
CxFlow works with SMTP and SendGrid to notify users through e-mail.
637+
638+
```yaml
639+
cx-flow:
640+
bug-tracker: Email
641+
mail:
642+
host: smtp.gmail.com
643+
port: 587
644+
username: xxx
645+
password: xxx
646+
notification: true # Required if using SendGrid
647+
sendgrid:
648+
api-token: your-sendgrid-token-here
649+
```
650+
651+
`cx-flow.mail.notification` send two e-mail events: Scan Submitted and Scan Completed. The default is `false` (no e-mail are sent, even if all parameters are configured).
652+
653+
If using SMTP, the following fields are required:
654+
655+
```yaml
656+
cx-flow:
657+
bug-tracker: Email
658+
mail:
659+
host: smtp.gmail.com
660+
port: 587
661+
username: xxx
662+
password: xxx
663+
notification: true
664+
```
665+
666+
If using SendGrid, only the notification field and the API Token are required.
667+
668+
```yaml
669+
cx-flow:
670+
mail:
671+
notification: true # Required if using SendGrid
672+
sendgrid:
673+
api-token: your-sendgrid-token-here
674+
```
633675

634676
## <a name="none">NONE | WAIT</a>
635677
If you want to trigger scans asynchronously, use **NONE**

Diff for: src/main/java/com/checkmarx/flow/config/FlowProperties.java

+21
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ public static class Mail {
339339
private boolean notificationEnabled = false;
340340
private boolean allowEmptyMail = false;
341341
private String template;
342+
private SendGrid sendgrid;
342343

343344
public String getHost() {
344345
return this.host;
@@ -395,6 +396,26 @@ public void setAllowEmptyMail(boolean allowEmptyMail) {
395396
public String getTemplate() { return template; }
396397

397398
public void setTemplate(String template) { this.template = template; }
399+
400+
public SendGrid getSendgrid() {
401+
return sendgrid;
402+
}
403+
404+
public void setSendgrid(SendGrid sendgrid) {
405+
this.sendgrid = sendgrid;
406+
}
407+
}
408+
409+
public static class SendGrid {
410+
private String apiToken;
411+
412+
public String getApiToken() {
413+
return apiToken;
414+
}
415+
416+
public void setApiToken(String apiToken) {
417+
this.apiToken = apiToken;
418+
}
398419
}
399420

400421
public boolean isCxGoEnabled() {

Diff for: src/main/java/com/checkmarx/flow/service/EmailService.java

+85-38
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,28 @@ public class EmailService {
3333
private final FlowProperties flowProperties;
3434
private final TemplateEngine templateEngine;
3535
private final JavaMailSender emailSender;
36+
private final SendGridService sendGridService;
3637

37-
@ConstructorProperties({"flowProperties", "templateEngine", "emailSender"})
38-
public EmailService(FlowProperties flowProperties, @Qualifier("cxFlowTemplateEngine") TemplateEngine templateEngine, JavaMailSender emailSender) {
38+
@ConstructorProperties({"flowProperties", "templateEngine", "emailSender", "sendGridService"})
39+
public EmailService(FlowProperties flowProperties,
40+
@Qualifier("cxFlowTemplateEngine") TemplateEngine templateEngine,
41+
JavaMailSender emailSender,
42+
SendGridService sendGridService) {
3943
this.flowProperties = flowProperties;
4044
this.templateEngine = templateEngine;
4145
this.emailSender = emailSender;
46+
this.sendGridService = sendGridService;
4247
}
4348

4449
/**
4550
* Send email
4651
*
47-
* @param recipients
48-
* @param subject
49-
* @param ctx
50-
* @param template
52+
* @param recipients The list of recipients.
53+
* @param subject The subject.
54+
* @param ctx The context. It has information to generate the content.
55+
* @param template What template to use.
5156
*/
52-
public void sendmail(List<String> recipients, @NotNull String subject, @NotNull Map<String, Object> ctx, String template) {
57+
public void sendSmtpMail(List<String> recipients, @NotNull String subject, @NotNull Map<String, Object> ctx, String template) {
5358

5459
MimeMessagePreparator messagePreparator = mimeMessage -> {
5560
log.info("Sending email notification.");
@@ -96,9 +101,9 @@ public void sendmail(List<String> recipients, @NotNull String subject, @NotNull
96101
/**
97102
* Generate HTML content for email
98103
*
99-
* @param ctx
100-
* @param template
101-
* @return
104+
* @param ctx The context. It has information to generate the content.
105+
* @param template What template to use.
106+
* @return The e-mail content, as HTML.
102107
*/
103108
private String generateContent(Map<String, Object> ctx, String template) {
104109
Context context = new Context();
@@ -107,42 +112,55 @@ private String generateContent(Map<String, Object> ctx, String template) {
107112
}
108113

109114
public void sendScanSubmittedEmail(ScanRequest request) {
110-
if (isEmailNotificationAllowed()) {
111-
String prefixMessage = "Checkmarx Scan submitted for %s/%s ";
112-
String scanSubmittedSubject = String.format(prefixMessage, request.getNamespace(), request.getRepoName());
113-
String scanSubmittedMessage = String.format(prefixMessage, request.getNamespace(), request.getRepoName());
114-
Map<String, Object> emailCtx = prepareEmailContext("Scan Request Submitted", scanSubmittedMessage, request.getRepoUrl());
115-
sendmail(request.getEmail(), scanSubmittedSubject, emailCtx, "message.html");
115+
if (!isEmailNotificationAllowed()) {
116+
log.info("cx-flow.mail.notification not set or set to false. Skipping Scan Submitted e-mail...");
117+
return;
116118
}
119+
120+
FlowProperties.Mail mail = flowProperties.getMail();
121+
String prefixMessage = "Checkmarx Scan submitted for %s/%s ";
122+
String scanSubmittedSubject = String.format(prefixMessage, request.getNamespace(), request.getRepoName());
123+
Map<String, Object> emailCtx = prepareEmailContext("Scan Request Submitted", scanSubmittedSubject, request.getRepoUrl());
124+
sendMail(request.getEmail(), mail, scanSubmittedSubject, emailCtx, "message.html");
117125
}
118126

119127
public void sendScanCompletedEmail(ScanRequest request, ScanResults results) {
120-
if(request.getBugTracker()!=null) {
121-
BugTracker.Type bugTrackerType = request.getBugTracker().getType();
122-
if (isEmailNotificationAllowed() && !bugTrackerType.equals(BugTracker.Type.NONE) &&
123-
!bugTrackerType.equals(BugTracker.Type.EMAIL)) {
124-
prepareAndSendEmail(request, results);
125-
}
128+
if (!isEmailNotificationAllowed()) {
129+
log.info("cx-flow.mail.notification not set or set to false. Skipping Scan Completed e-mail...");
130+
return;
131+
}
132+
133+
if (request.getBugTracker() == null) {
134+
return;
135+
}
136+
137+
BugTracker.Type bugTrackerType = request.getBugTracker().getType();
138+
if (bugTrackerType.equals(BugTracker.Type.NONE) ||
139+
!bugTrackerType.equals(BugTracker.Type.EMAIL)) {
140+
return;
126141
}
142+
143+
prepareAndSendScanCompletedEmail(request, results);
127144
}
128145

129146
public void handleEmailBugTracker(ScanRequest request, ScanResults results) {
130-
if (flowProperties.getMail() != null) {
131-
if (ScanUtils.empty(results.getXIssues())) {
132-
if (flowProperties.getMail().isEmptyMailAllowed()) {
133-
prepareAndSendEmail(request, results);
134-
}
135-
} else {
136-
prepareAndSendEmail(request, results);
137-
}
147+
FlowProperties.Mail mail = flowProperties.getMail();
148+
if (mail == null) {
149+
return;
150+
}
151+
152+
if (ScanUtils.empty(results.getXIssues()) && !mail.isEmptyMailAllowed()) {
153+
return;
138154
}
155+
156+
prepareAndSendScanCompletedEmail(request, results);
139157
}
140158

141159
private boolean isEmailNotificationAllowed() {
142160
return flowProperties.getMail() != null && flowProperties.getMail().isNotificationEnabled();
143161
}
144162

145-
public void prepareAndSendEmail(ScanRequest request, ScanResults results) {
163+
public void prepareAndSendScanCompletedEmail(ScanRequest request, ScanResults results) {
146164
String namespace = request.getNamespace();
147165
String repoName = request.getRepoName();
148166
String scanCompletedMessage = COMPLETED_PROCESSING.concat(namespace).concat("/").concat(repoName);
@@ -154,20 +172,49 @@ public void prepareAndSendEmail(ScanRequest request, ScanResults results) {
154172
emailCtx.put("issues", results.getXIssues());
155173
emailCtx.put("link", results.getLink());
156174
}
175+
157176
emailCtx.put("repo_fullname", namespace.concat("/").concat(repoName));
158177

159-
String template = flowProperties.getMail().getTemplate();
178+
FlowProperties.Mail mail = flowProperties.getMail();
179+
String template = mail.getTemplate();
160180

161-
if(ScanUtils.empty(template)) {
162-
sendmail(request.getEmail(), scanCompletedSubject, emailCtx, "template-demo.html");
163-
}
164-
else
165-
{
166-
sendmail(request.getEmail(), scanCompletedSubject, emailCtx, template);
181+
if (ScanUtils.empty(template)) {
182+
template = "template-demo.html";
167183
}
184+
185+
sendMail(request.getEmail(), mail, scanCompletedSubject, emailCtx, template);
168186
log.info("Email notification sent.");
169187
}
170188

189+
/**
190+
* Resolves how to send the Scan Submitted e-mail. If `cx-flow.mail.sendgrid` is set, sends through Sendgrid.
191+
* Otherwise sends through SMTP.
192+
*
193+
* @param emails List of e-mails with all the recipients.
194+
* @param mailProperties Configured properties for mail, through YAML, env variables or command-line arguments.
195+
* @param scanCompletedSubject The e-mail subject
196+
* @param emailCtx The e-mail context. Used to generate the content.
197+
* @param template The template chosen.
198+
*/
199+
private void sendMail(List<String> emails, FlowProperties.Mail mailProperties, String scanCompletedSubject,
200+
Map<String, Object> emailCtx, String template) {
201+
FlowProperties.SendGrid sendGrid = mailProperties.getSendgrid();
202+
if (sendGrid != null && sendGrid.getApiToken() != null) {
203+
log.info("Using Sendgrid to send the Scan Completed e-mail notification.");
204+
String content = generateContent(emailCtx, template);
205+
206+
String from = flowProperties.getContact();
207+
if (StringUtils.isEmpty(from)) {
208+
209+
}
210+
211+
sendGridService.sendEmailThroughSendGrid(emails, from, sendGrid.getApiToken(), scanCompletedSubject, content);
212+
} else {
213+
log.info("Using SMTP to send the Scan Completed e-mail notification.");
214+
sendSmtpMail(emails, scanCompletedSubject, emailCtx, template);
215+
}
216+
}
217+
171218
private Map<String, Object> prepareEmailContext(String heading, String message, String repoUrl) {
172219
Map<String, Object> emailCtx = new HashMap<>();
173220
emailCtx.put(HEADING_KEY, heading);

0 commit comments

Comments
 (0)