Browse code

update generated kubeconfig keys to match osc login

deads2k authored on 2015/06/04 04:03:13
Showing 7 changed files
... ...
@@ -289,11 +289,9 @@ This section covers how to perform all the steps of building, deploying, and upd
289 289
 
290 290
      If you want to see the build logs of a complete build, use the
291 291
      command below (substituting your build name from the "osc get builds"
292
-     output). Notice that for now only cluster admins can run the `build-logs`
293
-     command, so we have to explicitly tell the command to use the `master`
294
-     context from the $OPENSHIFTCONFIG config file:
292
+     output). 
295 293
 
296
-         $ osc build-logs ruby-sample-build-1 --context=master -n test
294
+         $ osc build-logs ruby-sample-build-1 -n test
297 295
 
298 296
     The creation of the new image in the Docker registry will
299 297
     automatically trigger a deployment of the application, creating a
... ...
@@ -238,17 +238,20 @@ OS_PID=$!
238 238
 
239 239
 export HOME="${FAKE_HOME_DIR}"
240 240
 
241
+export OPENSHIFTCONFIG="${MASTER_CONFIG_DIR}/admin.kubeconfig"
242
+CLUSTER_ADMIN_CONTEXT=$(osc config view --flatten -o template -t '{{index . "current-context"}}')
243
+
241 244
 if [[ "${API_SCHEME}" == "https" ]]; then
242 245
 	export CURL_CA_BUNDLE="${MASTER_CONFIG_DIR}/ca.crt"
243 246
 	export CURL_CERT="${MASTER_CONFIG_DIR}/admin.crt"
244 247
 	export CURL_KEY="${MASTER_CONFIG_DIR}/admin.key"
245 248
 
246 249
 	# Make osc use ${MASTER_CONFIG_DIR}/admin.kubeconfig, and ignore anything in the running user's $HOME dir
247
-	export OPENSHIFTCONFIG="${MASTER_CONFIG_DIR}/admin.kubeconfig"
248 250
 	sudo chmod -R a+rwX "${OPENSHIFTCONFIG}"
249 251
 	echo "[INFO] To debug: export OPENSHIFTCONFIG=$OPENSHIFTCONFIG"
250 252
 fi
251 253
 
254
+
252 255
 wait_for_url "${KUBELET_SCHEME}://${KUBELET_HOST}:${KUBELET_PORT}/healthz" "[INFO] kubelet: " 0.5 60
253 256
 wait_for_url "${API_SCHEME}://${API_HOST}:${API_PORT}/healthz" "apiserver: " 0.25 80
254 257
 wait_for_url "${API_SCHEME}://${API_HOST}:${API_PORT}/api/v1beta3/nodes/${KUBELET_HOST}" "apiserver(nodes): " 0.25 80
... ...
@@ -307,7 +310,7 @@ docker push ${DOCKER_REGISTRY}/cache/ruby-20-centos7:latest
307 307
 echo "[INFO] Pushed ruby-20-centos7"
308 308
 
309 309
 echo "[INFO] Back to 'master' context with 'admin' user..."
310
-osc project default
310
+osc project ${CLUSTER_ADMIN_CONTEXT}
311 311
 
312 312
 # Process template and create
313 313
 echo "[INFO] Submitting application template json for processing..."
... ...
@@ -1,6 +1,7 @@
1 1
 package config
2 2
 
3 3
 import (
4
+	"crypto/x509"
4 5
 	"net/url"
5 6
 	"reflect"
6 7
 	"strings"
... ...
@@ -9,12 +10,18 @@ import (
9 9
 	clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/third_party/golang/netutil"
11 11
 
12
+	"github.com/openshift/origin/pkg/auth/authenticator/request/x509request"
12 13
 	osclient "github.com/openshift/origin/pkg/client"
13 14
 )
14 15
 
15
-// getClusterNickname returns host:port of the clientConfig.Host, with .'s replaced by -'s
16
-func getClusterNickname(clientCfg *client.Config) (string, error) {
17
-	u, err := url.Parse(clientCfg.Host)
16
+// GetClusterNicknameFromConfig returns host:port of the clientConfig.Host, with .'s replaced by -'s
17
+func GetClusterNicknameFromConfig(clientCfg *client.Config) (string, error) {
18
+	return GetClusterNicknameFromURL(clientCfg.Host)
19
+}
20
+
21
+// GetClusterNicknameFromURL returns host:port of the apiServerLocation, with .'s replaced by -'s
22
+func GetClusterNicknameFromURL(apiServerLocation string) (string, error) {
23
+	u, err := url.Parse(apiServerLocation)
18 24
 	if err != nil {
19 25
 		return "", err
20 26
 	}
... ...
@@ -24,9 +31,9 @@ func getClusterNickname(clientCfg *client.Config) (string, error) {
24 24
 	return strings.Replace(hostPort, ".", "-", -1), nil
25 25
 }
26 26
 
27
-// getUserNickname returns "username(as known by the server)/getClusterNickname".  This allows tab completion for switching users to
27
+// GetUserNicknameFromConfig returns "username(as known by the server)/GetClusterNicknameFromConfig".  This allows tab completion for switching users to
28 28
 // work easily and obviously.
29
-func getUserNickname(clientCfg *client.Config) (string, error) {
29
+func GetUserNicknameFromConfig(clientCfg *client.Config) (string, error) {
30 30
 	client, err := osclient.New(clientCfg)
31 31
 	if err != nil {
32 32
 		return "", err
... ...
@@ -36,7 +43,7 @@ func getUserNickname(clientCfg *client.Config) (string, error) {
36 36
 		return "", err
37 37
 	}
38 38
 
39
-	clusterNick, err := getClusterNickname(clientCfg)
39
+	clusterNick, err := GetClusterNicknameFromConfig(clientCfg)
40 40
 	if err != nil {
41 41
 		return "", err
42 42
 	}
... ...
@@ -44,10 +51,19 @@ func getUserNickname(clientCfg *client.Config) (string, error) {
44 44
 	return userInfo.Name + "/" + clusterNick, nil
45 45
 }
46 46
 
47
-// getContextNickname returns "namespace/getClusterNickname/username(as known by the server)".  This allows tab completion for switching projects/context
47
+func GetUserNicknameFromCert(clusterNick string, chain ...*x509.Certificate) (string, error) {
48
+	userInfo, _, err := x509request.SubjectToUserConversion(chain)
49
+	if err != nil {
50
+		return "", err
51
+	}
52
+
53
+	return userInfo.GetName() + "/" + clusterNick, nil
54
+}
55
+
56
+// GetContextNicknameFromConfig returns "namespace/GetClusterNicknameFromConfig/username(as known by the server)".  This allows tab completion for switching projects/context
48 57
 // to work easily.  First tab is the most selective on project.  Second stanza in the next most selective on cluster name.  The chances of a user trying having
49 58
 // one projects on a single server that they want to operate against with two identities is low, so username is last.
50
-func getContextNickname(namespace string, clientCfg *client.Config) (string, error) {
59
+func GetContextNicknameFromConfig(namespace string, clientCfg *client.Config) (string, error) {
51 60
 	client, err := osclient.New(clientCfg)
52 61
 	if err != nil {
53 62
 		return "", err
... ...
@@ -57,7 +73,7 @@ func getContextNickname(namespace string, clientCfg *client.Config) (string, err
57 57
 		return "", err
58 58
 	}
59 59
 
60
-	clusterNick, err := getClusterNickname(clientCfg)
60
+	clusterNick, err := GetClusterNicknameFromConfig(clientCfg)
61 61
 	if err != nil {
62 62
 		return "", err
63 63
 	}
... ...
@@ -65,19 +81,24 @@ func getContextNickname(namespace string, clientCfg *client.Config) (string, err
65 65
 	return namespace + "/" + clusterNick + "/" + userInfo.Name, nil
66 66
 }
67 67
 
68
+func GetContextNickname(namespace, clusterNick, userNick string) (string, error) {
69
+	tokens := strings.SplitN(userNick, "/", 2)
70
+	return namespace + "/" + clusterNick + "/" + tokens[0], nil
71
+}
72
+
68 73
 // CreatePartialConfig takes a clientCfg and builds a config (kubeconfig style) from it.
69 74
 func CreateConfig(namespace string, clientCfg *client.Config) (*clientcmdapi.Config, error) {
70
-	clusterNick, err := getClusterNickname(clientCfg)
75
+	clusterNick, err := GetClusterNicknameFromConfig(clientCfg)
71 76
 	if err != nil {
72 77
 		return nil, err
73 78
 	}
74 79
 
75
-	userNick, err := getUserNickname(clientCfg)
80
+	userNick, err := GetUserNicknameFromConfig(clientCfg)
76 81
 	if err != nil {
77 82
 		return nil, err
78 83
 	}
79 84
 
80
-	contextNick, err := getContextNickname(namespace, clientCfg)
85
+	contextNick, err := GetContextNicknameFromConfig(namespace, clientCfg)
81 86
 	if err != nil {
82 87
 		return nil, err
83 88
 	}
... ...
@@ -134,11 +134,9 @@ func (o CreateClientOptions) CreateClientFolder() error {
134 134
 		APIServerURL:       o.APIServerURL,
135 135
 		PublicAPIServerURL: o.PublicAPIServerURL,
136 136
 		APIServerCAFile:    clientCopyOfCAFile,
137
-		ServerNick:         "master",
138 137
 
139 138
 		CertFile: clientCertFile,
140 139
 		KeyFile:  clientKeyFile,
141
-		UserNick: o.User,
142 140
 
143 141
 		ContextNamespace: kapi.NamespaceDefault,
144 142
 
... ...
@@ -16,6 +16,8 @@ import (
16 16
 
17 17
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
18 18
 	clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
19
+	cliconfig "github.com/openshift/origin/pkg/cmd/cli/config"
20
+	"github.com/openshift/origin/pkg/cmd/server/crypto"
19 21
 	cmdutil "github.com/openshift/origin/pkg/cmd/util"
20 22
 )
21 23
 
... ...
@@ -25,13 +27,10 @@ type CreateKubeConfigOptions struct {
25 25
 	APIServerURL       string
26 26
 	PublicAPIServerURL string
27 27
 	APIServerCAFile    string
28
-	ServerNick         string
29 28
 
30 29
 	CertFile string
31 30
 	KeyFile  string
32
-	UserNick string
33 31
 
34
-	ContextNick      string
35 32
 	ContextNamespace string
36 33
 
37 34
 	KubeConfigFile string
... ...
@@ -92,11 +91,8 @@ users:
92 92
 	flags.StringVar(&options.APIServerURL, "master", "https://localhost:8443", "The API server's URL.")
93 93
 	flags.StringVar(&options.PublicAPIServerURL, "public-master", "", "The API public facing server's URL (if applicable).")
94 94
 	flags.StringVar(&options.APIServerCAFile, "certificate-authority", "openshift.local.config/master/ca.crt", "Path to the API server's CA file.")
95
-	flags.StringVar(&options.ServerNick, "cluster", "master", "Nick name for this server in .kubeconfig.")
96 95
 	flags.StringVar(&options.CertFile, "client-certificate", "", "The client cert file.")
97 96
 	flags.StringVar(&options.KeyFile, "client-key", "", "The client key file.")
98
-	flags.StringVar(&options.UserNick, "user", "user", "Nick name for this user in .kubeconfig.")
99
-	flags.StringVar(&options.ContextNick, "context", "", "Nick name for this context in .kubeconfig.")
100 97
 	flags.StringVar(&options.ContextNamespace, "namespace", kapi.NamespaceDefault, "Namespace for this context in .kubeconfig.")
101 98
 	flags.StringVar(&options.KubeConfigFile, "kubeconfig", ".kubeconfig", "Path for the resulting .kubeconfig file.")
102 99
 
... ...
@@ -119,15 +115,12 @@ func (o CreateKubeConfigOptions) Validate(args []string) error {
119 119
 	if len(o.APIServerCAFile) == 0 {
120 120
 		return errors.New("certificate-authority must be provided")
121 121
 	}
122
-	if len(o.ServerNick) == 0 {
123
-		return errors.New("cluster must be provided")
124
-	}
125
-	if len(o.UserNick) == 0 {
126
-		return errors.New("user-nick must be provided")
127
-	}
128 122
 	if len(o.ContextNamespace) == 0 {
129 123
 		return errors.New("namespace must be provided")
130 124
 	}
125
+	if len(o.APIServerURL) == 0 {
126
+		return errors.New("master must be provided")
127
+	}
131 128
 
132 129
 	return nil
133 130
 }
... ...
@@ -135,11 +128,7 @@ func (o CreateKubeConfigOptions) Validate(args []string) error {
135 135
 func (o CreateKubeConfigOptions) CreateKubeConfig() (*clientcmdapi.Config, error) {
136 136
 	glog.V(2).Infof("creating a .kubeconfig with: %#v", o)
137 137
 
138
-	// if you don't specify a context nick, assign it to the context namespace
139
-	if len(o.ContextNick) == 0 {
140
-		o.ContextNick = o.ContextNamespace
141
-	}
142
-
138
+	// read all the refenced filenames
143 139
 	caData, err := ioutil.ReadFile(o.APIServerCAFile)
144 140
 	if err != nil {
145 141
 		return nil, err
... ...
@@ -152,41 +141,66 @@ func (o CreateKubeConfigOptions) CreateKubeConfig() (*clientcmdapi.Config, error
152 152
 	if err != nil {
153 153
 		return nil, err
154 154
 	}
155
+	certConfig, err := crypto.GetTLSCertificateConfig(o.CertFile, o.KeyFile)
156
+	if err != nil {
157
+		return nil, err
158
+	}
159
+
160
+	// determine all the nicknames
161
+	clusterNick, err := cliconfig.GetClusterNicknameFromURL(o.APIServerURL)
162
+	if err != nil {
163
+		return nil, err
164
+	}
165
+	userNick, err := cliconfig.GetUserNicknameFromCert(clusterNick, certConfig.Certs...)
166
+	if err != nil {
167
+		return nil, err
168
+	}
169
+	contextNick, err := cliconfig.GetContextNickname(o.ContextNamespace, clusterNick, userNick)
170
+	if err != nil {
171
+		return nil, err
172
+	}
155 173
 
156 174
 	credentials := make(map[string]clientcmdapi.AuthInfo)
157
-	credentials[o.UserNick] = clientcmdapi.AuthInfo{
175
+	credentials[userNick] = clientcmdapi.AuthInfo{
158 176
 		ClientCertificateData: certData,
159 177
 		ClientKeyData:         keyData,
160 178
 	}
161 179
 
162 180
 	clusters := make(map[string]clientcmdapi.Cluster)
163
-	clusters[o.ServerNick] = clientcmdapi.Cluster{
181
+	clusters[clusterNick] = clientcmdapi.Cluster{
164 182
 		Server: o.APIServerURL,
165 183
 		CertificateAuthorityData: caData,
166 184
 	}
167 185
 
168 186
 	contexts := make(map[string]clientcmdapi.Context)
169
-	contexts[o.ContextNick] = clientcmdapi.Context{Cluster: o.ServerNick, AuthInfo: o.UserNick, Namespace: o.ContextNamespace}
187
+	contexts[contextNick] = clientcmdapi.Context{Cluster: clusterNick, AuthInfo: userNick, Namespace: o.ContextNamespace}
170 188
 
171
-	createPublic := len(o.PublicAPIServerURL) > 0
189
+	createPublic := (len(o.PublicAPIServerURL) > 0) && o.APIServerURL != o.PublicAPIServerURL
172 190
 	if createPublic {
173
-		publicClusterNick := "public-" + o.ServerNick
174
-		publicContextNick := "public-" + o.ContextNick
191
+		publicClusterNick, err := cliconfig.GetClusterNicknameFromURL(o.PublicAPIServerURL)
192
+		if err != nil {
193
+			return nil, err
194
+		}
195
+		publicContextNick, err := cliconfig.GetContextNickname(o.ContextNamespace, publicClusterNick, userNick)
196
+		if err != nil {
197
+			return nil, err
198
+		}
199
+
175 200
 		clusters[publicClusterNick] = clientcmdapi.Cluster{
176 201
 			Server: o.PublicAPIServerURL,
177 202
 			CertificateAuthorityData: caData,
178 203
 		}
179
-		contexts[publicContextNick] = clientcmdapi.Context{Cluster: publicClusterNick, AuthInfo: o.UserNick, Namespace: o.ContextNamespace}
204
+		contexts[publicContextNick] = clientcmdapi.Context{Cluster: publicClusterNick, AuthInfo: userNick, Namespace: o.ContextNamespace}
180 205
 	}
181 206
 
182 207
 	kubeConfig := &clientcmdapi.Config{
183 208
 		Clusters:       clusters,
184 209
 		AuthInfos:      credentials,
185 210
 		Contexts:       contexts,
186
-		CurrentContext: o.ContextNick,
211
+		CurrentContext: contextNick,
187 212
 	}
188 213
 
189
-	fmt.Fprintf(o.Output.Get(), "Generating '%s' API client config as %s\n", o.UserNick, o.KubeConfigFile)
214
+	fmt.Fprintf(o.Output.Get(), "Generating '%s' API client config as %s\n", userNick, o.KubeConfigFile)
190 215
 	// Ensure the parent dir exists
191 216
 	if err := os.MkdirAll(filepath.Dir(o.KubeConfigFile), os.FileMode(0755)); err != nil {
192 217
 		return nil, err
... ...
@@ -184,11 +184,9 @@ func (o CreateMasterCertsOptions) createAPIClients(getSignerCertOptions *GetSign
184 184
 			APIServerURL:       o.APIServerURL,
185 185
 			PublicAPIServerURL: o.PublicAPIServerURL,
186 186
 			APIServerCAFile:    getSignerCertOptions.CertFile,
187
-			ServerNick:         "master",
188 187
 
189 188
 			CertFile: clientCertInfo.CertLocation.CertFile,
190 189
 			KeyFile:  clientCertInfo.CertLocation.KeyFile,
191
-			UserNick: clientCertInfo.User,
192 190
 
193 191
 			ContextNamespace: kapi.NamespaceDefault,
194 192
 
... ...
@@ -323,11 +323,9 @@ func (o CreateNodeConfigOptions) MakeKubeConfig(clientCertFile, clientKeyFile, c
323 323
 	createKubeConfigOptions := CreateKubeConfigOptions{
324 324
 		APIServerURL:    o.APIServerURL,
325 325
 		APIServerCAFile: clientCopyOfCAFile,
326
-		ServerNick:      "master",
327 326
 
328 327
 		CertFile: clientCertFile,
329 328
 		KeyFile:  clientKeyFile,
330
-		UserNick: "node",
331 329
 
332 330
 		ContextNamespace: kapi.NamespaceDefault,
333 331