コード例 #1
0
ファイル: target_test.go プロジェクト: vmware/vic
func TestProcess(t *testing.T) {
	passwd := "pass"
	url1, _ := soap.ParseURL("127.0.0.1")
	url2, _ := soap.ParseURL("root:@127.0.0.1")
	url3, _ := soap.ParseURL("line:[email protected]")
	url4, _ := soap.ParseURL("root:[email protected]")
	result, _ := url.Parse("https://*****:*****@127.0.0.1/sdk")
	passEmpty := ""
	result1, _ := url.Parse("https://root:@127.0.0.1/sdk")
	tests := []struct {
		URL      *url.URL
		User     string
		Password *string

		err    error
		result *url.URL
	}{
		{nil, "", nil, cli.NewExitError("--target argument must be specified", 1), nil},
		{nil, "root", nil, cli.NewExitError("--target argument must be specified", 1), nil},
		{nil, "root", &passwd, cli.NewExitError("--target argument must be specified", 1), nil},
		{url1, "root", &passwd, nil, result},
		{url4, "", nil, nil, result},
		{url3, "root", &passwd, nil, result},
		{url2, "", &passwd, nil, result},
		{url1, "root", &passEmpty, nil, result1},
	}

	for _, test := range tests {
		target := NewTarget()
		target.URL = test.URL
		target.User = test.User
		target.Password = test.Password
		if target.URL != nil {
			t.Logf("Before processing, url: %s", target.URL.String())
		}
		e := target.HasCredentials()
		if test.err != nil {
			if e == nil {
				t.Errorf("Empty error")
			}
			if e.Error() != test.err.Error() {
				t.Errorf("Unexpected error message: %s", e.Error())
			}
		} else if e != nil {
			t.Errorf("Unexpected error %s", e.Error())
		} else {
			if target.URL != test.URL {
				t.Errorf("unexpected result url: %s", target.URL.String())
			} else {
				t.Logf("result url: %s", target.URL.String())
			}
		}
	}
}
コード例 #2
0
ファイル: client.go プロジェクト: robvanmieghem/machine
func (flag *ClientFlag) Set(s string) error {
	var err error

	flag.url, err = soap.ParseURL(s)

	return err
}
コード例 #3
0
ファイル: target_test.go プロジェクト: vmware/vic
func TestURLWithoutPassword(t *testing.T) {
	target := NewTarget()
	target.URL, _ = soap.ParseURL("root:[email protected]")
	if target.URLWithoutPassword().String() != "https://[email protected]/sdk" {
		t.Errorf("Unexpected return of without password URL string, %s", target.URLWithoutPassword().String())
	}
}
コード例 #4
0
ファイル: session.go プロジェクト: jak-atx/vic
// Connect establishes the connection for the session but nothing more
func (s *Session) Connect(ctx context.Context) (*Session, error) {
	soapURL, err := soap.ParseURL(s.Service)
	if soapURL == nil || err != nil {
		return nil, errors.Errorf("SDK URL (%s) could not be parsed: %s", s.Service, err)
	}

	// update the service URL with the resolved soapURL
	s.Service = soapURL.String()

	// we can't set a keep alive if we log in directly with client creation
	user := soapURL.User
	soapURL.User = nil

	// 1st connect without any userinfo to get the API type
	s.Client, err = govmomi.NewClient(ctx, soapURL, s.Insecure)
	if err != nil {
		return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err)
	}

	if s.HasCertificate() && s.Client.IsVC() {
		// load the certificates
		cert, err2 := tls.X509KeyPair([]byte(s.ExtensionCert), []byte(s.ExtensionKey))
		if err2 != nil {
			return nil, errors.Errorf("Unable to load X509 key pair(%s,%s): %s",
				s.ExtensionCert, s.ExtensionKey, err2)
		}

		// create the new client
		s.Client, err = govmomi.NewClientWithCertificate(ctx, soapURL, s.Insecure, cert)
		if err != nil {
			return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.String(), err)
		}
	}

	if s.Keepalive != 0 {
		// now that we've verified everything, enable keepalive
		s.RoundTripper = session.KeepAlive(s.Client.RoundTripper, s.Keepalive)
	}

	// and now that the keepalive is registered we can log in to trigger it
	if !s.IsVC() || !s.HasCertificate() {
		log.Debugf("Trying to log in with username/password in lieu of cert")
		err = s.Client.Login(ctx, user)
	} else {
		log.Debugf("Logging into extension %s", s.ExtensionName)
		err = s.LoginExtensionByCertificate(ctx, s.ExtensionName, "")
	}
	if err != nil {
		return nil, errors.Errorf("Failed to log in to %s: %s", soapURL.String(), err)
	}

	s.Finder = find.NewFinder(s.Vim25(), true)
	// log high-level environement information
	s.logEnvironmentInfo()
	return s, nil
}
コード例 #5
0
ファイル: helper.go プロジェクト: vmware/vic
// URL parses the GOVMOMI_TEST_URL environment variable if set.
func URL() *url.URL {
	s := os.Getenv("GOVMOMI_TEST_URL")
	if s == "" {
		return nil
	}
	u, err := soap.ParseURL(s)
	if err != nil {
		panic(err)
	}
	return u
}
コード例 #6
0
ファイル: client_test.go プロジェクト: vmware/vic
// Duplicated to prevent cyclic dependency...
func testURL(t *testing.T) *url.URL {
	s := os.Getenv("GOVMOMI_TEST_URL")
	if s == "" {
		t.SkipNow()
	}
	u, err := soap.ParseURL(s)
	if err != nil {
		panic(err)
	}
	return u
}
コード例 #7
0
// URL parses the GOVMOMI_TEST_URL environment variable if set.
func URL() *url.URL {
	s := os.Getenv("VCENTER_URL")
	if s == "" {
		panic("VCENTER_URL env not set.  Please set to url of your vcenter sdk endpoint")
	}
	u, err := soap.ParseURL(s)
	if err != nil {
		panic(err)
	}
	return u
}
コード例 #8
0
ファイル: server.go プロジェクト: vmware/vic
// renders the page for login and handles authorization requests
func (s *server) loginPage(res http.ResponseWriter, req *http.Request) {
	defer trace.End(trace.Begin(""))
	ctx := context.Background()
	if req.Method == "POST" {
		// take the form data and use it to try to authenticate with vsphere

		// create a userconfig
		userconfig := session.Config{
			Insecure:       false,
			Thumbprint:     rootConfig.Thumbprint,
			Keepalive:      rootConfig.Keepalive,
			ClusterPath:    rootConfig.ClusterPath,
			DatacenterPath: rootConfig.DatacenterPath,
			DatastorePath:  rootConfig.DatastorePath,
			HostPath:       rootConfig.Config.HostPath,
			PoolPath:       rootConfig.PoolPath,
		}
		user := url.UserPassword(req.FormValue("username"), req.FormValue("password"))
		serviceURL, err := soap.ParseURL(rootConfig.Service)
		if err != nil {
			// this could happen for a number of reasons but most likely for a plain ol' auth failure
			log.Errorf("vSphere service URL was not a valid format; parsing returned error: %s", err)
			http.Error(res, genericErrorMessage, http.StatusInternalServerError)
			return
		}

		serviceURL.User = user
		userconfig.Service = serviceURL.String()

		// check login
		usersession, err := vSphereSessionGet(&userconfig)
		if err != nil || usersession == nil {
			// something went wrong or we could not authenticate
			log.Warnf("User %s from %s failed to authenticated at %s", user, req.RemoteAddr, time.Now())
			http.Error(res, "Authentication failed due to incorrect credential(s)", 400)
			return
		}

		// successful login above; user is authenticated
		// log out, disregard errors
		usersession.Client.Logout(context.Background())

		// create a token to save as an encrypted & signed cookie
		websession, err := s.uss.cookies.Get(req, sessionCookieKey)
		if websession == nil {
			log.Errorf("Web session object could not be created due to error %s", err)
			http.Error(res, genericErrorMessage, http.StatusInternalServerError)
			return
		}

		// save user config locally
		usersess := s.uss.Add(websession.ID, &userconfig)

		timeNow, err := usersess.created.MarshalText()
		if err != nil {
			log.Errorf("Failed to unmarshal time object %+v into text due to error: %s", usersess.created, err)
			http.Error(res, genericErrorMessage, http.StatusInternalServerError)
			return
		}

		websession.Values[sessionCreationTimeKey] = string(timeNow)
		websession.Values[sessionKey] = websession.ID

		remoteAddr := strings.SplitN(req.RemoteAddr, ":", 2)
		if len(remoteAddr) != 2 { // TODO: ctrl+f RemoteAddr and move this routine to helper
			log.Errorf("Format of IP address %s (should be IP:PORT) not recognized", req.RemoteAddr)
			http.Error(res, genericErrorMessage, http.StatusInternalServerError)
			return
		}
		websession.Values[ipAddressKey] = remoteAddr[0]

		if err := websession.Save(req, res); err != nil {
			log.Errorf("\"%s\" occurred while trying to save session to browser", err.Error())
			http.Error(res, genericErrorMessage, http.StatusInternalServerError)
			return
		}

		// redirect to dashboard
		http.Redirect(res, req, "/", http.StatusTemporaryRedirect)
		return
	}

	// Render login page (shows up on non-POST requests):
	sess, err := client(&rootConfig)
	if err != nil {
		log.Errorf("Could not render login page due to vSphere connection error: %s", err.Error())
		http.Error(res, genericErrorMessage, http.StatusInternalServerError)
		return
	}
	v := vicadmin.NewValidator(ctx, &vchConfig, sess)
	tmpl, err := template.ParseFiles("auth.html")
	err = tmpl.ExecuteTemplate(res, "auth.html", v)
	if err != nil {
		log.Errorf("Error parsing template: %s", err)
		http.Error(res, genericErrorMessage, http.StatusInternalServerError)
		return
	}
}
コード例 #9
0
ファイル: session.go プロジェクト: vmware/vic
// Connect establishes the connection for the session but nothing more
func (s *Session) Connect(ctx context.Context) (*Session, error) {
	soapURL, err := soap.ParseURL(s.Service)
	if soapURL == nil || err != nil {
		return nil, errors.Errorf("SDK URL (%s) could not be parsed: %s", s.Service, err)
	}

	// LoginExtensionByCertificate proxies connections to a virtual host (sdkTunnel:8089) and
	// Go's http.Transport.DialTLS isn't called when using a proxy.  Even if using a known CA,
	// "sdkTunnel" does not pass Go's tls.VerifyHostname check.
	// We are moving away from LoginExtensionByCertificate anyhow, so disable thumbprint checks for now.
	if s.HasCertificate() {
		s.Insecure = true
	}

	// Update the service URL with expanded defaults
	s.Service = soapURL.String()

	soapClient := soap.NewClient(soapURL, s.Insecure)
	var login func(context.Context) error

	if s.HasCertificate() {
		cert, err2 := tls.X509KeyPair([]byte(s.ExtensionCert), []byte(s.ExtensionKey))
		if err2 != nil {
			return nil, errors.Errorf("Unable to load X509 key pair(%s,%s): %s",
				s.ExtensionCert, s.ExtensionKey, err2)
		}

		soapClient.SetCertificate(cert)
		log.Debugf("Logging in via extension %s certificate", s.ExtensionName)

		login = func(ctx context.Context) error {
			return s.LoginExtensionByCertificate(ctx, s.ExtensionName, "")
		}
	} else {
		log.Debugf("Logging in via username/password")

		login = func(ctx context.Context) error {
			return s.Client.Login(ctx, soapURL.User)
		}
	}

	soapClient.SetThumbprint(soapURL.Host, s.Thumbprint)

	// TODO: option to set http.Client.Transport.TLSClientConfig.RootCAs

	vimClient, err := vim25.NewClient(ctx, soapClient)
	if err != nil {
		return nil, errors.Errorf("Failed to connect to %s: %s", soapURL.Host, err)
	}

	if s.Keepalive != 0 {
		vimClient.RoundTripper = session.KeepAliveHandler(soapClient, s.Keepalive,
			func(roundTripper soap.RoundTripper) error {
				_, err := methods.GetCurrentTime(context.Background(), roundTripper)
				if err == nil {
					return nil
				}

				log.Warnf("session keepalive error: %s", err)

				if isNotAuthenticated(err) {

					if err = login(ctx); err != nil {
						log.Errorf("session keepalive failed to re-authenticate: %s", err)
					} else {
						log.Info("session keepalive re-authenticated")
					}
				}

				return nil
			})
	}

	// TODO: get rid of govmomi.Client usage, only provides a few helpers we don't need.
	s.Client = &govmomi.Client{
		Client:         vimClient,
		SessionManager: session.NewManager(vimClient),
	}

	err = login(ctx)
	if err != nil {
		return nil, errors.Errorf("Failed to log in to %s: %s", soapURL.Host, err)
	}

	s.Finder = find.NewFinder(s.Vim25(), false)
	// log high-level environment information
	s.logEnvironmentInfo()
	return s, nil
}