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

[kwokctl] Refactor the pki and the subcommand 'get kubeconfig' #642

Merged
merged 1 commit into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ linters-settings:
- log: "please use `sigs.k8s.io/kwok/pkg/log` instead"
# Use sigs.k8s.io/kwok/pkg/utils/wait, which is a wrapper around wait
- k8s.io/apimachinery/pkg/util/wait: "please use `sigs.k8s.io/kwok/pkg/utils/wait` instead"
# Use sigs.k8s.io/kwok/pkg/utils/slices, which is a wrapper around slices
- k8s.io/utils/strings/slices: "please use `sigs.k8s.io/kwok/pkg/utils/slices` instead"
gocyclo:
min-complexity: 50
gosec:
Expand Down
3 changes: 1 addition & 2 deletions pkg/kwok/controllers/finalizers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ package controllers
import (
"strconv"

"k8s.io/utils/strings/slices"

"sigs.k8s.io/kwok/pkg/apis/internalversion"
"sigs.k8s.io/kwok/pkg/utils/slices"
)

type jsonpathOperation struct {
Expand Down
126 changes: 121 additions & 5 deletions pkg/kwokctl/cmd/get/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,41 @@ package kubeconfig
import (
"context"
"errors"
"fmt"
"net"
"net/url"
"os"
"time"

"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

"sigs.k8s.io/kwok/pkg/config"
"sigs.k8s.io/kwok/pkg/kwokctl/pki"
"sigs.k8s.io/kwok/pkg/kwokctl/runtime"
"sigs.k8s.io/kwok/pkg/log"
"sigs.k8s.io/kwok/pkg/utils/exec"
"sigs.k8s.io/kwok/pkg/utils/kubeconfig"
"sigs.k8s.io/kwok/pkg/utils/path"
"sigs.k8s.io/kwok/pkg/utils/slices"
)

type flagpole struct {
Name string
Name string
Host string
InsecureSkipTLSVerify bool
User string
Groups []string
}

// NewCommand returns a new cobra.Command for getting the list of clusters
func NewCommand(ctx context.Context) *cobra.Command {
flags := &flagpole{}
flags := &flagpole{
Host: "127.0.0.1",
User: pki.DefaultUser,
Groups: pki.DefaultGroups,
InsecureSkipTLSVerify: false,
}

cmd := &cobra.Command{
Args: cobra.NoArgs,
Expand All @@ -48,6 +65,11 @@ func NewCommand(ctx context.Context) *cobra.Command {
return runE(cmd.Context(), flags)
},
}

cmd.Flags().StringVar(&flags.Host, "host", flags.Host, "Override host[:port] for kubeconfig")
cmd.Flags().BoolVar(&flags.InsecureSkipTLSVerify, "insecure-skip-tls-verify", flags.InsecureSkipTLSVerify, "Skip server certificate verification")
cmd.Flags().StringVar(&flags.User, "user", flags.User, "Signing certificate with the specified user if modified")
cmd.Flags().StringSliceVar(&flags.Groups, "group", flags.Groups, "Signing certificate with the specified groups if modified")
return cmd
}

Expand All @@ -67,7 +89,101 @@ func runE(ctx context.Context, flags *flagpole) error {
return err
}

err = rt.KubectlInCluster(exec.WithStdIO(ctx), "config", "view", "--minify", "--flatten", "--raw")
kubeconfigPath := rt.GetWorkdirPath(runtime.InHostKubeconfigName)

kubeConfig, err := clientcmd.LoadFromFile(kubeconfigPath)
if err != nil {
return fmt.Errorf("failed to load kubeconfig file %s: %w", kubeconfigPath, err)
}

err = clientcmdapi.MinifyConfig(kubeConfig)
if err != nil {
return fmt.Errorf("failed to minify kubeconfig file %s: %w", kubeconfigPath, err)
}
currentContext := kubeConfig.CurrentContext

clusterName := kubeConfig.Contexts[currentContext].Cluster
if clusterName == "" || kubeConfig.Clusters[clusterName] == nil {
return fmt.Errorf("failed to load kubeconfig file %s: %w", kubeconfigPath, err)
}

if flags.Host != "" {
cluster := kubeConfig.Clusters[clusterName]
host, err := modifyAddress(cluster.Server, flags.Host)
if err != nil {
return fmt.Errorf("failed to modify host %s: %w", cluster.Server, err)
}
kubeConfig.Clusters[clusterName].Server = host
}

if flags.InsecureSkipTLSVerify {
cluster := kubeConfig.Clusters[clusterName]
cluster.InsecureSkipTLSVerify = true
cluster.CertificateAuthorityData = nil
}

userName := kubeConfig.Contexts[currentContext].AuthInfo

if userName != "" && (!slices.Equal(pki.DefaultGroups, flags.Groups) || flags.User != pki.DefaultUser) {
// Load CA cert and key
caCert, caKey, err := pki.ReadCertAndKey(rt.GetWorkdirPath(runtime.PkiName), "ca")
if err != nil {
return err
}

// Sign admin cert and key
now := time.Now()
notBefore := now.UTC()
notAfter := now.Add(pki.CertificateValidity).UTC()
cert, key, err := pki.GenerateSignCert(flags.User, caCert, caKey, notBefore, notAfter, flags.Groups, nil)
if err != nil {
return fmt.Errorf("failed to generate admin cert and key: %w", err)
}

return err
// Modify kubeconfig
keyData, err := pki.EncodePrivateKeyToPEM(key)
if err != nil {
return err
}
certData := pki.EncodeCertToPEM(cert)
kubeConfig.AuthInfos[userName].ClientCertificateData = certData
kubeConfig.AuthInfos[userName].ClientCertificate = ""
kubeConfig.AuthInfos[userName].ClientKeyData = keyData
kubeConfig.AuthInfos[userName].ClientKey = ""
}

err = clientcmdapi.FlattenConfig(kubeConfig)
if err != nil {
return fmt.Errorf("failed to flatten kubeconfig file %s: %w", kubeconfigPath, err)
}

// Encode kubeconfig
kubeconfigData, err := kubeconfig.EncodeKubeconfig(kubeConfig)
if err != nil {
return fmt.Errorf("failed to encode kubeconfig: %w", err)
}

_, err = os.Stdout.Write(kubeconfigData)
if err != nil {
return err
}

return nil
}

func modifyAddress(origin string, address string) (string, error) {
u, err := url.Parse(origin)
if err != nil {
return "", err
}
if _, _, err = net.SplitHostPort(address); err == nil {
u.Host = address
} else {
_, port, err := net.SplitHostPort(u.Host)
if err != nil {
return "", err
}
u.Host = net.JoinHostPort(address, port)
}
return u.String(), nil
}
12 changes: 5 additions & 7 deletions pkg/kwokctl/components/kube_controller_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ func BuildKubeControllerManagerComponent(conf BuildKubeControllerManagerComponen
MountPath: "/root/.kube/config",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.CaCertPath,
MountPath: "/etc/kubernetes/pki/ca.crt",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.AdminCertPath,
MountPath: "/etc/kubernetes/pki/admin.crt",
Expand Down Expand Up @@ -163,13 +168,6 @@ func BuildKubeControllerManagerComponent(conf BuildKubeControllerManagerComponen

if conf.KubeAuthorization {
if inContainer {
volumes = append(volumes,
internalversion.Volume{
HostPath: conf.CaCertPath,
MountPath: "/etc/kubernetes/pki/ca.crt",
ReadOnly: true,
},
)
kubeControllerManagerArgs = append(kubeControllerManagerArgs,
"--root-ca-file=/etc/kubernetes/pki/ca.crt",
"--service-account-private-key-file=/etc/kubernetes/pki/admin.key",
Expand Down
5 changes: 5 additions & 0 deletions pkg/kwokctl/components/kube_scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ func BuildKubeSchedulerComponent(conf BuildKubeSchedulerComponentConfig) (compon
MountPath: "/root/.kube/config",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.CaCertPath,
MountPath: "/etc/kubernetes/pki/ca.crt",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.AdminCertPath,
MountPath: "/etc/kubernetes/pki/admin.crt",
Expand Down
6 changes: 6 additions & 0 deletions pkg/kwokctl/components/kwok_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type BuildKwokControllerComponentConfig struct {
Port uint32
ConfigPath string
KubeconfigPath string
CaCertPath string
AdminCertPath string
AdminKeyPath string
NodeName string
Expand Down Expand Up @@ -61,6 +62,11 @@ func BuildKwokControllerComponent(conf BuildKwokControllerComponentConfig) (comp
MountPath: "/root/.kube/config",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.CaCertPath,
MountPath: "/etc/kubernetes/pki/ca.crt",
ReadOnly: true,
},
internalversion.Volume{
HostPath: conf.AdminCertPath,
MountPath: "/etc/kubernetes/pki/admin.crt",
Expand Down
49 changes: 0 additions & 49 deletions pkg/kwokctl/k8s/kubeconfig.go

This file was deleted.

24 changes: 0 additions & 24 deletions pkg/kwokctl/k8s/kubeconfig.yaml.tpl

This file was deleted.

Loading