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 }