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

add-IPsecExternal #1667

Merged
merged 3 commits into from
Jan 8, 2024
Merged

Conversation

JoshSalomon
Copy link
Contributor

Add api to enable/disable extern (NS) ipsec. The feature (NS ipsec) is in TR in 4.14, and in 4.15 we provide API for simple enablement (in 4.14 the enablement is awkward with no clear API

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 16, 2023
Copy link
Contributor

openshift-ci bot commented Nov 16, 2023

Hello @JoshSalomon! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci openshift-ci bot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Nov 16, 2023
@openshift-ci openshift-ci bot requested review from bparees and deads2k November 16, 2023 09:59
@yuvalk
Copy link

yuvalk commented Nov 16, 2023

/retest

@yuvalk
Copy link

yuvalk commented Nov 16, 2023

The generated files for this change

can you reword the commit msg title, so it'll reference the other commit?
otherwise "this change" is ambiguous

// ipsecExtern enables external (NS) IPsec for the node, the configuration
// is done via nmstate operator.
// +optional
IPsecExtern *IPsecExtern `json:"ipsecExtern,omitempty"`
Copy link

Choose a reason for hiding this comment

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

we might consider making it a flag not config like
IPsecHostEnable (with true/false possible values)

not 100% sure what's the best practice here though

@JoshSalomon JoshSalomon changed the title wip-add-IPsecExtern add-IPsecExternal Nov 16, 2023
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 16, 2023
// ipsecExternal enables external (NS) IPsec for the node, the configuration
// is done via nmstate operator.
// +optional
IPsecExternal *IPsecExternal `json:"ipsecExternal,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

You're using the presence of the struct to enable the external ipsec? Would prefer to have an enum with the struct with an enum defining the state.

Does this field have any interactions with other fields within this configuration? Eg must I not specify some other fields when this field is specified?

Given you're adding a struct, do you expect there to be additional configuration in the future for this feature?

Copy link

Choose a reason for hiding this comment

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

This is following the exact same pattern as the above IPsecConfig..

there is no interaction with other fields at the API level. the implementation will take care of all the relevant cases, mainly around the interaction between IPsecConfig and IPsecExternal (but they are both independent of each other on the API level)

and yes, it gives us the opportunity to add more config options in the future, without changing the API
see my comment - #1667 (comment)

Copy link
Contributor Author

@JoshSalomon JoshSalomon Nov 19, 2023

Choose a reason for hiding this comment

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

@yuvalk - Does it make sense to put in this struct (in the future) reference to nmstate configuration to be used for the ipsec configuration. (name of the nmstate CRD?)

Copy link
Contributor

Choose a reason for hiding this comment

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

This is following the exact same pattern as the above IPsecConfig..

That API was merged 3 years ago, and API guidance has changed over time as we learn about prior mistakes. The Network resource is considered to be a configuration API. Where we prefer discoverability. To enable discoverability, we implement a few rules, eg, avoiding pointers and omitempty where possible.

Current guidance would suggest that this field should be

IPSecExternal IPSecExternal `json:"ipsecExternal"`

And the struct should contain a field

// +kubebuilder:validation:Enum="";Enabled;Disabled
// +kubebuilder:validation:Required
State IPSecExteranlState `json:"state"`

That said, looking at this, why is IPSecConfig and IPSecExternal not mutually exclusive.

there is no interaction with other fields at the API level. the implementation will take care of all the relevant cases, mainly around the interaction between IPsecConfig and IPsecExternal (but they are both independent of each other on the API level)

I'm interested in the behaviour that the operator will take care of, not just the interactions at the API level that we have defined so far. Given my question about not being mutually exclusive, I think understanding what the operator does might help here.

Copy link

@yuvalk yuvalk Nov 20, 2023

Choose a reason for hiding this comment

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

the names might be misleading
IPSecConfig - the old one. is used to enable/disable East-West IPsec
IPSecExternal - the new one, is used to enable/disable North-South IPsec

both will first deploy a MC to enable the host ipsec extension (ie - install libreswan and enable ipsec.service)
E-W is also running a DS that runs ovs ipsec monitor (used to configre ipsec policies between nodes)
N-S wont do anything else (beside the mentioned MC). ie - configuration is on the customer

there's also logic that handles upgrades etc.

openshift/enhancements#1453

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think we could make that clearer in the godoc, since I bet most people won't understand. How would you explain the north-south and east-west in laymans terms for the godoc? I think we probably want to update the documentation on both fields here to make it obvious where the traffic goes based on these two ipsec configurations

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JoelSpeed @yuvalk I am going to fix this, but I wonder if making this mandatory is not creating bw compatibility so that exiting yaml files will not work anymore. Shouldn't we make it optional with disabled value and remove the omitempty for discoverability?

Copy link

Choose a reason for hiding this comment

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

IPSecExternal IPSecExternal json:"ipsecExternal"

@JoelSpeed does this means there is no default and it'll have to be specified at install time? (ie installer also need to change, and any place where even customer is injecting network config)

Copy link
Contributor

Choose a reason for hiding this comment

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

In situations such as this, we normally create an alias for the empty string, so that the empty string has the same meaning, in this case, as disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JoelSpeed - I made all the changes and tested them as much as I can, I hope it is OK now.

@JoshSalomon
Copy link
Contributor Author

The generated files for this change

can you reword the commit msg title, so it'll reference the other commit? otherwise "this change" is ambiguous

Done

@yuvalk
Copy link

yuvalk commented Nov 22, 2023

maybe something like this is better:

diff --git a/operator/v1/types_network.go b/operator/v1/types_network.go
index 52e9d53f..c98506f6 100644
--- a/operator/v1/types_network.go
+++ b/operator/v1/types_network.go
@@ -440,6 +440,11 @@ type OVNKubernetesConfig struct {
        // cluster.
        // +optional
        IPsecConfig *IPsecConfig `json:"ipsecConfig,omitempty"`
+       // ipsecExtern enables external (North-South). this will only install IPsec and
+       // enable it's service. the actuall NS IPsec policies should be specified by
+       // users. this can be done with k8s-nmstate operator.
+       // +optional
+       IPsecExternal IPsecExternal `json:"ipsecExternal"`
        // policyAuditConfig is the configuration for network policy audit events. If unset,
        // reported defaults are used.
        // +optional
@@ -480,6 +485,12 @@ type HybridOverlayConfig struct {
 type IPsecConfig struct {
 }
 
+type IPsecExternal struct {
+       // +kubebuilder:validation:Enum="";Enabled;Disabled
+       // +kubebuilder:validation:Required
+       State string `json:"state"`
+}
+
 type IPForwardingMode string
 
 const (

@JoelSpeed
Copy link
Contributor

@yuvalk suggestion is what I was imagining. You could if you prefer, instead of the empty string use a default to default the value to Disabled

@openshift-ci openshift-ci bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Nov 23, 2023
@@ -485,6 +487,11 @@ type IPsecConfig struct {
}

type IPsecExternal struct {
// State controls the node's external (aka NS) ipsec service state.
// +kubebuilder:validation:Enum="";Enabled;Disabled
Copy link

Choose a reason for hiding this comment

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

deafault=Disabled, means we can remove the empty string "" option

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This didn't work for me when the cluster starts. Somehow even with this default during the installation I got an error that value "" is not supported.

Copy link

Choose a reason for hiding this comment

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

not sure which didnt work
the default setting?
or the ""

assuming default works, I'm saying you can remove the ""..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

even with default=disabled, I got an error that "" is not supported. I am not sure how this works, but since the object is mandatory and is created by the system and not by the user, is is created with a value of "". My suggestion is that in the operator we will change "" to Disabled so for discoverability we will see only enable or disable but on the yaml file empty string is acceptable as valid input.


const (
// IPSecExternalStateEmpty is used for defaulting, it is the same as disabled
IPSecExternalStateEmpty IPSecExternalState = ""
Copy link

Choose a reason for hiding this comment

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

also from here

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 not sure this can be removed if the enum includes an empty string (I just don't know, I am not sure that giving a name to an empty string is a good idea, but hit is currently a valid value in the enum.

@JoshSalomon JoshSalomon force-pushed the ipsec-api branch 2 times, most recently from e1d74f2 to 74a7268 Compare November 23, 2023 20:43
@JoshSalomon
Copy link
Contributor Author

/retest

// State controls the node's external (aka NS) ipsec service state.
// +kubebuilder:validation:Enum="";Enabled;Disabled
// +kubebuilder:validation:Required
// +kubebuilder:default=Disabled
Copy link
Contributor

Choose a reason for hiding this comment

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

To use a default the field must be optional and have omitempty in the json tag, if you update this then you can remove the empty string case

You also need a second tag, since multiple tools rely on different tags for understanding the defaults

// + default:=Disabled

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 had to play with the syntax but it seems that // +default="Disabled" does the trick and generates the correct openapi.json file. As far as I tested now everything works, and retrieving the CRD immediately after reboot before any change shows this:

    defaultNetwork:
      ovnKubernetesConfig:
        egressIPConfig: {}
        gatewayConfig:
          ipv4: {}
          ipv6: {}
          routingViaHost: false
        genevePort: 6081
        ipsecExternal:
          state: Disabled
        mtu: 1400

I hope everything is OK now ;-)

@@ -480,6 +486,14 @@ type HybridOverlayConfig struct {
type IPsecConfig struct {
}

type IPsecExternal struct {
// State controls the node's external (aka NS) ipsec service state.
Copy link
Contributor

Choose a reason for hiding this comment

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

Comments should start with the JSON tag name.

I'd appreciate if you could expand the documentation on this field, please review the API conventions on writing good godocs and expand this with relevant information.

@JoshSalomon JoshSalomon force-pushed the ipsec-api branch 2 times, most recently from 4216db7 to 8fc7980 Compare November 26, 2023 13:37
@yuvalk
Copy link

yuvalk commented Nov 27, 2023

@JoshSalomon I think it' will aslo be nice if you add at least the following test:

diff --git a/operator/v1/stable.network.testsuite.yaml b/operator/v1/stable.network.testsuite.yaml
index 698e4bf4..bac7f67c 100644
--- a/operator/v1/stable.network.testsuite.yaml
+++ b/operator/v1/stable.network.testsuite.yaml
@@ -227,4 +227,22 @@ tests:
               ipv6:
                 internalMasqueradeSubnet: "abcd:ef01:2345:6789:abcd:ef01:2345::/125"
     expectedError: "Invalid value: \"string\": a valid IPv6 address must contain 8 segments unless elided (::), in which case it must contain at most 6 non-empty segments"
-    
\ No newline at end of file
+  - name: Should have state disabled by default when specifiying north-south IPsec
+    initial: |
+      apiVersion: operator.openshift.io/v1
+      kind: Network
+      spec:
+       defaultNetwork:
+          ovnKubernetesConfig:
+            ipsecExternal: {}
+    expected: |
+      apiVersion: operator.openshift.io/v1
+      kind: Network
+      spec:
+        defaultNetwork:
+          ovnKubernetesConfig:
+            ipsecExternal:
+              state: Disabled
+        disableNetworkDiagnostics: false
+        logLevel: Normal
+        operatorLogLevel: Normal

might also want to add a test for state: Enabled

and you can run just this test locally with: GINKGO_EXTRA_ARGS="--focus ipsec" make integration

@openshift-merge-robot openshift-merge-robot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Nov 27, 2023
@openshift-ci openshift-ci bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jan 7, 2024
JoshSalomon added a commit to JoshSalomon/cluster-network-operator that referenced this pull request Jan 7, 2024
This is a change based on the api PR
(openshift/api#1667) before its approval, the
api vendoring is from a private commit - this is needed only for testing
until the api PR is merged.

Signed-off-by: Josh Salomon <[email protected]>
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 7, 2024
@openshift-ci openshift-ci bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jan 7, 2024
Copy link
Contributor

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

Just need to drop this mention of omitted and we are good to merge

operator/v1/types_network.go Outdated Show resolved Hide resolved
The mode field can have 3 values:
- Disabled: Disable the ipsec.service on the node level
- External: Enable ipsec.service on the node level, but additional
  configoration is required (usually by nmstate, usually for external
  communication)
- Full: Enable ipsec.service on the node and configure secure
  communications between pods in the cluster. If required ipsec can be
  configured for external secure communications as in the case of mode
  External

Signed-off-by: Josh Salomon <[email protected]>
Testing that empty ipsecConfig translates into disabled mode, and that
empty strings are not allowed for ipsecConfog.mode
Added transition tests (added OnUpdate section to the file) for checking
that ipsecConfog.mode can not be removed once set, that ipsec can be
safely disabled, and that empty ispecConfig is not changed when changing
other ovnKubernetesConfig fields.
Additionally updated all successful path tests (without expecterError)
since ipsecConfig setting appears now on all the out yaml file as a
feature.

Signed-off-by: Josh Salomon <[email protected]>
@JoelSpeed
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jan 8, 2024
Copy link
Contributor

openshift-ci bot commented Jan 8, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JoelSpeed, JoshSalomon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 8, 2024
@yuvalk
Copy link

yuvalk commented Jan 8, 2024

/retest

yuvalk pushed a commit to yuvalk/cluster-network-operator that referenced this pull request Jan 8, 2024
This is a change based on the api PR
(openshift/api#1667) before its approval, the
api vendoring is from a private commit - this is needed only for testing
until the api PR is merged.

Signed-off-by: Josh Salomon <[email protected]>
@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD c7a2d3b and 2 for PR HEAD 0e619cd in total

JoshSalomon added a commit to JoshSalomon/cluster-network-operator that referenced this pull request Jan 8, 2024
This is a change based on the api PR
(openshift/api#1667) before its approval, the
api vendoring is from a private commit - this is needed only for testing
until the api PR is merged.

Signed-off-by: Josh Salomon <[email protected]>
@yuvalk
Copy link

yuvalk commented Jan 8, 2024

/cherry-pick release-4.15

@openshift-cherrypick-robot

@yuvalk: once the present PR merges, I will cherry-pick it on top of release-4.15 in a new PR and assign it to you.

In response to this:

/cherry-pick release-4.15

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD 7b0f600 and 1 for PR HEAD 0e619cd in total

Copy link
Contributor

openshift-ci bot commented Jan 8, 2024

@JoshSalomon: all tests passed!

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@openshift-merge-bot openshift-merge-bot bot merged commit 355cd25 into openshift:master Jan 8, 2024
16 checks passed
@openshift-cherrypick-robot

@yuvalk: new pull request created: #1719

In response to this:

/cherry-pick release-4.15

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

yuvalk pushed a commit to yuvalk/cluster-network-operator that referenced this pull request Jan 8, 2024
This is a change based on the api PR
(openshift/api#1667) before its approval, the
api vendoring is from a private commit - this is needed only for testing
until the api PR is merged.

Signed-off-by: Josh Salomon <[email protected]>
@openshift-bot
Copy link

[ART PR BUILD NOTIFIER]

This PR has been included in build ose-cluster-config-api-container-v4.16.0-202401090832.p0.g355cd25.assembly.stream for distgit ose-cluster-config-api.
All builds following this will include this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.