Skip to content
Snippets Groups Projects
Commit 4e5b0ec5 authored by Kamil Trzcinski's avatar Kamil Trzcinski
Browse files

Automatically load TLS certificates stored in /etc/gitlab-runner/certs/<host-name>.crt

- Allow to provide custom tls_ca_file during registration or in config.toml file
- Allow to set tls_skip_verify which will disable certificate verification
parent ad3b86c4
Branches
Tags
No related merge requests found
......@@ -2,9 +2,19 @@ package commands
import (
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/network"
"os"
"path/filepath"
)
func getDefaultConfigFile() string {
return filepath.Join(getDefaultConfigDirectory(), "config.toml")
}
func getDefaultCertificateDirectory() string {
return filepath.Join(getDefaultConfigDirectory(), "certs")
}
type configOptions struct {
config *common.Config
......@@ -44,4 +54,6 @@ func init() {
if configFile == "" {
os.Setenv("CONFIG_FILE", getDefaultConfigFile())
}
network.CertificateDirectory = getDefaultCertificateDirectory()
}
......@@ -8,13 +8,13 @@ import (
"path/filepath"
)
func getDefaultConfigFile() string {
func getDefaultConfigDirectory() string {
if os.Getuid() == 0 {
return "/etc/gitlab-runner/config.toml"
return "/etc/gitlab-runner"
} else if homeDir := helpers.GetHomeDir(); homeDir != "" {
return filepath.Join(homeDir, ".gitlab-runner", "config.toml")
return filepath.Join(homeDir, ".gitlab-runner")
} else if currentDir := helpers.GetCurrentWorkingDirectory(); currentDir != "" {
return filepath.Join(currentDir, "config.toml")
return currentDir
} else {
panic("Cannot get default config file location")
}
......
package commands
func getDefaultConfigFile() string {
return "config.toml"
import (
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers"
)
func getDefaultConfigDirectory() string {
if currentDir := helpers.GetCurrentWorkingDirectory(); currentDir != "" {
return currentDir
} else {
panic("Cannot get default config file location")
}
}
......@@ -39,8 +39,10 @@ type ParallelsConfig 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"`
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"`
TLSSkipVerify bool `toml:"tls-skip-verify" json:"tls-skip-verify" long:"tls-skip-verify" env:"CI_SERVER_TLS_SKIP_VERIFY" description:"Whether to verify the TLS certificate when using HTTPS (INSECURE)"`
TLSCAFile string `toml:"tls-ca-file" 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"`
}
type RunnerConfig struct {
......
......@@ -3,12 +3,17 @@ package network
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"github.com/Sirupsen/logrus"
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
......@@ -16,11 +21,17 @@ import (
type client struct {
http.Client
url *url.URL
caFile string
skipVerify bool
updateTime time.Time
}
func (n *client) ensureTlsConfig() {
// certificate got modified
if stat, err := os.Stat(n.caFile); err == nil && n.updateTime.Before(stat.ModTime()) {
n.Transport = nil
}
// create or update transport
if n.Transport == nil {
n.updateTime = time.Now()
......@@ -35,6 +46,25 @@ func (n *client) createTransport() {
InsecureSkipVerify: n.skipVerify,
}
// load TLS certificate
if file := n.caFile; file != "" {
logrus.Debugln("Trying to load", file, "...")
data, err := ioutil.ReadFile(file)
if err == nil {
pool := x509.NewCertPool()
if pool.AppendCertsFromPEM(data) {
tlsConfig.RootCAs = pool
} else {
logrus.Errorln("Failed to parse PEM in", n.caFile)
}
} else {
if !os.IsNotExist(err) {
logrus.Errorln("Failed to load", n.caFile, err)
}
}
}
// create transport
n.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
......@@ -107,7 +137,14 @@ func newClient(config common.RunnerCredentials) (c *client, err error) {
}
c = &client{
url: url,
url: url,
skipVerify: config.TLSSkipVerify,
caFile: config.TLSCAFile,
}
if CertificateDirectory != "" && c.caFile == "" {
hostAndPort := strings.Split(url.Host, ":")
c.caFile = filepath.Join(CertificateDirectory, hostAndPort[0]+".crt")
}
return
......
package network
var CertificateDirectory string
......@@ -16,13 +16,14 @@ func (n *GitLabClient) getClient(runner RunnerCredentials) (c *client, err error
if n.clients == nil {
n.clients = make(map[string]*client)
}
c = n.clients[runner.URL]
key := fmt.Sprintf("%s_%d_%s", runner.URL, runner.TLSSkipVerify, runner.TLSCAFile)
c = n.clients[key]
if c == nil {
c, err = newClient(runner)
if err != nil {
return
}
n.clients[runner.URL] = c
n.clients[key] = c
}
return
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment