-
Notifications
You must be signed in to change notification settings - Fork 666
OCPBUGS-44235: Fix Helm chart installation with CA/TLS certificates #15607
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have the impression that there are no references to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great question! I thought of these tests as regression prevention. The bug happened specifically because we were setting
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But your question brought up a idea that this should be documented in code with a comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a general rule, I'm on-board with preventative safeguards. In this case, I'm not sure where in the code to put your suggested comment. 😞 We would want it in some place where developers always look (which probably doesn't exist...), or we want it in each place where a developer would be tempted to add the offending code (which would be at least the places that you edited, and probably more) which is likely to create a "litter problem". 😝 So, given those as options, your idea of adding a test looks like a much superior solution. 😆 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| package actions | ||
|
|
||
| import ( | ||
| "io/ioutil" | ||
| "testing" | ||
|
|
||
| configv1 "github.com/openshift/api/config/v1" | ||
| "github.com/openshift/api/helm/v1beta1" | ||
| "github.com/stretchr/testify/require" | ||
| "helm.sh/helm/v3/pkg/action" | ||
| v1 "k8s.io/api/core/v1" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/runtime" | ||
| k8sfake "k8s.io/client-go/kubernetes/fake" | ||
| ) | ||
|
|
||
| func TestAuthenticationDoesNotSetRepoURL(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| config *v1beta1.ConnectionConfig | ||
| hasCA bool | ||
| hasTLS bool | ||
| expectCaFile bool | ||
| expectCertFile bool | ||
| }{ | ||
| { | ||
| name: "CA certificate only", | ||
| config: &v1beta1.ConnectionConfig{ | ||
| URL: "https://charts.example.com", | ||
| CA: configv1.ConfigMapNameReference{Name: "test-ca"}, | ||
| }, | ||
| hasCA: true, | ||
| expectCaFile: true, | ||
| }, | ||
|
Comment on lines
+26
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I completely agree. This test case is valid and should be added for completeness and regression guard I mentioned in another review comment. |
||
| { | ||
| name: "Client TLS only", | ||
| config: &v1beta1.ConnectionConfig{ | ||
| URL: "https://charts.example.com", | ||
| TLSClientConfig: configv1.SecretNameReference{Name: "test-tls"}, | ||
| }, | ||
| hasTLS: true, | ||
| expectCertFile: true, | ||
| }, | ||
| { | ||
| name: "Both CA and client TLS", | ||
| config: &v1beta1.ConnectionConfig{ | ||
| URL: "https://charts.example.com", | ||
| CA: configv1.ConfigMapNameReference{Name: "test-ca"}, | ||
| TLSClientConfig: configv1.SecretNameReference{Name: "test-tls"}, | ||
| }, | ||
| hasCA: true, | ||
| hasTLS: true, | ||
| expectCaFile: true, | ||
| expectCertFile: true, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| opts := &action.ChartPathOptions{} | ||
| objs := []runtime.Object{} | ||
|
|
||
| if tt.hasCA { | ||
| caConfigMap := &v1.ConfigMap{ | ||
| Data: map[string]string{caBundleKey: "FAKE_CA_DATA"}, | ||
| ObjectMeta: metav1.ObjectMeta{Name: "test-ca", Namespace: configNamespace}, | ||
| } | ||
| objs = append(objs, caConfigMap) | ||
| } | ||
|
|
||
| if tt.hasTLS { | ||
| cert, _ := ioutil.ReadFile("./server.crt") | ||
| key, _ := ioutil.ReadFile("./server.key") | ||
| tlsSecret := &v1.Secret{ | ||
| Data: map[string][]byte{ | ||
| tlsSecretCertKey: cert, | ||
| tlsSecretKey: key, | ||
| }, | ||
| ObjectMeta: metav1.ObjectMeta{Name: "test-tls", Namespace: configNamespace}, | ||
| } | ||
| objs = append(objs, tlsSecret) | ||
| } | ||
|
|
||
| coreClient := k8sfake.NewSimpleClientset(objs...).CoreV1() | ||
|
|
||
| tlsFiles, err := setUpAuthentication(opts, tt.config, coreClient) | ||
| require.NoError(t, err) | ||
|
|
||
| require.Empty(t, opts.RepoURL) | ||
|
|
||
| // Verify auth fields are set | ||
| if tt.expectCaFile { | ||
| require.NotEmpty(t, opts.CaFile) | ||
| } | ||
| if tt.expectCertFile { | ||
| require.NotEmpty(t, opts.CertFile) | ||
| require.NotEmpty(t, opts.KeyFile) | ||
| } | ||
|
Comment on lines
+92
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Not empty" is a pretty low bar...should we be checking the actual value? (Ditto for line 135.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right that we could be more thorough. I am open to strengthening the assertions. Maybe add a check if they point to a readable file or check the contents match expected. |
||
|
|
||
| expectedFileCount := 0 | ||
| if tt.hasCA { | ||
| expectedFileCount++ | ||
| } | ||
| if tt.hasTLS { | ||
| expectedFileCount += 2 | ||
| } | ||
| require.Len(t, tlsFiles, expectedFileCount) | ||
|
|
||
| // Cleanup | ||
| for _, f := range tlsFiles { | ||
| f.Close() | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestAuthenticationProjectDoesNotSetRepoURL(t *testing.T) { | ||
| opts := &action.ChartPathOptions{} | ||
| config := &v1beta1.ConnectionConfigNamespaceScoped{ | ||
| URL: "https://charts.example.com", | ||
| CA: configv1.ConfigMapNameReference{Name: "test-ca"}, | ||
| } | ||
|
|
||
| caConfigMap := &v1.ConfigMap{ | ||
| Data: map[string]string{caBundleKey: "FAKE_CA_DATA"}, | ||
| ObjectMeta: metav1.ObjectMeta{Name: "test-ca", Namespace: "test-ns"}, | ||
| } | ||
|
|
||
| coreClient := k8sfake.NewSimpleClientset(caConfigMap).CoreV1() | ||
|
|
||
| tlsFiles, err := setUpAuthenticationProject(opts, config, coreClient, "test-ns") | ||
| require.NoError(t, err) | ||
|
|
||
| require.Empty(t, opts.RepoURL) | ||
| require.NotEmpty(t, opts.CaFile) | ||
|
|
||
| // Cleanup | ||
| for _, f := range tlsFiles { | ||
|
Comment on lines
+135
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No check on the number of TLS files?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good eye @webbnh! |
||
| f.Close() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,11 +84,7 @@ func UpgradeRelease( | |
| return nil, fmt.Errorf("error setting up authentication: %v", err) | ||
| } | ||
| } | ||
| if len(tlsFiles) == 0 { | ||
| chartLocation = chartUrl | ||
| } else { | ||
| chartLocation = chartInfo.Name | ||
| } | ||
| chartLocation = chartUrl | ||
| client.ChartPathOptions.Version = chartInfo.Version | ||
| cp, err = client.ChartPathOptions.LocateChart(chartLocation, settings) | ||
| if err != nil { | ||
|
|
@@ -199,11 +195,7 @@ func UpgradeReleaseAsync( | |
| return nil, fmt.Errorf("error setting up authentication: %v", err) | ||
| } | ||
| } | ||
| if len(tlsFiles) == 0 { | ||
| chartLocation = chartUrl | ||
| } else { | ||
| chartLocation = chartInfo.Name | ||
| } | ||
| chartLocation = chartUrl | ||
| client.ChartPathOptions.Version = chartInfo.Version | ||
| cp, err = client.ChartPathOptions.LocateChart(chartLocation, settings) | ||
|
Comment on lines
+198
to
200
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless we are trying to minimize the changes (and, possibly, even if we're not!...), I recommend removing the A similar comment applies to the occurrences in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are correct @webbnh! I fully agree that |
||
| if err != nil { | ||
|
|
||
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.
After you remove these four (write) references, are there any remaining references (read or write) to this field? If not, shouldn't you remove the field itself?
The field claims to be associated with the
--repooption. Is that option used (either as an input to the package or in a generated command line executed by the package)?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.
The
ChartPathOptionsis not defined in our code. It's part of helm API. It's imported from:helm.sh/helm/v3/pkg/action.