Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose new Admin endpoint on orderer for the channel participation API #1939

Merged
merged 2 commits into from
Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions common/fabhttp/fabhttp_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
Copyright IBM Corp All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package fabhttp_test

import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net/http"
"path/filepath"
"testing"

"github.com/hyperledger/fabric/common/crypto/tlsgen"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestFabHTTP(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "FabHTTP Suite")
}

func generateCertificates(tempDir string) {
serverCA, err := tlsgen.NewCA()
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "server-ca.pem"), serverCA.CertBytes(), 0640)
Expect(err).NotTo(HaveOccurred())
serverKeyPair, err := serverCA.NewServerCertKeyPair("127.0.0.1")
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "server-cert.pem"), serverKeyPair.Cert, 0640)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "server-key.pem"), serverKeyPair.Key, 0640)
Expect(err).NotTo(HaveOccurred())

clientCA, err := tlsgen.NewCA()
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "client-ca.pem"), clientCA.CertBytes(), 0640)
Expect(err).NotTo(HaveOccurred())
clientKeyPair, err := clientCA.NewClientCertKeyPair()
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "client-cert.pem"), clientKeyPair.Cert, 0640)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(tempDir, "client-key.pem"), clientKeyPair.Key, 0640)
Expect(err).NotTo(HaveOccurred())
}

func newHTTPClient(tlsDir string, withClientCert bool) *http.Client {
clientCertPool := x509.NewCertPool()
caCert, err := ioutil.ReadFile(filepath.Join(tlsDir, "server-ca.pem"))
Expect(err).NotTo(HaveOccurred())
clientCertPool.AppendCertsFromPEM(caCert)

tlsClientConfig := &tls.Config{
RootCAs: clientCertPool,
}
if withClientCert {
clientCert, err := tls.LoadX509KeyPair(
filepath.Join(tlsDir, "client-cert.pem"),
filepath.Join(tlsDir, "client-key.pem"),
)
Expect(err).NotTo(HaveOccurred())
tlsClientConfig.Certificates = []tls.Certificate{clientCert}
}

return &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsClientConfig,
},
}
}
115 changes: 115 additions & 0 deletions common/fabhttp/fakes/logger.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 144 additions & 0 deletions common/fabhttp/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
Copyright IBM Corp All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package fabhttp

import (
"context"
"crypto/tls"
"net"
"net/http"
"os"
"time"

"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/middleware"
)

//go:generate counterfeiter -o fakes/logger.go -fake-name Logger . Logger

type Logger interface {
Warn(args ...interface{})
Warnf(template string, args ...interface{})
}

type Options struct {
Logger Logger
ListenAddress string
TLS TLS
}

type Server struct {
logger Logger
options Options
httpServer *http.Server
mux *http.ServeMux
addr string
}

func NewServer(o Options) *Server {
logger := o.Logger
if logger == nil {
logger = flogging.MustGetLogger("fabhttp")
}

server := &Server{
logger: logger,
options: o,
}

server.initializeServer()

return server
}

func (s *Server) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missed that, but where do you use this method? It's seems unused.

Copy link
Contributor Author

@wlahti wlahti Oct 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows us to run as an ifrit.Runner. It's currently used in tests via ifrit.Invoke. I preserved this functionality as it was added by Matt when he implemented the operations service.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for the clarification.

err := s.Start()
if err != nil {
return err
}

close(ready)

<-signals
return s.Stop()
}

func (s *Server) Start() error {
listener, err := s.Listen()
if err != nil {
return err
}
s.addr = listener.Addr().String()

go s.httpServer.Serve(listener)

return nil
}

func (s *Server) Stop() error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

return s.httpServer.Shutdown(ctx)
}

func (s *Server) initializeServer() {
s.mux = http.NewServeMux()
s.httpServer = &http.Server{
Addr: s.options.ListenAddress,
Handler: s.mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 2 * time.Minute,
}
}

func (s *Server) HandlerChain(h http.Handler, secure bool) http.Handler {
if secure {
return middleware.NewChain(middleware.RequireCert(), middleware.WithRequestID(util.GenerateUUID)).Handler(h)
}
return middleware.NewChain(middleware.WithRequestID(util.GenerateUUID)).Handler(h)
}

// RegisterHandler registers into the ServeMux a handler chain that borrows
// its security properties from the fabhttp.Server. This method is thread
// safe because ServeMux.Handle() is thread safe, and options are immutable.
// This method can be called either before or after Server.Start(). If the
// pattern exists the method panics.
func (s *Server) RegisterHandler(pattern string, handler http.Handler, secure bool) {
s.mux.Handle(
pattern,
s.HandlerChain(
handler,
secure,
),
)
}

func (s *Server) Listen() (net.Listener, error) {
listener, err := net.Listen("tcp", s.options.ListenAddress)
if err != nil {
return nil, err
}
tlsConfig, err := s.options.TLS.Config()
if err != nil {
return nil, err
}
if tlsConfig != nil {
listener = tls.NewListener(listener, tlsConfig)
}
return listener, nil
}

func (s *Server) Addr() string {
return s.addr
}

func (s *Server) Log(keyvals ...interface{}) error {
s.logger.Warn(keyvals...)
return nil
}
Loading