func (c *BasicChallengeHandler) HandleChallenge(requestURL string, headers http.Header) (http.Header, bool, error) { if c.prompted { glog.V(2).Info("already prompted for challenge, won't prompt again") return nil, false, nil } if c.handled { glog.V(2).Info("already handled basic challenge") return nil, false, nil } username := c.Username password := c.Password missingUsername := len(username) == 0 missingPassword := len(password) == 0 if (missingUsername || missingPassword) && c.Reader != nil { w := c.Writer if w == nil { w = os.Stdout } if _, realm := basicRealm(headers); len(realm) > 0 { fmt.Fprintf(w, "Authentication required for %s (%s)\n", c.Host, realm) } else { fmt.Fprintf(w, "Authentication required for %s\n", c.Host) } if missingUsername { username = util.PromptForString(c.Reader, w, "Username: "******"Username: %s\n", username) } if missingPassword { password = util.PromptForPasswordString(c.Reader, w, "Password: "******":") { return nil, false, fmt.Errorf("username %s is invalid for basic auth", username) } responseHeaders := http.Header{} responseHeaders.Set("Authorization", getBasicHeader(username, password)) // remember so we don't re-handle non-interactively c.handled = true return responseHeaders, true, nil } glog.V(2).Info("no username or password available") return nil, false, nil }
func (c *BasicChallengeHandler) HandleChallenge(headers http.Header) (http.Header, bool, error) { if c.prompted { glog.V(2).Info("already prompted for challenge, won't prompt again") return nil, false, nil } if c.Reader == nil && c.handled { glog.V(2).Info("already handled basic challenge, no reader to alter inputs") return nil, false, nil } username := c.Username password := c.Password missingUsername := len(username) == 0 missingPassword := len(password) == 0 if (missingUsername || missingPassword) && c.Reader != nil { w := c.Writer if w == nil { w = os.Stdout } if _, realm := basicRealm(headers); len(realm) > 0 { fmt.Fprintf(w, "Authentication required for %s (%s)\n", c.Host, realm) } else { fmt.Fprintf(w, "Authentication required for %s\n", c.Host) } if missingUsername { username = util.PromptForString(c.Reader, w, "Username: "******"Username: %s\n", username) } if missingPassword { password = util.PromptForPasswordString(c.Reader, w, "Password: "******"Authorization", getBasicHeader(username, password)) // remember so we don't re-handle non-interactively c.handled = true return responseHeaders, true, nil } glog.V(2).Info("no username or password available") return nil, false, nil }
// Do watches for unauthorized challenges. If we know to respond, we respond to the challenge func (client *challengingClient) Do(req *http.Request) (*http.Response, error) { // Set custom header required by server to avoid CSRF attacks on browsers using basic auth if req.Header == nil { req.Header = http.Header{} } req.Header.Set(CSRFTokenHeader, "1") resp, err := client.delegate.Do(req) if err != nil { return nil, err } if resp.StatusCode == http.StatusUnauthorized { if wantsBasicAuth, realm := isBasicAuthChallenge(resp); wantsBasicAuth { username := client.defaultUsername password := client.defaultPassword missingUsername := len(username) == 0 missingPassword := len(password) == 0 url := *req.URL url.Path, url.RawQuery, url.Fragment = "", "", "" if (missingUsername || missingPassword) && client.reader != nil { fmt.Printf("Authentication required for %s (%s)\n", &url, realm) if missingUsername { username = util.PromptForString(client.reader, "Username: "******"Password: ") } } if len(username) > 0 || len(password) > 0 { client.delegate.Transport = kclient.NewBasicAuthRoundTripper(username, password, client.delegate.Transport) return client.delegate.Do(resp.Request) } } } return resp, err }
func (o *EncryptOptions) Encrypt() error { // Get data var data []byte var warnWhitespace = true switch { case len(o.CleartextFile) > 0: if d, err := ioutil.ReadFile(o.CleartextFile); err != nil { return err } else { data = d } case len(o.CleartextData) > 0: // Don't warn in cases where we're explicitly being given the data to use warnWhitespace = false data = o.CleartextData case o.CleartextReader != nil && util.IsTerminalReader(o.CleartextReader) && o.PromptWriter != nil: // Read a single line from stdin with prompting data = []byte(util.PromptForString(o.CleartextReader, o.PromptWriter, "Data to encrypt: ")) case o.CleartextReader != nil: // Read data from stdin without prompting (allows binary data and piping) if d, err := ioutil.ReadAll(o.CleartextReader); err != nil { return err } else { data = d } } if warnWhitespace && (o.PromptWriter != nil) && (len(data) > 0) { r1, _ := utf8.DecodeRune(data) r2, _ := utf8.DecodeLastRune(data) if unicode.IsSpace(r1) || unicode.IsSpace(r2) { fmt.Fprintln(o.PromptWriter, "Warning: Data includes leading or trailing whitespace, which will be included in the encrypted value") } } // Get key var key []byte switch { case len(o.KeyFile) > 0: if block, ok, err := pemutil.BlockFromFile(o.KeyFile, configapi.StringSourceKeyBlockType); err != nil { return err } else if !ok { return fmt.Errorf("%s does not contain a valid PEM block of type %q", o.KeyFile, configapi.StringSourceKeyBlockType) } else if len(block.Bytes) == 0 { return fmt.Errorf("%s does not contain a key", o.KeyFile) } else { key = block.Bytes } case len(o.GenKeyFile) > 0: key = make([]byte, 32) if _, err := rand.Read(key); err != nil { return err } } if len(key) == 0 { return errors.New("--genkey or --key is required") } // Encrypt dataBlock, err := x509.EncryptPEMBlock(rand.Reader, configapi.StringSourceEncryptedBlockType, data, key, x509.PEMCipherAES256) if err != nil { return err } // Write data if len(o.EncryptedFile) > 0 { if err := pemutil.BlockToFile(o.EncryptedFile, dataBlock, os.FileMode(0644)); err != nil { return err } } else if o.EncryptedWriter != nil { encryptedBytes, err := pemutil.BlockToBytes(dataBlock) if err != nil { return err } n, err := o.EncryptedWriter.Write(encryptedBytes) if err != nil { return err } if n != len(encryptedBytes) { return fmt.Errorf("could not completely write encrypted data") } } // Write key if len(o.GenKeyFile) > 0 { keyBlock := &pem.Block{Bytes: key, Type: configapi.StringSourceKeyBlockType} if err := pemutil.BlockToFile(o.GenKeyFile, keyBlock, os.FileMode(0600)); err != nil { return err } } return nil }
// Negotiate a bearer token with the auth server, or try to reuse one based on the // information already present. In case of any missing information, ask for user input // (usually username and password, interactive depending on the Reader). func (o *LoginOptions) gatherAuthInfo() error { directClientConfig, err := o.getClientConfig() if err != nil { return err } // make a copy and use it to avoid mutating the original t := *directClientConfig clientConfig := &t // if a token were explicitly provided, try to use it if o.tokenProvided() { clientConfig.BearerToken = o.Token if osClient, err := client.New(clientConfig); err == nil { me, err := whoAmI(osClient) if err == nil { o.Username = me.Name o.Config = clientConfig fmt.Fprintf(o.Out, "Logged into %q as %q using the token provided.\n\n", o.Config.Host, o.Username) return nil } if !kerrors.IsUnauthorized(err) { return err } fmt.Fprintln(o.Out, "The token provided is invalid (probably expired).\n") } } // if a token was provided try to make use of it // make sure we have a username before continuing if !o.usernameProvided() { if cmdutil.IsTerminal(o.Reader) { for !o.usernameProvided() { o.Username = cmdutil.PromptForString(o.Reader, "Username: "******"Already logged into %q as %q.\n\n", o.Config.Host, o.Username) } return nil } } } } } // if kubeconfig doesn't already have a matching user stanza... clientConfig.BearerToken = "" clientConfig.CertData = []byte{} clientConfig.KeyData = []byte{} clientConfig.CertFile = o.CertFile clientConfig.KeyFile = o.KeyFile token, err := tokencmd.RequestToken(o.Config, o.Reader, o.Username, o.Password) if err != nil { return err } clientConfig.BearerToken = token osClient, err := client.New(clientConfig) if err != nil { return err } me, err := whoAmI(osClient) if err != nil { return err } o.Username = me.Name o.Config = clientConfig fmt.Fprintln(o.Out, "Login successful.\n") return nil }