Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
// 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
}