mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-09 08:40:29 +00:00
enhance: support client certificates for mutual TLS (#1273)
Add `runner.client_cert_file` and `runner.client_key_file` for Gitea instances that require mutual TLS. The runner presents the certificate on its RPCs, job summary uploads, and the action, reusable workflow and `builtin:checkout` clones from the instance. The files are read on use, so renewed certificates apply without a restart. Job steps do not get them. An incomplete or mismatched pair fails startup. Clones now decide the token, client certificate and `runner.insecure` with one host check, which also gives reusable workflow clones the TLS settings they lacked. `runner.insecure` still only covers the registered address. Fixes: https://gitea.com/gitea/runner/issues/321 Co-authored-by: silverwind <[email protected]> Co-authored-by: silverwind <[email protected]> Reviewed-on: https://gitea.com/gitea/runner/pulls/1273 Reviewed-by: silverwind <[email protected]> Co-authored-by: bircni <[email protected]>
This commit is contained in:
1 parent
e5aa9add02
commit
f963e9cfe8
21 files changed
+298
-202
No files matched your search
@@ -4,6 +4,13 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -42,6 +49,49 @@ cache:
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestClientCertIsValidatedAndAbsoluteOnLoadReadOnUseAndOfferedOnlyWhenAccepted(t *testing.T) {
|
||||
require.True(t, (&Runner{Insecure: true}).TLSConfig().InsecureSkipVerify)
|
||||
|
||||
dir := t.TempDir()
|
||||
certPath, keyPath := filepath.Join(dir, "client.crt"), filepath.Join(dir, "client.key")
|
||||
writePair := func() []byte {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
template := &x509.Certificate{SerialNumber: big.NewInt(1)}
|
||||
der, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
|
||||
require.NoError(t, err)
|
||||
keyDER, err := x509.MarshalPKCS8PrivateKey(key)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.WriteFile(certPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0o600))
|
||||
require.NoError(t, os.WriteFile(keyPath, pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), 0o600))
|
||||
return der
|
||||
}
|
||||
load := func(certFile, keyFile string) (*Config, error) {
|
||||
return LoadDefault(write(t, "runner:\n client_cert_file: '"+certFile+"'\n client_key_file: '"+keyFile+"'\n"))
|
||||
}
|
||||
writePair()
|
||||
|
||||
_, err := load(certPath, "")
|
||||
require.ErrorContains(t, err, "must be set together")
|
||||
_, err = load(keyPath, keyPath)
|
||||
require.ErrorContains(t, err, "load runner client certificate")
|
||||
|
||||
t.Chdir(dir)
|
||||
cfg, err := load("client.crt", "client.key")
|
||||
require.NoError(t, err)
|
||||
require.True(t, filepath.IsAbs(cfg.Runner.ClientCertFile))
|
||||
require.True(t, filepath.IsAbs(cfg.Runner.ClientKeyFile))
|
||||
renewed := writePair()
|
||||
info := &tls.CertificateRequestInfo{Version: tls.VersionTLS13, SignatureSchemes: []tls.SignatureScheme{tls.ECDSAWithP256AndSHA256}}
|
||||
pair, err := cfg.Runner.TLSConfig().GetClientCertificate(info)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, renewed, pair.Certificate[0])
|
||||
info.AcceptableCAs = [][]byte{[]byte("another CA")}
|
||||
pair, err = cfg.Runner.TLSConfig().GetClientCertificate(info)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, pair.Certificate)
|
||||
}
|
||||
|
||||
func TestLoadDefault_ExpandsEnvironmentValues(t *testing.T) {
|
||||
t.Setenv("RUNNER_CAPACITY", "4")
|
||||
t.Setenv("RUNNER_LABEL", "linux:host")
|
||||
|
||||
Reference in new issue
Block a user