bhouse-nexthop commented on code in PR #14357:
URL: https://github.com/apache/cloudstack/pull/14357#discussion_r4502940911


##########
server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java:
##########
@@ -690,6 +692,33 @@ protected void 
validateSourceStartAndEndPorts(NetworkACLItemVO networkACLItemVO)
         }
     }
 
+    /**
+     * Ports are only applied to TCP and UDP, so they cannot be given with any 
other protocol number:
+     * the rule would be applied to the whole protocol, ignoring them.
+     */
+    protected void validatePortsAreUsableWithProtocol(String protocol, Integer 
sourcePortStart, Integer sourcePortEnd) {
+        if ((sourcePortStart == null && sourcePortEnd == null) || 
!StringUtils.isNumeric(protocol)) {
+            return;
+        }
+        int protoNumber = NumberUtils.toInt(protocol, -1);
+        if (protoNumber != NetUtils.TCP_PROTO_NUMBER && protoNumber != 
NetUtils.UDP_PROTO_NUMBER) {
+            throw new InvalidParameterValueException(String.format("Start and 
end port can only be given for TCP or UDP (protocol number %d or %d), not for 
protocol number [%s]",
+                    NetUtils.TCP_PROTO_NUMBER, NetUtils.UDP_PROTO_NUMBER, 
protocol));
+        }
+    }
+
+    /**
+     * On update the ports a rule already carries are only checked when the 
protocol is given too, so
+     * that a rule stored with ports on another protocol number can still be 
edited otherwise, while a
+     * protocol change cannot leave them on it.
+     */
+    protected void 
validatePortsAreUsableWithProtocolOnUpdate(UpdateNetworkACLItemCmd 
updateNetworkACLItemCmd, NetworkACLItemVO networkACLItemVo) {
+        boolean protocolGiven = 
StringUtils.isNotBlank(updateNetworkACLItemCmd.getProtocol());
+        validatePortsAreUsableWithProtocol(networkACLItemVo.getProtocol(),
+                protocolGiven ? networkACLItemVo.getSourcePortStart() : 
updateNetworkACLItemCmd.getSourcePortStart(),

Review Comment:
   @weizhouapache thanks for writing out the cases. Here's how each one behaves 
on this branch with the default `partialupgrade=true`. Take a stored rule with 
`tcp` and ports 80-80, or `icmp` with type 8 code 0:
   
   | Stored | Update | Result today |
   |---|---|---|
   | ports | protocol that can't carry ports (`icmp`, `all`, `47`), no ports 
passed | rejected: the stored ports are checked against the new protocol |
   | ports | new protocol that can carry ports (`tcp` to `udp`), no ports 
passed | ports kept |
   | ports | new protocol with new ports | new ports applied, checked against 
the new protocol |
   | icmp type/code | protocol other than icmp, no type/code passed | rejected 
("Can specify icmpCode and icmpType for ICMP protocol only") |
   | icmp type/code | protocol other than icmp, type/code passed | rejected, 
same check |
   | icmp type/code | `icmp` again (or `1`) with a different type/code | new 
type/code applied |
   
   With `partialupgrade=false`, every field is replaced from the call, so 
stored ports and ICMP type/code are dropped unless they're passed again. That 
already gives the "clean up, then check only what the API was given" behaviour 
when it's wanted.
   
   I'd rather not change the partial-update semantics in this PR. Silently 
dropping stored ports on a protocol change would turn a call that's rejected 
today into one that succeeds with a wider rule than the caller may expect: 
`tcp` 22 changed to `all` would end up allowing everything. It would also 
change the default update path right before the 4.22.2 freeze. Callers who want 
a clean replace can use `partialupgrade=false`. If you think the partial path 
should clear them too, I can open a separate issue for it so it gets its own 
review.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to