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 Custom API Server CA Certificate for Karmada Instance in Operator #5842

Merged
merged 4 commits into from
Nov 22, 2024

Conversation

jabellard
Copy link
Contributor

@jabellard jabellard commented Nov 20, 2024

What type of PR is this?

/kind feature

What this PR does / why we need it:
This is an implementation of this proposal to add support for custom API server CA certificates in the Karmada operator.

Which issue(s) this PR fixes:
Fixes #5784
Special notes for your reviewer:

Does this PR introduce a user-facing change?:

`karmada-operator`: The new `CustomCertificate.ApiServerCACert` field added as part of the Karmada spec can be used to specify the reference to a secret that contains a custom CA certificate for the Karmada API Server.

@karmada-bot karmada-bot added the kind/feature Categorizes issue or PR as related to a new feature. label Nov 20, 2024
@karmada-bot karmada-bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Nov 20, 2024
Signed-off-by: Joe Nathan Abellard <[email protected]>
@RainbowMango
Copy link
Member

/retest
the failing unit test is not related but an known issue.

@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 25.71429% with 52 lines in your changes missing coverage. Please review.

Project coverage is 45.99%. Comparing base (6795dba) to head (620638d).

Files with missing lines Patch % Lines
operator/pkg/tasks/init/cert.go 3.03% 31 Missing and 1 partial ⚠️
operator/pkg/init.go 0.00% 17 Missing and 1 partial ⚠️
operator/pkg/certs/certs.go 83.33% 2 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5842      +/-   ##
==========================================
- Coverage   46.02%   45.99%   -0.04%     
==========================================
  Files         660      660              
  Lines       53987    54028      +41     
==========================================
+ Hits        24848    24850       +2     
- Misses      27521    27558      +37     
- Partials     1618     1620       +2     
Flag Coverage Δ
unittests 45.99% <25.71%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.


🚨 Try these New Features:

caName string
cert []byte
key []byte
PairName string
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we avoid exposing internal fields by adding a new function to generate KarmadaCert, thereby minimizing the scope of changes?

Copy link
Member

Choose a reason for hiding this comment

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

@zhzhuang-zju So, what's your suggestion?
Do you mean to introduce some set methods?

Copy link
Contributor

Choose a reason for hiding this comment

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

How about

func NewKarmadaCert(pairName,caName string , cert, key []byte) *KarmadaCert{
	return &KarmadaCert{
		pairName: pairName,
		caName: caName,
		cert: cert,
		key: key,
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zhzhuang-zju , thanks for the suggestion.

Kubeconfig *rest.Config
KarmadaVersion string
CRDTarball operatorv1alpha1.CRDTarball
CustomCertificateConfig operatorv1alpha1.CustomCertificate
Copy link
Contributor

Choose a reason for hiding this comment

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

We can consider not adding a new field CustomCertificateConfig since Karmada already contains the configuration for customcertificates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point. Thanks for bringing it up. I considered that, but if you take a closer look, the root Karmada object is not part of this type. It's possible to add it and get rid of a lot of fields here, but that would take a refactor with very wide scope. I think it's fine for now, as this object is meant to carry the only the info needed in downstream functions.

Copy link
Contributor

Choose a reason for hiding this comment

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

the root Karmada object is not part of this type

Sorry, I didn't get it. Could you please explain it more?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can add the entire Karmada object to this field and get rid of some of the other fields, but that will introduce a refactor of a very wide scope with a lot of changes to the code. Can we avoid doing that for now?

Copy link
Contributor

Choose a reason for hiding this comment

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

type InitOptions struct {
Name string
Namespace string
Kubeconfig *rest.Config
KarmadaVersion string
CRDTarball operatorv1alpha1.CRDTarball
KarmadaDataDir string
Karmada *operatorv1alpha1.Karmada
}

But the current struct InitOptions already have the entire Karmada object. There's no need to remove other fields; it's just that no new fields need to be added.

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. Now I see where the confusion is coming from. I could have it explained it a bit better, so it's my fault. This is the struct I meant to refer to it. It's what's used to carry information to the downstream functions, not InitOptions. Notice how the root Karmada type is not in there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That struct is then abstracted behind this interface which is what is used directly in those functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zhzhuang-zju , just let me know if have any other comments/questions.

Copy link
Contributor

Choose a reason for hiding this comment

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

hah, Thank you for the clarification. I understand that CustomCertificateConfig is required for initdata, but is it possible to obtain it through initoptions.Karmada.Spec.CustomCertificate instead of adding it directly to initoptions? I actually don't want initoptions to become too large.

Copy link
Member

Choose a reason for hiding this comment

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

We can add the entire Karmada object to this field and get rid of some of the other fields, but that will introduce a refactor of a very wide scope with a lot of changes to the code. Can we avoid doing that for now?

Yeah, I agree that.

Comment on lines 109 to 130
if kc.Name == constants.CaCertAndKeyName && customCertConfig.APIServerCACert != nil {
secretRef := customCertConfig.APIServerCACert
klog.V(4).InfoS("[certs] Loading custom CA certificate", "secret", secretRef.Name, "namespace", secretRef.Namespace)

certData, keyData, err := loadCACertFromSecret(data.RemoteClient(), secretRef)
if err != nil {
return fmt.Errorf("failed to load custom CA certificate: %w", err)
}

klog.V(2).InfoS("[certs] Successfully loaded custom CA certificate", "secret", secretRef.Name)

customKarmadaCert := &certs.KarmadaCert{
PairName: kc.Name,
CAName: kc.CAName,
Cert: certData,
Key: keyData,
}

data.AddCert(customKarmadaCert)
klog.V(2).InfoS("[certs] Successfully added custom CA certificate to cert store", "certName", kc.Name)
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

How about extracting two functions: one to determine whether it is a custom CA, and another to load the karmadaCert using secretRef. This may enhance the extensibility of the code.

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 think this is fine. It's a one liner that's very specific to the API Server CA. It's not general.

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 this is fine. It's a one liner that's very specific to the API Server CA. It's not general.

Get it~
Could we abstract the process of loading the karmadaCert by secretRef into a function? This way, if there's a need for custom other certificates in the future, this function could be used universally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what you mean. That's actually already done in the loadCACertFromSecret function.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean L111-L125 can be extracted into a function. However, this is not important either; we can consider it when there is a real need.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. I agree with you on not abstracting the logic prematurely.

Signed-off-by: Joe Nathan Abellard <[email protected]>
Signed-off-by: Joe Nathan Abellard <[email protected]>
@jabellard
Copy link
Contributor Author

@zhzhuang-zju , thanks for comments and suggestions. Left some notes and just pushed some changes.

@zhzhuang-zju
Copy link
Contributor

thanks, others LGTM

Copy link
Member

@RainbowMango RainbowMango left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

@karmada-bot karmada-bot added the lgtm Indicates that a PR is ready to be merged. label Nov 22, 2024
@karmada-bot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: RainbowMango

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

@karmada-bot karmada-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 22, 2024
@RainbowMango
Copy link
Member

/hold

@karmada-bot karmada-bot merged commit 4dbcfaf into karmada-io:master Nov 22, 2024
19 checks passed
@karmada-bot karmada-bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 22, 2024
@RainbowMango
Copy link
Member

Oh... I meant to squash the commits...

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. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/feature Categorizes issue or PR as related to a new feature. 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.

Add Support for Custom Certificates in Karmada Operator
5 participants