New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
endpoint: Do not override deny entries with proxy redirects #26344
endpoint: Do not override deny entries with proxy redirects #26344
Conversation
/test |
This is a bug in the Cilium redirect creation logic that needs to be fixed for both deny and auth rules to be properly handled. This current form of the PR seems to break Agent restart FQDN tests, so some more investigation is needed on why that happens. Update: Figured out that it is natural for new L3-specific DNS proxy redirects to generate no MapState as the proxy has yet to allocate any identities. Removed the check for the number of entries generated and removed the removal of redirects that do not generate any MapState (earlier I had assumed that would only happen if deny entry overrides all the MapState for the new redirect). |
7ba5878
to
c0cf2dc
Compare
827b53b
to
fc3fe4c
Compare
Removed unrelated change/cleanup to make both reviews and backports easier. |
fc3fe4c
to
1d0fc87
Compare
Fixed commit message. |
Added additional needs-backport labels |
/test |
pkg/endpoint/bpf.go
Outdated
} | ||
if entry.IsRedirectEntry() { | ||
entry.ProxyPort = redirectPort | ||
} | ||
e.desiredPolicy.PolicyMapState[keyFromFilter] = entry | ||
e.desiredPolicy.PolicyMapState.DenyPreferredInsertWithChanges(keyFromFilter, entry, insertedDesiredMapState, nil, idLookup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it expected that DenyPreferredInsertWithChanges
will insert into insertedDesiredMapState
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we were inserting into insertedDesiredMapState
only when the key/entry did not exist previously, now DenyPreferredInsertWithChanges
inserts into insertedDesiredMapState
also when the there was a previous entry with the same key. This does not matter, as where these are used in the revert code below, we first delete all inserted keys, then add back the old values, if they existed, from updatedDesiredMapState
. End result is that same before and after, previously the revert code directly replaced the new value with the old one, now the new value is deleted first, and the old one added back after.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. if there were old values also for (e.g., L3L4) entries created by DenyPreferredInsertWithChanges
then the old values of those can not be reverted back in case of a failure with the current code in the PR. I may have to change adds
and deletes
arguments to DenyPreferredInsertWithChanges
to be MapState
instead of just Keys
to make DenyPreferredInsertWithChanges
revertible. Let me try that!
pkg/policy/mapstate.go
Outdated
// Merging owners from the new entry to the existing one has no datapath impact so we skip | ||
// adding anything to 'adds' here. | ||
if oldEntry, exists := keys[key]; exists && (oldEntry.IsRedirectEntry() || oldEntry.IsDeny) { | ||
// Merging owners has the effect of keeping the shered entry alive as long as one of the owners exists. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
// Merging owners has the effect of keeping the shered entry alive as long as one of the owners exists. | |
// Merging owners has the effect of keeping the shared entry alive as long as one of the owners exists. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks!
if oldEntry, exists := keys[key]; exists && (oldEntry.IsRedirectEntry() || oldEntry.IsDeny) { | ||
// Merging owners has the effect of keeping the shered entry alive as long as one of the owners exists. | ||
if oldEntry, exists := keys[key]; exists && | ||
(!entry.IsRedirectEntry() && oldEntry.IsRedirectEntry() || oldEntry.IsDeny) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, this is not changing functional behavior and we are just adding an extra condition for explicitness for the if-statement, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now I think that is the case, yes. I was thinking that if the proxy port of an existing entry needs to be updated, then this code path should allow for that. I think this is currently not happening, but we are replacing direct manipulation of the redirect entry in bpf.go
with the DenyPreferredInsertWithChanges
that will end up here for a non-deny entry, so I thought it would be best to allow for proxy port to be updated by that call, if it ever needs to happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated with a new 1st commit that exports DenyPreferredInsertWithChanges()
and makes it revertible, including unit testing.
Use DenyPreferredInsert instead of directly manipulating policy map state to make sure deny entries are not overridden by new proxy redirect entries.
Prior to this fix it was possible for a proxy redirect to be pushed onto the policy map when it should have been overridden by a deny at least in these cases:
It is clear that in the latter case the addition of the redirect can not be completely blocked, so we can't fix this by making AllowsL4 more restrictive. But also in the former case it is possible that the deny rule only covers a subset of security identities, while the redirect rule covers some of the same security identities, but also some more that should not be blocked. Hence the correct fix here is to leave
AllowsL4
to be L3-independent, and cover these cases with deny preferred insert instead of adding redirect entries to the map directly.This PR also contains a related change that allows a redirect entry to be updated, maybe with a changed proxy port. I've not seen evidence that this is currently fixing a bug, but it feels like a real possibility.
Fixes: #12716