From 10d23a0393b12efc230435b3cc1125f2ff1cfb02 Mon Sep 17 00:00:00 2001 From: Stephen Nelson <stephen@sfnelson.org> Date: Sat, 7 May 2016 23:28:12 +1200 Subject: [PATCH] Add support for TLS client authentication Allow gitlab-ci to connect to a gitlab host using TLS client authentication (mutual authentication). Adds configuration and support for using TLS client certificates when using go's TLS transport layer and also sets git enviromental variables for runners. --- common/build.go | 25 ++++ common/config.go | 16 +- common/network.go | 22 ++- docs/configuration/advanced-configuration.md | 2 + network/client.go | 96 +++++++++--- network/client_test.go | 148 ++++++++++++++++++- network/gitlab.go | 28 +++- network/gitlab_test.go | 20 ++- shells/abstract.go | 18 +-- 9 files changed, 323 insertions(+), 52 deletions(-) diff --git a/common/build.go b/common/build.go index 2f289c5c82c..02baaa4193d 100644 --- a/common/build.go +++ b/common/build.go @@ -382,11 +382,36 @@ func (b *Build) GetDefaultVariables() JobVariables { } } +func (b *Build) GetCITLSVariables() JobVariables { + variables := JobVariables{} + if b.TLSCAChain != "" { + variables = append(variables, JobVariable{"CI_SERVER_TLS_CA_FILE", b.TLSCAChain, true, true, true}) + } + if b.TLSAuthCert != "" && b.TLSAuthKey != "" { + variables = append(variables, JobVariable{"CI_SERVER_TLS_CERT_FILE", b.TLSAuthCert, true, true, true}) + variables = append(variables, JobVariable{"CI_SERVER_TLS_KEY_FILE", b.TLSAuthKey, true, true, true}) + } + return variables +} + +func (b *Build) GetGitTLSVariables() JobVariables { + variables := JobVariables{} + if b.TLSCAChain != "" { + variables = append(variables, JobVariable{"GIT_SSL_CAINFO", b.TLSCAChain, true, true, true}) + } + if b.TLSAuthCert != "" && b.TLSAuthKey != "" { + variables = append(variables, JobVariable{"GIT_SSL_CERT", b.TLSAuthCert, true, true, true}) + variables = append(variables, JobVariable{"GIT_SSL_KEY", b.TLSAuthKey, true, true, true}) + } + return variables +} + func (b *Build) GetAllVariables() (variables JobVariables) { if b.Runner != nil { variables = append(variables, b.Runner.GetVariables()...) } variables = append(variables, b.GetDefaultVariables()...) + variables = append(variables, b.GetCITLSVariables()...) variables = append(variables, b.Variables...) return variables.Expand() } diff --git a/common/config.go b/common/config.go index c8034080236..5c576be6146 100644 --- a/common/config.go +++ b/common/config.go @@ -149,9 +149,11 @@ type KubernetesConfig struct { } type RunnerCredentials struct { - URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"` - Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"` - TLSCAFile string `toml:"tls-ca-file,omitempty" json:"tls-ca-file" long:"tls-ca-file" env:"CI_SERVER_TLS_CA_FILE" description:"File containing the certificates to verify the peer when using HTTPS"` + URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"` + Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"` + TLSCAFile string `toml:"tls-ca-file,omitempty" json:"tls-ca-file" long:"tls-ca-file" env:"CI_SERVER_TLS_CA_FILE" description:"File containing the certificates to verify the peer when using HTTPS"` + TLSCertFile string `toml:"tls-cert-file,omitempty" json:"tls-cert-file" long:"tls-cert-file" env:"CI_SERVER_TLS_CERT_FILE" description:"File containing certificate for TLS client auth when using HTTPS"` + TLSKeyFile string `toml:"tls-key-file,omitempty" json:"tls-key-file" long:"tls-key-file" env:"CI_SERVER_TLS_KEY_FILE" description:"File containing private key for TLS client auth when using HTTPS"` } type CacheConfig struct { @@ -279,6 +281,14 @@ func (c *RunnerCredentials) GetTLSCAFile() string { return c.TLSCAFile } +func (c *RunnerCredentials) GetTLSCertFile() string { + return c.TLSCertFile +} + +func (c *RunnerCredentials) GetTLSKeyFile() string { + return c.TLSKeyFile +} + func (c *RunnerCredentials) GetToken() string { return c.Token } diff --git a/common/network.go b/common/network.go index 17172068f4d..d37f48a52ef 100644 --- a/common/network.go +++ b/common/network.go @@ -209,7 +209,9 @@ type JobResponse struct { Credentials []Credentials `json:"credentials"` Dependencies Dependencies `json:"dependencies"` - TLSCAChain string `json:"-"` + TLSCAChain string `json:"-"` + TLSAuthCert string `json:"-"` + TLSAuthKey string `json:"-"` } func (j *JobResponse) RepoCleanURL() string { @@ -224,10 +226,12 @@ type UpdateJobRequest struct { } type JobCredentials struct { - ID int `long:"id" env:"CI_JOB_ID" description:"The build ID to upload artifacts for"` - Token string `long:"token" env:"CI_JOB_TOKEN" required:"true" description:"Build token"` - URL string `long:"url" env:"CI_SERVER_URL" required:"true" description:"GitLab CI URL"` - TLSCAFile string `long:"tls-ca-file" env:"CI_SERVER_TLS_CA_FILE" description:"File containing the certificates to verify the peer when using HTTPS"` + ID int `long:"id" env:"CI_JOB_ID" description:"The build ID to upload artifacts for"` + Token string `long:"token" env:"CI_JOB_TOKEN" required:"true" description:"Build token"` + URL string `long:"url" env:"CI_SERVER_URL" required:"true" description:"GitLab CI URL"` + TLSCAFile string `long:"tls-ca-file" env:"CI_SERVER_TLS_CA_FILE" description:"File containing the certificates to verify the peer when using HTTPS"` + TLSCertFile string `long:"tls-cert-file" env:"CI_SERVER_TLS_CERT_FILE" description:"File containing certificate for TLS client auth with runner when using HTTPS"` + TLSKeyFile string `long:"tls-key-file" env:"CI_SERVER_TLS_KEY_FILE" description:"File containing private key for TLS client auth with runner when using HTTPS"` } func (j *JobCredentials) GetURL() string { @@ -238,6 +242,14 @@ func (j *JobCredentials) GetTLSCAFile() string { return j.TLSCAFile } +func (j *JobCredentials) GetTLSCertFile() string { + return j.TLSCertFile +} + +func (j *JobCredentials) GetTLSKeyFile() string { + return j.TLSKeyFile +} + func (j *JobCredentials) GetToken() string { return j.Token } diff --git a/docs/configuration/advanced-configuration.md b/docs/configuration/advanced-configuration.md index 2a559ce8ccb..89f69358f31 100644 --- a/docs/configuration/advanced-configuration.md +++ b/docs/configuration/advanced-configuration.md @@ -39,6 +39,8 @@ This defines one runner entry. | `url` | CI URL | | `token` | runner token | | `tls-ca-file` | file containing the certificates to verify the peer when using HTTPS | +| `tls-cert-file` | file containing the certificate to authenticate with the peer when using HTTPS | +| `tls-key-file` | file containing the private key to authenticate with the peer when using HTTPS | | `tls-skip-verify` | whether to verify the TLS certificate when using HTTPS, default: false | | `limit` | limit how many jobs can be handled concurrently by this token. `0` (default) simply means don't limit | | `executor` | select how a project should be built, see next section | diff --git a/network/client.go b/network/client.go index 99f02c55e57..8e3a2dfd96e 100644 --- a/network/client.go +++ b/network/client.go @@ -29,6 +29,8 @@ type requestCredentials interface { GetURL() string GetToken() string GetTLSCAFile() string + GetTLSCertFile() string + GetTLSKeyFile() string } var dialer = net.Dialer{ @@ -40,6 +42,8 @@ type client struct { http.Client url *url.URL caFile string + certFile string + keyFile string caData []byte skipVerify bool updateTime time.Time @@ -47,6 +51,12 @@ type client struct { compatibleWithGitLab bool } +type ResponseTLSData struct { + CAChain string + CertFile string + KeyFile string +} + func (n *client) getLastUpdate() string { return n.lastUpdate } @@ -63,6 +73,16 @@ func (n *client) ensureTLSConfig() { n.Transport = nil } + // client certificate got modified + if stat, err := os.Stat(n.certFile); err == nil && n.updateTime.Before(stat.ModTime()) { + n.Transport = nil + } + + // client private key got modified + if stat, err := os.Stat(n.keyFile); err == nil && n.updateTime.Before(stat.ModTime()) { + n.Transport = nil + } + // create or update transport if n.Transport == nil { n.updateTime = time.Now() @@ -70,14 +90,8 @@ func (n *client) ensureTLSConfig() { } } -func (n *client) createTransport() { - // create reference TLS config - tlsConfig := tls.Config{ - MinVersion: tls.VersionTLS10, - InsecureSkipVerify: n.skipVerify, - } - - // load TLS certificate +func (n *client) addTLSCA(tlsConfig *tls.Config) { + // load TLS CA certificate if file := n.caFile; file != "" && !n.skipVerify { logrus.Debugln("Trying to load", file, "...") @@ -96,6 +110,34 @@ func (n *client) createTransport() { } } } +} + +func (n *client) addTLSAuth(tlsConfig *tls.Config) { + // load TLS client keypair + if cert, key := n.certFile, n.keyFile; cert != "" && key != "" { + logrus.Debugln("Trying to load", cert, "and", key, "pair...") + + certificate, err := tls.LoadX509KeyPair(cert, key) + if err == nil { + tlsConfig.Certificates = []tls.Certificate{certificate} + tlsConfig.BuildNameToCertificate() + } else { + if !os.IsNotExist(err) { + logrus.Errorln("Failed to load", cert, key, err) + } + } + } +} + +func (n *client) createTransport() { + // create reference TLS config + tlsConfig := tls.Config{ + MinVersion: tls.VersionTLS10, + InsecureSkipVerify: n.skipVerify, + } + + n.addTLSCA(&tlsConfig) + n.addTLSAuth(&tlsConfig) // create transport n.Transport = &http.Transport{ @@ -175,13 +217,13 @@ func (n *client) do(uri, method string, request io.Reader, requestType string, h return } -func (n *client) doJSON(uri, method string, statusCode int, request interface{}, response interface{}) (int, string, string) { +func (n *client) doJSON(uri, method string, statusCode int, request interface{}, response interface{}) (int, string, ResponseTLSData) { var body io.Reader if request != nil { requestBody, err := json.Marshal(request) if err != nil { - return -1, fmt.Sprintf("failed to marshal project object: %v", err), "" + return -1, fmt.Sprintf("failed to marshal project object: %v", err), ResponseTLSData{} } body = bytes.NewReader(requestBody) } @@ -193,7 +235,7 @@ func (n *client) doJSON(uri, method string, statusCode int, request interface{}, res, err := n.do(uri, method, body, "application/json", headers) if err != nil { - return -1, err.Error(), "" + return -1, err.Error(), ResponseTLSData{} } defer res.Body.Close() defer io.Copy(ioutil.Discard, res.Body) @@ -202,20 +244,26 @@ func (n *client) doJSON(uri, method string, statusCode int, request interface{}, if response != nil { isApplicationJSON, err := isResponseApplicationJSON(res) if !isApplicationJSON { - return -1, err.Error(), "" + return -1, err.Error(), ResponseTLSData{} } d := json.NewDecoder(res.Body) err = d.Decode(response) if err != nil { - return -1, fmt.Sprintf("Error decoding json payload %v", err), "" + return -1, fmt.Sprintf("Error decoding json payload %v", err), ResponseTLSData{} } } } n.setLastUpdate(res.Header) - return res.StatusCode, res.Status, n.getCAChain(res.TLS) + TLSData := ResponseTLSData{ + CAChain: n.getCAChain(res.TLS), + CertFile: n.certFile, + KeyFile: n.keyFile, + } + + return res.StatusCode, res.Status, TLSData } func isResponseApplicationJSON(res *http.Response) (result bool, err error) { @@ -241,6 +289,16 @@ func fixCIURL(url string) string { return url } +func (n *client) findCertificate(certificate *string, base string, name string) { + if *certificate != "" { + return + } + path := filepath.Join(base, name) + if _, err := os.Stat(path); err == nil { + *certificate = path + } +} + func newClient(requestCredentials requestCredentials) (c *client, err error) { url, err := url.Parse(fixCIURL(requestCredentials.GetURL()) + "/api/v4/") if err != nil { @@ -255,12 +313,16 @@ func newClient(requestCredentials requestCredentials) (c *client, err error) { c = &client{ url: url, caFile: requestCredentials.GetTLSCAFile(), + certFile: requestCredentials.GetTLSCertFile(), + keyFile: requestCredentials.GetTLSKeyFile(), compatibleWithGitLab: true, } - if CertificateDirectory != "" && c.caFile == "" { - hostAndPort := strings.Split(url.Host, ":") - c.caFile = filepath.Join(CertificateDirectory, hostAndPort[0]+".crt") + host := strings.Split(url.Host, ":")[0] + if CertificateDirectory != "" { + c.findCertificate(&c.caFile, CertificateDirectory, host+".crt") + c.findCertificate(&c.certFile, CertificateDirectory, host+".auth.crt") + c.findCertificate(&c.keyFile, CertificateDirectory, host+".auth.key") } return diff --git a/network/client_test.go b/network/client_test.go index 4f680770bdf..2ae168872e8 100644 --- a/network/client_test.go +++ b/network/client_test.go @@ -1,18 +1,24 @@ package network import ( + "crypto/rsa" + "crypto/tls" + "crypto/x509" "encoding/pem" "errors" "fmt" "io/ioutil" + "net" "net/http" "net/http/httptest" + "net/url" "os" "path/filepath" "testing" "github.com/Sirupsen/logrus" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" . "gitlab.com/gitlab-org/gitlab-ci-multi-runner/common" ) @@ -56,6 +62,33 @@ func writeTLSCertificate(s *httptest.Server, file string) error { return ioutil.WriteFile(file, encoded, 0600) } +func writeTLSKeyPair(s *httptest.Server, certFile string, keyFile string) error { + c := s.TLS.Certificates[0] + if c.Certificate == nil || c.Certificate[0] == nil { + return errors.New("no predefined certificate") + } + + encodedCert := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: c.Certificate[0], + }) + + if err := ioutil.WriteFile(certFile, encodedCert, 0600); err != nil { + return err + } + + switch k := c.PrivateKey.(type) { + case *rsa.PrivateKey: + encodedKey := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(k), + }) + return ioutil.WriteFile(keyFile, encodedKey, 0600) + default: + return errors.New("unexpected private key type") + } +} + func TestNewClient(t *testing.T) { c, err := newClient(&RunnerCredentials{ URL: "http://test.example.com/ci///", @@ -137,29 +170,134 @@ func TestClientTLSCAFile(t *testing.T) { URL: s.URL, TLSCAFile: file.Name(), }) - statusCode, statusText, certificates := c.doJSON("test/ok", "GET", 200, nil, nil) + statusCode, statusText, tlsData := c.doJSON("test/ok", "GET", 200, nil, nil) assert.Equal(t, 200, statusCode, statusText) - assert.NotEmpty(t, certificates) + assert.NotEmpty(t, tlsData.CAChain) } func TestClientCertificateInPredefinedDirectory(t *testing.T) { s := httptest.NewTLSServer(http.HandlerFunc(clientHandler)) defer s.Close() + serverURL, err := url.Parse(s.URL) + require.NoError(t, err) + hostname, _, err := net.SplitHostPort(serverURL.Host) + require.NoError(t, err) + + tempDir, err := ioutil.TempDir("", "certs") + assert.NoError(t, err) + defer os.RemoveAll(tempDir) + CertificateDirectory = tempDir + + err = writeTLSCertificate(s, filepath.Join(tempDir, hostname+".crt")) + assert.NoError(t, err) + + c, _ := newClient(&RunnerCredentials{ + URL: s.URL, + }) + statusCode, statusText, tlsData := c.doJSON("test/ok", "GET", 200, nil, nil) + assert.Equal(t, 200, statusCode, statusText) + assert.NotEmpty(t, tlsData.CAChain) +} + +func TestClientInvalidTLSAuth(t *testing.T) { + s := httptest.NewUnstartedServer(http.HandlerFunc(clientHandler)) + s.TLS = new(tls.Config) + s.TLS.ClientAuth = tls.RequireAnyClientCert + s.StartTLS() + defer s.Close() + + ca, err := ioutil.TempFile("", "cert_") + assert.NoError(t, err) + ca.Close() + defer os.Remove(ca.Name()) + + err = writeTLSCertificate(s, ca.Name()) + assert.NoError(t, err) + + c, _ := newClient(&RunnerCredentials{ + URL: s.URL, + TLSCAFile: ca.Name(), + }) + statusCode, statusText, _ := c.doJSON("test/ok", "GET", 200, nil, nil) + assert.Equal(t, -1, statusCode, statusText) + assert.Contains(t, statusText, "tls: bad certificate") +} + +func TestClientTLSAuth(t *testing.T) { + s := httptest.NewUnstartedServer(http.HandlerFunc(clientHandler)) + s.TLS = new(tls.Config) + s.TLS.ClientAuth = tls.RequireAnyClientCert + s.StartTLS() + defer s.Close() + + ca, err := ioutil.TempFile("", "cert_") + assert.NoError(t, err) + ca.Close() + defer os.Remove(ca.Name()) + + err = writeTLSCertificate(s, ca.Name()) + assert.NoError(t, err) + + cert, err := ioutil.TempFile("", "cert_") + assert.NoError(t, err) + cert.Close() + defer os.Remove(cert.Name()) + + key, err := ioutil.TempFile("", "key_") + assert.NoError(t, err) + key.Close() + defer os.Remove(key.Name()) + + err = writeTLSKeyPair(s, cert.Name(), key.Name()) + assert.NoError(t, err) + + c, _ := newClient(&RunnerCredentials{ + URL: s.URL, + TLSCAFile: ca.Name(), + TLSCertFile: cert.Name(), + TLSKeyFile: key.Name(), + }) + statusCode, statusText, tlsData := c.doJSON("test/ok", "GET", 200, nil, nil) + assert.Equal(t, 200, statusCode, statusText) + assert.NotEmpty(t, tlsData.CAChain) + assert.Equal(t, cert.Name(), tlsData.CertFile) + assert.Equal(t, key.Name(), tlsData.KeyFile) +} + +func TestClientTLSAuthCertificatesInPredefinedDirectory(t *testing.T) { + s := httptest.NewUnstartedServer(http.HandlerFunc(clientHandler)) + s.TLS = new(tls.Config) + s.TLS.ClientAuth = tls.RequireAnyClientCert + s.StartTLS() + defer s.Close() + tempDir, err := ioutil.TempDir("", "certs") assert.NoError(t, err) defer os.RemoveAll(tempDir) CertificateDirectory = tempDir - err = writeTLSCertificate(s, filepath.Join(tempDir, "127.0.0.1.crt")) + serverURL, err := url.Parse(s.URL) + require.NoError(t, err) + hostname, _, err := net.SplitHostPort(serverURL.Host) + require.NoError(t, err) + + err = writeTLSCertificate(s, filepath.Join(tempDir, hostname+".crt")) + assert.NoError(t, err) + + err = writeTLSKeyPair(s, + filepath.Join(tempDir, hostname+".auth.crt"), + filepath.Join(tempDir, hostname+".auth.key")) assert.NoError(t, err) c, _ := newClient(&RunnerCredentials{ URL: s.URL, }) - statusCode, statusText, certificates := c.doJSON("test/ok", "GET", 200, nil, nil) + statusCode, statusText, tlsData := c.doJSON("test/ok", "GET", 200, nil, nil) assert.Equal(t, 200, statusCode, statusText) - assert.NotEmpty(t, certificates) + assert.NotEmpty(t, tlsData.CAChain) + assert.NotEmpty(t, tlsData.CertFile) + assert.NotEmpty(t, tlsData.KeyFile) } func TestUrlFixing(t *testing.T) { diff --git a/network/gitlab.go b/network/gitlab.go index ae73995c265..33a049e311b 100644 --- a/network/gitlab.go +++ b/network/gitlab.go @@ -35,7 +35,7 @@ func (n *GitLabClient) getClient(credentials requestCredentials) (c *client, err if n.clients == nil { n.clients = make(map[string]*client) } - key := fmt.Sprintf("%s_%s_%s", credentials.GetURL(), credentials.GetToken(), credentials.GetTLSCAFile()) + key := fmt.Sprintf("%s_%s_%s_%s", credentials.GetURL(), credentials.GetToken(), credentials.GetTLSCAFile(), credentials.GetTLSCertFile()) c = n.clients[key] if c == nil { c, err = newClient(credentials) @@ -86,10 +86,10 @@ func (n *GitLabClient) doRaw(credentials requestCredentials, method, uri string, return c.do(uri, method, request, requestType, headers) } -func (n *GitLabClient) doJSON(credentials requestCredentials, method, uri string, statusCode int, request interface{}, response interface{}) (int, string, string) { +func (n *GitLabClient) doJSON(credentials requestCredentials, method, uri string, statusCode int, request interface{}, response interface{}) (int, string, ResponseTLSData) { c, err := n.getClient(credentials) if err != nil { - return clientError, err.Error(), "" + return clientError, err.Error(), ResponseTLSData{} } return c.doJSON(uri, method, statusCode, request, response) @@ -197,6 +197,24 @@ func (n *GitLabClient) UnregisterRunner(runner common.RunnerCredentials) bool { } } +func addTLSData(response *common.JobResponse, tlsData ResponseTLSData) { + if tlsData.CAChain != "" { + response.TLSCAChain = tlsData.CAChain + } + + if tlsData.CertFile != "" && tlsData.KeyFile != "" { + data, err := ioutil.ReadFile(tlsData.CertFile) + if err == nil { + response.TLSAuthCert = string(data) + } + data, err = ioutil.ReadFile(tlsData.KeyFile) + if err == nil { + response.TLSAuthKey = string(data) + } + + } +} + func (n *GitLabClient) RequestJob(config common.RunnerConfig) (*common.JobResponse, bool) { request := common.JobRequest{ Info: n.getRunnerVersion(config), @@ -205,7 +223,7 @@ func (n *GitLabClient) RequestJob(config common.RunnerConfig) (*common.JobRespon } var response common.JobResponse - result, statusText, certificates := n.doJSON(&config.RunnerCredentials, "POST", "jobs/request", 201, &request, &response) + result, statusText, tlsData := n.doJSON(&config.RunnerCredentials, "POST", "jobs/request", 201, &request, &response) switch result { case 201: @@ -213,7 +231,7 @@ func (n *GitLabClient) RequestJob(config common.RunnerConfig) (*common.JobRespon "job": strconv.Itoa(response.ID), "repo_url": response.RepoCleanURL(), }).Println("Checking for jobs...", "received") - response.TLSCAChain = certificates + addTLSData(&response, tlsData) return &response, true case 403: config.Log().Errorln("Checking for jobs...", "forbidden") diff --git a/network/gitlab_test.go b/network/gitlab_test.go index bf570c41a2e..bab2319c033 100644 --- a/network/gitlab_test.go +++ b/network/gitlab_test.go @@ -42,12 +42,26 @@ func TestClients(t *testing.T) { URL: "http://test/", TLSCAFile: "ca_file", }) - c6, c6err := c.getClient(&brokenCredentials) + c6, _ := c.getClient(&RunnerCredentials{ + URL: "http://test/", + TLSCAFile: "ca_file", + TLSCertFile: "cert_file", + TLSKeyFile: "key_file", + }) + c7, _ := c.getClient(&RunnerCredentials{ + URL: "http://test/", + TLSCAFile: "ca_file", + TLSCertFile: "cert_file", + TLSKeyFile: "key_file2", + }) + c8, c8err := c.getClient(&brokenCredentials) assert.NotEqual(t, c1, c2) assert.NotEqual(t, c1, c4) assert.Equal(t, c4, c5) - assert.Nil(t, c6) - assert.Error(t, c6err) + assert.NotEqual(t, c5, c6) + assert.Equal(t, c6, c7) + assert.Nil(t, c8) + assert.Error(t, c8err) } func testRegisterRunnerHandler(w http.ResponseWriter, r *http.Request, t *testing.T) { diff --git a/shells/abstract.go b/shells/abstract.go index 41d09f9702b..78c9d5d6838 100644 --- a/shells/abstract.go +++ b/shells/abstract.go @@ -28,15 +28,9 @@ func (b *AbstractShell) writeExports(w ShellWriter, info common.ShellScriptInfo) } } -func (b *AbstractShell) writeTLSCAInfo(w ShellWriter, build *common.Build, key string) { - if build.TLSCAChain != "" { - w.Variable(common.JobVariable{ - Key: key, - Value: build.TLSCAChain, - Public: true, - Internal: true, - File: true, - }) +func (b *AbstractShell) writeGitExports(w ShellWriter, info common.ShellScriptInfo) { + for _, variable := range info.Build.GetGitTLSVariables() { + w.Variable(variable) } } @@ -293,7 +287,7 @@ func (b *AbstractShell) writeSubmoduleUpdateCmds(w ShellWriter, info common.Shel func (b *AbstractShell) writeGetSourcesScript(w ShellWriter, info common.ShellScriptInfo) (err error) { b.writeExports(w, info) - b.writeTLSCAInfo(w, info.Build, "GIT_SSL_CAINFO") + b.writeGitExports(w, info) if info.PreCloneScript != "" && info.Build.GetGitStrategy() != common.GitNone { b.writeCommands(w, info.PreCloneScript) @@ -313,7 +307,6 @@ func (b *AbstractShell) writeGetSourcesScript(w ShellWriter, info common.ShellSc func (b *AbstractShell) writeRestoreCacheScript(w ShellWriter, info common.ShellScriptInfo) (err error) { b.writeExports(w, info) b.writeCdBuildDir(w, info) - b.writeTLSCAInfo(w, info.Build, "CI_SERVER_TLS_CA_FILE") // Try to restore from main cache, if not found cache for master b.cacheExtractor(w, info) @@ -323,7 +316,6 @@ func (b *AbstractShell) writeRestoreCacheScript(w ShellWriter, info common.Shell func (b *AbstractShell) writeDownloadArtifactsScript(w ShellWriter, info common.ShellScriptInfo) (err error) { b.writeExports(w, info) b.writeCdBuildDir(w, info) - b.writeTLSCAInfo(w, info.Build, "CI_SERVER_TLS_CA_FILE") // Process all artifacts b.downloadAllArtifacts(w, info) @@ -503,7 +495,6 @@ func (b *AbstractShell) writeAfterScript(w ShellWriter, info common.ShellScriptI func (b *AbstractShell) writeArchiveCacheScript(w ShellWriter, info common.ShellScriptInfo) (err error) { b.writeExports(w, info) b.writeCdBuildDir(w, info) - b.writeTLSCAInfo(w, info.Build, "CI_SERVER_TLS_CA_FILE") // Find cached files and archive them b.cacheArchiver(w, info) @@ -513,7 +504,6 @@ func (b *AbstractShell) writeArchiveCacheScript(w ShellWriter, info common.Shell func (b *AbstractShell) writeUploadArtifactsScript(w ShellWriter, info common.ShellScriptInfo) (err error) { b.writeExports(w, info) b.writeCdBuildDir(w, info) - b.writeTLSCAInfo(w, info.Build, "CI_SERVER_TLS_CA_FILE") // Upload artifacts b.uploadArtifacts(w, info) -- GitLab