From f9f4fbd4d79aab17aad918ec42b1f9035f00d82d Mon Sep 17 00:00:00 2001 From: Emeline Gaulard Date: Thu, 29 Mar 2018 10:18:33 +0200 Subject: [PATCH] Use env variable to switch between prod and staging environment (#388) * add staging defaults * Use NERD_ENV env var to switch between prod and staging --- command/login.go | 12 +++++++++++- command/project_set.go | 31 ++----------------------------- nerd/conf/conf.go | 26 +++++++++++++++++++++++++- pkg/populator/oidc.go | 29 +++++++++++++++-------------- pkg/populator/populator.go | 4 ++-- 5 files changed, 55 insertions(+), 47 deletions(-) diff --git a/command/login.go b/command/login.go index c3de66c28..7baf17f23 100644 --- a/command/login.go +++ b/command/login.go @@ -5,12 +5,14 @@ import ( "math/rand" "net/http" "net/url" + "os" "time" "github.com/mitchellh/cli" v1auth "github.com/nerdalize/nerd/nerd/client/auth/v1" "github.com/nerdalize/nerd/nerd/conf" "github.com/nerdalize/nerd/nerd/oauth" + "github.com/nerdalize/nerd/pkg/populator" "github.com/pkg/errors" "github.com/skratchdot/open-golang/open" ) @@ -49,6 +51,9 @@ func LoginFactory() (cli.Command, error) { //DoRun is called by run and allows an error to be returned func (cmd *Login) DoRun(args []string) error { + if os.Getenv("NERD_ENV") == "staging" { + cmd.config = conf.StagingDefaults() + } authbase, err := url.Parse(cmd.config.Auth.APIEndpoint) if err != nil { return HandleError(errors.Wrapf(err, "auth endpoint '%v' is not a valid URL", cmd.config.Auth.APIEndpoint)) @@ -101,9 +106,14 @@ func (cmd *Login) DoRun(args []string) error { return nil } var projectSlug string + c := populator.Client{ + Secret: cmd.config.Auth.SecureClientSecret, + ID: cmd.config.Auth.SecureClientID, + IDPIssuerURL: cmd.config.Auth.IDPIssuerURL, + } for _, project := range list.Projects { projectSlug = project.Nk - err = setProject(cmd.opts.KubeConfig, cmd.opts.Config, project, cmd.outputter.Logger) + err = setProject(&c, cmd.opts.KubeConfig, cmd.opts.Config, project, cmd.outputter.Logger) if err != nil { projectSlug = "" continue diff --git a/command/project_set.go b/command/project_set.go index e41f08804..61cde1fe8 100644 --- a/command/project_set.go +++ b/command/project_set.go @@ -2,18 +2,15 @@ package command import ( "log" - "net/url" "os" "path/filepath" "github.com/mitchellh/cli" homedir "github.com/mitchellh/go-homedir" "github.com/nerdalize/nerd/cmd" - "github.com/nerdalize/nerd/nerd/client/auth/v1" v1payload "github.com/nerdalize/nerd/nerd/client/auth/v1/payload" "github.com/nerdalize/nerd/nerd/conf" - "github.com/nerdalize/nerd/nerd/oauth" "github.com/nerdalize/nerd/pkg/populator" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -56,30 +53,6 @@ func (cmd *ProjectSet) DoRun(args []string) (err error) { } projectSlug := args[0] - authbase, err := url.Parse(cmd.config.Auth.APIEndpoint) - if err != nil { - return errors.Wrapf(err, "auth endpoint '%v' is not a valid URL", cmd.config.Auth.APIEndpoint) - } - authOpsClient := v1auth.NewOpsClient(v1auth.OpsClientConfig{ - Base: authbase, - Logger: cmd.outputter.Logger, - }) - client := v1auth.NewClient(v1auth.ClientConfig{ - Base: authbase, - Logger: cmd.outputter.Logger, - OAuthTokenProvider: oauth.NewConfigProvider(authOpsClient, cmd.config.Auth.SecureClientID, cmd.config.Auth.SecureClientSecret, cmd.session), - }) - - project, err := client.GetProject(projectSlug) - if err != nil { - return HandleError(errors.Wrap(err, "Project not found, please check the project name. You can get a list of your projects by running `nerd project list`.")) - } - - err = setProject(cmd.opts.KubeConfig, cmd.opts.Config, project, cmd.outputter.Logger) - if err != nil { - return HandleError(err) - } - err = cmd.session.WriteProject(projectSlug, conf.DefaultAWSRegion) if err != nil { return HandleError(err) @@ -89,7 +62,7 @@ func (cmd *ProjectSet) DoRun(args []string) (err error) { return nil } -func setProject(kubeConfig, conf string, project *v1payload.GetProjectOutput, logger *log.Logger) error { +func setProject(c *populator.Client, kubeConfig, conf string, project *v1payload.GetProjectOutput, logger *log.Logger) error { var ( hdir string err error @@ -101,7 +74,7 @@ func setProject(kubeConfig, conf string, project *v1payload.GetProjectOutput, lo if kubeConfig == "" { kubeConfig = filepath.Join(hdir, ".kube", "config") } - p, err := populator.New(conf, kubeConfig, hdir, project) + p, err := populator.New(c, conf, kubeConfig, hdir, project) if err != nil { return err } diff --git a/nerd/conf/conf.go b/nerd/conf/conf.go index c379fd296..b65ea80af 100644 --- a/nerd/conf/conf.go +++ b/nerd/conf/conf.go @@ -29,6 +29,7 @@ type AuthConfig struct { SecureClientSecret string `json:"secure_client_secret"` OAuthSuccessURL string `json:"oauth_success_url"` OAuthLocalServer string `json:"oauth_localserver"` + IDPIssuerURL string `json:"idp_issuer_url"` } //LoggingConfig contains config details about local logging of command output @@ -37,6 +38,29 @@ type LoggingConfig struct { FileLocation string `json:"file_location"` } +//StagingDefaults provides the default for the staging environment when the config file misses certain fields. +func StagingDefaults() *Config { + return &Config{ + Auth: AuthConfig{ + APIEndpoint: "https://auth.staging.nlze.nl/v1/", + OAuthLocalServer: "localhost:9876", + OAuthSuccessURL: "https://auth.staging.nlze.nl/do/login_complete/?client=CLI", + SecureClientID: "ckvyq40yyGSH", + SecureClientSecret: "0c4feb1e9d11790451a4364e803284a60905cef1a5f9bf7bad5f0eeb", + IDPIssuerURL: "https://auth.staging.nlze.nl", + PublicKey: `-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBthEmchVCtA3ZPXqiCXdj+7/ZFuhxRgx +grTxIHK+b0vEqKqA3O++ggD1GgjqtTfNLGUjLCE3KxyIN78TsK+HU4VVexTjlWXy +WPtidD68xGD0JVPU1cSfu8iP0XzwgttG +-----END PUBLIC KEY----- +`}, + Logging: LoggingConfig{ + Enabled: false, + FileLocation: "~/.nerd/log", + }, + } +} + //Defaults provides the default for when the config file misses certain fields. func Defaults() *Config { return &Config{ @@ -46,6 +70,7 @@ func Defaults() *Config { OAuthSuccessURL: "https://auth.nerdalize.com/do/login_complete/?client=CLI", SecureClientID: "T8I0H3qAeWGA", SecureClientSecret: "93177b0e77369537ceac900b26f0a9600484564fdda5d431b05e994b", + IDPIssuerURL: "https://auth.nerdalize.com", PublicKey: `-----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBthEmchVCtA3ZPXqiCXdj+7/ZFuhxRgx grTxIHK+b0vEqKqA3O++ggD1GgjqtTfNLGUjLCE3KxyIN78TsK+HU4VVexTjlWXy @@ -56,7 +81,6 @@ WPtidD68xGD0JVPU1cSfu8iP0XzwgttG Enabled: false, FileLocation: "~/.nerd/log", }, - NerdAPIEndpoint: "https://batch.nerdalize.com/v1", } } diff --git a/pkg/populator/oidc.go b/pkg/populator/oidc.go index 805f976ff..943e64c14 100644 --- a/pkg/populator/oidc.go +++ b/pkg/populator/oidc.go @@ -18,20 +18,19 @@ import ( ) const ( - // ClientSecret necessary for OpenID connect - ClientSecret = "93177b0e77369537ceac900b26f0a9600484564fdda5d431b05e994b" - // ClientID is a client id that all tokens must be issued for. - ClientID = "T8I0H3qAeWGA" - // IDPIssuerURL is the URL of the provider which allows the API server to discover public signing keys. - IDPIssuerURL = "https://auth.nerdalize.com" // DirPermissions are the output directory's permissions. DirPermissions = 0755 ) -var ( - authEndpoint = fmt.Sprintf("%s/v1/o/authorize", IDPIssuerURL) - tokenEndpoint = fmt.Sprintf("%s/v1/o/token", IDPIssuerURL) -) +// Client provides necessary information to successfully use OIDC +type Client struct { + // Secret necessary for OpenID connect + Secret string + // ID is a client id that all tokens must be issued for. + ID string + // IDPIssuerURL is the URL of the provider which allows the API server to discover public signing keys. + IDPIssuerURL string +} //OIDCPopulator is an implementation of the P interface using on Open ID Connect credentials. type OIDCPopulator struct { @@ -41,12 +40,14 @@ type OIDCPopulator struct { project *v1payload.GetProjectOutput homedir string + client *Client } -func newOIDC(kubeConfigFile, homedir string, project *v1payload.GetProjectOutput) *OIDCPopulator { +func newOIDC(c *Client, kubeConfigFile, homedir string, project *v1payload.GetProjectOutput) *OIDCPopulator { o := &OIDCPopulator{ project: project, homedir: homedir, + client: c, } o.kubeConfigFile.Store(kubeConfigFile) return o @@ -107,10 +108,10 @@ func (o *OIDCPopulator) PopulateKubeConfig(project string) error { auth.AuthProvider = &api.AuthProviderConfig{ Name: "oidc", Config: map[string]string{ - "client-id": ClientID, - "client-secret": ClientSecret, + "client-id": o.client.ID, + "client-secret": o.client.Secret, "id-token": config.OAuth.IDToken, - "idp-issuer-url": IDPIssuerURL, + "idp-issuer-url": o.client.IDPIssuerURL, "refresh-token": config.OAuth.RefreshToken, }, } diff --git a/pkg/populator/populator.go b/pkg/populator/populator.go index fee25d488..3e231d217 100644 --- a/pkg/populator/populator.go +++ b/pkg/populator/populator.go @@ -26,10 +26,10 @@ type P interface { } //New instantiates a new P interface using the conf parameter. It can return a env, endpoint or oidc populator. -func New(conf, kubeConfigFile, homedir string, project *v1payload.GetProjectOutput) (P, error) { +func New(c *Client, conf, kubeConfigFile, homedir string, project *v1payload.GetProjectOutput) (P, error) { switch conf { case "oidc": - return newOIDC(kubeConfigFile, homedir, project), nil + return newOIDC(c, kubeConfigFile, homedir, project), nil case "endpoint": return newEndpoint(kubeConfigFile), nil case "env":