-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
nodeconfig.go
152 lines (142 loc) · 4.04 KB
/
nodeconfig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"--token",
"-t",
"--agent-token",
"--datastore-endpoint",
"--cluster-secret",
"--etcd-s3-access-key",
"--etcd-s3-secret-key",
}
for _, secret := range secretData {
if key == secret {
return true
}
}
return false
}