istio.io/istio@v0.0.0-20240520182934-d79c90f27776/security/pkg/server/ca/authenticate/cert_authenticator_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package authenticate 16 17 import ( 18 "context" 19 "crypto/tls" 20 "crypto/x509" 21 "crypto/x509/pkix" 22 "reflect" 23 "testing" 24 25 "google.golang.org/grpc/credentials" 26 "google.golang.org/grpc/peer" 27 28 "istio.io/istio/pkg/security" 29 "istio.io/istio/security/pkg/pki/util" 30 ) 31 32 type mockAuthInfo struct { 33 authType string 34 } 35 36 func (ai mockAuthInfo) AuthType() string { 37 return ai.authType 38 } 39 40 func TestAuthenticate_clientCertAuthenticator(t *testing.T) { 41 callerID := "test.identity" 42 ids := []util.Identity{ 43 {Type: util.TypeURI, Value: []byte(callerID)}, 44 } 45 sanExt, err := util.BuildSANExtension(ids) 46 if err != nil { 47 t.Error(err) 48 } 49 50 testCases := map[string]struct { 51 certChain [][]*x509.Certificate 52 caller *security.Caller 53 authenticateErrMsg string 54 fakeAuthInfo *mockAuthInfo 55 }{ 56 "No client certificate": { 57 certChain: nil, 58 caller: nil, 59 authenticateErrMsg: "no client certificate is presented", 60 }, 61 "Unsupported auth type": { 62 certChain: nil, 63 caller: nil, 64 authenticateErrMsg: "unsupported auth type: \"not-tls\"", 65 fakeAuthInfo: &mockAuthInfo{"not-tls"}, 66 }, 67 "Empty cert chain": { 68 certChain: [][]*x509.Certificate{}, 69 caller: nil, 70 authenticateErrMsg: "no verified chain is found", 71 }, 72 "Certificate has no SAN": { 73 certChain: [][]*x509.Certificate{ 74 { 75 { 76 Version: 1, 77 }, 78 }, 79 }, 80 authenticateErrMsg: "the SAN extension does not exist", 81 }, 82 "With client certificate": { 83 certChain: [][]*x509.Certificate{ 84 { 85 { 86 Extensions: []pkix.Extension{*sanExt}, 87 }, 88 }, 89 }, 90 caller: &security.Caller{Identities: []string{callerID}}, 91 }, 92 } 93 94 auth := &ClientCertAuthenticator{} 95 96 for id, tc := range testCases { 97 ctx := context.Background() 98 if tc.certChain != nil { 99 tlsInfo := credentials.TLSInfo{ 100 State: tls.ConnectionState{VerifiedChains: tc.certChain}, 101 } 102 p := &peer.Peer{AuthInfo: tlsInfo} 103 ctx = peer.NewContext(ctx, p) 104 } 105 if tc.fakeAuthInfo != nil { 106 ctx = peer.NewContext(ctx, &peer.Peer{AuthInfo: tc.fakeAuthInfo}) 107 } 108 109 result, err := auth.Authenticate(security.AuthContext{GrpcContext: ctx}) 110 if len(tc.authenticateErrMsg) > 0 { 111 if err == nil { 112 t.Errorf("Case %s: Succeeded. Error expected: %v", id, err) 113 } else if err.Error() != tc.authenticateErrMsg { 114 t.Errorf("Case %s: Incorrect error message: want %s but got %s", 115 id, tc.authenticateErrMsg, err.Error()) 116 } 117 continue 118 } else if err != nil { 119 t.Fatalf("Case %s: Unexpected Error: %v", id, err) 120 } 121 122 if !reflect.DeepEqual(tc.caller, result) { 123 t.Errorf("Case %q: Unexpected authentication result: want %v but got %v", 124 id, tc.caller, result) 125 } 126 } 127 }