View Javadoc
1   /*
2    * Cloudformation Plugin for SonarQube
3    * Copyright (C) 2019 James Pether Sörling
4    * james@hack23.com
5    *
6    * This program is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public License
17   * along with this program; if not, write to the Free Software Foundation,
18   * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19   */
20  package com.hack23.sonar.cloudformation.reports.checkov;
21  
22  import static org.junit.Assert.assertFalse;
23  
24  import java.io.IOException;
25  import java.io.InputStreamReader;
26  import java.nio.charset.StandardCharsets;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.commons.csv.CSVFormat;
32  import org.apache.commons.csv.CSVParser;
33  import org.apache.commons.csv.CSVRecord;
34  import org.junit.Test;
35  
36  /**
37   * The Class CheckovSonarqubeRuleGeneratorTest.
38   */
39  public class CheckovSonarqubeRuleGeneratorTest {
40  
41  	/** The Constant XML_ENTRY. */
42  	private final static String XML_ENTRY ="    <rule>\n"
43  			+ "		<key>{IaC}-{RULE_ID}</key>\n"
44  			+ "		<name>{NAME}</name>\n"
45  			+ "		<internalKey>{IaC}-{RULE_ID}</internalKey>\n"
46  			+ "		<description>{NAME}</description>\n"
47  			+ "		<severity>CRITICAL</severity>\n"
48  			+ "		<cardinality>SINGLE</cardinality>\n"
49  			+ "		<status>READY</status>\n"
50  			+ "		<type>VULNERABILITY</type>\n"
51  			+ "		<tag>security</tag>\n"
52  			+ "		<tag>checkov</tag>\n"
53  			+ "		<tag>{IaC}</tag>{EXTRA_TAGS}\n"
54  			+ "		<remediationFunction>CONSTANT_ISSUE</remediationFunction>\n"
55  			+ "		<remediationFunctionBaseEffort>10min</remediationFunctionBaseEffort>\n"
56  			+ "    </rule>";
57  
58  //	Group the rules to NIST 800-53
59  //	800-53-AC-4 AC-4 INFORMATION FLOW ENFORCEMENT https://nvd.nist.gov/800-53/Rev4/control/AC-4
60  //
61  //	800-53-AC-6 AC-6 LEAST PRIVILEGE https://nvd.nist.gov/800-53/Rev4/control/AC-6
62  //
63  //	800-53-AU-12 AU-12 AUDIT GENERATION https://nvd.nist.gov/800-53/Rev4/control/AU-12
64  //
65  //	800-53-IA-5 IA-5 AUTHENTICATOR MANAGEMENT https://nvd.nist.gov/800-53/Rev4/control/IA-5
66  //
67  //	800-53-SC-5 SC-5 DENIAL OF SERVICE PROTECTION https://nvd.nist.gov/800-53/Rev4/control/SC-5
68  //
69  //	800-53-SC-7 SC-7 BOUNDARY PROTECTION https://nvd.nist.gov/800-53/Rev4/control/SC-7
70  //
71  //	800-53-SC-8 SC-8 TRANSMISSION CONFIDENTIALITY AND INTEGRITY https://nvd.nist.gov/800-53/Rev4/control/SC-8
72  //
73  //	800-53-SC-12 SC-12 CRYPTOGRAPHIC KEY ESTABLISHMENT AND MANAGEMENT https://nvd.nist.gov/800-53/Rev4/control/SC-12
74  //
75  //	800-53-SC-13 SC-13 CRYPTOGRAPHIC PROTECTION https://nvd.nist.gov/800-53/Rev4/control/SC-13
76  //
77  //	800-53-CP-9 CP-9 INFORMATION SYSTEM BACKUP https://nvd.nist.gov/800-53/Rev4/control/CP-9
78  //
79  //	800-53-RA-5 RA-5 VULNERABILITY SCANNING https://nvd.nist.gov/800-53/Rev4/control/RA-5
80  //
81  //	800-53-AU-11 AU-11 AUDIT RECORD RETENTION https://nvd.nist.gov/800-53/Rev4/control/AU-11
82  
83  
84  
85  	/*
86      | Id           | Type              | Entity                                                                       | Policy                                                                                                                                                                                                   | IaC            |
87  |-----|--------------|-------------------|------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
88  |   0 | CKV_AWS_1    | data              | aws_iam_policy_document                                                      | Ensure IAM policies that allow full "*-*" administrative privileges are not created                                                                                                                      | Terraform      |
89  |   1 | CKV_AWS_1    | resource          | serverless_aws                                                               | Ensure IAM policies that allow full "*-*" administrative privileges are not created                                                                                                                      | serverless     |
90  |   2 | CKV_AWS_2    | resource          | aws_alb_listener                                                             | Ensure ALB protocol is HTTPS                                                                                                                                                                             | Terraform      |
91  |   3 | CKV_AWS_2    | resource          | aws_lb_listener                                                              | Ensure ALB protocol is HTTPS                                                                                                                                                                             | Terraform      |
92  	*
93  	*/
94  
95  	/** The nist policy string mapping. */
96  	private static Map<String,String> NIST_POLICY_STRING_MAPPING = new HashMap<>();
97  
98  	/** The Constant DETECT_SC_13. */
99  	private static final String DETECT_SC_13 ="encrypted at rest";
100 
101 	/** The Constant DETECT2_SC_13. */
102 	private static final String DETECT2_SC_13 ="securely encrypted";
103 
104 	/** The Constant SC_13_TAGS. */
105 	private static final String SC_13_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-311</tag>\n		<tag>800-53-sc-13</tag>";
106 
107 	/** The Constant DETECT_SC_12. */
108 	private static final String DETECT_SC_12 ="Ensure rotation";
109 
110 	/** The Constant SC_12_TAGS. */
111 	private static final String SC_12_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-320</tag>\n		<tag>800-53-sc-12</tag>";
112 
113 	/** The Constant DETECT_SC_8. */
114 	private static final String DETECT_SC_8 ="encryption transit";
115 
116 	/** The Constant DETECT2_SC_8. */
117 	private static final String DETECT2_SC_8 ="https";
118 
119 	/** The Constant DETECT3_SC_8. */
120 	private static final String DETECT3_SC_8 ="uses SSL";
121 
122 	/** The Constant DETECT4_SC_8. */
123 	private static final String DETECT4_SC_8 ="node-to-node encryption";
124 
125 	/** The Constant SC_8_TAGS. */
126 	private static final String SC_8_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-311</tag>\n		<tag>800-53-sc-8</tag>";
127 
128 	/** The Constant DETECT_AC_6. */
129 	private static final String DETECT_AC_6 ="IAM policies";
130 
131 	/** The Constant DETECT_IA_5. */
132 	private static final String DETECT_IA_5 ="IAM password policy";
133 
134 	/** The Constant IA_5_TAGS. */
135 	private static final String IA_5_TAGS ="\n		<tag>owasp-a3</tag>\n		<tag>cweid-257</tag>\n		<tag>800-53-ia-5</tag>";
136 
137 	/** The Constant AC_6_TAGS. */
138 	private static final String AC_6_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-272</tag>\n		<tag>800-53-ac-6</tag>";
139 
140 	/** The Constant DETECT_AC_4_GROUP. */
141 	private static final String DETECT_AC_4_GROUP ="security group";
142 
143 	/** The Constant AC_4_TAGS_GROUP. */
144 	private static final String AC_4_TAGS_GROUP ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-732</tag>\n		<tag>800-53-ac-4</tag>";
145 
146 	/** The Constant DETECT_AC_4. */
147 	private static final String DETECT_AC_4 ="public";
148 
149 	/** The Constant AC_4_TAGS. */
150 	private static final String AC_4_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-732</tag>\n		<tag>800-53-ac-4</tag>";
151 
152 	/** The Constant DETECT_AU_12. */
153 	private static final String DETECT_AU_12 ="logging";
154 
155 	/** The Constant AU_12_TAGS. */
156 	private static final String AU_12_TAGS ="\n		<tag>owasp-a10</tag>\n		<tag>cweid-778</tag>\n		<tag>800-53-au-12</tag>";
157 
158 	/** The Constant DETECT_CP_9. */
159 	private static final String DETECT_CP_9 ="retention backup";
160 
161 	/** The Constant CP_9_TAGS. */
162 	private static final String CP_9_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-693</tag>\n		<tag>800-53-cp-9</tag>";
163 
164 	/** The Constant DETECT_AU_11. */
165 	private static final String DETECT_AU_11 ="retention log";
166 
167 	/** The Constant AU_11_TAGS. */
168 	private static final String AU_11_TAGS ="\n		<tag>owasp-a6</tag>\n		<tag>cweid-779</tag>\n		<tag>800-53-au-11</tag>";
169 
170 	static {
171 		NIST_POLICY_STRING_MAPPING.put(DETECT_SC_13,SC_13_TAGS);
172 		NIST_POLICY_STRING_MAPPING.put(DETECT2_SC_13,SC_13_TAGS);
173 		NIST_POLICY_STRING_MAPPING.put(DETECT_SC_12,SC_12_TAGS);
174 		NIST_POLICY_STRING_MAPPING.put(DETECT_SC_8,SC_8_TAGS);
175 		NIST_POLICY_STRING_MAPPING.put(DETECT2_SC_8,SC_8_TAGS);
176 		NIST_POLICY_STRING_MAPPING.put(DETECT3_SC_8,SC_8_TAGS);
177 		NIST_POLICY_STRING_MAPPING.put(DETECT4_SC_8,SC_8_TAGS);
178 		NIST_POLICY_STRING_MAPPING.put(DETECT_IA_5,IA_5_TAGS);
179 		NIST_POLICY_STRING_MAPPING.put(DETECT_AC_6,AC_6_TAGS);
180 		NIST_POLICY_STRING_MAPPING.put(DETECT_AC_4,AC_4_TAGS);
181 		NIST_POLICY_STRING_MAPPING.put(DETECT_AC_4_GROUP,AC_4_TAGS_GROUP);
182 		NIST_POLICY_STRING_MAPPING.put(DETECT_AU_12,AU_12_TAGS);
183 		NIST_POLICY_STRING_MAPPING.put(DETECT_CP_9,CP_9_TAGS);
184 		NIST_POLICY_STRING_MAPPING.put(DETECT_AU_11,AU_11_TAGS);
185 	}
186 
187 
188 	/**
189 	 * Generate sonarqube rule definitions for checkov cloudformation test.
190 	 *
191 	 * @throws IOException Signals that an I/O exception has occurred.
192 	 */
193 	@Test
194 	public void generateSonarqubeRuleDefinitionsForCheckovCloudformationTest() throws IOException {
195 		final CSVParser parser = CSVParser.parse(new InputStreamReader(this.getClass().getResourceAsStream("/checkov/rules.txt"),StandardCharsets.UTF_8), CSVFormat.EXCEL.withHeader().withDelimiter('|').withTrim());
196 		final List<CSVRecord> records = parser.getRecords();
197 		assertFalse(records.isEmpty());
198 		records.remove(0);
199 		final Map<String,String> map = new HashMap<>();
200 		for (final CSVRecord csvRecord : records) {
201 			if ((csvRecord.isSet("Id") && "resource".equals(csvRecord.get("Type")) && !map.containsKey(csvRecord.get("IaC") +"-" + csvRecord.get("Id"))) && "cloudformation".equalsIgnoreCase(csvRecord.get("IaC")) ) {
202 			String ruleEntryUntagged = XML_ENTRY.replace("{RULE_ID}",csvRecord.get("Id")).replace("{NAME}",csvRecord.get("Policy")).replace("{IaC}",csvRecord.get("IaC").toLowerCase()).replace("\"","&quot;");
203 
204 			for (final String key : NIST_POLICY_STRING_MAPPING.keySet()) {
205 				if (ruleEntryUntagged.toLowerCase().contains(key.toLowerCase())) {
206 					ruleEntryUntagged = ruleEntryUntagged.replace("{EXTRA_TAGS}",NIST_POLICY_STRING_MAPPING.get(key));
207 				}
208 			}
209 			ruleEntryUntagged = ruleEntryUntagged.replace("{EXTRA_TAGS}","");
210 			System.out.println(ruleEntryUntagged);
211 
212 			map.put(csvRecord.get("IaC") +"-" + csvRecord.get("Id"),"");
213 			}
214 		}
215 
216 	}
217 
218 	/**
219 	 * Generate sonarqube rule definitions for checkov terraform test.
220 	 *
221 	 * @throws IOException Signals that an I/O exception has occurred.
222 	 */
223 	@Test
224 	public void generateSonarqubeRuleDefinitionsForCheckovTerraformTest() throws IOException {
225 		final CSVParser parser = CSVParser.parse(new InputStreamReader(this.getClass().getResourceAsStream("/checkov/rules.txt"),StandardCharsets.UTF_8), CSVFormat.EXCEL.withHeader().withDelimiter('|').withTrim());
226 		final List<CSVRecord> records = parser.getRecords();
227 		assertFalse(records.isEmpty());
228 		records.remove(0);
229 		final Map<String,String> map = new HashMap<>();
230 		for (final CSVRecord csvRecord : records) {
231 			if ((csvRecord.isSet("Id") && "resource".equals(csvRecord.get("Type")) && !map.containsKey(csvRecord.get("IaC") +"-" + csvRecord.get("Id"))) && "terraform".equalsIgnoreCase(csvRecord.get("IaC"))) {
232 			String ruleEntryUntagged = XML_ENTRY.replace("{RULE_ID}",csvRecord.get("Id")).replace("{NAME}",csvRecord.get("Policy")).replace("{IaC}",csvRecord.get("IaC").toLowerCase()).replace("\"","&quot;");
233 
234 			for (final String key : NIST_POLICY_STRING_MAPPING.keySet()) {
235 				if (ruleEntryUntagged.toLowerCase().contains(key.toLowerCase())) {
236 					ruleEntryUntagged = ruleEntryUntagged.replace("{EXTRA_TAGS}",NIST_POLICY_STRING_MAPPING.get(key));
237 				}
238 			}
239 			ruleEntryUntagged = ruleEntryUntagged.replace("{EXTRA_TAGS}","");
240 			System.out.println(ruleEntryUntagged);
241 
242 			map.put(csvRecord.get("IaC") +"-" + csvRecord.get("Id"),"");
243 			}
244 		}
245 
246 	}
247 
248 }