metadata-service: fix ssh key retrieval and application

The metadata service wasn't properly fetching the ssh keys from metadata.
Drop the key traversal in favor of explict key urls.
This commit is contained in:
Alex Crawford 2014-06-30 16:23:46 -07:00
parent cb7fbd4668
commit 7fcc540154
2 changed files with 47 additions and 36 deletions

View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"strings" "strings"
"github.com/coreos/coreos-cloudinit/pkg" "github.com/coreos/coreos-cloudinit/pkg"
@ -23,7 +24,7 @@ const (
BaseUrl = "http://169.254.169.254/" BaseUrl = "http://169.254.169.254/"
Ec2ApiVersion = "2009-04-04" Ec2ApiVersion = "2009-04-04"
Ec2UserdataUrl = BaseUrl + Ec2ApiVersion + "/user-data" Ec2UserdataUrl = BaseUrl + Ec2ApiVersion + "/user-data"
Ec2MetadataUrl = BaseUrl + Ec2ApiVersion + "/meta-data/" Ec2MetadataUrl = BaseUrl + Ec2ApiVersion + "/meta-data"
OpenstackApiVersion = "openstack/2012-08-10" OpenstackApiVersion = "openstack/2012-08-10"
OpenstackUserdataUrl = BaseUrl + OpenstackApiVersion + "/user_data" OpenstackUserdataUrl = BaseUrl + OpenstackApiVersion + "/user_data"
OpenstackMetadataUrl = BaseUrl + OpenstackApiVersion + "/meta_data.json" OpenstackMetadataUrl = BaseUrl + OpenstackApiVersion + "/meta_data.json"
@ -78,10 +79,45 @@ func fetchMetadata(client getter) ([]byte, error) {
return nil, err return nil, err
} }
attrs, err := fetchChildAttributes(client, Ec2MetadataUrl) attrs := make(map[string]interface{})
if err != nil { if keynames, err := fetchAttributes(client, fmt.Sprintf("%s/public-keys", Ec2MetadataUrl)); err == nil {
keyIDs := make(map[string]string)
for _, keyname := range keynames {
tokens := strings.SplitN(keyname, "=", 2)
if len(tokens) != 2 {
return nil, fmt.Errorf("malformed public key: %q\n", keyname)
}
keyIDs[tokens[1]] = tokens[0]
}
keys := make(map[string]string)
for name, id := range keyIDs {
sshkey, err := fetchAttribute(client, fmt.Sprintf("%s/public-keys/%s/openssh-key", Ec2MetadataUrl, id))
if err != nil {
return nil, err
}
keys[name] = sshkey
fmt.Printf("Found SSH key for %q\n", name)
}
attrs["public_keys"] = keys
} else if _, ok := err.(pkg.ErrNotFound); !ok {
return nil, err return nil, err
} }
if hostname, err := fetchAttribute(client, fmt.Sprintf("%s/hostname", Ec2MetadataUrl)); err == nil {
attrs["hostname"] = hostname
} else if _, ok := err.(pkg.ErrNotFound); !ok {
return nil, err
}
if content_path, err := fetchAttribute(client, fmt.Sprintf("%s/network_config/content_path", Ec2MetadataUrl)); err == nil {
attrs["network_config"] = map[string]string{
"content_path": content_path,
}
} else if _, ok := err.(pkg.ErrNotFound); !ok {
return nil, err
}
return json.Marshal(attrs) return json.Marshal(attrs)
} }
@ -93,37 +129,15 @@ func fetchAttributes(client getter, url string) ([]string, error) {
scanner := bufio.NewScanner(bytes.NewBuffer(resp)) scanner := bufio.NewScanner(bytes.NewBuffer(resp))
data := make([]string, 0) data := make([]string, 0)
for scanner.Scan() { for scanner.Scan() {
data = append(data, strings.Split(scanner.Text(), "=")[0]) data = append(data, scanner.Text())
} }
return data, scanner.Err() return data, scanner.Err()
} }
func fetchAttribute(client getter, url string) (interface{}, error) { func fetchAttribute(client getter, url string) (string, error) {
if attrs, err := fetchAttributes(client, url); err == nil && len(attrs) > 0 { if attrs, err := fetchAttributes(client, url); err == nil && len(attrs) > 0 {
return attrs[0], nil return attrs[0], nil
} else { } else {
return "", err return "", err
} }
} }
func fetchChildAttributes(client getter, url string) (interface{}, error) {
attrs := make(map[string]interface{})
attrList, err := fetchAttributes(client, url)
if err != nil {
return nil, err
}
for _, attr := range attrList {
var fetchFunc func(getter, string) (interface{}, error)
if strings.HasSuffix(attr, "/") {
fetchFunc = fetchChildAttributes
} else {
fetchFunc = fetchAttribute
}
if value, err := fetchFunc(client, url+attr); err == nil {
attrs[strings.TrimSuffix(attr, "/")] = value
} else {
return nil, err
}
}
return attrs, nil
}

View File

@ -137,15 +137,13 @@ func TestFetchMetadata(t *testing.T) {
}{ }{
{ {
metadata: map[string]string{ metadata: map[string]string{
"http://169.254.169.254/2009-04-04/meta-data/": "a\nb\nc/", "http://169.254.169.254/2009-04-04/meta-data/hostname": "host",
"http://169.254.169.254/2009-04-04/meta-data/c/": "d\ne/", "http://169.254.169.254/2009-04-04/meta-data/public-keys": "0=test1\n",
"http://169.254.169.254/2009-04-04/meta-data/c/e/": "f", "http://169.254.169.254/2009-04-04/meta-data/public-keys/0": "openssh-key",
"http://169.254.169.254/2009-04-04/meta-data/a": "1", "http://169.254.169.254/2009-04-04/meta-data/public-keys/0/openssh-key": "key",
"http://169.254.169.254/2009-04-04/meta-data/b": "2", "http://169.254.169.254/2009-04-04/meta-data/network_config/content_path": "path",
"http://169.254.169.254/2009-04-04/meta-data/c/d": "3",
"http://169.254.169.254/2009-04-04/meta-data/c/e/f": "4",
}, },
expect: []byte(`{"a":"1","b":"2","c":{"d":"3","e":{"f":"4"}}}`), expect: []byte(`{"hostname":"host","network_config":{"content_path":"path"},"public_keys":{"test1":"key"}}`),
}, },
{ {
metadata: map[string]string{ metadata: map[string]string{
@ -154,7 +152,6 @@ func TestFetchMetadata(t *testing.T) {
expect: []byte("test"), expect: []byte("test"),
}, },
{err: pkg.ErrTimeout{fmt.Errorf("test error")}}, {err: pkg.ErrTimeout{fmt.Errorf("test error")}},
{err: pkg.ErrNotFound{fmt.Errorf("test error")}},
} { } {
client := &TestHttpClient{tt.metadata, tt.err} client := &TestHttpClient{tt.metadata, tt.err}
metadata, err := fetchMetadata(client) metadata, err := fetchMetadata(client)