mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.1 KiB
153 lines
4.1 KiB
package nodeconfig |
|
|
|
import ( |
|
"crypto/sha256" |
|
"encoding/base32" |
|
"encoding/json" |
|
"fmt" |
|
"os" |
|
"strings" |
|
|
|
"github.com/k3s-io/k3s/pkg/configfilearg" |
|
"github.com/k3s-io/k3s/pkg/daemons/config" |
|
"github.com/k3s-io/k3s/pkg/version" |
|
"github.com/pkg/errors" |
|
corev1 "k8s.io/api/core/v1" |
|
) |
|
|
|
var ( |
|
NodeArgsAnnotation = version.Program + ".io/node-args" |
|
NodeEnvAnnotation = version.Program + ".io/node-env" |
|
NodeConfigHashAnnotation = version.Program + ".io/node-config-hash" |
|
ClusterEgressLabel = "egress." + version.Program + ".io/cluster" |
|
) |
|
|
|
const ( |
|
OmittedValue = "********" |
|
) |
|
|
|
func getNodeArgs() (string, error) { |
|
nodeArgsList := []string{} |
|
for _, arg := range configfilearg.MustParse(os.Args[1:]) { |
|
if strings.HasPrefix(arg, "--") && strings.Contains(arg, "=") { |
|
parsedArg := strings.SplitN(arg, "=", 2) |
|
nodeArgsList = append(nodeArgsList, parsedArg...) |
|
continue |
|
} |
|
nodeArgsList = append(nodeArgsList, arg) |
|
} |
|
for i, arg := range nodeArgsList { |
|
if isSecret(arg) { |
|
if i+1 < len(nodeArgsList) { |
|
nodeArgsList[i+1] = OmittedValue |
|
} |
|
} |
|
} |
|
nodeArgs, err := json.Marshal(nodeArgsList) |
|
if err != nil { |
|
return "", errors.Wrap(err, "Failed to retrieve argument list for node") |
|
} |
|
return string(nodeArgs), nil |
|
} |
|
|
|
func getNodeEnv() (string, error) { |
|
k3sEnv := make(map[string]string) |
|
for _, v := range os.Environ() { |
|
keyValue := strings.SplitN(v, "=", 2) |
|
if strings.HasPrefix(keyValue[0], version.ProgramUpper+"_") { |
|
k3sEnv[keyValue[0]] = keyValue[1] |
|
} |
|
} |
|
for key := range k3sEnv { |
|
if isSecret(key) { |
|
k3sEnv[key] = OmittedValue |
|
} |
|
} |
|
k3sEnvJSON, err := json.Marshal(k3sEnv) |
|
if err != nil { |
|
return "", errors.Wrap(err, "Failed to retrieve environment map for node") |
|
} |
|
return string(k3sEnvJSON), nil |
|
} |
|
|
|
// SetNodeConfigAnnotations stores a redacted version of the k3s cli args and |
|
// environment variables as annotations on the node object. It also stores a |
|
// hash of the combined args + variables. These are used by other components |
|
// to determine if the node configuration has been changed. |
|
func SetNodeConfigAnnotations(nodeConfig *config.Node, node *corev1.Node) (bool, error) { |
|
nodeArgs, err := getNodeArgs() |
|
if err != nil { |
|
return false, err |
|
} |
|
nodeEnv, err := getNodeEnv() |
|
if err != nil { |
|
return false, err |
|
} |
|
h := sha256.New() |
|
_, err = h.Write([]byte(nodeArgs + nodeEnv)) |
|
if err != nil { |
|
return false, fmt.Errorf("Failed to hash the node config: %v", err) |
|
} |
|
if node.Annotations == nil { |
|
node.Annotations = make(map[string]string) |
|
} |
|
configHash := h.Sum(nil) |
|
encoded := base32.StdEncoding.EncodeToString(configHash[:]) |
|
if node.Annotations[NodeConfigHashAnnotation] == encoded { |
|
return false, nil |
|
} |
|
|
|
node.Annotations[NodeEnvAnnotation] = nodeEnv |
|
node.Annotations[NodeArgsAnnotation] = nodeArgs |
|
node.Annotations[NodeConfigHashAnnotation] = encoded |
|
return true, nil |
|
} |
|
|
|
// SetNodeConfigLabels adds labels for functionality flags |
|
// that may not be present on down-level or up-level nodes. |
|
// These labels are used by other components to determine whether |
|
// or not a node supports particular functionality. |
|
func SetNodeConfigLabels(nodeConfig *config.Node, node *corev1.Node) (bool, error) { |
|
if node.Labels == nil { |
|
node.Labels = make(map[string]string) |
|
} |
|
_, hasLabel := node.Labels[ClusterEgressLabel] |
|
switch nodeConfig.EgressSelectorMode { |
|
case config.EgressSelectorModeCluster, config.EgressSelectorModePod: |
|
if !hasLabel { |
|
node.Labels[ClusterEgressLabel] = "true" |
|
return true, nil |
|
} |
|
default: |
|
if hasLabel { |
|
delete(node.Labels, ClusterEgressLabel) |
|
return true, nil |
|
} |
|
} |
|
return false, nil |
|
} |
|
|
|
func isSecret(key string) bool { |
|
secretData := []string{ |
|
version.ProgramUpper + "_TOKEN", |
|
version.ProgramUpper + "_DATASTORE_ENDPOINT", |
|
version.ProgramUpper + "_AGENT_TOKEN", |
|
version.ProgramUpper + "_CLUSTER_SECRET", |
|
version.ProgramUpper + "_VPN_AUTH", |
|
"AWS_ACCESS_KEY_ID", |
|
"AWS_SECRET_ACCESS_KEY", |
|
"--token", |
|
"-t", |
|
"--agent-token", |
|
"--datastore-endpoint", |
|
"--etcd-s3-access-key", |
|
"--etcd-s3-secret-key", |
|
"--vpn-auth", |
|
} |
|
for _, secret := range secretData { |
|
if key == secret { |
|
return true |
|
} |
|
} |
|
return false |
|
}
|
|
|