// Send sends the given metrics to the collector service. func (s *HttpSender) Send(metrics []*wireformat.MetricBatch) (*wireformat.Response, error) { b, err := json.Marshal(metrics) if err != nil { return nil, errors.Trace(err) } r := bytes.NewBuffer(b) t := utils.NewHttpTLSTransport(&tls.Config{RootCAs: metricsCertsPool}) client := &http.Client{Transport: t} resp, err := client.Post(metricsHost, "application/json", r) if err != nil { return nil, errors.Trace(err) } if resp.StatusCode != http.StatusOK { return nil, errors.Errorf("failed to send metrics http %v", resp.StatusCode) } defer resp.Body.Close() respReader := json.NewDecoder(resp.Body) metricsResponse := wireformat.Response{} err = respReader.Decode(&metricsResponse) if err != nil { return nil, errors.Trace(err) } return &metricsResponse, nil }
func (b *backendSuite) tlsServerAndClient(c *gc.C) (client *http.Client, url, dataDir string) { listener, url, dataDir := startServerTLS(c) b.AddCleanup(func(*gc.C) { listener.Close() }) caCerts := x509.NewCertPool() c.Assert(caCerts.AppendCertsFromPEM([]byte(coretesting.CACert)), jc.IsTrue) client = &http.Client{ Transport: utils.NewHttpTLSTransport(&tls.Config{RootCAs: caCerts}), } return client, url, dataDir }
// NewHTTPClient returns an HTTP client initialized based on State. func (s *State) NewHTTPClient() *http.Client { httpclient := utils.GetValidatingHTTPClient() tlsconfig := tls.Config{ RootCAs: s.certPool, // We want to be specific here (rather than just using "anything". // See commit 7fc118f015d8480dfad7831788e4b8c0432205e8 (PR 899). ServerName: "juju-apiserver", } httpclient.Transport = utils.NewHttpTLSTransport(&tlsconfig) return httpclient }
// ClientTLS returns a storage object that will talk to the // storage server at the given network address (see Serve), // using TLS. The client is given an authentication key, // which the server will verify for Put and Remove* operations. func ClientTLS(addr string, caCertPEM string, authkey string) (storage.Storage, error) { logger.Debugf("using https storage at %q", addr) caCerts := x509.NewCertPool() if !caCerts.AppendCertsFromPEM([]byte(caCertPEM)) { return nil, errors.New("error adding CA certificate to pool") } return &localStorage{ addr: addr, authkey: authkey, client: &http.Client{ Transport: utils.NewHttpTLSTransport(&tls.Config{RootCAs: caCerts}), }, }, nil }
// bakeryDo provides a function suitable for using in httpRequestParams.Do // that will use the given http client (or utils.GetNonValidatingHTTPClient() // if client is nil) and use the given getBakeryError function // to translate errors in responses. func bakeryDo(client *http.Client, getBakeryError func(*http.Response) error) func(*http.Request) (*http.Response, error) { bclient := httpbakery.NewClient() if client != nil { bclient.Client = client } else { // Configure the default client to skip verification/ tlsConfig := utils.SecureTLSConfig() tlsConfig.InsecureSkipVerify = true bclient.Client.Transport = utils.NewHttpTLSTransport(tlsConfig) } return func(req *http.Request) (*http.Response, error) { var body io.ReadSeeker if req.Body != nil { body = req.Body.(io.ReadSeeker) req.Body = nil } return bclient.DoWithBodyAndCustomError(req, body, getBakeryError) } }
// open is the unexported version of open that also includes // an explicit clock instance argument. func open( info *Info, opts DialOpts, clock clock.Clock, ) (Connection, error) { if err := info.Validate(); err != nil { return nil, errors.Annotate(err, "validating info for opening an API connection") } if clock == nil { return nil, errors.NotValidf("nil clock") } conn, tlsConfig, err := dialAPI(info, opts) if err != nil { return nil, errors.Trace(err) } client := rpc.NewConn(jsoncodec.NewWebsocket(conn), observer.None()) client.Start() bakeryClient := opts.BakeryClient if bakeryClient == nil { bakeryClient = httpbakery.NewClient() } else { // Make a copy of the bakery client and its HTTP client c := *opts.BakeryClient bakeryClient = &c httpc := *bakeryClient.Client bakeryClient.Client = &httpc } apiHost := conn.Config().Location.Host // Technically when there's no CACert, we don't need this // machinery, because we could just use http.DefaultTransport // for everything, but it's easier just to leave it in place. bakeryClient.Client.Transport = &hostSwitchingTransport{ primaryHost: apiHost, primary: utils.NewHttpTLSTransport(tlsConfig), fallback: http.DefaultTransport, } st := &state{ client: client, conn: conn, clock: clock, addr: apiHost, cookieURL: &url.URL{ Scheme: "https", Host: conn.Config().Location.Host, Path: "/", }, pingerFacadeVersion: facadeVersions["Pinger"], serverScheme: "https", serverRootAddress: conn.Config().Location.Host, // We populate the username and password before // login because, when doing HTTP requests, we'll want // to use the same username and password for authenticating // those. If login fails, we discard the connection. tag: tagToString(info.Tag), password: info.Password, macaroons: info.Macaroons, nonce: info.Nonce, tlsConfig: tlsConfig, bakeryClient: bakeryClient, modelTag: info.ModelTag, } if !info.SkipLogin { if err := st.Login(info.Tag, info.Password, info.Nonce, info.Macaroons); err != nil { conn.Close() return nil, errors.Trace(err) } } st.broken = make(chan struct{}) st.closed = make(chan struct{}) go (&monitor{ clock: clock, ping: st.Ping, pingPeriod: PingPeriod, pingTimeout: pingTimeout, closed: st.closed, dead: client.Dead(), broken: st.broken, }).run() return st, nil }
// This unexported open method is used both directly above in the Open // function, and also the OpenWithVersion function below to explicitly cause // the API server to think that the client is older than it really is. func open( info *Info, opts DialOpts, loginFunc func(st *state, tag names.Tag, pwd, nonce string, ms []macaroon.Slice) error, ) (Connection, error) { if err := info.Validate(); err != nil { return nil, errors.Annotate(err, "validating info for opening an API connection") } conn, tlsConfig, err := connectWebsocket(info, opts) if err != nil { return nil, errors.Trace(err) } client := rpc.NewConn(jsoncodec.NewWebsocket(conn), nil) client.Start() bakeryClient := opts.BakeryClient if bakeryClient == nil { bakeryClient = httpbakery.NewClient() } else { // Make a copy of the bakery client and its // HTTP client c := *opts.BakeryClient bakeryClient = &c httpc := *bakeryClient.Client bakeryClient.Client = &httpc } apiHost := conn.Config().Location.Host bakeryClient.Client.Transport = &hostSwitchingTransport{ primaryHost: apiHost, primary: utils.NewHttpTLSTransport(tlsConfig), fallback: http.DefaultTransport, } st := &state{ client: client, conn: conn, addr: apiHost, cookieURL: &url.URL{ Scheme: "https", Host: conn.Config().Location.Host, Path: "/", }, serverScheme: "https", serverRootAddress: conn.Config().Location.Host, // why are the contents of the tag (username and password) written into the // state structure BEFORE login ?!? tag: tagToString(info.Tag), password: info.Password, macaroons: info.Macaroons, nonce: info.Nonce, tlsConfig: tlsConfig, bakeryClient: bakeryClient, } if !info.SkipLogin { if err := loginFunc(st, info.Tag, info.Password, info.Nonce, info.Macaroons); err != nil { conn.Close() return nil, err } } st.broken = make(chan struct{}) st.closed = make(chan struct{}) go st.heartbeatMonitor() return st, nil }