Skip to content
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

Support proper parsing of IPs with leading zeros #3138

Merged
merged 1 commit into from Oct 14, 2022

Conversation

arkadeepsen
Copy link
Contributor

@arkadeepsen arkadeepsen commented Sep 2, 2022

Changed all ParseIP and ParseCIDR functions of net package to ParseIPSloppy and ParseCIDRSloppy of k8s.io/utils/net package respectively for k8s API objects. This is done to allow IPs and CIDRs with leading zeros to be parsed without any error.

Additionally have added conversion of any IP in string format to net.IP format and then conversion to string format again to remove any leading zeros.

Following set of IP strings are validated:

  • service.Spec.ClusterIP
  • service.Spec.ClusterIPs
  • service.Spec.ExternalIPs
  • service.Status.LoadBalancer.Ingress[*].IP
  • node.Status.Addresses[*].Address (for address types NodeInternalIP and NodeExternalIP)
  • endpointSlice.Endpoints[*].Addresses
  • pod.Status.PodIP
  • pod.Status.PodIPs[*].IP

Signed-off-by: Arkadeep Sen arsen@redhat.com

Fixes: https://issues.redhat.com/browse/OCPBUGS-463

@arkadeepsen arkadeepsen force-pushed the leading-zeros branch 2 times, most recently from 70cc1a4 to c6aec2e Compare September 3, 2022 14:15
@coveralls
Copy link

coveralls commented Sep 3, 2022

Coverage Status

Coverage increased (+0.003%) to 52.794% when pulling dbe0a91 on arkadeepsen:leading-zeros into c4fd149 on ovn-org:master.

@arkadeepsen
Copy link
Contributor Author

arkadeepsen commented Sep 5, 2022

@martinkennelly PTAL

@arkadeepsen
Copy link
Contributor Author

/retest-failed

@npinaeva npinaeva self-requested a review September 7, 2022 09:03
@npinaeva
Copy link
Member

npinaeva commented Sep 8, 2022

Hey @arkadeepsen, as we discussed, we need to add ips validation for all k8s objects that can set ips (and CIDRs)
So I'd suggest to have a list of these objects, and then create parsing functions, to make sure we parse every ip/cidr before working with it.
So we would have functions like util.GetClusterIPs(service) and it should return properly parsed ips, then we won't need duplicate code like this https://github.com/ovn-org/ovn-kubernetes/pull/3138/files#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155R417-R426
wdyt?

@arkadeepsen
Copy link
Contributor Author

Hey @arkadeepsen, as we discussed, we need to add ips validation for all k8s objects that can set ips (and CIDRs) So I'd suggest to have a list of these objects, and then create parsing functions, to make sure we parse every ip/cidr before working with it. So we would have functions like util.GetClusterIPs(service) and it should return properly parsed ips, then we won't need duplicate code like this https://github.com/ovn-org/ovn-kubernetes/pull/3138/files#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155R417-R426 wdyt?

Makes more sense @npinaeva. I'll make the appropriate changes.

@arkadeepsen arkadeepsen force-pushed the leading-zeros branch 4 times, most recently from 8c977e4 to 4e83aae Compare September 8, 2022 13:55
@arkadeepsen
Copy link
Contributor Author

/retest

@arkadeepsen
Copy link
Contributor Author

/retest-failed

@ovn-robot
Copy link
Collaborator

Oops, something went wrong:

This workflow is already running

@arkadeepsen
Copy link
Contributor Author

/retest-failed

@ovn-robot
Copy link
Collaborator

Oops, something went wrong:

This workflow run cannot be retried

@@ -17,11 +16,14 @@ import (
"strings"
"testing"

"k8s.io/client-go/kubernetes"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove newline?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Will remove it.

@npinaeva
Copy link
Member

I am a bit confused by changes like
c48d854#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155L429
and then
92b8cd3#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155R429
you basically did the change in the first commit and reverted it in the next. Can you please rebase commits so that they have final changes?
Also the commits as they are right now are bit difficult to review - maybe having commit that replaces net.Parse functions with parseSloppy and nothing else, and then next commits for changes related to objects you listed in the description will be easier to review?
Also, can you add some comments for unit test changes you did? I don't see why this 4e83aae change is required - it looks for me like ClusterIP is the right service type

@arkadeepsen
Copy link
Contributor Author

I am a bit confused by changes like
c48d854#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155L429
and then
92b8cd3#diff-bb96390aa4d292c5ff6e2bc554446182b8abd55e12ba2a0290853b92aa4e1155R429
you basically did the change in the first commit and reverted it in the next. Can you please rebase commits so that they have final changes?
Also the commits as they are right now are bit difficult to review - maybe having commit that replaces net.Parse functions with parseSloppy and nothing else, and then next commits for changes related to objects you listed in the description will be easier to review?

I will make these changes and push separate commits.

Also, can you add some comments for unit test changes you did? I don't see why this 4e83aae change is required - it looks for me like ClusterIP is the right service type

The Status field of the Service has Loadbalancer Ingress IP set. I updated the buildServiceLBConfigs to use GetExternalAndLBIPs which adds an additional check on the type of Service and only fetches the LB IP if the type is set to LoadBalancer. As it was set to ClusterIP the unit test was failing.

@arkadeepsen
Copy link
Contributor Author

I will make these changes and push separate commits.

@npinaeva I have pushed 2 separate commits. One for replacing the net.ParseIP and net.ParseCIDR, and the other for the changes related to the objects.

@npinaeva
Copy link
Member

/lgtm
great work, thanks!

@@ -104,14 +105,14 @@ func (pi *PodInfo) String() string {
}

func (si SvcInfo) getL3Ver() string {
if net.ParseIP(si.ClusterIP).To4() != nil {
if utilnet.ParseIPSloppy(si.ClusterIP).To4() != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to use the sloppy functions when parsing k8s API objects, but for other objects, it would be better to make sure that they only ever contain valid IP addresses. So, eg, here, it would be better to change getSvcInfo to set si.ClusterIP using ValidateAndGetIPString(). Or alternatively, make si.ClusterIP a net.IP rather than a string, and set it with utilnet.ParseIPSloppy(svc.Spec.ClusterIP).

(This comment applies everywhere; I'm not going to comment in each place.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll make the appropriate changes. For parsing IPs and CIDRs from the annotation of various objects like namespace, pod, etc., should we use the sloppy version of functions or the parse functions from the net package?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have to deal with possibly-bad values in those annotations written by old versions of ovn-kubernetes, then you need to use the sloppy functions. If not, then you don't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the value assignment to the annotations of all the objects and didn't find any bad values (IP or CIDR) being assigned.

Wherever IP strings are being used directly from the k8s API objects I have used ValidateAndGetIPString to get the valid IP address first, and then assigned it to other variables or struct fields.

_, dpuSubnet, _ := net.ParseCIDR("10.0.0.101/24")
nodeIP := net.ParseIP("10.0.1.11")
_, dpuSubnet, _ := utilnet.ParseCIDRSloppy("10.0.0.101/24")
nodeIP := utilnet.ParseIPSloppy("10.0.1.11")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use the sloppy functions for const strings that you know are valid.

net.ParseIP and net.ParseCIDR should still be the default for parsing IPs/CIDRs. The sloppy versions should only be used in contexts where you need to accept invalid strings as user input for backward-compatibility reasons. (Basically, the parameter passed to ParseIPSloppy or ParseCIDRSloppy should almost always be exactly one of the items in your list in the initial PR description (service.Spec.ClusterIP, endpointSlice.Endpoints[*].Addresses, etc)

(EDIT: or, as above, if we were previously copying the bad values from those fields into an annotation, then you'll need to use the sloppy functions for that annotation too.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reverted the changes in the unit test files where valid const strings are being used.


// ValidateAndGetIPString validates the IP address and returns the IP in
// string format removing any leading zeros.
func ValidateAndGetIPString(ip string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are only using this function for IPs in kubernetes API objects, then those fields have already been validated, so you know they contain IPs that are valid according to net.ParseIP, and it's just a matter of removing the leading zeros. In which case, you don't need to return an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still returning the error from this function, but I have removed the error checking whenever it's called for any k8s API object. If this function is used for other strings which are not valid IPs then it will panic. Though this function is only being used for k8s API objects as of now.

Copy link
Contributor

@danwinship danwinship left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The existing commits should be squashed
  2. This appears to have a bunch of "go 1.19 gofmt changes" mixed in with the actual IP parsing changes. It would be better to undo those. If you can't, then this should wait until Update comment formatting for Go 1.19 #3207 merges and then be rebased on top of that.
  3. The PR would be a lot simpler if you removed the unused error return from ValidateAndGetIPString. If someone needed a version that also works on unvalidated strings later, then they could add that later. You could also rename the function to make it clearer that it requires an already-validated IP string so people don't mistakenly use it on unvalidated IP strings later. But anyway, I'm not going to say you have to change that if you think this way is better.

lgtm with the first two points (at least) fixed, but I feel like someone who is still active in ovn-k development should do the actual merging

…Sloppy and ParseCIDRSloppy of k8s.io/utils/net package respectively for k8s API objects. This is done to allow IPs and CIDRs with leading zeros to be parsed without any error. Additionally have added conversion of any IP in string format to net.IP format and then conversion to string format again to remove any leading zeros.

Signed-off-by: arkadeepsen <arsen@redhat.com>
@arkadeepsen
Copy link
Contributor Author

  1. The existing commits should be squashed

I have squashed the existing commits.

  1. This appears to have a bunch of "go 1.19 gofmt changes" mixed in with the actual IP parsing changes. It would be better to undo those. If you can't, then this should wait until Update comment formatting for Go 1.19 #3207 merges and then be rebased on top of that.

I have undone those changes. I also have rebased after #3207 is merged.

  1. The PR would be a lot simpler if you removed the unused error return from ValidateAndGetIPString. If someone needed a version that also works on unvalidated strings later, then they could add that later. You could also rename the function to make it clearer that it requires an already-validated IP string so people don't mistakenly use it on unvalidated IP strings later. But anyway, I'm not going to say you have to change that if you think this way is better.

I have removed the error checking. However, after removing the error checking it just becomes a single line function. So I have removed the function altogether and replaced wherever it was called with ParseIPSloppy(ip).String().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants