Azure在运行golang程序时出现get-credentials错误。

huangapple go评论106阅读模式
英文:

Azure get-credentials errors running in golang program

问题

我正在尝试使用以下脚本在Azure ACS Kubernetes中获取凭据:

#! /bin/sh
az login --service-principal --username=user -password=password --tenant=tenant
az acs kubernetes get-credentials --resource-group=rg --name=acs1 --file=/tmp/kubeconfig.json --ssh-key-file=private.key --output=json --debug --verbose

在Mac命令行上运行该脚本可以正常工作。但是,当我尝试运行一个调用相同脚本的golang程序"cmd := exec.Command("/bin/sh", "-c", scriptName)"时,我会收到以下错误:

No existing session
Traceback (most recent call last):
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/main.py", line 36, in main
    cmd_result = APPLICATION.execute(args)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/application.py", line 211, in execute
    result = expanded_arg.func(params)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 351, in __call__
    return self.handler(*args, **kwargs)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 555, in _execute_command
    reraise(*sys.exc_info())
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 532, in _execute_command
    result = op(client, **kwargs) if client else op(**kwargs)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/custom.py", line 785, in k8s_get_credentials
    _k8s_get_credentials_internal(name, acs_info, path, ssh_key_file)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/custom.py", line 806, in _k8s_get_credentials_internal
    '.kube/config', path_candidate, key_filename=ssh_key_file)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/acs_client.py", line 62, in secure_copy
    ssh.connect(host, username=user, pkey=pkey)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/paramiko/client.py", line 394, in connect
    look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/paramiko/client.py", line 649, in _auth
    raise saved_exception
SSHException: No existing session

有什么想法吗?

英文:

I am trying to azure acs kubernetes credentials with the following script:

#! /bin/sh
az login --service-principal --username=user -password=password --tenant=tenant
az acs kubernetes get-credentials --resource-group=rg --name=acs1 --file=/tmp/kubeconfig.json --ssh-key-file=private.key --output=json --debug --verbose

Running the script from command line on the mac works ok. When I try to run a golang program "cmd := exec.Command("/bin/sh", "-c", scriptName)" that calls the same script on the same computer I get the following error:

No existing session
Traceback (most recent call last):
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/main.py", line 36, in main
    cmd_result = APPLICATION.execute(args)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/application.py", line 211, in execute
    result = expanded_arg.func(params)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 351, in __call__
    return self.handler(*args, **kwargs)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 555, in _execute_command
    reraise(*sys.exc_info())
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 532, in _execute_command
    result = op(client, **kwargs) if client else op(**kwargs)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/custom.py", line 785, in k8s_get_credentials
    _k8s_get_credentials_internal(name, acs_info, path, ssh_key_file)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/custom.py", line 806, in _k8s_get_credentials_internal
    '.kube/config', path_candidate, key_filename=ssh_key_file)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/azure/cli/command_modules/acs/acs_client.py", line 62, in secure_copy
    ssh.connect(host, username=user, pkey=pkey)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/paramiko/client.py", line 394, in connect
    look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
  File "/Users/aarontorgerson/lib/azure-cli/lib/python2.7/site-packages/paramiko/client.py", line 649, in _auth
    raise saved_exception
SSHException: No existing session

Any ideas?

答案1

得分: 0

根据您的描述和错误信息SSHException: No existing session,看起来您正在使用os/exec调用您的shell脚本文件,但失败了,因为命令az需要在ssh会话中的.azure路径下使用类似azureProfile.json的东西。

所以我建议您尝试使用下面的代码,使用golang.org/x/crypto/ssh包来实现。

以下是我认为与MacOS上相同的Linux示例代码:

package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/crypto/ssh"
)

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
}

func main() {
	hostKey, err := getHostKey("localhost")
	if err != nil {
		log.Fatal(err)
	}
	config := &ssh.ClientConfig{
		User: "peter",
		Auth: []ssh.AuthMethod{
			ssh.Password("peter ssh password"),
		},
		HostKeyCallback: ssh.FixedHostKey(hostKey),
	}
	// Dial your ssh server.
	conn, err := ssh.Dial("tcp", "localhost:22", config)
	if err != nil {
		log.Fatal("unable to connect: ", err)
	}
	defer conn.Close()
	session, err := conn.NewSession()
	if err != nil {
		log.Fatal("Failed to create session: ", err)
	}
	defer session.Close()

	// Once a Session is created, you can execute a single command on
	// the remote side using the Run method.
	var b bytes.Buffer
	session.Stdout = &b
	if err := session.Run("./test.sh"); err != nil {
		log.Fatal("Failed to run: " + err.Error())
	}
	fmt.Println(b.String())
}

注意:在您的.ssh/known_hosts文件中,必须有像下面的内容一样的记录,针对localhost。如果没有,请先通过ssh登录以生成它,并将主机更改为localhost

|localhost|qx8q1geNHGyRFp8Ttu+m2xY4OpU=|noyfrjpDRvtIzP2gzWEV77VZULo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKXlyt/EFLnqwlNDimn73+wZVgCh3dhXi2YMWN6tHUj5LMirrUt0AtmQQVHex2b2ur79L5P6/L2J28NID569qAA=

希望对您有所帮助。

英文:

According to your description and the error information SSHException: No existing session, it sounds like you were using os/exec for calling your shell script file, but failed because command az needs to use something like azureProfile.json at the path .azure within a ssh session.

So I suggested you can try to use the code below with golang.org/x/crypto/ssh package to do it.

Here is my sample code for Linux which I think the same as on MacOS.

package main
import (
"bufio"
"bytes"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"golang.org/x/crypto/ssh"
)
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
}
func main() {
hostKey, err := getHostKey("localhost")
if err != nil {
log.Fatal(err)
}
config := &ssh.ClientConfig{
User: "peter",
Auth: []ssh.AuthMethod{
ssh.Password("peter ssh password"),
},
HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Dial your ssh server.
conn, err := ssh.Dial("tcp", "localhost:22", config)
if err != nil {
log.Fatal("unable to connect: ", err)
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
log.Fatal("Failed to create session: ", err)
}
defer session.Close()
// Once a Session is created, you can execute a single command on
// the remote side using the Run method.
var b bytes.Buffer
session.Stdout = &b
if err := session.Run("./test.sh"); err != nil {
log.Fatal("Failed to run: " + err.Error())
}
fmt.Println(b.String())
}

Notes: There must be a record like the content below for localhost in your .ssh/known_hosts file. If not, you can first login via ssh to generate it and change the host with localhost.

> |localhost|qx8q1geNHGyRFp8Ttu+m2xY4OpU=|noyfrjpDRvtIzP2gzWEV77VZULo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKXlyt/EFLnqwlNDimn73+wZVgCh3dhXi2YMWN6tHUj5LMirrUt0AtmQQVHex2b2ur79L5P6/L2J28NID569qAA=

Hope it helps.

huangapple
  • 本文由 发表于 2017年8月22日 06:26:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/45806377.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定