英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论