github.com/hyperledger/fabric-ca@v2.0.0-alpha.0.20201120210307-7b4f34729db1+incompatible/lib/server/operations/system_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package operations_test
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"net"
    13  	"net/http"
    14  	"os"
    15  	"path/filepath"
    16  	"time"
    17  
    18  	"github.com/hyperledger/fabric-ca/lib/server/operations"
    19  	"github.com/hyperledger/fabric/common/metrics/disabled"
    20  	"github.com/hyperledger/fabric/common/metrics/prometheus"
    21  	"github.com/hyperledger/fabric/common/metrics/statsd"
    22  	. "github.com/onsi/ginkgo"
    23  	. "github.com/onsi/gomega"
    24  )
    25  
    26  var _ = Describe("System", func() {
    27  	var (
    28  		tempDir string
    29  
    30  		authClient   *http.Client
    31  		unauthClient *http.Client
    32  		options      operations.Options
    33  		system       *operations.System
    34  	)
    35  
    36  	BeforeEach(func() {
    37  		var err error
    38  		tempDir, err = ioutil.TempDir("", "system")
    39  		Expect(err).NotTo(HaveOccurred())
    40  
    41  		err = generateCertificates(tempDir)
    42  		Expect(err).NotTo(HaveOccurred())
    43  
    44  		options = operations.Options{
    45  			ListenAddress: "127.0.0.1:0",
    46  			Metrics: operations.MetricsOptions{
    47  				Provider: "disabled",
    48  			},
    49  			TLS: operations.TLS{
    50  				Enabled:            true,
    51  				CertFile:           filepath.Join(tempDir, "server-cert.pem"),
    52  				KeyFile:            filepath.Join(tempDir, "server-key.pem"),
    53  				ClientCertRequired: false,
    54  				ClientCACertFiles:  []string{filepath.Join(tempDir, "client-ca.pem")},
    55  			},
    56  		}
    57  
    58  		system = operations.NewSystem(options)
    59  
    60  		authClient = newHTTPClient(tempDir, true)
    61  		unauthClient = newHTTPClient(tempDir, false)
    62  	})
    63  
    64  	AfterEach(func() {
    65  		os.RemoveAll(tempDir)
    66  		if system != nil {
    67  			system.Stop()
    68  		}
    69  	})
    70  
    71  	It("hosts an unsecured endpoint for the version information", func() {
    72  		err := system.Start()
    73  		Expect(err).NotTo(HaveOccurred())
    74  
    75  		versionURL := fmt.Sprintf("https://%s/version", system.Addr())
    76  		resp, err := unauthClient.Get(versionURL)
    77  		Expect(err).NotTo(HaveOccurred())
    78  		Expect(resp.StatusCode).To(Equal(http.StatusOK))
    79  		resp.Body.Close()
    80  	})
    81  
    82  	Context("when ClientCertRequired is true", func() {
    83  		BeforeEach(func() {
    84  			options.TLS.ClientCertRequired = true
    85  			system = operations.NewSystem(options)
    86  		})
    87  
    88  		It("requires a client cert to connect", func() {
    89  			err := system.Start()
    90  			Expect(err).NotTo(HaveOccurred())
    91  
    92  			_, err = unauthClient.Get(fmt.Sprintf("https://%s/metrics", system.Addr()))
    93  			Expect(err).To(HaveOccurred())
    94  			Expect(err.Error()).To(ContainSubstring("remote error: tls: bad certificate"))
    95  		})
    96  	})
    97  
    98  	Context("when listen fails", func() {
    99  		var listener net.Listener
   100  
   101  		BeforeEach(func() {
   102  			var err error
   103  			listener, err = net.Listen("tcp", "127.0.0.1:0")
   104  			Expect(err).NotTo(HaveOccurred())
   105  
   106  			options.ListenAddress = listener.Addr().String()
   107  			system = operations.NewSystem(options)
   108  		})
   109  
   110  		AfterEach(func() {
   111  			listener.Close()
   112  		})
   113  
   114  		It("returns an error", func() {
   115  			err := system.Start()
   116  			Expect(err).To(HaveOccurred())
   117  			Expect(err.Error()).To(ContainSubstring("bind: address already in use"))
   118  		})
   119  	})
   120  
   121  	Context("when a bad TLS configuration is provided", func() {
   122  		BeforeEach(func() {
   123  			options.TLS.CertFile = "cert-file-does-not-exist"
   124  			system = operations.NewSystem(options)
   125  		})
   126  
   127  		It("returns an error", func() {
   128  			err := system.Start()
   129  			Expect(err).To(MatchError("open cert-file-does-not-exist: no such file or directory"))
   130  		})
   131  	})
   132  
   133  	Context("when the metrics provider is disabled", func() {
   134  		BeforeEach(func() {
   135  			options.Metrics = operations.MetricsOptions{
   136  				Provider: "disabled",
   137  			}
   138  			system = operations.NewSystem(options)
   139  			Expect(system).NotTo(BeNil())
   140  		})
   141  
   142  		It("sets up a disabled provider", func() {
   143  			Expect(system.Provider).To(Equal(&disabled.Provider{}))
   144  		})
   145  	})
   146  
   147  	Context("when the metrics provider is prometheus", func() {
   148  		BeforeEach(func() {
   149  			options.Metrics = operations.MetricsOptions{
   150  				Provider: "prometheus",
   151  			}
   152  			system = operations.NewSystem(options)
   153  			Expect(system).NotTo(BeNil())
   154  		})
   155  
   156  		It("sets up prometheus as a provider", func() {
   157  			Expect(system.Provider).To(Equal(&prometheus.Provider{}))
   158  		})
   159  
   160  		It("hosts a secure endpoint for metrics", func() {
   161  			err := system.Start()
   162  			Expect(err).NotTo(HaveOccurred())
   163  
   164  			metricsURL := fmt.Sprintf("https://%s/metrics", system.Addr())
   165  			resp, err := authClient.Get(metricsURL)
   166  			Expect(err).NotTo(HaveOccurred())
   167  			Expect(resp.StatusCode).To(Equal(http.StatusOK))
   168  			body, err := ioutil.ReadAll(resp.Body)
   169  			resp.Body.Close()
   170  			Expect(err).NotTo(HaveOccurred())
   171  			Expect(body).To(ContainSubstring("# TYPE go_gc_duration_seconds summary"))
   172  		})
   173  	})
   174  
   175  	Context("when the metrics provider is statsd", func() {
   176  		var listener net.Listener
   177  
   178  		BeforeEach(func() {
   179  			var err error
   180  			listener, err = net.Listen("tcp", "127.0.0.1:0")
   181  			Expect(err).NotTo(HaveOccurred())
   182  
   183  			options.Metrics = operations.MetricsOptions{
   184  				Provider: "statsd",
   185  				Statsd: &operations.Statsd{
   186  					Network:       "tcp",
   187  					Address:       listener.Addr().String(),
   188  					WriteInterval: 100 * time.Millisecond,
   189  					Prefix:        "prefix",
   190  				},
   191  			}
   192  			system = operations.NewSystem(options)
   193  			Expect(system).NotTo(BeNil())
   194  		})
   195  
   196  		AfterEach(func() {
   197  			listener.Close()
   198  		})
   199  
   200  		It("sets up statsd as a provider", func() {
   201  			provider, ok := system.Provider.(*statsd.Provider)
   202  			Expect(ok).To(BeTrue())
   203  			Expect(provider.Statsd).NotTo(BeNil())
   204  		})
   205  
   206  		Context("when checking the network and address fails", func() {
   207  			BeforeEach(func() {
   208  				options.Metrics.Statsd.Network = "bob-the-network"
   209  				system = operations.NewSystem(options)
   210  			})
   211  
   212  			It("returns an error", func() {
   213  				err := system.Start()
   214  				Expect(err).To(HaveOccurred())
   215  				Expect(err.Error()).To(ContainSubstring("bob-the-network"))
   216  			})
   217  		})
   218  	})
   219  
   220  	Context("when the metrics provider is unknown", func() {
   221  		BeforeEach(func() {
   222  			options.Metrics.Provider = "something-unknown"
   223  			system = operations.NewSystem(options)
   224  		})
   225  
   226  		It("sets up a disabled provider", func() {
   227  			Expect(system.Provider).To(Equal(&disabled.Provider{}))
   228  		})
   229  	})
   230  })