forked from github/multus-cni
This change make binary file and directory name consistent. In addition, change the package name cni to server because cni is a bit umbiguous for cni plugin's repository.
148 lines
4.6 KiB
Go
148 lines
4.6 KiB
Go
// Copyright (c) 2021 Multus Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const userRWPermission = 0600
|
|
|
|
const (
|
|
cniConfigDirVarName = "cni-config-dir"
|
|
k8sCAFilePathVarName = "kube-ca-file"
|
|
k8sServiceHostVarName = "k8s-service-host"
|
|
k8sServicePortVarName = "k8s-service-port"
|
|
serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
|
|
skipTLSVerifyVarName = "skip-tls-verify"
|
|
)
|
|
|
|
const (
|
|
defaultCniConfigDir = "/host/etc/cni/net.d"
|
|
defaultK8sCAFilePath = ""
|
|
defaultK8sServiceHost = ""
|
|
defaultK8sServicePort = 0
|
|
defaultSkipTLSValue = false
|
|
)
|
|
|
|
func main() {
|
|
k8sServiceHost := flag.String(k8sServiceHostVarName, defaultK8sServiceHost, "Cluster IP of the kubernetes service")
|
|
k8sServicePort := flag.Int(k8sServicePortVarName, defaultK8sServicePort, "Port of the kubernetes service")
|
|
skipTLSVerify := flag.Bool(skipTLSVerifyVarName, defaultSkipTLSValue, "Should TLS verification be skipped")
|
|
kubeCAFilePath := flag.String(k8sCAFilePathVarName, defaultK8sCAFilePath, "Override the default kubernetes CA file path")
|
|
cniConfigDir := flag.String(cniConfigDirVarName, defaultCniConfigDir, "CNI config dir")
|
|
flag.Parse()
|
|
|
|
if *k8sServiceHost == defaultK8sServiceHost {
|
|
logInvalidArg("must provide the k8s service cluster port")
|
|
}
|
|
if *k8sServicePort == defaultK8sServicePort {
|
|
logInvalidArg("must provide the k8s service cluster port")
|
|
}
|
|
if *kubeCAFilePath == defaultK8sServiceHost {
|
|
*kubeCAFilePath = serviceAccountPath + "/ca.crt"
|
|
}
|
|
|
|
tlsCfg := "insecure-skip-tls-verify: true"
|
|
if !*skipTLSVerify {
|
|
kubeCAFileContents, err := k8sCAFileContentsBase64(*kubeCAFilePath)
|
|
if err != nil {
|
|
logError("failed grabbing CA file: %w", err)
|
|
}
|
|
tlsCfg = "certificate-authority-data: " + kubeCAFileContents
|
|
}
|
|
|
|
multusConfigDir := *cniConfigDir + "/multus.d/"
|
|
if err := prepareCNIConfigDir(multusConfigDir); err != nil {
|
|
logError("failed to create CNI config dir: %w", err)
|
|
}
|
|
kubeConfigFilePath := *cniConfigDir + "/multus.d/multus.kubeconfig"
|
|
serviceAccountToken, err := k8sKubeConfigToken(serviceAccountPath + "/token")
|
|
if err != nil {
|
|
logError("failed grabbing k8s token: %w", err)
|
|
}
|
|
if err := writeKubeConfig(kubeConfigFilePath, "https", *k8sServiceHost, *k8sServicePort, tlsCfg, serviceAccountToken); err != nil {
|
|
logError("failed generating kubeconfig: %w", err)
|
|
}
|
|
}
|
|
|
|
func k8sCAFileContentsBase64(pathCAFile string) (string, error) {
|
|
data, err := ioutil.ReadFile(pathCAFile)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed reading file %s: %w", pathCAFile, err)
|
|
}
|
|
return strings.Trim(base64.StdEncoding.EncodeToString(data), "\n"), nil
|
|
}
|
|
|
|
func k8sKubeConfigToken(tokenPath string) (string, error) {
|
|
data, err := ioutil.ReadFile(tokenPath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed reading file %s: %w", tokenPath, err)
|
|
}
|
|
return string(data), nil
|
|
}
|
|
|
|
func writeKubeConfig(outputPath string, protocol string, k8sServiceIP string, k8sServicePort int, tlsConfig string, serviceAccountToken string) error {
|
|
kubeConfigTemplate := `
|
|
# Kubeconfig file for Multus CNI plugin.
|
|
apiVersion: v1
|
|
kind: Config
|
|
clusters:
|
|
- name: local
|
|
cluster:
|
|
server: %s://[%s]:%d
|
|
%s
|
|
users:
|
|
- name: multus
|
|
user:
|
|
token: "%s"
|
|
contexts:
|
|
- name: multus-context
|
|
context:
|
|
cluster: local
|
|
user: multus
|
|
current-context: multus-context
|
|
`
|
|
kubeconfig := fmt.Sprintf(kubeConfigTemplate, protocol, k8sServiceIP, k8sServicePort, tlsConfig, serviceAccountToken)
|
|
logInfo("Generated KubeConfig: \n%s", kubeconfig)
|
|
return ioutil.WriteFile(outputPath, []byte(kubeconfig), userRWPermission)
|
|
}
|
|
|
|
func prepareCNIConfigDir(cniConfigDirPath string) error {
|
|
return os.MkdirAll(cniConfigDirPath, userRWPermission)
|
|
}
|
|
|
|
func logInvalidArg(format string, values ...interface{}) {
|
|
log.Printf("ERROR: %s", fmt.Errorf(format, values...).Error())
|
|
flag.PrintDefaults()
|
|
os.Exit(1)
|
|
}
|
|
|
|
func logError(format string, values ...interface{}) {
|
|
log.Printf("ERROR: %s", fmt.Errorf(format, values...).Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
func logInfo(format string, values ...interface{}) {
|
|
log.Printf("INFO: %s", fmt.Sprintf(format, values...))
|
|
}
|