Example #1
0
// Parse reads from the given io.ReadCloser and
// parses read contents of a cloud-config file.
func Parse(rdr io.ReadCloser) (*Digest, error) {
	buf, err := ioutil.ReadAll(rdr)
	if err != nil {
		return nil, err
	}
	rdr.Close()

	var conf cloudConfig
	if err := yaml.Unmarshal(buf, &conf); err != nil {
		return nil, err
	}
	var c Digest

	c.Commands = parseCommands(conf.RunCMD)

	c.AuthorizedKeys = make(map[string][]ssh.Key)
	for _, key := range conf.AuthorizedKeys {
		c.AuthorizedKeys["root"] = append(c.AuthorizedKeys["root"], ssh.Key(key))
	}

	public_keys, private_keys := make(map[string]string), make(map[string]string)

	// TODO: Extend ssh key syntax beyond cloud-config
	for k, v := range conf.SSHKeyPairs {
		if strings.HasSuffix(k, "private") {
			private_keys[strings.TrimSuffix(k, "_private")] = v
		} else {
			public_keys[strings.TrimSuffix(k, "_public")] = v
		}
	}

	for key, value := range public_keys {
		c.SSHKeyPairs = append(c.SSHKeyPairs, ssh.KeyPair{
			Public:  ssh.Key(value),
			Private: ssh.Key(private_keys[key]),
		})
	}

	c.Groups = parseGroups(conf.Groups)
	c.Users = parseUsers(conf.Users)
	/*
	* BUG(yaml.v2): Embedded structs are not unmarshaled properly.
	* TODO(tmrts): Use another yaml library or extend identity.User.
	*for _, usr := range conf.Users {
	*    for _, key := range usr.AuthorizedSSHKeys {
	*       c.AuthorizedKeys[usr.Name] = append(c.AuthorizedKeys[usr.Name], ssh.Key(key))
	*    }
	*}
	 */

	c.Files = conf.Files

	return &c, nil
}
Example #2
0
func TestRetrievesDataFromEC2(t *testing.T) {
	Convey("Given an EC2 meta-data service", t, func() {
		// mock EC2 metadata server
		server := NewMockServer(func(w http.ResponseWriter, r *http.Request) {
			attributes := map[string]string{
				"hostname":                  "centos.ec2",
				"local-ipv4":                "10.240.51.29",
				"public-ipv4":               "104.155.21.99",
				"public-keys/0/openssh-key": "ssh-rsa OPENSSH_KEY",
			}

			if strings.Contains(r.URL.String(), "/2009-04-04/meta-data/") {
				for attr, value := range attributes {
					if strings.HasSuffix(r.URL.String(), attr) {
						w.Write([]byte(value))
					}
				}
			} else if strings.HasSuffix(r.URL.String(), "/2009-04-04/user-data") {
				w.Write([]byte("#cloud-config\n"))
			} else {
				http.Error(w, "requested resource is not found", http.StatusNotFound)
			}
		})

		service := ec2.MetadataService{
			URL: provider.FormatURL(server.URL + "/%v/%v/%v"),
		}

		Convey("It should retrieve meta-data from EC2 meta-data service", func() {
			digest, err := service.FetchMetadata()
			So(err, ShouldBeNil)

			So(digest.Hostname, ShouldEqual, "centos.ec2")

			ifc := digest.PrimaryNetworkInterface()
			So(ifc.PublicIPs[0].String(), ShouldEqual, "104.155.21.99")

			sshKeys := digest.SSHKeys

			So(sshKeys["root"], ShouldConsistOf, ssh.Key("ssh-rsa OPENSSH_KEY"))
		})

		Convey("It should retrieve user-data from EC2 meta-data service", func() {
			userdata, err := service.FetchUserdata()
			So(err, ShouldBeNil)

			So(userdata["user-data"], ShouldEqual, "#cloud-config\n")
		})

	})
}
func TestSSHKeyParsing(t *testing.T) {
	Convey("Given a cloud-config file containing SSH-key directives", t, func() {
		configFile, err := os.Open(filepath.Join(testConfigDirectory, "sshkeys.yaml"))
		So(err, ShouldBeNil)

		Convey("It should parse the ssh keys", func() {
			conf, err := cloudconfig.Parse(configFile)
			So(err, ShouldBeNil)

			So(conf.AuthorizedKeys["root"], ShouldConsistOf,
				ssh.Key("ssh-rsa RSA_PUBLIC_KEY_1 mykey@host"),
				ssh.Key("ssh-rsa RSA_PUBLIC_KEY_2 mykey@host"),
			)

			So(conf.SSHKeyPairs, ShouldConsistOf,
				ssh.KeyPair{
					Public:  ssh.Key("ssh-rsa RSA_PUBLIC_KEY smoser@localhost"),
					Private: ssh.Key("-----BEGIN RSA PRIVATE KEY-----\nRSA_PRIVATE_KEY\n-----END RSA PRIVATE KEY-----\n"),
				},
			)
		})
	})
}
Example #4
0
// Digest extracts the important parts of meta-data and returns it.
func (md *Metadata) Digest() metadata.Digest {
	sshKeys := make(map[string][]ssh.Key)

	for usr, rawKeys := range md.PublicKeys {
		keys := strings.Split(rawKeys, "\n")

		for _, key := range keys {
			if key != "" {
				sshKeys[usr] = append(sshKeys[usr], ssh.Key(key))
			}
		}
	}

	return metadata.Digest{
		Hostname: md.Hostname,
		SSHKeys:  sshKeys,
	}
}
Example #5
0
// Digest extracts the important parts of meta-data and returns it.
func (m *Metadata) Digest() metadata.Digest {
	sshKeys := make(map[string][]ssh.Key)

	for _, publicKey := range m.PublicKeys {
		sshKeys["root"] = append(sshKeys["root"], ssh.Key(publicKey))
	}

	primaryNetworkInterface := metadata.NetworkInterface{
		PrivateIP: m.LocalIPv4,
		PublicIPs: []net.IP{m.PublicIPv4},
	}

	return metadata.Digest{
		Hostname: m.Hostname,
		SSHKeys:  sshKeys,

		NetworkInterfaces: []metadata.NetworkInterface{
			primaryNetworkInterface,
		},
	}
}
Example #6
0
// Digest extracts the important parts of meta-data and returns it.
func (md *Metadata) Digest() metadata.Digest {
	interfaces := []metadata.NetworkInterface{}
	for _, ifc := range md.Instance.NetworkInterfaces {
		i := metadata.NetworkInterface{
			NetworkName: ifc.Network,
			PrivateIP:   ifc.IP,
			PublicIPs:   []net.IP{},
		}

		for _, conf := range ifc.AccessConfigs {
			i.PublicIPs = append(i.PublicIPs, conf.ExternalIP)
		}

		interfaces = append(interfaces, i)
	}

	rawKeys := md.Project.Attributes.SSHKeys

	sshKeys := make(map[string][]ssh.Key)

	for _, line := range strings.Split(rawKeys, "\n") {
		if line != "" {
			tokens := strings.Split(line, ":")

			userName, key := tokens[0], tokens[1]

			sshKeys[userName] = append(sshKeys[userName], ssh.Key(key))
		}
	}

	return metadata.Digest{
		Hostname: md.Instance.Hostname,
		SSHKeys:  sshKeys,

		NetworkInterfaces: interfaces,
	}
}
Example #7
0
func TestRetrievesDataFromConfigDrive(t *testing.T) {
	Convey("Given a mounted config drive", t, func() {
		tmpdir, err := ioutil.TempDir("", "flamingotest")
		So(err, ShouldBeNil)
		defer os.RemoveAll(tmpdir)

		dataPath := strings.Join([]string{tmpdir, "openstack", "2012-08-10"}, "/")
		err = os.MkdirAll(dataPath, 0755)
		So(err, ShouldBeNil)

		buf, err := ioutil.ReadFile("../openstack/test_metadata/2012-08-10.json")
		err = file.New(filepath.Join(dataPath, "meta_data.json"), file.Contents(string(buf)))
		So(err, ShouldBeNil)

		err = file.New(filepath.Join(dataPath, "user_data"), file.Contents("#cloud-config\n"))
		So(err, ShouldBeNil)

		mount := &configdrive.Mount{tmpdir}

		Convey("It should return a metadata digest", func() {
			digest, err := mount.FetchMetadata()
			So(err, ShouldBeNil)

			So(digest.Hostname, ShouldEqual, "test.novalocal")
			So(digest.SSHKeys["mykey"], ShouldConsistOf,
				ssh.Key("ssh-rsa RSA_PUBLIC_KEY Generated by Nova"))
		})

		Convey("It should return user-data", func() {
			userdata, err := mount.FetchUserdata()
			So(err, ShouldBeNil)

			So(userdata["user-data"], ShouldEqual, "#cloud-config\n")
		})
	})
}
Example #8
0
func TestGoogleComputeMetadataRetrieval(t *testing.T) {
	Convey("Given a GCE meta-data service", t, func() {
		// mock GCE metadata server
		server := NewMockServer(func(w http.ResponseWriter, r *http.Request) {
			var json_path string
			if r.Header.Get("Metadata-Flavor") != "Google" {
				http.Error(w, "metadata header is not found", http.StatusBadRequest)
				return
			}

			if strings.Contains(r.URL.String(), "project") {
				json_path = filepath.Join(testMetadataDir, "GCEv1_project.json")
			} else if strings.Contains(r.URL.String(), "instance") {
				json_path = filepath.Join(testMetadataDir, "GCEv1_instance.json")
			} else {
				http.Error(w, "requested resource is not found", http.StatusNotFound)
				return
			}

			buf, err := ioutil.ReadFile(json_path)
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}

			w.Write(buf)
		})

		service := gce.MetadataService{
			URL: provider.FormatURL(server.URL + "/%v/%v"),
		}

		Convey("It should retrieve meta-data from GCE meta-data service", func() {
			digest, err := service.FetchMetadata()
			So(err, ShouldBeNil)

			So(digest.Hostname, ShouldEqual, "centos.internal")

			ifc := digest.PrimaryNetworkInterface()
			So(ifc.PrivateIP.String(), ShouldEqual, "10.240.45.128")

			So(ifc.PublicIPs[0].String(), ShouldEqual, "104.155.21.159")
			So(ifc.PublicIPs[1].String(), ShouldEqual, "104.155.21.160")

			sshKeys := digest.SSHKeys

			So(sshKeys["user1"], ShouldConsistOf,
				ssh.Key("ssh-rsa RSA_PUBLIC_KEY_FOR_USER_1 user1@machine"),
				ssh.Key("ssh-dsa DSA_PUBLIC_KEY_FOR_USER_1 user1@machine"))

			So(sshKeys["user2"], ShouldConsistOf,
				ssh.Key("ssh-rsa RSA_PUBLIC_KEY_FOR_USER_2 user2@machine"))
		})

		Convey("It should retrieve user-data from GCE meta-data service", func() {
			userdata, err := service.FetchUserdata()
			So(err, ShouldBeNil)

			So(userdata["user-data"], ShouldEqual, "#cloud-config\n")
		})

	})
}