github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/credentials/spiffe_test.go (about)

     1  /*
     2   *
     3   * Copyright 2020 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package credentials
    20  
    21  import (
    22  	"encoding/pem"
    23  	"io/ioutil"
    24  	"net/url"
    25  	"testing"
    26  
    27  	"github.com/hxx258456/ccgo/x509"
    28  
    29  	tls "github.com/hxx258456/ccgo/gmtls"
    30  
    31  	"github.com/hxx258456/ccgo/grpc/internal/grpctest"
    32  	"github.com/hxx258456/ccgo/grpc/testdata"
    33  )
    34  
    35  const wantURI = "spiffe://foo.bar.com/client/workload/1"
    36  
    37  type s struct {
    38  	grpctest.Tester
    39  }
    40  
    41  func Test(t *testing.T) {
    42  	grpctest.RunSubTests(t, s{})
    43  }
    44  
    45  func (s) TestSPIFFEIDFromState(t *testing.T) {
    46  	tests := []struct {
    47  		name string
    48  		urls []*url.URL
    49  		// If we expect a SPIFFE ID to be returned.
    50  		wantID bool
    51  	}{
    52  		{
    53  			name:   "empty URIs",
    54  			urls:   []*url.URL{},
    55  			wantID: false,
    56  		},
    57  		{
    58  			name: "good SPIFFE ID",
    59  			urls: []*url.URL{
    60  				{
    61  					Scheme:  "spiffe",
    62  					Host:    "foo.bar.com",
    63  					Path:    "workload/wl1",
    64  					RawPath: "workload/wl1",
    65  				},
    66  			},
    67  			wantID: true,
    68  		},
    69  		{
    70  			name: "invalid host",
    71  			urls: []*url.URL{
    72  				{
    73  					Scheme:  "spiffe",
    74  					Host:    "",
    75  					Path:    "workload/wl1",
    76  					RawPath: "workload/wl1",
    77  				},
    78  			},
    79  			wantID: false,
    80  		},
    81  		{
    82  			name: "invalid path",
    83  			urls: []*url.URL{
    84  				{
    85  					Scheme:  "spiffe",
    86  					Host:    "foo.bar.com",
    87  					Path:    "",
    88  					RawPath: "",
    89  				},
    90  			},
    91  			wantID: false,
    92  		},
    93  		{
    94  			name: "large path",
    95  			urls: []*url.URL{
    96  				{
    97  					Scheme:  "spiffe",
    98  					Host:    "foo.bar.com",
    99  					Path:    string(make([]byte, 2050)),
   100  					RawPath: string(make([]byte, 2050)),
   101  				},
   102  			},
   103  			wantID: false,
   104  		},
   105  		{
   106  			name: "large host",
   107  			urls: []*url.URL{
   108  				{
   109  					Scheme:  "spiffe",
   110  					Host:    string(make([]byte, 256)),
   111  					Path:    "workload/wl1",
   112  					RawPath: "workload/wl1",
   113  				},
   114  			},
   115  			wantID: false,
   116  		},
   117  		{
   118  			name: "multiple URI SANs",
   119  			urls: []*url.URL{
   120  				{
   121  					Scheme:  "spiffe",
   122  					Host:    "foo.bar.com",
   123  					Path:    "workload/wl1",
   124  					RawPath: "workload/wl1",
   125  				},
   126  				{
   127  					Scheme:  "spiffe",
   128  					Host:    "bar.baz.com",
   129  					Path:    "workload/wl2",
   130  					RawPath: "workload/wl2",
   131  				},
   132  				{
   133  					Scheme:  "https",
   134  					Host:    "foo.bar.com",
   135  					Path:    "workload/wl1",
   136  					RawPath: "workload/wl1",
   137  				},
   138  			},
   139  			wantID: false,
   140  		},
   141  		{
   142  			name: "multiple URI SANs without SPIFFE ID",
   143  			urls: []*url.URL{
   144  				{
   145  					Scheme:  "https",
   146  					Host:    "foo.bar.com",
   147  					Path:    "workload/wl1",
   148  					RawPath: "workload/wl1",
   149  				},
   150  				{
   151  					Scheme:  "ssh",
   152  					Host:    "foo.bar.com",
   153  					Path:    "workload/wl1",
   154  					RawPath: "workload/wl1",
   155  				},
   156  			},
   157  			wantID: false,
   158  		},
   159  		{
   160  			name: "multiple URI SANs with one SPIFFE ID",
   161  			urls: []*url.URL{
   162  				{
   163  					Scheme:  "spiffe",
   164  					Host:    "foo.bar.com",
   165  					Path:    "workload/wl1",
   166  					RawPath: "workload/wl1",
   167  				},
   168  				{
   169  					Scheme:  "https",
   170  					Host:    "foo.bar.com",
   171  					Path:    "workload/wl1",
   172  					RawPath: "workload/wl1",
   173  				},
   174  			},
   175  			wantID: false,
   176  		},
   177  	}
   178  	for _, tt := range tests {
   179  		t.Run(tt.name, func(t *testing.T) {
   180  			state := tls.ConnectionState{PeerCertificates: []*x509.Certificate{{URIs: tt.urls}}}
   181  			id := SPIFFEIDFromState(state)
   182  			if got, want := id != nil, tt.wantID; got != want {
   183  				t.Errorf("want wantID = %v, but SPIFFE ID is %v", want, id)
   184  			}
   185  		})
   186  	}
   187  }
   188  
   189  func (s) TestSPIFFEIDFromCert(t *testing.T) {
   190  	tests := []struct {
   191  		name     string
   192  		dataPath string
   193  		// If we expect a SPIFFE ID to be returned.
   194  		wantID bool
   195  	}{
   196  		{
   197  			name:     "good certificate with SPIFFE ID",
   198  			dataPath: "x509/spiffe_cert.pem",
   199  			wantID:   true,
   200  		},
   201  		{
   202  			name:     "bad certificate with SPIFFE ID and another URI",
   203  			dataPath: "x509/multiple_uri_cert.pem",
   204  			wantID:   false,
   205  		},
   206  		{
   207  			name:     "certificate without SPIFFE ID",
   208  			dataPath: "x509/client1_cert.pem",
   209  			wantID:   false,
   210  		},
   211  	}
   212  	for _, tt := range tests {
   213  		t.Run(tt.name, func(t *testing.T) {
   214  			data, err := ioutil.ReadFile(testdata.Path(tt.dataPath))
   215  			if err != nil {
   216  				t.Fatalf("ioutil.ReadFile(%s) failed: %v", testdata.Path(tt.dataPath), err)
   217  			}
   218  			block, _ := pem.Decode(data)
   219  			if block == nil {
   220  				t.Fatalf("Failed to parse the certificate: byte block is nil")
   221  			}
   222  			cert, err := x509.ParseCertificate(block.Bytes)
   223  			if err != nil {
   224  				t.Fatalf("x509.ParseCertificate(%b) failed: %v", block.Bytes, err)
   225  			}
   226  			uri := SPIFFEIDFromCert(cert)
   227  			if (uri != nil) != tt.wantID {
   228  				t.Fatalf("wantID got and want mismatch, got %t, want %t", uri != nil, tt.wantID)
   229  			}
   230  			if uri != nil && uri.String() != wantURI {
   231  				t.Fatalf("SPIFFE ID not expected, got %s, want %s", uri.String(), wantURI)
   232  			}
   233  		})
   234  	}
   235  }