gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/lib/servercertificates_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lib
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  	"testing"
    17  
    18  	"gitee.com/zhaochuninhefei/gmgo/gmhttp/httptest"
    19  
    20  	http "gitee.com/zhaochuninhefei/gmgo/gmhttp"
    21  
    22  	"gitee.com/zhaochuninhefei/cfssl-gm/certdb"
    23  	"gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/api"
    24  	"gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util"
    25  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib/caerrors"
    26  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib/mocks"
    27  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/certificaterequest"
    28  	dbutil "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/db/util"
    29  	dbuser "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/user"
    30  	"gitee.com/zhaochuninhefei/fabric-gm/common/metrics/metricsfakes"
    31  	"github.com/pkg/errors"
    32  	"github.com/stretchr/testify/assert"
    33  )
    34  
    35  func TestCertificatesHandler(t *testing.T) {
    36  	ctx := new(serverRequestContextImpl)
    37  	req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{}))
    38  	assert.NoError(t, err)
    39  	ctx.req = req
    40  	_, err = certificatesHandler(ctx)
    41  	util.ErrorContains(t, err, "No authorization header", "Failed to catch error")
    42  }
    43  
    44  func TestAuthChecks(t *testing.T) {
    45  	ctxMock := new(mocks.ServerRequestContext)
    46  	ctxMock.On("GetCaller").Return(nil, errors.New("Failed to get caller"))
    47  	err := authChecks(ctxMock)
    48  	util.ErrorContains(t, err, "Failed to get caller", "Expected to catch error from GetCaller() func")
    49  
    50  	ctx := new(serverRequestContextImpl)
    51  	user := &dbuser.Record{
    52  		Name: "NotRegistrar",
    53  	}
    54  	ctx.caller = dbuser.New(user, nil)
    55  	err = authChecks(ctx)
    56  	assert.Error(t, err, "Caller does not possess the appropriate attributes to request manage certificates")
    57  
    58  	attributes := []api.Attribute{
    59  		api.Attribute{
    60  			Name:  "hf.Registrar.Roles",
    61  			Value: "peer,client",
    62  		},
    63  	}
    64  
    65  	attr, err := util.Marshal(attributes, "attributes")
    66  	util.FatalError(t, err, "Failed to marshal attributes")
    67  	user = &dbuser.Record{
    68  		Name:       "Registrar",
    69  		Attributes: string(attr),
    70  	}
    71  	ctx.caller = dbuser.New(user, nil)
    72  	err = authChecks(ctx)
    73  	assert.NoError(t, err, "Should not fail, caller has 'hf.Registrar.Roles' attribute")
    74  
    75  	attributes = []api.Attribute{
    76  		api.Attribute{
    77  			Name:  "hf.Revoker",
    78  			Value: "true",
    79  		},
    80  	}
    81  	attr, err = util.Marshal(attributes, "attributes")
    82  	util.FatalError(t, err, "Failed to marshal attributes")
    83  	user = &dbuser.Record{
    84  		Name:       "Revoker",
    85  		Attributes: string(attr),
    86  	}
    87  	ctx.caller = dbuser.New(user, nil)
    88  	err = authChecks(ctx)
    89  	assert.NoError(t, err, "Should not fail, caller has 'hf.Revoker' with a value of 'true' attribute")
    90  
    91  	ctx = new(serverRequestContextImpl)
    92  	attributes = []api.Attribute{
    93  		api.Attribute{
    94  			Name:  "hf.Revoker",
    95  			Value: "false",
    96  		},
    97  	}
    98  	attr, err = util.Marshal(attributes, "attributes")
    99  	util.FatalError(t, err, "Failed to marshal attributes")
   100  	user = &dbuser.Record{
   101  		Name:       "NotRevoker",
   102  		Attributes: string(attr),
   103  	}
   104  	ctx.caller = dbuser.New(user, nil)
   105  	err = authChecks(ctx)
   106  	assert.Error(t, err, "Should fail, caller has 'hf.Revoker' but with a value of 'false' attribute")
   107  }
   108  
   109  func TestProcessCertificateRequest(t *testing.T) {
   110  	ctx := new(mocks.ServerRequestContext)
   111  	ctx.On("TokenAuthentication").Return("", errors.New("Token Auth Failed"))
   112  	err := processCertificateRequest(ctx)
   113  	util.ErrorContains(t, err, "Token Auth Failed", "Should have failed token auth")
   114  
   115  	ctx = new(mocks.ServerRequestContext)
   116  	ctx.On("TokenAuthentication").Return("", nil)
   117  	ctx.On("HasRole", "hf.Revoker").Return(errors.New("Does not have attribute"))
   118  	attr, err := util.Marshal([]api.Attribute{}, "attributes")
   119  	util.FatalError(t, err, "Failed to marshal attributes")
   120  	user := &dbuser.Record{
   121  		Name:       "NotRevoker",
   122  		Attributes: string(attr),
   123  	}
   124  	ctx.On("GetCaller").Return(dbuser.New(user, nil), nil)
   125  
   126  	err = processCertificateRequest(ctx)
   127  	t.Log("Error: ", err)
   128  	util.ErrorContains(t, err, fmt.Sprintf("%d", caerrors.ErrAuthorizationFailure), "Should have failed to due improper permissions")
   129  
   130  	ctx = new(mocks.ServerRequestContext)
   131  	ctx.On("TokenAuthentication").Return("", nil)
   132  	ctx.On("HasRole", "hf.Revoker").Return(nil)
   133  	ctx.On("GetCaller").Return(dbuser.New(user, nil), nil)
   134  	req, err := http.NewRequest("POST", "", bytes.NewReader([]byte{}))
   135  	util.FatalError(t, err, "Failed to get HTTP request")
   136  	ctx.On("GetReq").Return(req)
   137  	err = processCertificateRequest(ctx)
   138  	t.Log("Error: ", err)
   139  	util.ErrorContains(t, err, "Invalid request", "Should have failed to incorrect method type on HTTP request")
   140  
   141  }
   142  
   143  func TestProcessGetCertificateRequest(t *testing.T) {
   144  	ctx := new(serverRequestContextImpl)
   145  	req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{}))
   146  	util.FatalError(t, err, "Failed to get GET HTTP request")
   147  
   148  	url := req.URL.Query()
   149  	url.Add("revoked_end", "2012-12-123")
   150  	req.URL.RawQuery = url.Encode()
   151  	ctx.req = req
   152  	err = processGetCertificateRequest(ctx)
   153  	assert.Error(t, err, "Invalid time format, should have failed")
   154  
   155  	req, err = http.NewRequest("GET", "", bytes.NewReader([]byte{}))
   156  	util.FatalError(t, err, "Failed to get GET HTTP request")
   157  	url = req.URL.Query()
   158  	url.Add("notrevoked", "not_bool")
   159  	req.URL.RawQuery = url.Encode()
   160  	ctx.req = req
   161  
   162  	err = processGetCertificateRequest(ctx)
   163  	assert.Error(t, err, "Invalid boolean value, should have failed")
   164  
   165  	req, err = http.NewRequest("GET", "", bytes.NewReader([]byte{}))
   166  	util.FatalError(t, err, "Failed to get GET HTTP request")
   167  	url = req.URL.Query()
   168  	url.Add("revoked_end", "2012-12-12")
   169  	url.Add("notrevoked", "true")
   170  	req.URL.RawQuery = url.Encode()
   171  	ctx.req = req
   172  
   173  	err = processGetCertificateRequest(ctx)
   174  	assert.Error(t, err, "Invalid combination of filters, should have failed")
   175  }
   176  
   177  type mockHTTPWriter struct {
   178  	http.ResponseWriter
   179  	t *testing.T
   180  }
   181  
   182  // Header returns the header map that will be sent by WriteHeader.
   183  func (m *mockHTTPWriter) Header() http.Header {
   184  	return m.ResponseWriter.Header()
   185  }
   186  
   187  // WriteHeader sends an HTTP response header with status code.
   188  func (m *mockHTTPWriter) WriteHeader(scode int) {
   189  	m.WriteHeader(1)
   190  }
   191  
   192  // Write writes the data to the connection as part of an HTTP reply.
   193  func (m *mockHTTPWriter) Write(buf []byte) (int, error) {
   194  	w := m.ResponseWriter
   195  	if !strings.Contains(string(buf), "certs") && !strings.Contains(string(buf), "BEGIN CERTIFICATE") && !strings.Contains(string(buf), "caname") {
   196  		m.t.Error("Invalid response being sent back from certificates endpoint")
   197  	}
   198  	return w.Write(buf)
   199  }
   200  
   201  // Write writes the data to the connection as part of an HTTP reply.
   202  func (m *mockHTTPWriter) Flush() {}
   203  
   204  func TestServerGetCertificates(t *testing.T) {
   205  	os.RemoveAll("getCertTest")
   206  	defer os.RemoveAll("getCertTest")
   207  	var err error
   208  
   209  	level := &dbutil.Levels{
   210  		Affiliation: 1,
   211  		Identity:    1,
   212  		Certificate: 1,
   213  	}
   214  	mockOperationsServer := &mocks.OperationsServer{}
   215  	fakeCounter := &metricsfakes.Counter{}
   216  	fakeCounter.WithReturns(fakeCounter)
   217  	mockOperationsServer.NewCounterReturns(fakeCounter)
   218  	fakeHistogram := &metricsfakes.Histogram{}
   219  	fakeHistogram.WithReturns(fakeHistogram)
   220  	mockOperationsServer.NewHistogramReturns(fakeHistogram)
   221  	srv := &Server{
   222  		Operations: mockOperationsServer,
   223  		levels:     level,
   224  	}
   225  	ca, err := newCA("getCertTest/config.yaml", &CAConfig{}, srv, false)
   226  	util.FatalError(t, err, "Failed to get CA")
   227  
   228  	ctx := new(serverRequestContextImpl)
   229  	req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{}))
   230  	util.FatalError(t, err, "Failed to get GET HTTP request")
   231  
   232  	user := &dbuser.Record{
   233  		Name: "NotRevoker",
   234  	}
   235  	ctx.caller = dbuser.New(user, nil)
   236  
   237  	ctx.req = req
   238  	ctx.ca = ca
   239  	w := httptest.NewRecorder()
   240  	ctx.resp = &mockHTTPWriter{w, t}
   241  
   242  	err = testInsertCertificate(&certdb.CertificateRecord{
   243  		Serial: "1111",
   244  		AKI:    "9876",
   245  	}, "testCertificate", ca)
   246  	util.FatalError(t, err, "Failed to insert certificate with serial/AKI")
   247  
   248  	err = getCertificates(ctx, &certificaterequest.Impl{})
   249  	assert.NoError(t, err, "Should not have returned error, failed to process GET certificate request")
   250  
   251  	mockCtx := new(mocks.ServerRequestContext)
   252  	mockCtx.On("GetResp").Return(nil)
   253  	mockCtx.On("GetCaller").Return(nil, errors.New("failed to get caller"))
   254  	err = getCertificates(mockCtx, nil)
   255  	util.ErrorContains(t, err, "failed to get caller", "did not get correct error response")
   256  
   257  	testUser := dbuser.New(&dbuser.Record{Name: "testuser"}, nil)
   258  	mockCtx = new(mocks.ServerRequestContext)
   259  	mockCtx.On("GetResp").Return(nil)
   260  	mockCtx.On("GetCaller").Return(testUser, nil)
   261  	mockCtx.On("GetCertificates", (*certificaterequest.Impl)(nil), "").Return(nil, errors.New("failed to get certificates"))
   262  	err = getCertificates(mockCtx, nil)
   263  	util.ErrorContains(t, err, "failed to get certificates", "did not get correct error response")
   264  }
   265  
   266  func TestStoreCert(t *testing.T) {
   267  	dir, err := ioutil.TempDir("", "testStoreCert")
   268  	assert.NoError(t, err, "failed to create temp directory")
   269  	defer os.RemoveAll(dir)
   270  
   271  	cd := NewCertificateDecoder(dir)
   272  	err = cd.storeCert("testID", dir, []byte("testing store cert function"))
   273  	assert.NoError(t, err, "failed to store cert")
   274  
   275  	filePath := filepath.Join(dir, "testID.pem")
   276  	assert.Equal(t, true, util.FileExists(filePath))
   277  
   278  	cert, err := ioutil.ReadFile(filePath)
   279  	assert.NoError(t, err, "failed to read certificate file")
   280  	assert.Equal(t, "testing store cert function", string(cert))
   281  
   282  	err = cd.storeCert("testID", dir, []byte("testing store cert function - second cert"))
   283  	assert.NoError(t, err, "failed to store cert")
   284  
   285  	filePath = filepath.Join(dir, "testID-1.pem")
   286  	assert.Equal(t, true, util.FileExists(filePath))
   287  	cert, err = ioutil.ReadFile(filePath)
   288  	assert.NoError(t, err, "failed to read certificate file")
   289  	assert.Equal(t, "testing store cert function", string(cert))
   290  
   291  	filePath = filepath.Join(dir, "testID-2.pem")
   292  	assert.Equal(t, true, util.FileExists(filePath))
   293  	cert, err = ioutil.ReadFile(filePath)
   294  	assert.NoError(t, err, "failed to read certificate file")
   295  	assert.Equal(t, "testing store cert function - second cert", string(cert))
   296  
   297  	err = cd.storeCert("testID", dir, []byte("testing store cert function - third cert"))
   298  	assert.NoError(t, err, "failed to store cert")
   299  	filePath = filepath.Join(dir, "testID-3.pem")
   300  	assert.Equal(t, true, util.FileExists(filePath))
   301  
   302  	// Error case - renaming a certificate file that does not exist should fail
   303  	cd = NewCertificateDecoder(dir)
   304  	cd.certIDCount["testID2"] = 1
   305  	err = cd.storeCert("testID2", dir, []byte("testing store cert function"))
   306  	util.ErrorContains(t, err, "Failed to rename certificate", "Should have failed")
   307  }