I am searching for a way to answer to a shell password prompt in golang.
like :
bussiere@kus:~/Workspace/rteest$ ./passwordtest.sh
Password :
I would like to enter the password automatically with my token in golang after launching a shell command / script ...
I've made some script that get a one time token with mfa if everything is ok (in golang). So i need to enter the tempory token to a linux password prompt.
I know that there is the expect command but i would like to compile my program to embed it and have minimal depency.
Thanks and regards
edit thks to @nevermore i've tried this (but it doesn't work) : https://play.golang.org/p/Ffm3q5h636
package main
import (
"os/exec"
"fmt"
"log"
"io"
)
func main() {
cmdb := "git"
args := "clone https://[email protected]/bb/fzgs.git"
cmd := exec.Command(cmdb, args)
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
go func() {
defer stdin.Close()
io.WriteString(stdin, "QSRDFGHJfZERTYU")
}()
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
}
it gives me this :
2017/05/12 20:42:36 exit status 1
exit status 1
edit bis :
cmdb := "git"
args := "https://[email protected]/bb/fzgs.git"
cmd := exec.Command(cmdb, "clone", args)
it asks for the password :
Password for 'https://[email protected]':
The problem is that you are trying to send the password before Git asks you to do so.
And the way Git asks for password depends on whether credential helper is set. If the credential helper is not set, or doesn't return a password, the user is asked for input.
In most cases (at least with Github and Bitbucket) the Git server accepts
credentials passed via HTTPS URI, e.g. https://user:[email protected]/repo.git
.
cmd := exec.Command("git", "clone", "https://bb:[email protected]/bb/fzgs.git")
env := os.Environ()
env = append(env, "GIT_ASKPASS=")
cmd.Env = env
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
Another way is to make a credential helper script, e.g.:
#!/bin/bash -
printf '%s\n' 'YOUR_PASSWORD'
and pass it via GIT_ASKPASS
:
cmd := exec.Command("git", "clone", "https://[email protected]/bb/fzgs.git")
env := os.Environ()
env = append(env, "GIT_ASKPASS=/path/to/fzgs-askpass.sh")
cmd.Env = env
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
If a user is asked for a password in their shell, you can use golang to write to the io.Writer that is os.Stdin
Properly passing data on stdin to a command and receiving data from stdout of that command in golang
os.Stdin
is a os.File
created by
NewFile(uintptr(syscall.Stdin), "/dev/stdin")
And the password prompt will be reading from this file
You can execute ./passwordtest.sh
as in your question, and then write the password to os.Stdin
, and the bash script should accept the bytes written by golang as the password.
Alternatively is actually a method for this in the exec
package for the Cmd
type.
cmd.StdinPip()
cmd.CombinedOutput()
Cmd represents an external command being prepared or run.
https://golang.org/pkg/os/exec/#Cmd.StdinPipe
cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
go func() {
defer stdin.Close()
io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
}()
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
StdinPipe returns a pipe that will be connected to the command's standard input when the command starts. The pipe will be closed automatically after Wait sees the command exit. A caller need only call Close to force the pipe to close sooner. For example, if the command being run will not exit until standard input is closed, the caller must close the pipe.
Also, your cmd
arguments shouldn't combine clone and the url, try instead
cmd := exec.Command(cmdb, "clone", url)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With