Merge pull request #167 from crawford/sshkeys
metadata-service: fix ssh key retrieval and application
This commit is contained in:
commit
d8d3928978
@ -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 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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
|
||||||
}
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user