Skip to content

Commit a8e49fa

Browse files
Merge branch 'master' into Changing_extension_in_config_still_scanning_.xml_files_#20
2 parents ad0db10 + c540f2b commit a8e49fa

File tree

16 files changed

+192
-11
lines changed

16 files changed

+192
-11
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ For example, the rule store (rules-4.xml) has three rulesets (categories):
132132
or
133133
matches(//mule:mule/mule:flow/ee:transform/ee:message/ee:set-payload/@resource,'^.*dwl$')
134134
</rule>
135+
<rule id="2"
136+
name="Mule Credentials Vault should not use a hardcoded encryption key"
137+
description="Mule Credentials Vault should not use a hardcoded encryption key"
138+
severity="MAJOR" type="bug">
139+
count(//mule:mule/secure-properties:config)=0
140+
or
141+
is-configurable(//mule:mule/secure-properties:config/@key)
142+
</rule>
135143
</ruleset>
136144
</rulestore>
137145
```

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>com.mulesoft.services</groupId>
77
<artifactId>mule-validation-sonarqube-plugin</artifactId>
8-
<version>1.0.3</version>
8+
<version>1.0.4</version>
99
<packaging>jar</packaging>
1010

1111
<url>http://maven.apache.org</url>
@@ -36,6 +36,11 @@
3636
<!-- mandatory scope -->
3737
<scope>provided</scope>
3838
</dependency>
39+
<dependency>
40+
<groupId>org.sonarsource.analyzer-commons</groupId>
41+
<artifactId>sonar-xml-parsing</artifactId>
42+
<version>1.12.0.632</version>
43+
</dependency>
3944
<dependency>
4045
<groupId>org.jdom</groupId>
4146
<artifactId>jdom2</artifactId>

src/main/java/com/mulesoft/services/tools/sonarqube/measures/MuleTransformationCount.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public void compute(MeasureComputerContext context) {
2626
logger.info("Computing Mule Transformation Count");
2727

2828
if (context.getComponent().getType() != Component.Type.FILE) {
29-
int sumFlows = 0;
29+
int sumTransformations = 0;
3030
for (Measure child : context.getChildrenMeasures(MuleMetrics.TRANSFORMATIONS.key())) {
31-
sumFlows += child.getIntValue();
31+
sumTransformations += child.getIntValue();
3232
}
33-
context.addMeasure(MuleMetrics.TRANSFORMATIONS.key(), sumFlows);
33+
context.addMeasure(MuleMetrics.TRANSFORMATIONS.key(), sumTransformations);
3434

3535
}
3636

src/main/java/com/mulesoft/services/tools/sonarqube/rule/MuleRulesDefinition.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public interface PARAMS {
3636
String CATEGORY = "category";
3737
String SCOPE = "scope";
3838
String XPATH = "xpath-expression";
39+
String XPATH_LOCATION_HINT = "xpath-location-hint";
3940
}
4041

4142
@Override
@@ -97,8 +98,13 @@ private void addRuleTemplate(NewRepository repository, String language) {
9798
.setType(RuleParamType.STRING);
9899
x1Rule.createParam(PARAMS.XPATH).setDescription(prop.getProperty("rule.template.parameter.xpath"))
99100
.setType(RuleParamType.STRING);
101+
x1Rule.createParam(PARAMS.XPATH_LOCATION_HINT).setDescription(prop.getProperty("rule.template.parameter.xpathlocationhint"))
102+
.setType(RuleParamType.STRING);
100103
x1Rule.createParam(PARAMS.SCOPE).setDescription(prop.getProperty("rule.template.parameter.scope"))
101104
.setType(RuleParamType.STRING);
105+
106+
logger.info("addRuleTemplate x1Rule="+x1Rule);
107+
102108
}
103109

104110
private void addRule(NewRepository repository, Ruleset ruleset,
@@ -113,6 +119,8 @@ private void addRule(NewRepository repository, Ruleset ruleset,
113119
x1Rule.addTags(language);
114120
x1Rule.createParam(PARAMS.CATEGORY).setDefaultValue(ruleset.getCategory()).setType(RuleParamType.STRING);
115121
x1Rule.createParam(PARAMS.XPATH).setDefaultValue(rule.getValue()).setType(RuleParamType.STRING);
122+
logger.info("LocationHint="+rule.getLocationHint()+" for "+rule.getName());
123+
x1Rule.createParam(PARAMS.XPATH_LOCATION_HINT).setDefaultValue(rule.getLocationHint()).setType(RuleParamType.STRING);
116124
if (rule.getApplies() != null) {
117125
x1Rule.createParam(PARAMS.SCOPE).setDefaultValue(rule.getApplies()).setType(RuleParamType.STRING);
118126
}

src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/ApplicationStrategyScope.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void validate(XPathProcessor xpathValidator, Map<RuleKey, List<NewIssue>>
3737
String ruleId = rule.ruleKey().toString();
3838
boolean valid = xpathValidator.processXPath(rule.param(MuleRulesDefinition.PARAMS.XPATH).trim(),
3939
rootElement, Boolean.class).booleanValue();
40-
logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey());
40+
logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey()+" internalKey="+rule.internalKey());
4141
if (!valid && !valids.contains(ruleId) && !issues.containsKey(rule.ruleKey())) {
4242
NewIssue newIssue = context.newIssue().forRule(rule.ruleKey());
4343
NewIssueLocation primaryLocation = newIssue.newLocation().on(t);

src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/FileStrategyScope.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
import org.jdom2.Element;
1010
import org.jdom2.JDOMException;
1111
import org.jdom2.input.SAXBuilder;
12+
13+
import javax.xml.xpath.XPathConstants;
14+
import javax.xml.xpath.XPathExpressionException;
15+
import javax.xml.xpath.XPathFactory;
16+
1217
import org.sonar.api.batch.fs.InputFile;
1318
import org.sonar.api.batch.rule.ActiveRule;
1419
import org.sonar.api.batch.sensor.SensorContext;
@@ -18,6 +23,10 @@
1823
import org.sonar.api.utils.log.Logger;
1924
import org.sonar.api.utils.log.Loggers;
2025

26+
import org.sonarsource.analyzer.commons.xml.XmlFile;
27+
import org.sonarsource.analyzer.commons.xml.XmlTextRange;
28+
import org.w3c.dom.Node;
29+
2130
import com.mulesoft.services.tools.sonarqube.rule.MuleRulesDefinition;
2231
import com.mulesoft.services.xpath.XPathProcessor;
2332

@@ -35,8 +44,44 @@ public void validate(XPathProcessor xpathValidator, Map<RuleKey, List<NewIssue>>
3544
rootElement, Boolean.class).booleanValue();
3645
logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey());
3746
if (!valid) {
47+
48+
XmlTextRange textRange;
49+
try {
50+
// see org.sonarsource.analyzer.commons.xml.checks.SonarXmlCheck.reportIssue(Node, String)
51+
SonarXmlCheckHelper tempSonarXmlCheckHelper = new SonarXmlCheckHelper();
52+
XmlFile xmlFile = XmlFile.create(t);
53+
tempSonarXmlCheckHelper.scanFile(context, rule.ruleKey(), xmlFile); // just to fill the properties
54+
String locationFindingXPath = rule.param(MuleRulesDefinition.PARAMS.XPATH_LOCATION_HINT).trim();
55+
if (locationFindingXPath == null || locationFindingXPath.length()==0) {
56+
logger.info("No locationFindingXPath:params="+rule.params());
57+
textRange = null;
58+
} else {
59+
Node locationElement = (Node)XPathFactory.newInstance().newXPath().compile(locationFindingXPath).evaluate(xmlFile.getDocument().getFirstChild(), XPathConstants.NODE);
60+
if (locationElement == null) {
61+
textRange= null;
62+
logger.warn("Did not find node for "+locationFindingXPath);
63+
} else {
64+
textRange = XmlFile.nodeLocation(locationElement);
65+
logger.info("Found textRange="+textRange);
66+
}
67+
}
68+
} catch (RuntimeException | XPathExpressionException e) {
69+
logger.error("Ignore",e);
70+
textRange= null;
71+
}
72+
3873
NewIssue newIssue = context.newIssue().forRule(rule.ruleKey());
39-
NewIssueLocation primaryLocation = newIssue.newLocation().on(t);
74+
NewIssueLocation primaryLocation;
75+
if (textRange == null) {
76+
primaryLocation = newIssue.newLocation().on(t);
77+
} else {
78+
primaryLocation = newIssue.newLocation().on(t) .at(t.newRange(
79+
textRange.getStartLine(),
80+
textRange.getStartColumn(),
81+
textRange.getEndLine(),
82+
textRange.getEndColumn()));
83+
}
84+
4085
newIssue.at(primaryLocation);
4186
addIssue(issues, rule, newIssue);
4287
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.mulesoft.services.tools.sonarqube.rule.scope;
2+
3+
import org.sonarsource.analyzer.commons.xml.XmlFile;
4+
import org.sonarsource.analyzer.commons.xml.checks.SonarXmlCheck;
5+
6+
/**
7+
*
8+
*/
9+
public class SonarXmlCheckHelper extends SonarXmlCheck {
10+
11+
/**
12+
*
13+
*/
14+
@Override
15+
public void scanFile(XmlFile aFile) {
16+
// nothing to do
17+
}
18+
19+
}

src/main/java/com/mulesoft/services/tools/validation/rules/Rule.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ public class Rule {
9999
protected String applies;
100100
@XmlAttribute(name = "type")
101101
protected String type;
102+
@XmlAttribute(name = "locationHint")
103+
private String locationHint;
102104

103105
/**
104106
* Gets the value of the value property.
@@ -269,4 +271,18 @@ public void setType(String value) {
269271
this.type = value;
270272
}
271273

274+
/**
275+
*
276+
*/
277+
public String getLocationHint() {
278+
return locationHint;
279+
}
280+
281+
/**
282+
* @see #locationHint
283+
*/
284+
public void setLocationHint(String aLocationHint) {
285+
locationHint = aLocationHint;
286+
}
287+
272288
}

src/main/java/com/mulesoft/services/xpath/XPathProcessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.slf4j.LoggerFactory;
1717

1818
import com.mulesoft.services.xpath.jaxen.function.ext.MatchesFunction;
19+
import com.mulesoft.services.xpath.jaxen.function.ext.IsConfigurableFunction;
1920

2021
public class XPathProcessor {
2122
Logger logger = LoggerFactory.getLogger(getClass());
@@ -26,6 +27,7 @@ public class XPathProcessor {
2627

2728
public XPathProcessor() {
2829
MatchesFunction.registerSelfInSimpleContext();
30+
IsConfigurableFunction.registerSelfInSimpleContext();
2931
}
3032

3133
public XPathProcessor loadNamespaces(String resourceName) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.mulesoft.services.xpath.jaxen.function.ext;
2+
3+
import java.util.Iterator;
4+
import java.util.List;
5+
6+
import org.jaxen.Context;
7+
import org.jaxen.Function;
8+
import org.jaxen.FunctionCallException;
9+
import org.jaxen.Navigator;
10+
import org.jaxen.SimpleFunctionContext;
11+
import org.jaxen.XPathFunctionContext;
12+
import org.jaxen.function.StringFunction;
13+
14+
public class IsConfigurableFunction implements Function {
15+
16+
private static final String IS_CONFIGURABLE_REGEX = "^\\$\\{.*\\}$";
17+
18+
public static void registerSelfInSimpleContext() {
19+
// see http://jaxen.org/extensions.html
20+
((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "is-configurable",
21+
new IsConfigurableFunction());
22+
}
23+
24+
@Override
25+
public Object call(Context context, List args) throws FunctionCallException {
26+
27+
if (args.size() == 1) {
28+
return evaluate(args.get(0), context.getNavigator());
29+
}
30+
31+
throw new FunctionCallException("is-configurable() requires two arguments.");
32+
}
33+
34+
public static Boolean evaluate(Object strArg, Navigator nav) {
35+
if (strArg instanceof List) {
36+
@SuppressWarnings("unchecked")
37+
List<Object> objectList = (List<Object>) strArg;
38+
// Check if it could load any attribute - If Empty then False
39+
if (objectList.isEmpty()) {
40+
return Boolean.FALSE;
41+
}
42+
43+
for (Iterator<Object> iterator = objectList.iterator(); iterator.hasNext();) {
44+
Object object = iterator.next();
45+
String str = StringFunction.evaluate(object, nav);
46+
String regexp = StringFunction.evaluate(IS_CONFIGURABLE_REGEX, nav);
47+
System.out.println("str: " + str);
48+
System.out.println("regexp: " + regexp);
49+
if (!str.matches(regexp)) {
50+
return Boolean.FALSE;
51+
}
52+
}
53+
return Boolean.TRUE;
54+
} else {
55+
String str = StringFunction.evaluate(strArg, nav);
56+
String regexp = StringFunction.evaluate(IS_CONFIGURABLE_REGEX, nav);
57+
return (str.matches(regexp) ? Boolean.TRUE : Boolean.FALSE);
58+
}
59+
60+
}
61+
62+
}

0 commit comments

Comments
 (0)