Skip to content

Commit

Permalink
chore: Action updates
Browse files Browse the repository at this point in the history
  • Loading branch information
rsenden committed Apr 9, 2024
1 parent 3b8424c commit 48074be
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ public static final class ActionStepForEachDescriptor implements IActionIfSuppli
/** Processor that runs the forEach steps. This expression must evaluate to an
* IActionStepForEachProcessor instance. */
private SimpleExpression processor;
/** Values to iterate over */
private SimpleExpression values;
/** Optional if-expression, executing steps only if condition evaluates to true */
@JsonProperty("if") private SimpleExpression _if;
/** Optional break-expression, terminating forEach if condition evaluates to true */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,15 @@ private void processThrowStep(TemplateExpression message) {
}

private void processForEachStep(ActionStepForEachDescriptor forEach) {
spelEvaluator.evaluate(forEach.getProcessor(), localData, IActionStepForEachProcessor.class)
.process(node->processForEachStepNode(forEach, node));
var processor = forEach.getProcessor();
var values = forEach.getValues();
if ( processor!=null ) {
spelEvaluator.evaluate(processor, localData, IActionStepForEachProcessor.class)
.process(node->processForEachStepNode(forEach, node));
} else if ( values!=null ) {
spelEvaluator.evaluate(values, localData, ArrayNode.class)
.forEach(value->processForEachStepNode(forEach, value));
}
}

private boolean processForEachStepNode(ActionStepForEachDescriptor forEach, JsonNode node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ public static final String abbreviate(String text, int maxWidth) {
return StringUtils.abbreviate(text, maxWidth);
}

public static final String repeat(String text, int count) {
if ( count<0 ) { return ""; }
StringBuilder sb = new StringBuilder();
for ( int i=0; i<count; i++ ) {
sb.append(text);
}
return sb.toString();
}

/**
* @param html to be converted to plain text
* @return Formatted plain-text string for the given HTML contents
Expand Down Expand Up @@ -191,10 +200,17 @@ public static final String uriPart(String uriString, String part) {
* @param dateString JSON string representation of date to be formatted
* @return Formatted date
*/
public static final String formatDateTime(String pattern, String dateString) {
public static final String formatDateTime(String pattern, String... dateStrings) {
var dateString = dateStrings==null||dateStrings.length==0
? currentDateTime()
: dateStrings[0];
return formatDateTimeWithZoneId(pattern, dateString, ZoneId.systemDefault());
}

public static final String currentDateTime() {
return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
}

/**
* Parse the given dateString in the given time zone id as a JSON date (see {@link JSONDateTimeConverter},
* then format it using the given {@link DateTimeFormatter} pattern.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public JSONDateTimeConverter(DateTimeFormatter fmtDateTime, ZoneId defaultZoneId
this.defaultZoneId = defaultZoneId!=null ? defaultZoneId : ZoneId.systemDefault();
}

private static final DateTimeFormatter createDefaultDateTimeFormatter() {
public static final DateTimeFormatter createDefaultDateTimeFormatter() {
return DateTimeFormatter.ofPattern("yyyy-MM-dd[['T'][' ']HH:mm:ss[.SSS][.SS]][ZZZZ][Z][XXX][XX][X]");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ public static final String indent(String str, String indentStr) {
if ( str==null ) { return null; }
return Stream.of(str.split("\n")).collect(Collectors.joining("\n"+indentStr, indentStr, ""));
}

public static final String fmt(String str, String fmt) {
return String.format(fmt, str);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
usage:
header: Generate release summary.
description: |
This action generates a short summary listing issue counts and other statistics
for a given release.
defaults:
requestTarget: fod

parameters:
- name: file
cliAliases: f
description: "Optional output file name (or 'stdout' / 'stderr'). Default value: stdout"
required: false
defaultValue: stdout
- name: release
cliAliases: rel
description: "Required release id or <appName>:[<microserviceName>:]<releaseName>"
type: release_single

steps:
- set:
# Add short alias for release object
- name: r
value: ${parameters.release}
- name: dateFmt
value: YYYY-MM-dd HH:mm
- write:
- to: ${parameters.file}
valueTemplate: summary-md
- if: parameters.file!='stdout'
to: stdout
value: |
Output written to ${parameters.file}
valueTemplates:
- name: summary-md
contents: |
# Fortify on Demand Release Summary
## [${r.applicationName}${#isNotBlank(r.microserviceNae)?'- '+r.microserviceName:''} - ${r.releaseName}](${#fod.releaseBrowserUrl(r)})
Summary generated on: ${#formatDateTime(dateFmt)}
### Security Policy
**Rating:** ${#repeat("&bigstar;", r.rating)}${#repeat("&star;", 5-r.rating)}
**Status:** ${r.isPassed?'Pass':'Fail'}
### Issue Counts
| Type | Last Scan Date | Critical | High | Medium | Low |
| ----------- | ---------------- | -------- | -------- | -------- | -------- |
${
#isNotBlank(r.staticScanDate)? '| **Static** | '+#formatDateTime(dateFmt, r.staticScanDate) +' | '+#fmt(r.staticCritical, '%8s')+' | '+#fmt(r.staticHigh, '%8s')+' | '+#fmt(r.staticMedium, '%8s')+' | '+#fmt(r.staticLow, '%8s')+' |\n':''
+#isNotBlank(r.dynamicScanDate)?'| **Dynamic** | '+#formatDateTime(dateFmt, r.dynamicScanDate)+' | '+#fmt(r.dynamicCritical, '%8s')+' | '+#fmt(r.dynamicHigh, '%8s')+' | '+#fmt(r.dynamicMedium, '%8s')+' | '+#fmt(r.dynamicLow, '%8s')+' |\n':''
+#isNotBlank(r.mobileScanDate)? '| **Mobile** | '+#formatDateTime(dateFmt, r.mobileScanDate) +' | '+#fmt(r.mobileCritical, '%8s')+' | '+#fmt(r.mobileHigh, '%8s')+' | '+#fmt(r.mobileMedium, '%8s')+' | '+#fmt(r.mobileLow, '%8s')+' |\n':''
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
usage:
header: Generate application version summary.
description: |
This action generates a short summary listing issue counts and other statistics
for a given application version.
defaults:
requestTarget: ssc

parameters:
- name: file
cliAliases: f
description: "Optional output file name (or 'stdout' / 'stderr'). Default value: stdout"
required: false
defaultValue: stdout
- name: appversion
cliAliases: av
description: "Required application version id or <appName>:<versionName>"
type: appversion_single
- name: filtersets
cliAliases: fs
description: "Filter set names or guid's to display in the summary. If not specified, all filter sets will be included."
required: false

steps:
- progress: Loading issue selector sets
- requests:
- name: issueSelectorSet
uri: /api/v1/projectVersions/${parameters.appversion.id}/issueSelectorSet?fields=filterBySet
- forEach:
values: issueSelectorSet.filterBySet.^[displayName=='Analysis Type'].selectorOptions
name: analysisType
do:
- progress: Loading ${analysisType.displayName} data
- requests:
- name: artifacts
uri: /api/v1/projectVersions/${parameters.appversion.id}/artifacts
type: paged
query:
embed: scans
forEach:
name: artifact
breakIf: lastScans!=null && lastScans[analysisType.guid]!=null
do:
- set:
- name: lastScans
value: "${{analysisType.guid: artifact._embed.scans?.^[type==#root.analysisType.guid]}}"
operation: merge
- requests:
- name: issueGroups
uri: /api/v1/projectVersions/${parameters.appversion.id}/issueGroups
query:
qm: issues
groupingtype: FOLDER
filter: ISSUE[11111111-1111-1111-1111-111111111151]:${analysisType.guid}
type: paged
forEach:
name: folder
do:
- set:
- name: issueCounts2
value: "${{analysisType.displayName: folder}}"
operation: append
- write:
- to: stdout
value: ${issueCounts2}
# - progress: Processing issue data
# - requests:
# - name: issues
# uri: /api/v1/projectVersions/${parameters.appversion.id}/issues?limit=100
# query:
# filter: ISSUE[11111111-1111-1111-1111-111111111151]:SCA
# filterset: ${parameters.filterset.guid}
# pagingProgress:
# postPageProcess: Processed ${totalIssueCount?:0} of ${issues_raw.count} issues
# forEach:
# name: issue
# embed:
# - name: details
# uri: /api/v1/issueDetails/${issue.id}
# do:
# - set:
# - name: ruleCategories
# operation: merge
# - name: results
# operation: append
# - progress: Processing rule data
# - forEach:
# processor: "#ssc.ruleDescriptionsProcessor(parameters.appversion.id)"
# name: rule
# do:
# - set:
# - if: "#isNotBlank(ruleCategories[rule.id])"
# name: rules
# operation: append
# - write:
# - to: ${parameters.file}
# valueTemplate: github-sast-report
# - if: parameters.file!='stdout'
# to: stdout
# value: |
# Output written to ${parameters.file}

valueTemplates:
- name: ruleCategories
contents: "${{issue.primaryRuleGuid: issue.issueName}}"

- name: github-sast-report
contents:
"$schema": https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json
version: '2.1.0'
runs:
- tool:
driver:
name: 'Fortify SCA'
version: ${lastStaticScan?.engineVersion?:'unknown'}
rules: ${rules?:{}}
properties:
copyright: ${#copyright()}
applicationName: ${parameters.appversion.project.name}
applicationId: ${parameters.appversion.project.id}
versionName: ${parameters.appversion.name}
versionId: ${parameters.appversion.id}
results: ${results?:{}}

- name: rules
contents:
id: ${rule.id}
shortDescription:
text: ${ruleCategories[rule.id]}
fullDescription:
text: |
## ${ruleCategories[rule.id]}
${rule.abstract}
help:
text: |
${rule.explanation?:'No explanation available'}
## Recommendations
${rule.recommendations?:'Not available'}
## Tips
${#join('\n\n', rule.tips)?:'Not available'}
## References
${#numberedList(rule.references.![title
+(#isNotBlank(publisher)?", "+publisher:"")
+(#isNotBlank(author)?", "+author:"")
+(#isNotBlank(source)?", "+source:"")])?:'Not available'}
${#copyright()}
- name: results
contents:
ruleId: ${issue.primaryRuleGuid}
message:
text: ${issue.details?.brief} [More information](${#ssc.issueBrowserUrl(issue,parameters.filterset)})
level: ${(issue.friority matches "(Critical|High)") ? "warning":"note" }
partialFingerprints:
issueInstanceId: ${issue.issueInstanceId}
locations:
- physicalLocation:
artifactLocation:
uri: ${issue.fullFileName}
region:
startLine: ${issue.lineNumber==0||issue.lineNumber==null?1:issue.lineNumber}
endLine: ${issue.lineNumber==0||issue.lineNumber==null?1:issue.lineNumber}
startColumn: ${1} # Needs to be specified as an expression in order to end up as integer instead of string in JSON
endColumn: ${80}
codeFlows: |-
${
issue.details?.traceNodes==null ? {}
:
{{
threadFlows: issue.details?.traceNodes.![{
locations: #this.![{
location: {
message: {
text: text
},
physicalLocation: {
artifactLocation: {
uri: fullPath
},
region: {
startLine: line==0||line==null?1:line
}
}
}
}]
}]
}}
}

0 comments on commit 48074be

Please sign in to comment.