|
19 | 19 | */
|
20 | 20 | package org.sonar.python.checks.cdk;
|
21 | 21 |
|
22 |
| -import java.util.Locale; |
| 22 | +import java.io.BufferedReader; |
| 23 | +import java.io.IOException; |
| 24 | +import java.io.InputStream; |
| 25 | +import java.io.InputStreamReader; |
| 26 | +import java.nio.charset.StandardCharsets; |
| 27 | +import java.util.ArrayList; |
| 28 | +import java.util.Collections; |
| 29 | +import java.util.HashSet; |
| 30 | +import java.util.List; |
23 | 31 | import java.util.Optional;
|
| 32 | +import java.util.Set; |
24 | 33 | import java.util.function.Predicate;
|
25 | 34 | import javax.annotation.Nullable;
|
| 35 | +import org.sonar.api.utils.log.Logger; |
| 36 | +import org.sonar.api.utils.log.Loggers; |
26 | 37 | import org.sonar.check.Rule;
|
| 38 | +import org.sonar.plugins.python.api.SubscriptionCheck; |
27 | 39 | import org.sonar.plugins.python.api.tree.Expression;
|
28 | 40 | import org.sonar.python.checks.cdk.CdkUtils.ExpressionFlow;
|
29 | 41 |
|
|
32 | 44 | @Rule(key = "S6304")
|
33 | 45 | public class ResourceAccessPolicyCheck extends AbstractIamPolicyStatementCheck {
|
34 | 46 |
|
| 47 | + private static final Logger LOG = Loggers.get(ResourceAccessPolicyCheck.class); |
35 | 48 | private static final String MESSAGE = "Make sure granting access to all resources is safe here.";
|
36 | 49 | private static final String SECONDARY_MESSAGE = "Related effect";
|
| 50 | + // visible for testing |
| 51 | + String resourceNameSensitiveAwsActions = "ResourceAccessPolicyCheck.txt"; |
| 52 | + private Set<String> sensitiveAwsActions = null; |
| 53 | + |
| 54 | + void init() { |
| 55 | + try { |
| 56 | + sensitiveAwsActions = new HashSet<>(loadResource(resourceNameSensitiveAwsActions)); |
| 57 | + } catch (IOException e) { |
| 58 | + sensitiveAwsActions = Collections.emptySet(); |
| 59 | + LOG.error("Couldn't load resource '" + resourceNameSensitiveAwsActions + "', rule [S6304] ResourceAccessPolicyCheck will be disabled.", e); |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + @Override |
| 64 | + public void initialize(SubscriptionCheck.Context context) { |
| 65 | + super.initialize(context); |
| 66 | + init(); |
| 67 | + } |
| 68 | + |
| 69 | + private static List<String> loadResource(String resourceName) throws IOException { |
| 70 | + try (InputStream is = ResourceAccessPolicyCheck.class.getResourceAsStream(resourceName)) { |
| 71 | + if (is == null) { |
| 72 | + throw new IOException("Cannot find resource file '" + resourceName + "'"); |
| 73 | + } |
| 74 | + try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); |
| 75 | + BufferedReader br = new BufferedReader(isr)) { |
| 76 | + List<String> result = new ArrayList<>(); |
| 77 | + String line; |
| 78 | + while((line = br.readLine()) != null) { |
| 79 | + result.add(line); |
| 80 | + } |
| 81 | + return result; |
| 82 | + } |
| 83 | + } |
| 84 | + } |
37 | 85 |
|
38 | 86 | @Override
|
39 | 87 | protected void checkAllowingPolicyStatement(PolicyStatement policyStatement) {
|
40 | 88 | CdkUtils.ExpressionFlow actions = policyStatement.actions();
|
41 | 89 | CdkUtils.ExpressionFlow resources = policyStatement.resources();
|
42 | 90 |
|
43 |
| - if (resources == null || actions == null || hasOnlyKmsActions(actions)) { |
| 91 | + if (resources == null || actions == null || !isSensitiveAction(actions)) { |
44 | 92 | return;
|
45 | 93 | }
|
46 | 94 |
|
47 | 95 | Optional.ofNullable(getSensitiveExpression(resources, isWildcard()))
|
48 | 96 | .ifPresent(wildcard -> reportWildcardResourceAndEffect(wildcard, policyStatement.effect()));
|
49 | 97 | }
|
50 | 98 |
|
51 |
| - private static boolean hasOnlyKmsActions(ExpressionFlow actions) { |
52 |
| - return getSensitiveExpression(actions, notStartsWith("kms:")) == null; |
| 99 | + private boolean isSensitiveAction(ExpressionFlow actions) { |
| 100 | + return getSensitiveExpression(actions, inSensitiveSet()) != null; |
53 | 101 | }
|
54 | 102 |
|
55 |
| - public static Predicate<Expression> notStartsWith(String expected) { |
| 103 | + public Predicate<Expression> inSensitiveSet() { |
56 | 104 | return expression -> CdkUtils.getString(expression)
|
57 |
| - .filter(str -> !str.toLowerCase(Locale.ROOT).startsWith(expected)).isPresent(); |
| 105 | + .filter(sensitiveAwsActions::contains).isPresent(); |
58 | 106 | }
|
59 | 107 |
|
60 | 108 | private static void reportWildcardResourceAndEffect(ExpressionFlow wildcard, @Nullable ExpressionFlow effect) {
|
|
0 commit comments