bhouse-nexthop opened a new pull request, #14357:
URL: https://github.com/apache/cloudstack/pull/14357

   ### Description
   
   A VPC network ACL rule given by protocol number (1, 6, 17), or with an 
upper-case protocol name, can lose its port range or ICMP type on the virtual 
router. It is then applied to the whole protocol, and nothing is reported. A 
rule with ports on any other protocol number is accepted, and its ports are 
ignored.
   
   Fixes #14356
   
   #### Why it breaks
   
   The VR applies ports only to a rule it receives as `tcp` or `udp`, and an 
ICMP type/code only to one it receives as `icmp`. 
`SetNetworkACLCommand.generateFwRules()` sent the protocol exactly as stored. 
`SetNetworkAclConfigItem` turns anything else into a `ProtocolAclRule`: a bare 
protocol number with no port or ICMP fields. So:
   
   1. **Protocol 6 or 17 with ports** (the UI offers ports for "Protocol 
number", and the API accepts them) is applied to the whole protocol. "Protocol 
6, port 22, allow" becomes `-p tcp -j ACCEPT`, i.e. all TCP.
   2. **Protocol 1 set by `updateNetworkACLItem`.** `createNetworkACL` maps 
protocol `1` to `icmp`, but `updateNetworkACLItem` did not. The ICMP type is 
then cleared, so the VR allows all ICMP.
   3. **An upper-case `ICMP`** (stored as given) fails `generateFwRules()`'s 
case-sensitive `"icmp"` check. The rule is sent with the empty port range, 
`0:0`, where the ICMP type and code belong, so the VR applies `--icmp-type 0/0` 
(echo-reply only), whatever type was asked for.
   4. **Ports with any other protocol number** (e.g. 132) are accepted by the 
UI and API, and silently ignored by the VR.
   
   #### How it is fixed
   
   - **`SetNetworkACLCommand.generateFwRules()`** sends protocol 1, 6 and 17, 
and any case, to the VR as `icmp`, `tcp` and `udp`. Their ports or ICMP type 
then reach the rule the VR builds. A missing ICMP type or code is sent as `-1` 
(any) instead of `null`; a rule updated to protocol 1 may have neither, and 
`null` would make the VR side's `parseInt` fail. Normalising where the rule is 
encoded also fixes rules already stored this way, with no DB migration.
   - **`UpdateNetworkACLItemCmd.getProtocol()`** maps protocol 1 to `icmp`, the 
same as `CreateNetworkACLCmd`.
   - **`NetworkACLServiceImpl`** rejects ports given with a protocol number 
other than 6 or 17, since they can't be applied. On update, only ports given in 
that request are checked, so existing rules that already carry such ports stay 
editable.
   - **UI (`AclRulesTab.vue`)** only shows and sends Start/End port for TCP, 
UDP, and protocol number 6 or 17.
   
   #### Upgrade note
   
   Existing rules affected by 1–3 will be applied as configured from the next 
ACL apply:
   - **Narrower:** "protocol 6, port 22" stops allowing every other TCP port.
   - **Wider or narrower:** an `ICMP` rule with type "any" stops being 
echo-reply only and matches all ICMP.
   
   That is what those rules always asked for, but traffic that only got through 
(or was only blocked) because of the bug will be treated differently.
   
   #### How to reproduce the old behaviour
   
   1. In a VPC ACL list, add an ingress rule: Protocol number `6`, start/end 
port `22`, CIDR `0.0.0.0/0`, Allow. Attach the list to a tier.
   2. On the VR, run `iptables -S ACL_INBOUND_ethX`:
      - Before: `-A ACL_INBOUND_ethX -p tcp -j ACCEPT` (every TCP port open)
      - After: `-A ACL_INBOUND_ethX -p tcp -m tcp --dport 22 -j ACCEPT`
   3. `createNetworkACL protocol=ICMP icmptype=8 icmpcode=0 ...`:
      - Before: `-p icmp -m icmp --icmp-type 0/0`
      - After: `--icmp-type 8/0`
   
   ### Types of changes
   
   - [ ] Breaking change (fix or feature that would cause existing 
functionality to change)
   - [ ] New feature (non-breaking change which adds functionality)
   - [x] Bug fix (non-breaking change which fixes an issue)
   - [ ] Enhancement (improves an existing feature and functionality)
   - [ ] Cleanup (Code refactoring and cleanup, that may add test cases)
   - [ ] Build/CI
   - [x] Test (unit or integration test code)
   
   ### Feature/Enhancement Scale or Bug Severity
   
   #### Bug Severity
   
   - [ ] BLOCKER
   - [ ] Critical
   - [x] Major
   - [ ] Minor
   - [ ] Trivial
   
   ### How Has This Been Tested?
   
   - `SetNetworkACLCommandTest` checks the encoded rules:
     - 6/17 with ports keep them;
     - 1 keeps its ICMP type and code, or gets `-1;-1` when it has none;
     - `ICMP`/`TCP` in upper case;
     - other numbers and `all` pass through unchanged.
   - `UpdateNetworkACLItemCmdTest`: protocol 1 becomes `icmp`, and anything 
else is left as is.
   - `NetworkACLServiceImplTest`: ports are accepted with tcp/udp/6/17, and 
rejected with another protocol number when given (start port alone included).
   - The `api`, `core` and `server` modules build with checkstyle, and the 
three test classes pass (`NetworkACLServiceImplTest`: 108 tests).
   - ESLint (the UI's own config) is clean for `AclRulesTab.vue`.
   - I checked the before/after iptables text with real iptables; I have not 
run it on a VR.
   
   #### How did you try to break this feature and the system with this change?
   
   - **Revoked rules** keep their existing encoding.
   - **Other protocols:** `all`, other protocol numbers and lower-case names 
are encoded exactly as before.
   - **Existing rules with ports on another protocol number** can still be 
updated (e.g. renumbered) through the UI and the API.
   


-- 
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