Ejemplo n.º 1
0
// Retrieves OTP from user and validates it with Vault server. Also, if -verify
// option is chosen, a echo request message is sent to Vault instead of OTP. If
// a proper echo message is responded, the verification will be successful.
func Run(args []string) error {
	for _, arg := range args {
		if arg == "-v" || arg == "-version" || arg == "--version" {
			fmt.Println(formattedVersion())
			return nil
		}
	}

	var configFilePath string
	var verify bool
	flags := flag.NewFlagSet("ssh-helper", flag.ContinueOnError)
	flags.StringVar(&configFilePath, "config-file", "", "")
	flags.BoolVar(&verify, "verify", false, "")

	flags.Usage = func() {
		fmt.Printf("%s\n", Help())
		os.Exit(0)
	}

	if err := flags.Parse(args); err != nil {
		return err
	}

	args = flags.Args()

	if configFilePath == "" {
		return fmt.Errorf("missing config-file")
	}

	// Load the configuration for this helper
	config, err := api.LoadSSHAgentConfig(configFilePath)
	if err != nil {
		return err
	}

	// Get an http client to interact with Vault server based on the configuration
	client, err := config.NewClient()
	if err != nil {
		return err
	}

	// Logging SSH mount point since SSH backend mount point at Vault server
	// can vary and helper has no way of knowing it automatically. Agent reads
	// the mount point from the configuration file and uses the same to talk
	// to Vault. In case of errors, this can be used for debugging.
	//
	// If mount point is not mentioned in the config file, default mount point
	// of the SSH backend will be used.
	log.Printf("[INFO] Using SSH Mount point: %s", config.SSHMountPoint)
	var otp string
	if verify {
		otp = api.VerifyEchoRequest
	} else {
		// Reading the one-time-password from the prompt. This is enabled
		// by supplying 'expose_authtok' option to pam module config.
		otpBytes, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			return err
		}

		// Removing the terminator
		otp = strings.TrimSuffix(string(otpBytes), string('\x00'))
	}

	// If OTP is echo request, this will be a verify request. Otherwise, this
	// will be a OTP validation request.
	return helper.VerifyOTP(&helper.SSHVerifyRequest{
		Client:     client,
		MountPoint: config.SSHMountPoint,
		OTP:        otp,
		Config:     config,
	})
}
Ejemplo n.º 2
0
// Retrieves OTP from user and validates it with Vault server. Also, if -verify
// option is chosen, a echo request message is sent to Vault instead of OTP. If
// a proper echo message is responded, the verification will be successful.
func Run(args []string) error {
	for _, arg := range args {
		if arg == "version" || arg == "-v" || arg == "-version" || arg == "--version" {
			fmt.Println(formattedVersion())
			return nil
		}
	}

	var config string
	var dev, verifyOnly bool
	flags := flag.NewFlagSet("ssh-helper", flag.ContinueOnError)
	flags.StringVar(&config, "config", "", "")
	flags.BoolVar(&verifyOnly, "verify-only", false, "")
	flags.BoolVar(&dev, "dev", false, "")

	flags.Usage = func() {
		fmt.Printf("%s\n", Help())
		os.Exit(0)
	}

	if err := flags.Parse(args); err != nil {
		return err
	}

	args = flags.Args()

	if len(config) == 0 {
		return fmt.Errorf("at least one config path must be specified with -config")
	}

	// Load the configuration for this helper
	clientConfig, err := api.LoadSSHHelperConfig(config)
	if err != nil {
		return err
	}

	if dev {
		log.Printf("==> WARNING: Dev mode is enabled!")
		if strings.HasPrefix(strings.ToLower(clientConfig.VaultAddr), "https://") {
			return fmt.Errorf("unsupported scheme in 'dev' mode")
		}
		clientConfig.CACert = ""
		clientConfig.CAPath = ""
	} else if strings.HasPrefix(strings.ToLower(clientConfig.VaultAddr), "http://") {
		return fmt.Errorf("unsupported scheme. use 'dev' mode")
	}

	// Get an http client to interact with Vault server based on the configuration
	client, err := clientConfig.NewClient()
	if err != nil {
		return err
	}

	// Logging SSH mount point since SSH backend mount point at Vault server
	// can vary and helper has no way of knowing it automatically. ssh-helper reads
	// the mount point from the configuration file and uses the same to talk
	// to Vault. In case of errors, this can be used for debugging.
	//
	// If mount point is not mentioned in the config file, default mount point
	// of the SSH backend will be used.
	log.Printf("[INFO] using SSH mount point: %s", clientConfig.SSHMountPoint)
	var otp string
	if verifyOnly {
		otp = api.VerifyEchoRequest
	} else {
		// Reading the one-time-password from the prompt. This is enabled
		// by supplying 'expose_authtok' option to pam module config.
		otpBytes, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			return err
		}

		// Removing the terminator
		otp = strings.TrimSuffix(string(otpBytes), string('\x00'))
	}

	// If OTP is echo request, this will be a verify request. Otherwise, this
	// will be a OTP validation request.
	return helper.VerifyOTP(&helper.SSHVerifyRequest{
		Client:     client,
		MountPoint: clientConfig.SSHMountPoint,
		OTP:        otp,
		Config:     clientConfig,
	})
}