Skip to content

Commit

Permalink
add secret for kubeadmin pre-idp user
Browse files Browse the repository at this point in the history
  • Loading branch information
sallyom committed Dec 4, 2018
1 parent ec1abc2 commit e7aaedb
Show file tree
Hide file tree
Showing 15 changed files with 195 additions and 78 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ If you don't have [terraform](https://www.terraform.io/), run the following to c
hack/get-terraform.sh
```

The installer will show a series of prompts for user-specific information (e.g. admin password) and use reasonable defaults for everything else. In non-interactive contexts, prompts can be bypassed by providing appropriately-named environment variables. Refer to the [user documentation](docs/user) for more information.
The installer will show a series of prompts for user-specific information and use reasonable defaults for everything else. In non-interactive contexts, prompts can be bypassed by providing appropriately-named environment variables. Refer to the [user documentation](docs/user) for more information.

### Connect to the cluster

Expand Down
10 changes: 8 additions & 2 deletions cmd/openshift-install/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"io/ioutil"
"os/exec"
"path/filepath"
"strings"
Expand Down Expand Up @@ -249,7 +250,12 @@ func logComplete(directory string) error {
return err
}
kubeconfig := filepath.Join(absDir, "auth", "kubeconfig")
logrus.Infof("Install complete! Run 'export KUBECONFIG=%s' to manage your cluster.", kubeconfig)
logrus.Info("After exporting your kubeconfig, run 'oc -h' for a list of OpenShift client commands.")
pwFile := filepath.Join(absDir, "auth", "kubeadmin-password")
pw, err := ioutil.ReadFile(pwFile)
if err != nil {
return err
}
logrus.Infof("kubeadmin user password: %s", pw)
logrus.Infof("Install complete! The kubeconfig is located here: %s", kubeconfig)
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Secret
apiVersion: v1
metadata:
namespace: kube-system
name: kubeadmin
data:
kubeadmin: {{.Base64EncodedKubeadminPwHash}}
6 changes: 0 additions & 6 deletions docs/user/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ The installer accepts a number of environment variable that allow the interactiv

For libvirt, choose a name that is unique enough to be used as a prefix during cluster deletion.
For example, if you use `demo` as your cluster name, `openshift-install destroy cluster` may destroy all domains, networks, pools, and volumes that begin with `demo`.
* `OPENSHIFT_INSTALL_EMAIL_ADDRESS`:
The email address of the cluster administrator.
This will be used to log in to the console.
* `OPENSHIFT_INSTALL_PASSWORD`:
The password of the cluster administrator.
This will be used to log in to the console.
* `OPENSHIFT_INSTALL_PLATFORM`:
The platform onto which the cluster will be installed.
Valid values are `aws` and `libvirt`.
Expand Down
14 changes: 13 additions & 1 deletion pkg/asset/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/openshift/installer/pkg/asset/cluster/openstack"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/kubeconfig"
"github.com/openshift/installer/pkg/asset/password"
"github.com/openshift/installer/pkg/terraform"
"github.com/openshift/installer/pkg/types"
)
Expand All @@ -25,6 +26,11 @@ const (
metadataFileName = "metadata.json"
)

var (
// kubeadminPasswordPath is the path where kubeadmin user password is stored.
kubeadminPasswordPath = filepath.Join("auth", "kubeadmin-password")
)

// Cluster uses the terraform executable to launch a cluster
// with the given terraform tfvar and generated templates.
type Cluster struct {
Expand All @@ -45,6 +51,7 @@ func (c *Cluster) Dependencies() []asset.Asset {
&installconfig.InstallConfig{},
&TerraformVariables{},
&kubeconfig.Admin{},
&password.KubeadminPassword{},
}
}

Expand All @@ -53,7 +60,8 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
installConfig := &installconfig.InstallConfig{}
terraformVariables := &TerraformVariables{}
adminKubeconfig := &kubeconfig.Admin{}
parents.Get(installConfig, terraformVariables, adminKubeconfig)
kubeadminPassword := &password.KubeadminPassword{}
parents.Get(installConfig, terraformVariables, adminKubeconfig, kubeadminPassword)

// Copy the terraform.tfvars to a temp directory where the terraform will be invoked within.
tmpDir, err := ioutil.TempDir("", "openshift-install-")
Expand Down Expand Up @@ -85,6 +93,10 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
logrus.Error(err2)
}
}
c.FileList = append(c.FileList, &asset.File{
Filename: kubeadminPasswordPath,
Data: []byte(kubeadminPassword.Password),
})
// serialize metadata and stuff it into c.FileList
}()

Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/ignition/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (a *Bootstrap) Generate(dependencies asset.Parents) error {

a.Config.Passwd.Users = append(
a.Config.Passwd.Users,
igntypes.PasswdUser{Name: "core", SSHAuthorizedKeys: []igntypes.SSHAuthorizedKey{igntypes.SSHAuthorizedKey(installConfig.Config.Admin.SSHKey)}},
igntypes.PasswdUser{Name: "core", SSHAuthorizedKeys: []igntypes.SSHAuthorizedKey{igntypes.SSHAuthorizedKey(installConfig.Config.SSHKey)}},
)

data, err := json.Marshal(a.Config)
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/ignition/machine/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func pointerIgnitionConfig(installConfig *types.InstallConfig, rootCA []byte, ro
Passwd: ignition.Passwd{
Users: []ignition.PasswdUser{{
Name: "core",
SSHAuthorizedKeys: []ignition.SSHAuthorizedKey{ignition.SSHAuthorizedKey(installConfig.Admin.SSHKey)},
SSHAuthorizedKeys: []ignition.SSHAuthorizedKey{ignition.SSHAuthorizedKey(installConfig.SSHKey)},
}},
},
}
Expand Down
14 changes: 2 additions & 12 deletions pkg/asset/installconfig/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ var _ asset.WritableAsset = (*InstallConfig)(nil)
func (a *InstallConfig) Dependencies() []asset.Asset {
return []asset.Asset{
&clusterID{},
&emailAddress{},
&password{},
&sshPublicKey{},
&baseDomain{},
&clusterName{},
Expand All @@ -50,17 +48,13 @@ func (a *InstallConfig) Dependencies() []asset.Asset {
// Generate generates the install-config.yml file.
func (a *InstallConfig) Generate(parents asset.Parents) error {
clusterID := &clusterID{}
emailAddress := &emailAddress{}
password := &password{}
sshPublicKey := &sshPublicKey{}
baseDomain := &baseDomain{}
clusterName := &clusterName{}
pullSecret := &pullSecret{}
platform := &platform{}
parents.Get(
clusterID,
emailAddress,
password,
sshPublicKey,
baseDomain,
clusterName,
Expand All @@ -72,12 +66,8 @@ func (a *InstallConfig) Generate(parents asset.Parents) error {
ObjectMeta: metav1.ObjectMeta{
Name: clusterName.ClusterName,
},
ClusterID: clusterID.ClusterID,
Admin: types.Admin{
Email: emailAddress.EmailAddress,
Password: password.Password,
SSHKey: sshPublicKey.Key,
},
ClusterID: clusterID.ClusterID,
SSHKey: sshPublicKey.Key,
BaseDomain: baseDomain.BaseDomain,
Networking: types.Networking{
Type: "OpenshiftSDN",
Expand Down
39 changes: 0 additions & 39 deletions pkg/asset/installconfig/password.go

This file was deleted.

12 changes: 10 additions & 2 deletions pkg/asset/manifests/tectonic.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/machines"
"github.com/openshift/installer/pkg/asset/password"
"github.com/openshift/installer/pkg/asset/templates/content/tectonic"
)

Expand Down Expand Up @@ -40,20 +41,23 @@ func (t *Tectonic) Dependencies() []asset.Asset {
&ClusterK8sIO{},
&machines.Worker{},
&machines.Master{},
&password.KubeadminPassword{},

&tectonic.BindingDiscovery{},
&tectonic.CloudCredsSecret{},
&tectonic.KubeadminPasswordSecret{},
&tectonic.RoleCloudCredsSecretReader{},
}
}

// Generate generates the respective operator config.yml files
func (t *Tectonic) Generate(dependencies asset.Parents) error {
installConfig := &installconfig.InstallConfig{}
kubeadminPassword := &password.KubeadminPassword{}
clusterk8sio := &ClusterK8sIO{}
worker := &machines.Worker{}
master := &machines.Master{}
dependencies.Get(installConfig, clusterk8sio, worker, master)
dependencies.Get(installConfig, clusterk8sio, worker, master, kubeadminPassword)
var cloudCreds cloudCredsSecretData
platform := installConfig.Config.Platform.Name()
switch platform {
Expand Down Expand Up @@ -91,18 +95,22 @@ func (t *Tectonic) Generate(dependencies asset.Parents) error {
}

templateData := &tectonicTemplateData{
CloudCreds: cloudCreds,
CloudCreds: cloudCreds,
Base64EncodedKubeadminPwHash: base64.StdEncoding.EncodeToString(kubeadminPassword.PasswordHash),
}

bindingDiscovery := &tectonic.BindingDiscovery{}
cloudCredsSecret := &tectonic.CloudCredsSecret{}
kubeadminPasswordSecret := &tectonic.KubeadminPasswordSecret{}
roleCloudCredsSecretReader := &tectonic.RoleCloudCredsSecretReader{}
dependencies.Get(
bindingDiscovery,
cloudCredsSecret,
kubeadminPasswordSecret,
roleCloudCredsSecretReader)
assetData := map[string][]byte{
"99_binding-discovery.yaml": []byte(bindingDiscovery.Files()[0].Data),
"99_kubeadmin-password-secret.yaml": applyTemplateData(kubeadminPasswordSecret.Files()[0].Data, templateData),
"99_openshift-cluster-api_cluster.yaml": clusterk8sio.Raw,
"99_openshift-cluster-api_master-machines.yaml": master.MachinesRaw,
"99_openshift-cluster-api_master-user-data-secret.yaml": master.UserDataSecretRaw,
Expand Down
3 changes: 2 additions & 1 deletion pkg/asset/manifests/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ type bootkubeTemplateData struct {
}

type tectonicTemplateData struct {
CloudCreds cloudCredsSecretData
CloudCreds cloudCredsSecretData
Base64EncodedKubeadminPwHash string
}
79 changes: 79 additions & 0 deletions pkg/asset/password/password.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package password

import (
"crypto/rand"
"math/big"

"github.com/openshift/installer/pkg/asset"
"golang.org/x/crypto/bcrypt"
)

// KubeadminPassword is the asset for the kubeadmin user password
type KubeadminPassword struct {
Password string
PasswordHash []byte
}

var _ asset.Asset = (*KubeadminPassword)(nil)

// Dependencies returns no dependencies.
func (a *KubeadminPassword) Dependencies() []asset.Asset {
return []asset.Asset{}
}

// Generate the kubeadmin password
func (a *KubeadminPassword) Generate(asset.Parents) error {
err := a.generateRandomPasswordHash(23)
if err != nil {
return err
}
return nil
}

// generateRandomPasswordHash generates a hash of a random ASCII password
// 5char-5char-5char-5char
func (a *KubeadminPassword) generateRandomPasswordHash(length int) error {
const (
lowerLetters = "abcdefghijkmnopqrstuvwxyz"
upperLetters = "ABCDEFGHIJKLMNPQRSTUVWXYZ"
digits = "23456789"
all = lowerLetters + upperLetters + digits
)
var password string
for i := 0; i < length; i++ {
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(all))))
if err != nil {
return err
}
newchar := string(all[n.Int64()])
if password == "" {
password = newchar
}
if i < length-1 {
n, err = rand.Int(rand.Reader, big.NewInt(int64(len(password)+1)))
if err != nil {
return err
}
j := n.Int64()
password = password[0:j] + newchar + password[j:]
}
}
pw := []rune(password)
for _, replace := range []int{5, 11, 17} {
pw[replace] = '-'
}
if a.Password == "" {
a.Password = string(pw)
}
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return err
}
a.PasswordHash = bytes
return nil
}

// Name returns the human-friendly name of the asset.
func (a *KubeadminPassword) Name() string {
return "Kubeadmin Password"
}
Loading

0 comments on commit e7aaedb

Please sign in to comment.