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

Security group and Security group rules validation #165

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

itzikb-redhat
Copy link
Contributor

Add/Update Validations and validations tests to SecurityGroup and SecurityGroupRule

@github-actions github-actions bot added the semver:major Breaking change label Dec 31, 2024
@itzikb-redhat itzikb-redhat force-pushed the sg-validations branch 2 times, most recently from b25cf0a to dcf0f04 Compare January 2, 2025 19:13
@mdbooth
Copy link
Contributor

mdbooth commented Jan 3, 2025

@itzikb-redhat I just rebased this so it no longer includes #167, no other changes.

// +kubebuilder:validation:Enum:=IPv4;IPv6
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=16
// +kubebuilder:validation:MaxLength:=4
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious: what does MaxLength do when the field is an enum?

Copy link
Contributor

Choose a reason for hiding this comment

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

I also wondered this. It's possible that even though it's technically redundant for validation purposes, it may still be used in the runtime complexity calculations? I'll bet @JoelSpeed would know.

Choose a reason for hiding this comment

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

For runtime complexity, the openapi schema shows that the field is an enum, so the estimated worst case is based on the maximum length of the enum values. You don't actually need a maxlength on an enum WRT CEL, but it also cannot hurt to include it

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'll remove both length rules

Ethertype *Ethertype `json:"ethertype"`
// If the protocol is [tcp, udp, dccp sctp,udplite] this value must be less than
// or equal to the PortRangeMax attribute value.
// If the protocol is ICMP, this value must be an ICMP type
Copy link
Member

Choose a reason for hiding this comment

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

If the protocol is ICMP, this value must be an ICMP type

Before reading the code, I can't immediately find a meaning to this sentence

Copy link
Member

Choose a reason for hiding this comment

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

When setting up ICMP, I would naïvely leave PortRangeMin and PortRangeMax empty. Would I be wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

First I have a typo, PorRangeMin -> icmp type, PortRangeMax - icmp code
Can you suggest an alternative to the comment?
At least from my testing with the openstack client you can leave them out (Then I think the rule catch all the ICMP types)

Comment on lines 92 to 90
// Protocol is the IP protocol can be represented by a string, an
// integer, or null
// +optional
Copy link
Member

@pierreprinetti pierreprinetti Jan 3, 2025

Choose a reason for hiding this comment

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

(I'm commenting the comment) I don't believe you can represent the protocol as an integer here. You probably could if type Protocol's underlying type was an integer and you overrode UnmarshalJSON to also accept strings. But I am not sure that Kubebuilder would like it.

Do you really plan on accepting integers here? And if not, how do I set e.g. vrrp?

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'm not sure what the concern is. If you want vrrp to be set as a number you set the number "112" (as a string)

Copy link
Member

@pierreprinetti pierreprinetti Jan 6, 2025

Choose a reason for hiding this comment

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

If you want users to pass numbers as strings, you should tell them explicitly in the comment. Also would null be passed as "null"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Regarding null I think I'll just remove it. About numbers as strings - Do we want to use also allow integers?

Copy link
Member

Choose a reason for hiding this comment

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

that's a question for @mdbooth @mandre

Copy link
Contributor

Choose a reason for hiding this comment

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

I think:

  • We don't allow numbers and just use the strings
  • We should validate Protocol as an enum

As for null, what does OpenStack do with that? Is it the same as any? If so, I think we should support either any or null (meaning unspecified here), but not both.

If we go with null we should write it as 'if not specified...' or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok we'll go with not specified and use strings. As for enum - we use a pattern instead

Copy link
Member

Choose a reason for hiding this comment

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

@mdbooth
May I humour you with this

(also cf gophercloud/gophercloud#2442 (comment) )

@itzikb-redhat itzikb-redhat force-pushed the sg-validations branch 2 times, most recently from 96f711f to d6864c2 Compare January 8, 2025 16:24
@@ -26,37 +26,84 @@ type RuleDirection string
// +kubebuilder:validation:MaxLength:=16
type Protocol string

const (
ProtocolANY Protocol = "any"

Choose a reason for hiding this comment

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

Enums in Kube APIs are generally PascalCase, these probably want to follow that convention? Any, ICMP, ICMPv6, IPv6Encap etc

Copy link
Contributor

@mdbooth mdbooth Jan 9, 2025

Choose a reason for hiding this comment

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

@JoelSpeed I previously gave this some thought in the Image API. These constants are defined by the OpenStack API. In my first version of the Image API I translated the constants, but:

  • It's a huge mess in the code
  • It's another source of errors
  • I suspect it's more confusing for users who are likely using the OpenStack docs as a primary source for more complex things like this

So my current thinking is that we don't translate constants which are defined by the OpenStack API.

This is itself a source of confusion because now users need to understand which constants are OpenStack constants and which are not. I think either choice has trade offs, but my current feeling is that this has the better balance for this API.

@mandre Incidentally, if we agree with this we should document it explicitly in our API conventions.

Perhaps we could have a convention that we point out explicitly in the Godocs that these are 'passthrough' values which correlate exactly to OpenStack values.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sounds good. I've added the following to our API convention doc:

* Constants coming from OpenStack should be copied verbatim.

Choose a reason for hiding this comment

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

If that's the direction of the project, then that is fair. A lot of other projects around clouds have made the same decision. Though of course, you do then juxtapose with core Kube APIs and other APIs that follow kube conventions

If a user knows openstack uses snake case, and knows Kube uses pascal case, I guess they have a 50/50 of getting it right

// SecurityGroupRule defines a Security Group rule
// +kubebuilder:validation:MinProperties:=1
// +kubebuilder:validation:XValidation:rule="has(self.portRangeMin) == has(self.portRangeMax)",message="PortRangeMin and PortRangeMax should exist together"

Choose a reason for hiding this comment

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

Use the serialised version of the field name in the user facing error, also, maybe prefer must to should?

Suggested change
// +kubebuilder:validation:XValidation:rule="has(self.portRangeMin) == has(self.portRangeMax)",message="PortRangeMin and PortRangeMax should exist together"
// +kubebuilder:validation:XValidation:rule="has(self.portRangeMin) == has(self.portRangeMax)",message="portRangeMin and portRangeMax must only exist together"

Have you considered making an optional portRange struct, with min and max fields within that are required?

PortRangeMin *int32 `json:"portRangeMin,omitempty"`
PortRangeMax *int32 `json:"portRangeMax,omitempty"`
// +kubebuilder:validation:Required
Ethertype *Ethertype `json:"ethertype"`

Choose a reason for hiding this comment

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

Why a pointer for a required field?

Comment on lines 102 to 107
PortRangeMin *uint16 `json:"portRangeMin,omitempty"`
// If the protocol is [tcp, udp, dccp sctp,udplite] this value must be greater than
// or equal to the PortRangeMin attribute value.
// If the protocol is ICMP, this value must be an ICMP type
// +optional
PortRangeMax *uint16 `json:"portRangeMax,omitempty"`

Choose a reason for hiding this comment

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

Don't use uints, they don't translate into an openapi schema in any way that correctly validates the unsigned nature, use int32 and set a minimum value of zero using the appropriate kubebuilder marker

@@ -26,37 +26,85 @@ type RuleDirection string
// +kubebuilder:validation:MaxLength:=16
type Protocol string

const (

Choose a reason for hiding this comment

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

Why aren't you using an enum for protocol?

Add/Update Validations and validations tests to SecurityGroup and SecurityGroupRule
@itzikb-redhat itzikb-redhat marked this pull request as draft January 9, 2025 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver:major Breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants