From 23c5f13fa8cdc27ee0b3996d2bcb5e22ada5b6cd Mon Sep 17 00:00:00 2001 From: TangBin Date: Tue, 18 Dec 2018 12:26:30 +0800 Subject: [PATCH] keypair bugfix --- pkg/util/aws/image.go | 2 +- pkg/util/aws/instance.go | 4 +-- pkg/util/aws/keypair.go | 68 ++++++++++++++++++++++++++++++++--- pkg/util/aws/keypair_test.go | 30 ++++++++++++++++ pkg/util/aws/securitygroup.go | 3 -- 5 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 pkg/util/aws/keypair_test.go diff --git a/pkg/util/aws/image.go b/pkg/util/aws/image.go index 1d5736a486..416475687c 100644 --- a/pkg/util/aws/image.go +++ b/pkg/util/aws/image.go @@ -201,7 +201,7 @@ func (self *SRegion) GetImageByName(name string) (*SImage, error) { return nil, cloudprovider.ErrNotFound } - log.Debugf("%d image found match name %", len(images), name) + log.Debugf("%d image found match name %s", len(images), name) return &images[0], nil } diff --git a/pkg/util/aws/instance.go b/pkg/util/aws/instance.go index e4ec7a381f..6e7179b2c4 100644 --- a/pkg/util/aws/instance.go +++ b/pkg/util/aws/instance.go @@ -669,7 +669,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st if len(res.Instances) == 1 { return *res.Instances[0].InstanceId, nil } else { - msg := fmt.Sprintf("CreateInstance fail: %s instance created. ", len(res.Instances)) + msg := fmt.Sprintf("CreateInstance fail: %d instance created. ", len(res.Instances)) log.Errorf(msg) return "", fmt.Errorf(msg) } @@ -810,7 +810,7 @@ func (self *SRegion) ReplaceSystemDisk(ctx context.Context, instanceId string, i if rootDisk == nil { return "", fmt.Errorf("can not find root disk of instance %s", instanceId) } - log.Debugf("ReplaceSystemDisk replace root disk %s", rootDisk) + log.Debugf("ReplaceSystemDisk replace root disk %s", rootDisk.DiskId) image, err := self.GetImage(imageId) if err != nil { diff --git a/pkg/util/aws/keypair.go b/pkg/util/aws/keypair.go index 762892aa2b..f42fc1e71d 100644 --- a/pkg/util/aws/keypair.go +++ b/pkg/util/aws/keypair.go @@ -1,6 +1,10 @@ package aws import ( + "bytes" + "crypto/md5" + "crypto/rsa" + "crypto/x509" "fmt" "strconv" "time" @@ -17,8 +21,61 @@ type SKeypair struct { KeyPairName string } +// 只支持计算Openssh ras 格式公钥转换成DER格式后的MD5。 +func md5Fingerprint(publickey string) (string, error) { + pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publickey)) + if err != nil { + return "", fmt.Errorf("publicKey error %s", err) + } + + der := []byte{} + cryptoPub, ok := pk.(ssh.CryptoPublicKey) + if !ok { + return "", fmt.Errorf("public key trans to crypto public key failed") + } + + switch pk.Type() { + case ssh.KeyAlgoRSA: + rsaPK, ok := cryptoPub.CryptoPublicKey().(*rsa.PublicKey) + if !ok { + return "", fmt.Errorf("crypto public key trans to ras publickey failed") + } + der, err = x509.MarshalPKIXPublicKey(rsaPK) + if err != nil { + return "", fmt.Errorf("MarshalPKIXPublicKey ras publickey failed") + } + default: + return "", fmt.Errorf("unsupport public key format.Only ssh-rsa supported") + } + + var ret bytes.Buffer + fp := md5.Sum(der) + for i, b := range fp { + ret.WriteString(fmt.Sprintf("%02x", b)) + if i < len(fp)-1 { + ret.WriteString(":") + } + } + + return ret.String(), nil +} + func (self *SRegion) GetKeypairs(finger string, name string, offset int, limit int) ([]SKeypair, int, error) { - ret, err := self.ec2Client.DescribeKeyPairs(&ec2.DescribeKeyPairsInput{}) + params := &ec2.DescribeKeyPairsInput{} + filters := []*ec2.Filter{} + if len(finger) > 0 { + filters = AppendSingleValueFilter(filters, "fingerprint", finger) + } + + if len(name) > 0 { + params.SetKeyNames([]*string{&name}) + } + + if len(filters) > 0 { + params.SetFilters(filters) + } + + ret, err := self.ec2Client.DescribeKeyPairs(params) if err != nil { return nil, 0, err } @@ -35,6 +92,7 @@ func (self *SRegion) GetKeypairs(finger string, name string, offset int, limit i return keypairs, len(keypairs), nil } +// Aws貌似不支持ssh-dss格式密钥 func (self *SRegion) ImportKeypair(name string, pubKey string) (*SKeypair, error) { params := &ec2.ImportKeyPairInput{} params.SetKeyName(name) @@ -56,13 +114,13 @@ func (self *SRegion) DetachKeyPair(instanceId string, keypairName string) error } func (self *SRegion) lookUpAwsKeypair(publicKey string) (string, error) { - pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey)) + // https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/ec2-key-pairs.html + fingerprint, err := md5Fingerprint(publicKey) if err != nil { - return "", fmt.Errorf("publicKey error %s", err) + return "", err } - fingerprint := ssh.FingerprintLegacyMD5(pk) - ks, total, err := self.GetKeypairs(fingerprint, "*", 0, 1) + ks, total, err := self.GetKeypairs(fingerprint, "", 0, 1) if total < 1 { return "", fmt.Errorf("keypair not found %s", err) } else { diff --git a/pkg/util/aws/keypair_test.go b/pkg/util/aws/keypair_test.go new file mode 100644 index 0000000000..52477768f5 --- /dev/null +++ b/pkg/util/aws/keypair_test.go @@ -0,0 +1,30 @@ +package aws + +import "testing" + +type testPublicKey struct { + publickey string + fingerprint string +} + +func TestMd5Fingerprint(t *testing.T) { + rsa := testPublicKey{ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCBBuv9nsAGNpKVulxNc7zHXEEyiTqYU8J6sTfmB9lmrRea/RO/pUJg1ZGlHKLSbZ5h+d4mquASf8K3s3SQtz/4sBHroRijanO16i0Rk6t5kwcIRzaf11NiImImKgwNiCwZyiK2egAfsjDVEi8H+kSRA0N0PMxRfwOEZ/hNtVaNV7/MwkXylOuWUikGvPpm3sRmelfQoS3Hf055WM1m6POgddbjucq9bjQDW1O4dfDkWuX+385EOtfCBPtfeiAcOBBd+qEjmdfxroQwxHXLkZH7rdoS9jss3fi9P/K0ZpBKswKsed2sxKo9NNYfTDN19Kv8NBOW8W7MxN1po/2gvbd/", + "4c:ae:76:94:fb:59:66:8c:a6:07:e2:54:2f:14:19:c5", + } + + testKeys := []testPublicKey{rsa} + + for _, k := range testKeys { + fingerprint, err := md5Fingerprint(k.publickey) + if err != nil { + t.Errorf(err.Error()) + continue + } + + if fingerprint != k.fingerprint { + t.Errorf("ssh-rsa fingerprint is not as expected.%s != %s", fingerprint, k.fingerprint) + continue + } + } +} diff --git a/pkg/util/aws/securitygroup.go b/pkg/util/aws/securitygroup.go index 22ce526821..0fa1a30941 100644 --- a/pkg/util/aws/securitygroup.go +++ b/pkg/util/aws/securitygroup.go @@ -345,9 +345,6 @@ func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.Secur sort.Sort(secrules.SecurityRuleSet(rules)) sort.Sort(secrules.SecurityRuleSet(secgroup.Permissions)) - log.Debugf("local security rules %s", rules) - log.Debugf("remote security rules %s", secgroup.Permissions) - i, j := 0, 0 for i < len(rules) || j < len(secgroup.Permissions) { if i < len(rules) && j < len(secgroup.Permissions) {