github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/cluster/secrets.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package cluster contains Jackal-specific cluster management functions.
     5  package cluster
     6  
     7  import (
     8  	"encoding/base64"
     9  	"encoding/json"
    10  	"reflect"
    11  
    12  	corev1 "k8s.io/api/core/v1"
    13  
    14  	"github.com/Racer159/jackal/src/config"
    15  	"github.com/Racer159/jackal/src/pkg/message"
    16  	"github.com/Racer159/jackal/src/types"
    17  )
    18  
    19  // DockerConfig contains the authentication information from the machine's docker config.
    20  type DockerConfig struct {
    21  	Auths DockerConfigEntry `json:"auths"`
    22  }
    23  
    24  // DockerConfigEntry contains a map of DockerConfigEntryWithAuth for a registry.
    25  type DockerConfigEntry map[string]DockerConfigEntryWithAuth
    26  
    27  // DockerConfigEntryWithAuth contains a docker config authentication string.
    28  type DockerConfigEntryWithAuth struct {
    29  	Auth string `json:"auth"`
    30  }
    31  
    32  // GenerateRegistryPullCreds generates a secret containing the registry credentials.
    33  func (c *Cluster) GenerateRegistryPullCreds(namespace, name string, registryInfo types.RegistryInfo) *corev1.Secret {
    34  	secretDockerConfig := c.GenerateSecret(namespace, name, corev1.SecretTypeDockerConfigJson)
    35  
    36  	// Auth field must be username:password and base64 encoded
    37  	fieldValue := registryInfo.PullUsername + ":" + registryInfo.PullPassword
    38  	authEncodedValue := base64.StdEncoding.EncodeToString([]byte(fieldValue))
    39  
    40  	registry := registryInfo.Address
    41  	// Create the expected structure for the dockerconfigjson
    42  	dockerConfigJSON := DockerConfig{
    43  		Auths: DockerConfigEntry{
    44  			registry: DockerConfigEntryWithAuth{
    45  				Auth: authEncodedValue,
    46  			},
    47  		},
    48  	}
    49  
    50  	// Convert to JSON
    51  	dockerConfigData, err := json.Marshal(dockerConfigJSON)
    52  	if err != nil {
    53  		message.WarnErrf(err, "Unable to marshal the .dockerconfigjson secret data for the image pull secret")
    54  	}
    55  
    56  	// Add to the secret data
    57  	secretDockerConfig.Data[".dockerconfigjson"] = dockerConfigData
    58  
    59  	return secretDockerConfig
    60  }
    61  
    62  // GenerateGitPullCreds generates a secret containing the git credentials.
    63  func (c *Cluster) GenerateGitPullCreds(namespace, name string, gitServerInfo types.GitServerInfo) *corev1.Secret {
    64  	message.Debugf("k8s.GenerateGitPullCreds(%s, %s, gitServerInfo)", namespace, name)
    65  
    66  	gitServerSecret := c.GenerateSecret(namespace, name, corev1.SecretTypeOpaque)
    67  	gitServerSecret.StringData = map[string]string{
    68  		"username": gitServerInfo.PullUsername,
    69  		"password": gitServerInfo.PullPassword,
    70  	}
    71  
    72  	return gitServerSecret
    73  }
    74  
    75  // UpdateJackalManagedImageSecrets updates all Jackal-managed image secrets in all namespaces based on state
    76  func (c *Cluster) UpdateJackalManagedImageSecrets(state *types.JackalState) {
    77  	spinner := message.NewProgressSpinner("Updating existing Jackal-managed image secrets")
    78  	defer spinner.Stop()
    79  
    80  	if namespaces, err := c.GetNamespaces(); err != nil {
    81  		spinner.Errorf(err, "Unable to get k8s namespaces")
    82  	} else {
    83  		// Update all image pull secrets
    84  		for _, namespace := range namespaces.Items {
    85  			currentRegistrySecret, err := c.GetSecret(namespace.Name, config.JackalImagePullSecretName)
    86  			if err != nil {
    87  				continue
    88  			}
    89  
    90  			// Check if this is a Jackal managed secret or is in a namespace the Jackal agent will take action in
    91  			if currentRegistrySecret.Labels[config.JackalManagedByLabel] == "jackal" ||
    92  				(namespace.Labels[agentLabel] != "skip" && namespace.Labels[agentLabel] != "ignore") {
    93  				spinner.Updatef("Updating existing Jackal-managed image secret for namespace: '%s'", namespace.Name)
    94  
    95  				// Create the secret
    96  				newRegistrySecret := c.GenerateRegistryPullCreds(namespace.Name, config.JackalImagePullSecretName, state.RegistryInfo)
    97  				if !reflect.DeepEqual(currentRegistrySecret.Data, newRegistrySecret.Data) {
    98  					// Create or update the jackal registry secret
    99  					if _, err := c.CreateOrUpdateSecret(newRegistrySecret); err != nil {
   100  						message.WarnErrf(err, "Problem creating registry secret for the %s namespace", namespace.Name)
   101  					}
   102  				}
   103  			}
   104  		}
   105  		spinner.Success()
   106  	}
   107  }
   108  
   109  // UpdateJackalManagedGitSecrets updates all Jackal-managed git secrets in all namespaces based on state
   110  func (c *Cluster) UpdateJackalManagedGitSecrets(state *types.JackalState) {
   111  	spinner := message.NewProgressSpinner("Updating existing Jackal-managed git secrets")
   112  	defer spinner.Stop()
   113  
   114  	if namespaces, err := c.GetNamespaces(); err != nil {
   115  		spinner.Errorf(err, "Unable to get k8s namespaces")
   116  	} else {
   117  		// Update all git pull secrets
   118  		for _, namespace := range namespaces.Items {
   119  			currentGitSecret, err := c.GetSecret(namespace.Name, config.JackalGitServerSecretName)
   120  			if err != nil {
   121  				continue
   122  			}
   123  
   124  			// Check if this is a Jackal managed secret or is in a namespace the Jackal agent will take action in
   125  			if currentGitSecret.Labels[config.JackalManagedByLabel] == "jackal" ||
   126  				(namespace.Labels[agentLabel] != "skip" && namespace.Labels[agentLabel] != "ignore") {
   127  				spinner.Updatef("Updating existing Jackal-managed git secret for namespace: '%s'", namespace.Name)
   128  
   129  				// Create the secret
   130  				newGitSecret := c.GenerateGitPullCreds(namespace.Name, config.JackalGitServerSecretName, state.GitServer)
   131  				if !reflect.DeepEqual(currentGitSecret.StringData, newGitSecret.StringData) {
   132  					// Create or update the jackal git secret
   133  					if _, err := c.CreateOrUpdateSecret(newGitSecret); err != nil {
   134  						message.WarnErrf(err, "Problem creating git server secret for the %s namespace", namespace.Name)
   135  					}
   136  				}
   137  			}
   138  		}
   139  		spinner.Success()
   140  	}
   141  }