• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Golang cert.ParseCert函数代码示例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文整理汇总了Golang中github.com/juju/juju/cert.ParseCert函数的典型用法代码示例。如果您正苦于以下问题:Golang ParseCert函数的具体用法?Golang ParseCert怎么用?Golang ParseCert使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。



在下文中一共展示了ParseCert函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。

示例1: TestParseCertificate

func (certSuite) TestParseCertificate(c *gc.C) {
	xcert, err := cert.ParseCert(caCertPEM)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(xcert.Subject.CommonName, gc.Equals, "juju testing")

	xcert, err = cert.ParseCert(caKeyPEM)
	c.Check(xcert, gc.IsNil)
	c.Assert(err, gc.ErrorMatches, "no certificates found")

	xcert, err = cert.ParseCert("hello")
	c.Check(xcert, gc.IsNil)
	c.Assert(err, gc.ErrorMatches, "no certificates found")
}
开发者ID:imoapps,项目名称:juju,代码行数:13,代码来源:cert_test.go


示例2: TestWithNonUTCExpiry

func (certSuite) TestWithNonUTCExpiry(c *gc.C) {
	expiry, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", "2012-11-28 15:53:57 +0100 CET")
	c.Assert(err, jc.ErrorIsNil)
	certPEM, keyPEM, err := cert.NewCA("foo", expiry)
	xcert, err := cert.ParseCert(certPEM)
	c.Assert(err, jc.ErrorIsNil)
	checkNotAfter(c, xcert, expiry)

	var noHostnames []string
	certPEM, _, err = cert.NewServer(certPEM, keyPEM, expiry, noHostnames)
	xcert, err = cert.ParseCert(certPEM)
	c.Assert(err, jc.ErrorIsNil)
	checkNotAfter(c, xcert, expiry)
}
开发者ID:imoapps,项目名称:juju,代码行数:14,代码来源:cert_test.go


示例3: mustParseCert

func mustParseCert(pemData string) *x509.Certificate {
	cert, err := cert.ParseCert(pemData)
	if err != nil {
		panic(err)
	}
	return cert
}
开发者ID:imoapps,项目名称:juju,代码行数:7,代码来源:cert.go


示例4: Validate

// Validate ensures that config is a valid configuration.
func Validate(c Config) error {
	if v, ok := c[IdentityURL].(string); ok {
		u, err := url.Parse(v)
		if err != nil {
			return errors.Annotate(err, "invalid identity URL")
		}
		if u.Scheme != "https" {
			return errors.Errorf("URL needs to be https")
		}

	}

	if v, ok := c[IdentityPublicKey].(string); ok {
		var key bakery.PublicKey
		if err := key.UnmarshalText([]byte(v)); err != nil {
			return errors.Annotate(err, "invalid identity public key")
		}
	}

	caCert, caCertOK := c.CACert()
	if !caCertOK {
		return errors.Errorf("missing CA certificate")
	}
	if _, err := cert.ParseCert(caCert); err != nil {
		return errors.Annotate(err, "bad CA certificate in configuration")
	}

	if uuid, ok := c[ControllerUUIDKey].(string); ok && !utils.IsValidUUIDString(uuid) {
		return errors.Errorf("controller-uuid: expected UUID, got string(%q)", uuid)
	}

	return nil
}
开发者ID:kat-co,项目名称:juju,代码行数:34,代码来源:config.go


示例5: TestRsyslogCert

func (s *RsyslogSuite) TestRsyslogCert(c *gc.C) {
	st, m := s.st, s.machine
	err := s.machine.SetProviderAddresses(network.NewAddress("example.com"))
	c.Assert(err, jc.ErrorIsNil)

	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", []string{"0.1.2.3"})
	c.Assert(err, jc.ErrorIsNil)
	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
	defer worker.Kill()
	waitForFile(c, filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem"))

	rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem"))
	c.Assert(err, jc.ErrorIsNil)

	cert, err := cert.ParseCert(string(rsyslogCertPEM))
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(cert.DNSNames, gc.DeepEquals, []string{"example.com", "*"})

	subject := cert.Subject
	c.Assert(subject.CommonName, gc.Equals, "*")
	c.Assert(subject.Organization, gc.DeepEquals, []string{"juju"})

	issuer := cert.Issuer
	c.Assert(issuer.CommonName, gc.Equals, "juju-generated CA for environment \"rsyslog\"")
	c.Assert(issuer.Organization, gc.DeepEquals, []string{"juju"})
}
开发者ID:Pankov404,项目名称:juju,代码行数:27,代码来源:rsyslog_test.go


示例6: TestStartStop

func (s *CertUpdaterSuite) TestStartStop(c *gc.C) {
	var initialAddresses []string
	setter := func(info params.StateServingInfo, dying <-chan struct{}) error {
		// Only care about first time called.
		if len(initialAddresses) > 0 {
			return nil
		}
		srvCert, err := cert.ParseCert(info.Cert)
		c.Assert(err, jc.ErrorIsNil)
		initialAddresses = make([]string, len(srvCert.IPAddresses))
		for i, ip := range srvCert.IPAddresses {
			initialAddresses[i] = ip.String()
		}
		return nil
	}
	changes := make(chan struct{})
	certChangedChan := make(chan params.StateServingInfo)
	worker := certupdater.NewCertificateUpdater(
		&mockMachine{changes}, s, &mockConfigGetter{}, &mockAPIHostGetter{}, setter, certChangedChan,
	)
	worker.Kill()
	c.Assert(worker.Wait(), gc.IsNil)
	// Initial cert addresses initialised to cloud local ones.
	c.Assert(initialAddresses, jc.DeepEquals, []string{"192.168.1.1"})
}
开发者ID:claudiu-coblis,项目名称:juju,代码行数:25,代码来源:certupdater_test.go


示例7: TestCertificateUpdateWorkerUpdatesCertificate

func (s *MachineSuite) TestCertificateUpdateWorkerUpdatesCertificate(c *gc.C) {
	// Set up the machine agent.
	m, _, _ := s.primeAgent(c, state.JobManageModel)
	a := s.newAgent(c, m)
	a.ReadConfig(names.NewMachineTag(m.Id()).String())

	// Set up check that certificate has been updated.
	updated := make(chan struct{})
	go func() {
		for {
			stateInfo, _ := a.CurrentConfig().StateServingInfo()
			srvCert, err := cert.ParseCert(stateInfo.Cert)
			if !c.Check(err, jc.ErrorIsNil) {
				break
			}
			sanIPs := make([]string, len(srvCert.IPAddresses))
			for i, ip := range srvCert.IPAddresses {
				sanIPs[i] = ip.String()
			}
			if len(sanIPs) == 1 && sanIPs[0] == "0.1.2.3" {
				close(updated)
				break
			}
			time.Sleep(100 * time.Millisecond)
		}
	}()

	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
	s.assertChannelActive(c, updated, "certificate to be updated")
}
开发者ID:bac,项目名称:juju,代码行数:31,代码来源:machine_test.go


示例8: createSyslogServer

func (s *syslogSuite) createSyslogServer(c *gc.C, received chan rfc5424test.Message, done chan struct{}) string {
	server := rfc5424test.NewServer(rfc5424test.HandlerFunc(func(msg rfc5424test.Message) {
		select {
		case received <- msg:
		case <-done:
		}
	}))
	s.AddCleanup(func(*gc.C) { server.Close() })
	s.AddCleanup(func(*gc.C) { close(done) })

	serverCert, err := tls.X509KeyPair(
		[]byte(coretesting.ServerCert),
		[]byte(coretesting.ServerKey),
	)
	c.Assert(err, jc.ErrorIsNil)
	caCert, err := cert.ParseCert(coretesting.CACert)
	c.Assert(err, jc.ErrorIsNil)
	clientCAs := x509.NewCertPool()
	clientCAs.AddCert(caCert)
	server.TLS = &tls.Config{
		Certificates: []tls.Certificate{serverCert},
		ClientCAs:    clientCAs,
	}
	server.StartTLS()

	// We must use "localhost", as the certificate does not
	// have any IP SANs.
	port := server.Listener.Addr().(*net.TCPAddr).Port
	addr := net.JoinHostPort("localhost", fmt.Sprint(port))
	return addr
}
开发者ID:bac,项目名称:juju,代码行数:31,代码来源:syslog_test.go


示例9: verifyKeyPair

// verifyKeyPair verifies that the certificate and key parse correctly.
// The key is optional - if it is provided, we also check that the key
// matches the certificate.
func verifyKeyPair(certb, key string) error {
	if key != "" {
		_, err := tls.X509KeyPair([]byte(certb), []byte(key))
		return err
	}
	_, err := cert.ParseCert(certb)
	return err
}
开发者ID:imoapps,项目名称:juju,代码行数:11,代码来源:authkeys.go


示例10: dialWebsocket

func dialWebsocket(c *gc.C, addr, path string) (*websocket.Conn, error) {
	origin := "http://localhost/"
	url := fmt.Sprintf("wss://%s%s", addr, path)
	config, err := websocket.NewConfig(url, origin)
	c.Assert(err, jc.ErrorIsNil)
	pool := x509.NewCertPool()
	xcert, err := cert.ParseCert(coretesting.CACert)
	c.Assert(err, jc.ErrorIsNil)
	pool.AddCert(xcert)
	config.TlsConfig = &tls.Config{RootCAs: pool}
	return websocket.DialConfig(config)
}
开发者ID:imoapps,项目名称:juju,代码行数:12,代码来源:server_test.go


示例11: DialInfo

// DialInfo returns information on how to dial
// the state's mongo server with the given info
// and dial options.
func DialInfo(info Info, opts DialOpts) (*mgo.DialInfo, error) {
	if len(info.Addrs) == 0 {
		return nil, stderrors.New("no mongo addresses")
	}
	if len(info.CACert) == 0 {
		return nil, stderrors.New("missing CA certificate")
	}
	xcert, err := cert.ParseCert(info.CACert)
	if err != nil {
		return nil, fmt.Errorf("cannot parse CA certificate: %v", err)
	}
	pool := x509.NewCertPool()
	pool.AddCert(xcert)
	tlsConfig := utils.SecureTLSConfig()

	// TODO(natefinch): revisit this when are full-time on mongo 3.
	// We have to add non-ECDHE suites because mongo doesn't support ECDHE.
	moreSuites := []uint16{
		tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
		tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
	}

	tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, moreSuites...)
	tlsConfig.RootCAs = pool
	tlsConfig.ServerName = "juju-mongodb"

	dial := func(server *mgo.ServerAddr) (net.Conn, error) {
		addr := server.TCPAddr().String()
		c, err := net.DialTimeout("tcp", addr, opts.Timeout)
		if err != nil {
			logger.Warningf("mongodb connection failed, will retry: %v", err)
			return nil, err
		}
		cc := tls.Client(c, tlsConfig)
		if err := cc.Handshake(); err != nil {
			logger.Warningf("TLS handshake failed: %v", err)
			return nil, err
		}
		logger.Debugf("dialled mongodb server at %q", addr)
		return cc, nil
	}

	return &mgo.DialInfo{
		Addrs:      info.Addrs,
		Timeout:    opts.Timeout,
		DialServer: dial,
		Direct:     opts.Direct,
	}, nil
}
开发者ID:bac,项目名称:juju,代码行数:52,代码来源:open.go


示例12: SetRsyslogCert

// SetRsyslogCert sets the rsyslog CACert.
func (api *RsyslogAPI) SetRsyslogCert(args params.SetRsyslogCertParams) (params.ErrorResult, error) {
	var result params.ErrorResult
	if !api.canModify {
		result.Error = common.ServerError(common.ErrBadCreds)
		return result, nil
	}
	if _, err := cert.ParseCert(string(args.CACert)); err != nil {
		result.Error = common.ServerError(err)
		return result, nil
	}
	attrs := map[string]interface{}{"rsyslog-ca-cert": string(args.CACert)}
	if err := api.st.UpdateEnvironConfig(attrs, nil, nil); err != nil {
		result.Error = common.ServerError(err)
	}
	return result, nil
}
开发者ID:klyachin,项目名称:juju,代码行数:17,代码来源:rsyslog.go


示例13: updateRequired

// updateRequired returns true and a list of merged addresses if any of the
// new addresses are not yet contained in the server cert SAN list.
func updateRequired(serverCert string, newAddrs []string) ([]string, bool, error) {
	x509Cert, err := cert.ParseCert(serverCert)
	if err != nil {
		return nil, false, errors.Annotate(err, "cannot parse existing TLS certificate")
	}
	existingAddr := set.NewStrings()
	for _, ip := range x509Cert.IPAddresses {
		existingAddr.Add(ip.String())
	}
	logger.Debugf("existing cert addresses %v", existingAddr)
	logger.Debugf("new addresses %v", newAddrs)
	// Does newAddr contain any that are not already in existingAddr?
	newAddrSet := set.NewStrings(newAddrs...)
	update := newAddrSet.Difference(existingAddr).Size() > 0
	newAddrSet = newAddrSet.Union(existingAddr)
	return newAddrSet.SortedValues(), update, nil
}
开发者ID:claudiu-coblis,项目名称:juju,代码行数:19,代码来源:certupdater.go


示例14: tlsConfig

func (cfg RawConfig) tlsConfig() (*tls.Config, error) {
	clientCert, err := tls.X509KeyPair([]byte(cfg.ClientCert), []byte(cfg.ClientKey))
	if err != nil {
		return nil, errors.Annotate(err, "parsing client key pair")
	}

	caCert, err := cert.ParseCert(cfg.CACert)
	if err != nil {
		return nil, errors.Annotate(err, "parsing CA certificate")
	}
	rootCAs := x509.NewCertPool()
	rootCAs.AddCert(caCert)

	return &tls.Config{
		Certificates: []tls.Certificate{clientCert},
		RootCAs:      rootCAs,
	}, nil
}
开发者ID:bac,项目名称:juju,代码行数:18,代码来源:config.go


示例15: CreateCertPool

// CreateCertPool creates a new x509.CertPool and adds in the caCert passed
// in.  All certs from the cert directory (/etc/juju/cert.d on ubuntu) are
// also added.
func CreateCertPool(caCert string) (*x509.CertPool, error) {

	pool := x509.NewCertPool()
	if caCert != "" {
		xcert, err := cert.ParseCert(caCert)
		if err != nil {
			return nil, errors.Trace(err)
		}
		pool.AddCert(xcert)
	}

	count := processCertDir(pool)
	if count >= 0 {
		logger.Debugf("added %d certs to the pool from %s", count, certDir)
	}

	return pool, nil
}
开发者ID:imoapps,项目名称:juju,代码行数:21,代码来源:certpool.go


示例16: Connect

// Connect establishes a websocket connection to the API server using
// the Info, API path tail and (optional) request headers provided. If
// multiple API addresses are provided in Info they will be tried
// concurrently - the first successful connection wins.
//
// The path tail may be blank, in which case the default value will be
// used. Otherwise, it must start with a "/".
func Connect(info *Info, pathTail string, header http.Header, opts DialOpts) (*websocket.Conn, error) {
	if len(info.Addrs) == 0 {
		return nil, errors.New("no API addresses to connect to")
	}
	if pathTail != "" && !strings.HasPrefix(pathTail, "/") {
		return nil, errors.New(`path tail must start with "/"`)
	}

	pool := x509.NewCertPool()
	xcert, err := cert.ParseCert(info.CACert)
	if err != nil {
		return nil, errors.Annotate(err, "cert pool creation failed")
	}
	pool.AddCert(xcert)

	path := makeAPIPath(info.EnvironTag.Id(), pathTail)

	// Dial all addresses at reasonable intervals.
	try := parallel.NewTry(0, nil)
	defer try.Kill()
	for _, addr := range info.Addrs {
		err := dialWebsocket(addr, path, header, opts, pool, try)
		if err == parallel.ErrStopped {
			break
		}
		if err != nil {
			return nil, errors.Trace(err)
		}
		select {
		case <-time.After(opts.DialAddressInterval):
		case <-try.Dead():
		}
	}
	try.Close()
	result, err := try.Result()
	if err != nil {
		return nil, errors.Trace(err)
	}
	conn := result.(*websocket.Conn)
	logger.Infof("connection established to %q", conn.RemoteAddr())
	return conn, nil
}
开发者ID:Pankov404,项目名称:juju,代码行数:49,代码来源:apiclient.go


示例17: TestAddressChange

func (s *CertUpdaterSuite) TestAddressChange(c *gc.C) {
	var srvCert *x509.Certificate
	updated := make(chan struct{})
	setter := func(info params.StateServingInfo, dying <-chan struct{}) error {
		s.stateServingInfo = info
		var err error
		srvCert, err = cert.ParseCert(info.Cert)
		c.Assert(err, jc.ErrorIsNil)
		sanIPs := make([]string, len(srvCert.IPAddresses))
		for i, ip := range srvCert.IPAddresses {
			sanIPs[i] = ip.String()
		}
		sanIPsSet := set.NewStrings(sanIPs...)
		if sanIPsSet.Size() == 2 && sanIPsSet.Contains("0.1.2.3") && sanIPsSet.Contains("192.168.1.1") {
			close(updated)
		}
		return nil
	}
	changes := make(chan struct{})
	certChangedChan := make(chan params.StateServingInfo)
	worker := certupdater.NewCertificateUpdater(
		&mockMachine{changes}, s, &mockConfigGetter{}, &mockAPIHostGetter{}, setter, certChangedChan,
	)
	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
	defer worker.Kill()

	changes <- struct{}{}
	// Certificate should be updated with the address value.
	select {
	case <-updated:
	case <-time.After(coretesting.LongWait):
		c.Fatalf("timed out waiting for certificate to be updated")
	}

	// The server certificates must report "juju-apiserver" as a DNS
	// name for backwards-compatibility with API clients. They must
	// also report "juju-mongodb" because these certicates are also
	// used for serving MongoDB connections.
	c.Assert(srvCert.DNSNames, jc.SameContents,
		[]string{"localhost", "juju-apiserver", "juju-mongodb", "anything"})
}
开发者ID:claudiu-coblis,项目名称:juju,代码行数:41,代码来源:certupdater_test.go


示例18: TestCertificateDNSUpdated

func (s *MachineSuite) TestCertificateDNSUpdated(c *gc.C) {
	// Disable the certificate work so it doesn't update the certificate.
	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.ControllerConfigGetter,
		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
	) worker.Worker {
		return worker.NewNoOpWorker()
	}
	s.PatchValue(&newCertificateUpdater, newUpdater)

	// Set up the machine agent.
	m, _, _ := s.primeAgent(c, state.JobManageModel)
	a := s.newAgent(c, m)

	// Set up check that certificate has been updated when the agent starts.
	updated := make(chan struct{})
	expectedDnsNames := set.NewStrings("local", "juju-apiserver", "juju-mongodb")
	go func() {
		for {
			stateInfo, _ := a.CurrentConfig().StateServingInfo()
			srvCert, err := cert.ParseCert(stateInfo.Cert)
			c.Assert(err, jc.ErrorIsNil)
			certDnsNames := set.NewStrings(srvCert.DNSNames...)
			if !expectedDnsNames.Difference(certDnsNames).IsEmpty() {
				continue
			}
			pemContent, err := ioutil.ReadFile(filepath.Join(s.DataDir(), "server.pem"))
			c.Assert(err, jc.ErrorIsNil)
			if string(pemContent) == stateInfo.Cert+"\n"+stateInfo.PrivateKey {
				close(updated)
				break
			}
			time.Sleep(10 * time.Millisecond)
		}
	}()

	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
	s.assertChannelActive(c, updated, "certificate to be updated")
}
开发者ID:kat-co,项目名称:juju,代码行数:39,代码来源:machine_test.go


示例19: DialInfo

// DialInfo returns information on how to dial
// the state's mongo server with the given info
// and dial options.
func DialInfo(info Info, opts DialOpts) (*mgo.DialInfo, error) {
	if len(info.Addrs) == 0 {
		return nil, stderrors.New("no mongo addresses")
	}
	if len(info.CACert) == 0 {
		return nil, stderrors.New("missing CA certificate")
	}
	xcert, err := cert.ParseCert(info.CACert)
	if err != nil {
		return nil, fmt.Errorf("cannot parse CA certificate: %v", err)
	}
	pool := x509.NewCertPool()
	pool.AddCert(xcert)
	tlsConfig := &tls.Config{
		RootCAs:    pool,
		ServerName: "juju-mongodb",
	}
	dial := func(addr net.Addr) (net.Conn, error) {
		c, err := net.Dial("tcp", addr.String())
		if err != nil {
			logger.Debugf("connection failed, will retry: %v", err)
			return nil, err
		}
		cc := tls.Client(c, tlsConfig)
		if err := cc.Handshake(); err != nil {
			logger.Debugf("TLS handshake failed: %v", err)
			return nil, err
		}
		logger.Infof("dialled mongo successfully on address %q", addr)
		return cc, nil
	}

	return &mgo.DialInfo{
		Addrs:   info.Addrs,
		Timeout: opts.Timeout,
		Dial:    dial,
		Direct:  opts.Direct,
	}, nil
}
开发者ID:exekias,项目名称:juju,代码行数:42,代码来源:open.go


示例20: processCertDir

// processCertDir iterates through the certDir looking for *.pem files.
// Each pem file is read in turn and added to the pool.  A count of the number
// of successful certificates processed is returned.
func processCertDir(pool *x509.CertPool) (count int) {
	fileInfo, err := os.Stat(certDir)
	if os.IsNotExist(err) {
		logger.Tracef("cert dir %q does not exist", certDir)
		return -1
	}
	if err != nil {
		logger.Infof("unexpected error reading cert dir: %s", err)
		return -1
	}
	if !fileInfo.IsDir() {
		logger.Infof("cert dir %q is not a directory", certDir)
		return -1
	}

	matches, err := filepath.Glob(filepath.Join(certDir, "*.pem"))
	if err != nil {
		logger.Infof("globbing files failed: %s", err)
		return -1
	}

	for _, match := range matches {
		data, err := ioutil.ReadFile(match)
		if err != nil {
			logger.Infof("error reading %q: %v", match, err)
			continue
		}
		certificate, err := cert.ParseCert(string(data))
		if err != nil {
			logger.Infof("error parsing cert %q: %v", match, err)
			continue
		}
		pool.AddCert(certificate)
		count++
	}
	return count
}
开发者ID:imoapps,项目名称:juju,代码行数:40,代码来源:certpool.go



注:本文中的github.com/juju/juju/cert.ParseCert函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Golang cert.ParseCertAndKey函数代码示例发布时间:2022-05-23
下一篇:
Golang cert.NewServer函数代码示例发布时间:2022-05-23
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap