summaryrefslogtreecommitdiff
path: root/client/httpsclient_test.go
blob: d2c22938224aea1a1357bec537205c0e98ee7aa2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package client

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"path"
	"testing"

	"github.com/stretchr/testify/require"
	"gitlab.com/gitlab-org/gitlab-shell/client/testserver"
	"gitlab.com/gitlab-org/gitlab-shell/internal/testhelper"
)

//go:generate openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -out ../internal/testhelper/testdata/testroot/certs/client/server.crt -keyout ../internal/testhelper/testdata/testroot/certs/client/key.pem -subj "/C=US/ST=California/L=San Francisco/O=GitLab/OU=GitLab-Shell/CN=localhost"
func TestSuccessfulRequests(t *testing.T) {
	testCases := []struct {
		desc                                        string
		caFile, caPath                              string
		selfSigned                                  bool
		clientCAPath, clientCertPath, clientKeyPath string // used for TLS client certs
	}{
		{
			desc:   "Valid CaFile",
			caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"),
		},
		{
			desc:   "Valid CaPath",
			caPath: path.Join(testhelper.TestRoot, "certs/valid"),
			caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"),
		},
		{
			desc:       "Invalid cert with self signed cert option enabled",
			caFile:     path.Join(testhelper.TestRoot, "certs/valid/server.crt"),
			selfSigned: true,
		},
		{
			desc:   "Client certs with CA",
			caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"),
			// Run the command "go generate httpsclient_test.go" to
			// regenerate the following test fixtures:
			clientCAPath:   path.Join(testhelper.TestRoot, "certs/client/server.crt"),
			clientCertPath: path.Join(testhelper.TestRoot, "certs/client/server.crt"),
			clientKeyPath:  path.Join(testhelper.TestRoot, "certs/client/key.pem"),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.desc, func(t *testing.T) {
			client, err := setupWithRequests(t, tc.caFile, tc.caPath, tc.clientCAPath, tc.clientCertPath, tc.clientKeyPath, tc.selfSigned)
			require.NoError(t, err)

			response, err := client.Get(context.Background(), "/hello")
			require.NoError(t, err)
			require.NotNil(t, response)

			defer response.Body.Close()

			responseBody, err := io.ReadAll(response.Body)
			require.NoError(t, err)
			require.Equal(t, string(responseBody), "Hello")
		})
	}
}

func TestFailedRequests(t *testing.T) {
	testCases := []struct {
		desc          string
		caFile        string
		caPath        string
		expectedError string
	}{
		{
			desc:          "Invalid CaFile",
			caFile:        path.Join(testhelper.TestRoot, "certs/invalid/server.crt"),
			expectedError: "Internal API unreachable",
		},
		{
			desc:   "Invalid CaPath",
			caPath: path.Join(testhelper.TestRoot, "certs/invalid"),
		},
		{
			desc: "Empty config",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.desc, func(t *testing.T) {
			client, err := setupWithRequests(t, tc.caFile, tc.caPath, "", "", "", false)
			if tc.caFile == "" {
				require.Error(t, err)
				require.ErrorIs(t, err, ErrCafileNotFound)
			} else {
				_, err = client.Get(context.Background(), "/hello")
				require.Error(t, err)

				require.Equal(t, err.Error(), tc.expectedError)
			}
		})
	}
}

func setupWithRequests(t *testing.T, caFile, caPath, clientCAPath, clientCertPath, clientKeyPath string, selfSigned bool) (*GitlabNetClient, error) {
	testhelper.PrepareTestRootDir(t)

	requests := []testserver.TestRequestHandler{
		{
			Path: "/api/v4/internal/hello",
			Handler: func(w http.ResponseWriter, r *http.Request) {
				require.Equal(t, http.MethodGet, r.Method)

				fmt.Fprint(w, "Hello")
			},
		},
	}

	url := testserver.StartHttpsServer(t, requests, clientCAPath)

	var opts []HTTPClientOpt
	if clientCertPath != "" && clientKeyPath != "" {
		opts = append(opts, WithClientCert(clientCertPath, clientKeyPath))
	}

	httpClient, err := NewHTTPClientWithOpts(url, "", caFile, caPath, selfSigned, 1, opts)
	if err != nil {
		return nil, err
	}

	client, err := NewGitlabNetClient("", "", "", httpClient)

	return client, err
}