How to pull image from custom docker registry with golang? - go

Using docker sources how to pull image from custom registry? As a result of using such code
// Prepare auth registry for usage
func (app *App) PrepareRegistry() error {
app.AuthConfig = types.AuthConfig{
Username: Username,
Password: Password,
ServerAddress: DefaultServer,
}
resp, err := app.Client.RegistryLogin(context.Background(), app.AuthConfig)
if err != nil {
panic(err)
}
fmt.Println(resp.Status)
if resp.IdentityToken != "" {
app.AuthConfig.IdentityToken = resp.IdentityToken
}
app.AuthConfigEncoded, err = command.EncodeAuthToBase64(app.AuthConfig)
return err
}
func (app *App) ImagePull() error {
opts := types.ImagePullOptions{
All: true,
RegistryAuth: app.AuthConfigEncoded,
PrivilegeFunc: registryAuthentication(app.Name),
}
responseBody, err := app.Client.ImagePull(context.Background(), app.Name, opts)
defer responseBody.Close()
if err != nil {
return err
}
return nil
}
I am still getting the error
Login Succeeded
panic: Error response from daemon: Get https://registry-1.docker.io/v2/shalakhin/blender/tags/list: unauthorized: incorrect username or password
While ServerAddress is registry.gitlab.com, not registry-1.docker.io

Did you check identity token? That might cause an authentication problem.
A suggestion:
Docker client
This works fine, as I can see you did not specify the endpoint. I think you should add this info.

authConfig := types.AuthConfig{
Username: "username",
Password: "password",
}
encodedJSON, err := json.Marshal(authConfig)
if err != nil {
panic(err)
}
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
out, err := cli.ImagePull(ctx, "alpine", types.ImagePullOptions{RegistryAuth: authStr})
if err != nil {
panic(err)
}

Related

Upload image fails with error "dial tcp: lookup api.cloudinary.com: no such host"

I have been trying to upload to cloudinary via golang sdk. but sometimes it seems to fail after several requests (sometimes it works, other times it doesn't).
I run the app in localhost (windows) and without vpn.
error message:
"https://api.cloudinary.com/v1_1/dd6mdlpgj/auto/upload": dial tcp: lookup api.cloudinary.com: no such host
type cloudinaryStorageRepository struct {
cld *cloudinary.Cloudinary
}
func NewCloudinaryStorageRepository(cloudName string, apiKey string, apiSecret string) domain.StorageRepository {
cld, err := cloudinary.NewFromParams(cloudName, apiKey, apiSecret)
if err != nil {
panic(err)
}
return &cloudinaryStorageRepository{cld}
}
func (c *cloudinaryStorageRepository) Upload(ctx context.Context, storage *domain.Storage) (string, error) {
file, err := storage.File.Open()
defer func(file multipart.File) {
err := file.Close()
if err != nil {
logrus.Error(err)
}
}(file)
if err != nil {
logrus.Error(err)
return "", err
}
uploaded, err := c.cld.Upload.Upload(ctx, file, uploader.UploadParams{
Folder: storage.Folder,
PublicID: storage.Name,
})
if err != nil {
logrus.Error(err)
return "", err
}
return uploaded.SecureURL, nil
}
If I understand you correctly, you can try to reset your DNS on your computer or use another computer to run the code because it might be a misconfiguration of your local host.

Interact with a shell script running remotely via SSH

I am working an application written in golang,for which one of the capability will be to SSH into a device and execute a shell script there. With my current implementation,a normal script is getting executed.The problem lies in the execution of a script that requires user input: for e.g the script asks the user, can we proceed with the installation: and the user has to type in Y or N. This is the part where it is failing. Here is my implementation:
func main() {
cmdOutput,err := ExecuteScriptSSH()
if err != nil{
fmt.Printf("Error is %s",err)
}
fmt.Printf("Command Output is %s", cmdOutput)
}
func ExecuteScriptSSH() (string, error) {
script := "#!/bin/sh\n\n ls -l \n\n date"
params := make(map[string]interface{})
params["Username"] = "uname"
params["Password"] = "pwd"
params["IPAddress"] = "ip"
params["Port"] = "22"
connection := NewConnection(params)
client, err := connection.ConnectNonSecure()
if err != nil {
fmt.Printf("unable to Connect:%v ", err)
}
defer client.Close()
ss, err := client.NewSession()
if err != nil {
fmt.Printf("unable to create SSH session:%v ", err)
}
//Converting the Script to string to a shell script file by writing to it.
d1 := []byte(script)
err = os.WriteFile("/tmp/script.sh", d1, 0777)
if err != nil {
fmt.Printf("Error constructing Script file %v", err)
}
// opening the script file
scriptFile, err2 := os.OpenFile("/tmp/script.sh", os.O_RDWR|os.O_CREATE, 0777)
if err2 != nil {
fmt.Printf("Error opening Script file is %s", err)
}
cmdOutput := &bytes.Buffer{}
ss.Stdout = cmdOutput
ss.Stdin = scriptFile
interpreter := "sh"
err = ss.Run(interpreter)
if err != nil {
fmt.Printf("Error in Executing Script file %v", err.Error())
}
return cmdOutput.String(), err
}
type Params struct {
Username string
Password string
IPAddress string
Port string
}
func NewConnection(data map[string]interface{}) *Params {
var params Params
fmt.Printf("Data is %v",data)
err := mapstructure.Decode(data,&params)
if err != nil {
panic(err)
}
fmt.Printf("Mapped Connection details %v",params)
return &params
}
func (p *Params) ConnectNonSecure() (*ssh.Client, error){
config := &ssh.ClientConfig{
User: p.Username,
Auth: []ssh.AuthMethod{
ssh.Password(p.Password),
},
// Non-Production-only
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
fmt.Printf("Connection details %v",p)
// Connect to the remote server and perform a handshake
client, err := ssh.Dial("tcp", p.IPAddress+":"+p.Port, config)
if err != nil {
log.Fatalf("unable to connect to: %v %s", err,p.IPAddress)
}
return client, err
}
for simplicity sake I have added a very simple script,but actually the script is huge and requires user confirmation.Any idea on how to solve this issue?

Getting error "failed to send packet header: EOF" while uploading file to sftp server

I am facing an issue where in, whenever I try to upload a file to a remote sftp server, I get an error saying "failed to send packet header: EOF". This occurs when I try to perform the uploading step from my own hosted EC2 instance. While locally, everything works fine.
Sftp client is initiated as follow.
// Connect to server
var authMethods []ssh.AuthMethod
// Use password authentication if password provided
if pass != "" {
authMethods = append(authMethods, ssh.Password(pass))
}
config := ssh.ClientConfig{
User: user,
Auth: authMethods,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
conn, err := ssh.Dial("tcp", addr, &config)
if err != nil {
return nil, tearDown, errors.Wrap(err, fmt.Sprintf("failed to connect to %s", addr))
}
tearDown = func() {
_ = conn.Close()
}
// Create new SFTP client
sc, err := sftp.NewClient(conn)
if err != nil {
return nil, tearDown, errors.Wrap(err, "Unable to start SFTP subsystem")
}
tearDown = func() {
fmt.Println("defer is called. closing connection now .... ")
_ = conn.Close()
_ = sc.Close()
}
return sc, tearDown, nil
And instance of sc is attached to a struct and passed around the codebase
Function invoked while uploading file is as follow.
file, err := s.sc.OpenFile(remoteFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
defer func() {
if file == nil {
return
}
cErr := file.Close()
if cErr != nil {
fmt.Println(fmt.Sprintf("error while closing file %v", cErr))
}
}()
if err != nil {
fmt.Println(fmt.Sprintf("error while opening file %v", err))
return err
}
_, err = file.Write(data)
if err != nil {
fmt.Println(fmt.Sprintf("error while writing to file %v", err))
return err
}
return nil
Can someone guide me as in where is the error coming from?

SSH Handshake complains about missing host key

I'm trying to connect to a remote host and check if a file exist
At this stage I'm trying just to connect but I'm getting an error:
2017/08/01 18:16:39 unable to connect: ssh: handshake failed: ssh: required host key was nil
I've tried to find out if others had issues as mine but I just couldn't find.
I understand that I need to check the knowns_hosts somehow in the process but I just can't figure out how...
var hostKey ssh.PublicKey
// A public key may be used to authenticate against the remote
// server by using an unencrypted PEM-encoded private key file.
//
// If you have an encrypted private key, the crypto/x509 package
// can be used to decrypt it.
key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
if err != nil {
log.Fatalf("unable to read private key: %v", err)
}
// Create the Signer for this private key.
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
log.Fatalf("unable to parse private key: %v", err)
}
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Connect to the remote server and perform the SSH handshake.
client, err := ssh.Dial("tcp", "host.com:22", config)
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer client.Close()
}
I would suggest to use knownhosts subpackage
import knownhosts "golang.org/x/crypto/ssh/knownhosts"
...
hostKeyCallback, err := knownhosts.New("/Users/user/.ssh/known_hosts")
if err != nil {
log.Fatal(err)
}
...
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(signer),
},
HostKeyCallback: hostKeyCallback,
}
So that you avoid parsing known_hosts yourself...
hth,
Here what you are looking for:
func getHostKey(host string) (ssh.PublicKey, error) {
file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
if err != nil {
return nil, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
var hostKey ssh.PublicKey
for scanner.Scan() {
fields := strings.Split(scanner.Text(), " ")
if len(fields) != 3 {
continue
}
if strings.Contains(fields[0], host) {
var err error
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
if err != nil {
return nil, errors.New(fmt.Sprintf("error parsing %q: %v", fields[2], err))
}
break
}
}
if hostKey == nil {
return nil, errors.New(fmt.Sprintf("no hostkey for %s", host))
}
return hostKey, nil
}
Then replace your hostKey definition line with
hostKey, err := getHostKey("host.com")
if err != nil {
log.Fatal(err)
}
For more information on the subject:
official sample where I took parts of the code from
why a hostKey is necessary now
EDIT:
Also check out Anton's answer below about the golang.org/x/crypto/ssh/knownhosts package.

How to connect to client in GCE in GO

I can't able to connect to client. Is there any way to pass private key id and private key to client for get authorized?
So, far i see:
ctx := context.Background()
client, err := google.DefaultClient(ctx, compute.ComputeScope)
if err != nil {
//...
}
computeService, err := compute.New(client)
if err != nil {
//...
}
Firstly, Need to create a credential for service account in GCE and it will download a json file and it will use for authorize the client.
Sample Code :
data, err := ioutil.ReadFile("downloadedfile.json")
if err != nil {
log.Fatal(err)
}
conf, err := google.JWTConfigFromJSON(data, compute.ComputeScope) // give the specific permission for this client.
if err != nil {
log.Fatal(err)
}
client = conf.Client(oauth2.NoContext)
computeService, err := compute.New(client)
if err != nil {
//...
}

Resources