github.com/jenkins-x/jx/v2@v2.1.155/pkg/config/admin_secrets.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ghodss/yaml"
     7  
     8  	"io/ioutil"
     9  	"strings"
    10  
    11  	"github.com/jenkins-x/jx-logging/pkg/log"
    12  	"github.com/jenkins-x/jx/v2/pkg/util"
    13  	"github.com/pkg/errors"
    14  	"github.com/sethvargo/go-password/password"
    15  
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  const defaultMavenSettings = `<settings>
    20        <!-- sets the local maven repository outside of the ~/.m2 folder for easier mounting of secrets and repo -->
    21        <localRepository>${user.home}/.mvnrepository</localRepository>
    22        <!-- lets disable the download progress indicator that fills up logs -->
    23        <interactiveMode>false</interactiveMode>
    24        <mirrors>
    25            <mirror>
    26                <id>nexus</id>
    27                <mirrorOf>external:*</mirrorOf>
    28                <url>http://nexus/repository/maven-group/</url>
    29            </mirror>
    30        </mirrors>
    31        <servers>
    32            <server>
    33                <id>nexus</id>
    34                <username>admin</username>
    35                <password>%s</password>
    36            </server>
    37        </servers>
    38        <profiles>
    39            <profile>
    40                <id>nexus</id>
    41                <properties>
    42                    <altDeploymentRepository>nexus::default::http://nexus/repository/maven-snapshots/</altDeploymentRepository>
    43                    <altReleaseDeploymentRepository>nexus::default::http://nexus/repository/maven-releases/</altReleaseDeploymentRepository>
    44                    <altSnapshotDeploymentRepository>nexus::default::http://nexus/repository/maven-snapshots/</altSnapshotDeploymentRepository>
    45                </properties>
    46            </profile>
    47            <profile>
    48                <id>release</id>
    49                <properties>
    50                    <gpg.executable>gpg</gpg.executable>
    51                    <gpg.passphrase>mysecretpassphrase</gpg.passphrase>
    52                </properties>
    53            </profile>
    54        </profiles>
    55        <activeProfiles>
    56            <!--make the profile active all the time -->
    57            <activeProfile>nexus</activeProfile>
    58        </activeProfiles>
    59    </settings>
    60  `
    61  
    62  const allowedSymbols = "~!#%^_+-=?,."
    63  
    64  type ChartMuseum struct {
    65  	ChartMuseumEnv ChartMuseumEnv `json:"env"`
    66  }
    67  
    68  type ChartMuseumEnv struct {
    69  	ChartMuseumSecret ChartMuseumSecret `json:"secret"`
    70  }
    71  
    72  type ChartMuseumSecret struct {
    73  	User     string `json:"BASIC_AUTH_USER"`
    74  	Password string `json:"BASIC_AUTH_PASS"`
    75  }
    76  
    77  type Grafana struct {
    78  	GrafanaSecret GrafanaSecret `json:"server"`
    79  }
    80  
    81  type GrafanaSecret struct {
    82  	User     string `json:"adminUser"`
    83  	Password string `json:"adminPassword"`
    84  }
    85  
    86  type Jenkins struct {
    87  	JenkinsSecret JenkinsAdminSecret `json:"Master"`
    88  }
    89  
    90  type JenkinsAdminSecret struct {
    91  	Password string `json:"AdminPassword"`
    92  }
    93  
    94  type PipelineSecrets struct {
    95  	MavenSettingsXML string `json:"MavenSettingsXML,omitempty"`
    96  }
    97  
    98  // KanikoSecret store the kaniko service account
    99  type KanikoSecret struct {
   100  	Data string `json:"Data,omitempty"`
   101  }
   102  
   103  type AdminSecretsConfig struct {
   104  	IngressBasicAuth string           `json:"JXBasicAuth,omitempty"`
   105  	ChartMuseum      *ChartMuseum     `json:"chartmuseum,omitempty"`
   106  	Grafana          *Grafana         `json:"grafana,omitempty"`
   107  	Jenkins          *Jenkins         `json:"jenkins,omitempty"`
   108  	Nexus            *Nexus           `json:"nexus,omitempty"`
   109  	PipelineSecrets  *PipelineSecrets `json:"PipelineSecrets,omitempty"`
   110  	KanikoSecret     *KanikoSecret    `json:"KanikoSecret,omitempty"`
   111  }
   112  
   113  type Nexus struct {
   114  	DefaultAdminPassword string `json:"defaultAdminPassword,omitempty"`
   115  }
   116  
   117  type AdminSecretsService struct {
   118  	FileName    string
   119  	Secrets     AdminSecretsConfig
   120  	Flags       AdminSecretsFlags
   121  	ingressAuth BasicAuth
   122  }
   123  
   124  type AdminSecretsFlags struct {
   125  	DefaultAdminUsername string
   126  	DefaultAdminPassword string
   127  	KanikoSecret         string
   128  }
   129  
   130  func (s *AdminSecretsService) AddAdminSecretsValues(cmd *cobra.Command) {
   131  	cmd.Flags().StringVarP(&s.Flags.DefaultAdminPassword, "default-admin-password", "", "", "the default admin password to access Jenkins, Kubernetes Dashboard, ChartMuseum and Nexus")
   132  	cmd.Flags().StringVarP(&s.Flags.DefaultAdminUsername, "default-admin-username", "", "admin", "the default admin username to access Jenkins, Kubernetes Dashboard, ChartMuseum and Nexus")
   133  }
   134  
   135  func (s *AdminSecretsService) NewAdminSecretsConfig() error {
   136  	s.Secrets = AdminSecretsConfig{
   137  		ChartMuseum:     &ChartMuseum{},
   138  		Grafana:         &Grafana{},
   139  		Jenkins:         &Jenkins{},
   140  		PipelineSecrets: &PipelineSecrets{},
   141  		Nexus:           &Nexus{},
   142  		KanikoSecret:    &KanikoSecret{},
   143  	}
   144  
   145  	if s.Flags.DefaultAdminPassword == "" {
   146  		log.Logger().Debugf("No default password set, generating a random one")
   147  
   148  		input := password.GeneratorInput{
   149  			Symbols: allowedSymbols,
   150  		}
   151  
   152  		generator, err := password.NewGenerator(&input)
   153  		if err != nil {
   154  			return errors.Wrap(err, "unable to create password generator")
   155  		}
   156  
   157  		s.Flags.DefaultAdminPassword, _ = generator.Generate(20, 4, 2, false, true)
   158  	}
   159  
   160  	err := s.setDefaultSecrets()
   161  	if err != nil {
   162  		return errors.Wrap(err, "unable to set default secrets")
   163  	}
   164  	err = s.NewMavenSettingsXML()
   165  	if err != nil {
   166  		return errors.Wrap(err, "unable to generate maven settings")
   167  	}
   168  	s.newIngressBasicAuth()
   169  	s.newKanikoSecret()
   170  
   171  	return nil
   172  }
   173  
   174  func (s *AdminSecretsService) setDefaultSecrets() error {
   175  	s.Secrets.Jenkins.JenkinsSecret.Password = s.Flags.DefaultAdminPassword
   176  	s.Secrets.ChartMuseum.ChartMuseumEnv.ChartMuseumSecret.User = "admin"
   177  	s.Secrets.ChartMuseum.ChartMuseumEnv.ChartMuseumSecret.Password = s.Flags.DefaultAdminPassword
   178  	s.Secrets.Grafana.GrafanaSecret.User = "admin"
   179  	s.Secrets.Grafana.GrafanaSecret.Password = s.Flags.DefaultAdminPassword
   180  	s.Secrets.Nexus.DefaultAdminPassword = s.Flags.DefaultAdminPassword
   181  	return nil
   182  }
   183  
   184  // NewMavenSettingsXML generates the maven settings
   185  func (s *AdminSecretsService) NewMavenSettingsXML() error {
   186  	s.Secrets.PipelineSecrets.MavenSettingsXML = fmt.Sprintf(defaultMavenSettings, s.Flags.DefaultAdminPassword)
   187  	return nil
   188  }
   189  
   190  func (s *AdminSecretsService) NewAdminSecretsConfigFromSecret(decryptedSecretsFile string) error {
   191  	a := AdminSecretsConfig{}
   192  
   193  	data, err := ioutil.ReadFile(decryptedSecretsFile)
   194  	if err != nil {
   195  		return errors.Wrap(err, "unable to read file")
   196  	}
   197  
   198  	err = yaml.Unmarshal(data, &a)
   199  	if err != nil {
   200  		return errors.Wrap(err, "unable to unmarshall secrets")
   201  	}
   202  
   203  	s.Secrets = a
   204  	s.Flags.DefaultAdminPassword = s.Secrets.Jenkins.JenkinsSecret.Password
   205  
   206  	err = s.setDefaultSecrets()
   207  	if err != nil {
   208  		return errors.Wrap(err, "unable to set default secrets")
   209  	}
   210  	s.updateIngressBasicAuth()
   211  
   212  	return nil
   213  }
   214  
   215  func (s *AdminSecretsService) newKanikoSecret() {
   216  	s.Secrets.KanikoSecret.Data = s.Flags.KanikoSecret
   217  }
   218  
   219  func (s *AdminSecretsService) newIngressBasicAuth() {
   220  	password := s.Flags.DefaultAdminPassword
   221  	username := "admin"
   222  	s.ingressAuth = BasicAuth{
   223  		Username: "admin",
   224  		Password: password,
   225  	}
   226  	hash := util.HashPassword(password)
   227  	s.Secrets.IngressBasicAuth = fmt.Sprintf("%s:{SHA}%s", username, hash)
   228  }
   229  
   230  func (s *AdminSecretsService) updateIngressBasicAuth() {
   231  	password := s.Flags.DefaultAdminPassword
   232  	parts := strings.Split(s.Secrets.IngressBasicAuth, ":")
   233  	username := parts[0]
   234  	s.ingressAuth = BasicAuth{
   235  		Username: username,
   236  		Password: password,
   237  	}
   238  }
   239  
   240  // JenkinsAuth returns the current basic auth credentials for Jenkins
   241  func (s *AdminSecretsService) JenkinsAuth() BasicAuth {
   242  	return BasicAuth{
   243  		Username: "admin",
   244  		Password: s.Secrets.Jenkins.JenkinsSecret.Password,
   245  	}
   246  }
   247  
   248  // IngressAuth returns the current basic auth credentials for Ingress
   249  func (s *AdminSecretsService) IngressAuth() BasicAuth {
   250  	return s.ingressAuth
   251  }
   252  
   253  // ChartMuseumAuth returns the current credentials for ChartMuseum
   254  func (s *AdminSecretsService) ChartMuseumAuth() BasicAuth {
   255  	return BasicAuth{
   256  		Username: s.Secrets.ChartMuseum.ChartMuseumEnv.ChartMuseumSecret.User,
   257  		Password: s.Secrets.ChartMuseum.ChartMuseumEnv.ChartMuseumSecret.Password,
   258  	}
   259  }
   260  
   261  // GrafanaAuth returns the current credentials for Grafana
   262  func (s *AdminSecretsService) GrafanaAuth() BasicAuth {
   263  	return BasicAuth{
   264  		Username: s.Secrets.Grafana.GrafanaSecret.User,
   265  		Password: s.Secrets.Grafana.GrafanaSecret.Password,
   266  	}
   267  }
   268  
   269  // NexusAuth returns the current credentials for Nexus
   270  func (s *AdminSecretsService) NexusAuth() BasicAuth {
   271  	return BasicAuth{
   272  		Username: "admin",
   273  		Password: s.Secrets.Nexus.DefaultAdminPassword,
   274  	}
   275  }