|
26 | 26 |
|
27 | 27 | import javax.inject.Inject; |
28 | 28 |
|
29 | | -import com.cloud.dc.DataCenter; |
30 | | -import com.cloud.exception.PermissionDeniedException; |
31 | | -import com.cloud.network.dao.NetrisProviderDao; |
32 | | -import com.cloud.network.dao.NsxProviderDao; |
33 | | -import com.cloud.network.element.NetrisProviderVO; |
34 | | -import com.cloud.network.element.NsxProviderVO; |
| 29 | +import org.apache.cloudstack.api.ApiConstants; |
35 | 30 | import org.apache.cloudstack.api.ApiErrorCode; |
36 | 31 | import org.apache.cloudstack.api.ServerApiException; |
37 | 32 | import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; |
| 33 | +import org.apache.cloudstack.api.command.user.network.ImportNetworkACLCmd; |
38 | 34 | import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; |
39 | 35 | import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; |
40 | 36 | import org.apache.cloudstack.api.command.user.network.MoveNetworkAclItemCmd; |
|
43 | 39 | import org.apache.cloudstack.context.CallContext; |
44 | 40 | import org.apache.commons.codec.digest.DigestUtils; |
45 | 41 | import org.apache.commons.collections.CollectionUtils; |
| 42 | +import org.apache.commons.lang3.BooleanUtils; |
46 | 43 | import org.apache.commons.lang3.ObjectUtils; |
47 | 44 | import org.apache.commons.lang3.StringUtils; |
48 | 45 | import org.springframework.stereotype.Component; |
49 | 46 |
|
| 47 | +import com.cloud.dc.DataCenter; |
50 | 48 | import com.cloud.event.ActionEvent; |
51 | 49 | import com.cloud.event.EventTypes; |
52 | 50 | import com.cloud.exception.InvalidParameterValueException; |
| 51 | +import com.cloud.exception.PermissionDeniedException; |
53 | 52 | import com.cloud.exception.ResourceUnavailableException; |
54 | 53 | import com.cloud.network.Network; |
55 | 54 | import com.cloud.network.NetworkModel; |
56 | 55 | import com.cloud.network.Networks; |
| 56 | +import com.cloud.network.dao.NetrisProviderDao; |
57 | 57 | import com.cloud.network.dao.NetworkDao; |
58 | 58 | import com.cloud.network.dao.NetworkVO; |
| 59 | +import com.cloud.network.dao.NsxProviderDao; |
| 60 | +import com.cloud.network.element.NetrisProviderVO; |
| 61 | +import com.cloud.network.element.NsxProviderVO; |
59 | 62 | import com.cloud.network.vpc.NetworkACLItem.Action; |
60 | 63 | import com.cloud.network.vpc.NetworkACLItem.TrafficType; |
61 | 64 | import com.cloud.network.vpc.dao.NetworkACLDao; |
@@ -1070,6 +1073,111 @@ public NetworkACLItem moveRuleToTheTopInACLList(NetworkACLItem ruleBeingMoved) { |
1070 | 1073 | return moveRuleToTheTop(ruleBeingMoved, allRules); |
1071 | 1074 | } |
1072 | 1075 |
|
| 1076 | + @Override |
| 1077 | + public List<NetworkACLItem> importNetworkACLRules(ImportNetworkACLCmd cmd) throws ResourceUnavailableException { |
| 1078 | + long aclId = cmd.getAclId(); |
| 1079 | + Map<Object, Object> rules = cmd.getRules(); |
| 1080 | + List<NetworkACLItem> createdRules = new ArrayList<>(); |
| 1081 | + List<String> errors = new ArrayList<>(); |
| 1082 | + for (Map.Entry<Object, Object> entry : rules.entrySet()) { |
| 1083 | + try { |
| 1084 | + Map<String, Object> ruleMap = (Map<String, Object>) entry.getValue(); |
| 1085 | + NetworkACLItem item = createACLRuleFromMap(ruleMap, aclId); |
| 1086 | + createdRules.add(item); |
| 1087 | + } catch (Exception ex) { |
| 1088 | + String error = "Failed to import rule at index " + entry.getKey() + ": " + ex.getMessage(); |
| 1089 | + errors.add(error); |
| 1090 | + logger.error(error, ex); |
| 1091 | + } |
| 1092 | + } |
| 1093 | + // no rules got imported |
| 1094 | + if (createdRules.isEmpty() && !errors.isEmpty()) { |
| 1095 | + logger.error("Failed to import any ACL rules. Errors: {}", String.join("; ", errors)); |
| 1096 | + throw new CloudRuntimeException("Failed to import any ACL rules."); |
| 1097 | + } |
| 1098 | + |
| 1099 | + // apply ACL to network |
| 1100 | + if (!createdRules.isEmpty()) { |
| 1101 | + applyNetworkACL(aclId); |
| 1102 | + } |
| 1103 | + return createdRules; |
| 1104 | + } |
| 1105 | + |
| 1106 | + private NetworkACLItem createACLRuleFromMap(Map<String, Object> ruleMap, long aclId) { |
| 1107 | + String protocol = (String) ruleMap.get(ApiConstants.PROTOCOL); |
| 1108 | + if (protocol == null || protocol.trim().isEmpty()) { |
| 1109 | + throw new InvalidParameterValueException("Protocol is required"); |
| 1110 | + } |
| 1111 | + String action = (String) ruleMap.getOrDefault(ApiConstants.ACTION, "deny"); |
| 1112 | + String trafficType = (String) ruleMap.getOrDefault(ApiConstants.TRAFFIC_TYPE, NetworkACLItem.TrafficType.Ingress); |
| 1113 | + String forDisplay = (String) ruleMap.getOrDefault(ApiConstants.FOR_DISPLAY, "true"); |
| 1114 | + |
| 1115 | + // Create ACL rule using the service |
| 1116 | + CreateNetworkACLCmd cmd = new CreateNetworkACLCmd(); |
| 1117 | + cmd.setAclId(aclId); |
| 1118 | + cmd.setProtocol(protocol.toLowerCase()); |
| 1119 | + cmd.setAction(action.toLowerCase()); |
| 1120 | + cmd.setTrafficType(trafficType.toLowerCase()); |
| 1121 | + cmd.setDisplay(BooleanUtils.toBoolean(forDisplay)); |
| 1122 | + |
| 1123 | + // Optional parameters |
| 1124 | + if (ruleMap.containsKey(ApiConstants.CIDR_LIST)) { |
| 1125 | + Object cidrObj = ruleMap.get(ApiConstants.CIDR_LIST); |
| 1126 | + List<String> cidrList = new ArrayList<>(); |
| 1127 | + if (cidrObj instanceof String) { |
| 1128 | + for (String cidr : ((String) cidrObj).split(",")) { |
| 1129 | + cidrList.add(cidr.trim()); |
| 1130 | + } |
| 1131 | + } else if (cidrObj instanceof List) { |
| 1132 | + cidrList.addAll((List<String>) cidrObj); |
| 1133 | + } |
| 1134 | + cmd.setCidrList(cidrList); |
| 1135 | + } |
| 1136 | + |
| 1137 | + if (ruleMap.containsKey(ApiConstants.START_PORT)) { |
| 1138 | + cmd.setPublicStartPort(parseInt(ruleMap.get(ApiConstants.START_PORT))); |
| 1139 | + } |
| 1140 | + |
| 1141 | + if (ruleMap.containsKey(ApiConstants.END_PORT)) { |
| 1142 | + cmd.setPublicEndPort(parseInt(ruleMap.get(ApiConstants.END_PORT))); |
| 1143 | + } |
| 1144 | + |
| 1145 | + if (ruleMap.containsKey(ApiConstants.NUMBER)) { |
| 1146 | + cmd.setNumber(parseInt(ruleMap.get(ApiConstants.NUMBER))); |
| 1147 | + } |
| 1148 | + |
| 1149 | + if (ruleMap.containsKey(ApiConstants.ICMP_TYPE)) { |
| 1150 | + cmd.setIcmpType(parseInt(ruleMap.get(ApiConstants.ICMP_TYPE))); |
| 1151 | + } |
| 1152 | + |
| 1153 | + if (ruleMap.containsKey(ApiConstants.ICMP_CODE)) { |
| 1154 | + cmd.setIcmpCode(parseInt(ruleMap.get(ApiConstants.ICMP_CODE))); |
| 1155 | + } |
| 1156 | + |
| 1157 | + if (ruleMap.containsKey(ApiConstants.ACL_REASON)) { |
| 1158 | + cmd.setReason((String) ruleMap.get(ApiConstants.ACL_REASON)); |
| 1159 | + } |
| 1160 | + |
| 1161 | + return createNetworkACLItem(cmd); |
| 1162 | + } |
| 1163 | + |
| 1164 | + private Integer parseInt(Object value) { |
| 1165 | + if (value == null) { |
| 1166 | + return null; |
| 1167 | + } |
| 1168 | + if (value instanceof Integer) { |
| 1169 | + return (Integer) value; |
| 1170 | + } |
| 1171 | + if (value instanceof String) { |
| 1172 | + try { |
| 1173 | + return Integer.parseInt((String) value); |
| 1174 | + } catch (NumberFormatException e) { |
| 1175 | + throw new InvalidParameterValueException("Invalid integer value: " + value); |
| 1176 | + } |
| 1177 | + } |
| 1178 | + throw new InvalidParameterValueException("Cannot convert to integer: " + value); |
| 1179 | + } |
| 1180 | + |
1073 | 1181 | /** |
1074 | 1182 | * Validates the consistency of the ACL; the validation process is the following. |
1075 | 1183 | * <ul> |
|
0 commit comments