ecrtokenrefresher/pkg/secrets/common/common.go (143 lines of code) (raw):
package common
import (
"encoding/base64"
"fmt"
"os"
"path/filepath"
"strings"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"github.com/aws/eks-anywhere-packages/ecrtokenrefresher/pkg/constants"
k8s "github.com/aws/eks-anywhere-packages/ecrtokenrefresher/pkg/kubernetes"
"github.com/aws/eks-anywhere-packages/ecrtokenrefresher/pkg/secrets"
"github.com/aws/eks-anywhere-packages/ecrtokenrefresher/pkg/utils"
)
const defaultEmail = "test@test.com"
type dockerConfig struct {
Auths map[string]*dockerAuth `json:"auths"`
}
type dockerAuth struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Auth string `json:"auth"`
}
func GetDefaultClientSet() (*kubernetes.Clientset, error) {
config, err := rest.InClusterConfig()
if err != nil {
// Program is not being run from inside cluster. Try default kubeconfig
if val, ok := os.LookupEnv("KUBECONFIG"); ok {
config, err = clientcmd.BuildConfigFromFlags("", val)
} else {
config, err = clientcmd.BuildConfigFromFlags("",
filepath.Join(os.Getenv("HOME"), ".kube", "config"))
}
if err != nil {
return nil, err
}
}
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return clientSet, err
}
func GetRemoteClientSets(defaultClientset *kubernetes.Clientset) (secrets.ClusterClientSet, error) {
clusterNames, err := getClusterNameFromNamespaces(defaultClientset)
if err != nil {
return nil, err
}
remoteClientSets := make(secrets.ClusterClientSet)
for _, clusterName := range clusterNames {
secretName := clusterName + "-kubeconfig"
kubeconfigSecret, err := k8s.GetSecret(defaultClientset, secretName, constants.EksaSystemNamespace)
if err != nil {
return nil, err
}
kubeconfig := kubeconfigSecret.Data["value"]
if len(kubeconfig) <= 0 {
return nil, fmt.Errorf("kubeconfig string in secret not set")
}
clientConfig, err := clientcmd.NewClientConfigFromBytes(kubeconfig)
if err != nil {
return nil, fmt.Errorf("creating client config: %s", err)
}
config, err := clientConfig.ClientConfig()
if err != nil {
return nil, fmt.Errorf("creating rest config config: %s", err)
}
remoteClientSet, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
remoteClientSets[clusterName] = remoteClientSet
}
return remoteClientSets, nil
}
func getClusterNameFromNamespaces(clientSet kubernetes.Interface) ([]string, error) {
clusterNameList := make([]string, 0)
nslist, err := k8s.GetNamespaces(clientSet)
if err != nil {
return nil, err
}
for _, ns := range nslist.Items {
if strings.HasPrefix(ns.Name, constants.NamespacePrefix) {
clusterName := strings.TrimPrefix(ns.Name, constants.NamespacePrefix)
clusterNameList = append(clusterNameList, clusterName)
}
}
return clusterNameList, nil
}
func CreateDockerAuthConfig(creds []*secrets.Credential) *dockerConfig {
config := dockerConfig{Auths: make(map[string]*dockerAuth)}
for _, cred := range creds {
username := cred.Username
password := cred.Password
if username == "" {
username = "username"
}
if password == "" {
password = "password"
}
config.Auths[cred.Registry] = &dockerAuth{
Username: username,
Password: password,
Email: defaultEmail,
Auth: base64.StdEncoding.EncodeToString([]byte(username + ":" + password)),
}
}
return &config
}
func BroadcastDockerAuthConfig(configJson []byte, defaultClientSet, remoteClientSet kubernetes.Interface, secretName, clusterName string) {
namespaces, err := getNamespacesFromConfigMap(defaultClientSet, constants.NamespacePrefix+clusterName)
if err != nil {
utils.WarningLogger.Printf("failed to find config map for cluster %s\n", clusterName)
return
}
for _, ns := range namespaces {
secret, _ := k8s.GetSecret(remoteClientSet, secretName, ns)
if secret == nil {
_, err = k8s.CreateSecret(remoteClientSet, secretName, ns, map[string][]byte{corev1.DockerConfigJsonKey: configJson})
if err != nil {
utils.WarningLogger.Printf("failed to create %s in %s namespace\n", secretName, ns)
}
} else {
_, err = k8s.UpdateSecret(remoteClientSet, ns, secret, map[string][]byte{corev1.DockerConfigJsonKey: configJson})
if err != nil {
utils.WarningLogger.Printf("failed to update %s in %s namespace\n", secretName, ns)
}
}
}
}
func getNamespacesFromConfigMap(clientSet kubernetes.Interface, namespace string) ([]string, error) {
cm, err := k8s.GetConfigMap(clientSet, namespace)
if err != nil {
return nil, err
}
values := make([]string, 0)
for ns := range cm.Data {
values = append(values, ns)
}
return values, err
}