-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Append router CA to cluster CA in kubeconfig #1242
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package main | |
|
||
import ( | ||
"context" | ||
"crypto/x509" | ||
"fmt" | ||
"io/ioutil" | ||
"path/filepath" | ||
|
@@ -12,6 +13,7 @@ import ( | |
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
corev1 "k8s.io/api/core/v1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/fields" | ||
"k8s.io/apimachinery/pkg/util/wait" | ||
|
@@ -116,6 +118,10 @@ var ( | |
logrus.Fatal(err) | ||
} | ||
|
||
if err = addRouterCAToClusterCA(config, rootOpts.dir); err != nil { | ||
logrus.Fatal(err) | ||
} | ||
|
||
err = logComplete(rootOpts.dir, consoleURL) | ||
if err != nil { | ||
logrus.Fatal(err) | ||
|
@@ -186,6 +192,56 @@ func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args | |
} | ||
} | ||
|
||
// addRouterCAToClusterCA adds router CA to cluster CA in kubeconfig | ||
func addRouterCAToClusterCA(config *rest.Config, directory string) (err error) { | ||
client, err := kubernetes.NewForConfig(config) | ||
if err != nil { | ||
return errors.Wrap(err, "creating a Kubernetes client") | ||
} | ||
|
||
// Configmap may not exist. log and accept not-found errors with configmap. | ||
caConfigMap, err := client.CoreV1().ConfigMaps("openshift-config-managed").Get("router-ca", metav1.GetOptions{}) | ||
if err != nil { | ||
if apierrors.IsNotFound(err) { | ||
logrus.Infof("router-ca resource not found in cluster, perhaps you are not using default router CA") | ||
return nil | ||
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. Do we really want to silently ignore a missing 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 will check, but I think there's a possible expectation that it won't be created. 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. The secret will always be created. However, I'd suggest using the 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. thanks @Miciah will do! 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 also, at the very least log the error. preferably don't swallow it at all. 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've added a log msg for that error 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. Won't we want to poll/wait until the config-map has a non-empty CA instead of giving up? |
||
} | ||
return errors.Wrap(err, "fetching router-ca configmap from openshift-config-managed namespace") | ||
} | ||
|
||
routerCrtBytes := []byte(caConfigMap.Data["ca-bundle.crt"]) | ||
kubeconfig := filepath.Join(directory, "auth", "kubeconfig") | ||
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. Ideally we'd hold this in memory, but this is fine short-term. 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. yes I think there's a FIXME already elsewhere in this file for that |
||
kconfig, err := clientcmd.LoadFromFile(kubeconfig) | ||
if err != nil { | ||
wking marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return errors.Wrap(err, "loading kubeconfig") | ||
} | ||
|
||
if kconfig == nil || len(kconfig.Clusters) == 0 { | ||
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 think we want: if kconfig == nil || len(kconfig.Clusters) != 1 {
return errors.New("invalid kubeconfig")
} which will also allow us to drop the following loop over 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'll open a follow-up? I could not find how to get this string:
referencable names to cluster configs? What is that reference-able name? I'm happy to do some testing (and open a PR to clarify for others) to figure that out (or maybe someone knows and can tell me). But if there_were_ more than 1 cluster I'd want to add to each, so the != 0 seems ok here. If not I can also include that in the follow-up PR. |
||
return errors.New("kubeconfig is missing expected data") | ||
} | ||
|
||
for _, c := range kconfig.Clusters { | ||
clusterCABytes := c.CertificateAuthorityData | ||
if len(clusterCABytes) == 0 { | ||
return errors.New("kubeconfig CertificateAuthorityData not found") | ||
} | ||
certPool := x509.NewCertPool() | ||
if !certPool.AppendCertsFromPEM(clusterCABytes) { | ||
return errors.New("cluster CA found in kubeconfig not valid PEM format") | ||
} | ||
if !certPool.AppendCertsFromPEM(routerCrtBytes) { | ||
return errors.New("ca-bundle.crt from router-ca configmap not valid PEM format") | ||
} | ||
|
||
newCA := append(routerCrtBytes, clusterCABytes...) | ||
c.CertificateAuthorityData = newCA | ||
} | ||
if err := clientcmd.WriteToFile(*kconfig, kubeconfig); err != nil { | ||
return errors.Wrap(err, "writing kubeconfig") | ||
} | ||
return nil | ||
} | ||
|
||
// FIXME: pulling the kubeconfig and metadata out of the root | ||
// directory is a bit cludgy when we already have them in memory. | ||
func destroyBootstrap(ctx context.Context, config *rest.Config, directory string) (err error) { | ||
|
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.
Should this be fatal or only a warning? I thinking since it doesn't block accessing the cluster, but maybe it's ok to fail since this is the last step?
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.
I'm fine failing fast. We can relax later if necessary, but unless this is fatal by default we don't get CI coverage (or will e2e start failing without this step?).