1// Copyright 2018 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
15package caclient
16
17import (
18	"context"
19	"fmt"
20	"os"
21	"reflect"
22	"testing"
23
24	"istio.io/istio/security/pkg/nodeagent/caclient/providers/google/mock"
25)
26
27const mockServerAddress = "localhost:0"
28
29var (
30	fakeCert  = []string{"foo", "bar"}
31	fakeToken = "Bearer fakeToken"
32)
33
34func TestGoogleCAClient(t *testing.T) {
35	os.Setenv("GKE_CLUSTER_URL", "https://container.googleapis.com/v1/projects/testproj/locations/us-central1-c/clusters/cluster1")
36	defer func() {
37		os.Unsetenv("GKE_CLUSTER_URL")
38	}()
39
40	testCases := map[string]struct {
41		service      mock.CAService
42		expectedCert []string
43		expectedErr  string
44	}{
45		"Valid certs": {
46			service:      mock.CAService{Certs: fakeCert, Err: nil},
47			expectedCert: fakeCert,
48			expectedErr:  "",
49		},
50		"Error in response": {
51			service:      mock.CAService{Certs: nil, Err: fmt.Errorf("test failure")},
52			expectedCert: nil,
53			expectedErr:  "rpc error: code = Unknown desc = test failure",
54		},
55		"Empty response": {
56			service:      mock.CAService{Certs: []string{}, Err: nil},
57			expectedCert: nil,
58			expectedErr:  "invalid response cert chain",
59		},
60	}
61
62	for id, tc := range testCases {
63		// create a local grpc server
64		s, err := mock.CreateServer(mockServerAddress, &tc.service)
65		if err != nil {
66			t.Fatalf("Test case [%s]: failed to create server: %v", id, err)
67		}
68		defer s.Stop()
69
70		cli, err := NewGoogleCAClient(s.Address, false)
71		if err != nil {
72			t.Errorf("Test case [%s]: failed to create ca client: %v", id, err)
73		}
74
75		resp, err := cli.CSRSign(context.Background(), "12345678-1234-1234-1234-123456789012", []byte{01}, fakeToken, 1)
76		if err != nil {
77			if err.Error() != tc.expectedErr {
78				t.Errorf("Test case [%s]: error (%s) does not match expected error (%s)", id, err.Error(), tc.expectedErr)
79			}
80		} else {
81			if tc.expectedErr != "" {
82				t.Errorf("Test case [%s]: expect error: %s but got no error", id, tc.expectedErr)
83			} else if !reflect.DeepEqual(resp, tc.expectedCert) {
84				t.Errorf("Test case [%s]: resp: got %+v, expected %v", id, resp, tc.expectedCert)
85			}
86		}
87	}
88}
89
90func TestParseZone(t *testing.T) {
91	testCases := map[string]struct {
92		clusterURL   string
93		expectedZone string
94	}{
95		"Valid URL": {
96			clusterURL:   "https://container.googleapis.com/v1/projects/testproj1/locations/us-central1-c/clusters/c1",
97			expectedZone: "us-central1-c",
98		},
99		"InValid response": {
100			clusterURL:   "aaa",
101			expectedZone: "",
102		},
103	}
104
105	for id, tc := range testCases {
106		zone := parseZone(tc.clusterURL)
107		if zone != tc.expectedZone {
108			t.Errorf("Test case [%s]: proj: got %+v, expected %v", id, zone, tc.expectedZone)
109		}
110	}
111}
112