Client Certificates for Gitea/Gogs

Problem: Gitea/Gogs run behind reverse proxies that require client certificates. Drone Oauth2 cannot connect.

Solution: add a client certificate to the default transport, add a configuration option for client certificate path

Idea: in cmd/drone-server/inject_client.go update func defaultTransport similarly to the following:

func defaultTransport(skipverify bool, clientCertFile string, clientKeyFile string) http.RoundTripper {
    clientCert, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
    if err != nil {
        logrus.WithError(err).
        Fatalln("main: cannot load client certificates")
    }

    return &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        TLSClientConfig: &tls.Config{
            Certificates: []tls.Certificate{clientCert},
            InsecureSkipVerify: skipverify,
        },
    }
} 

(unless you have another idea, it would be necessary to add configuration parameters to the config file though)

The recommended solution is to mount certificates from your host machine into the container at /etc/ssl/certs/. The Go standard library will read the certs from this location. If you search this forum you can find some examples where developers are mounting the certificates [1]

[1] Drone-Agent can't connect over WSS, "x509: certificate signed by unknown authority" error
[2] [plugins/github-release] ca certificates with GHE

1 Like

Thanks, but I think you misunderstand the situation. It has nothing to do with containers and I am talking about client certificates, not server certificates.

Server certificates (such as you find in /etc/ssl/certs) prove the server’s identity to the user. Client certificates work in the other direction and are like a passport: they prove the user’s identity to the server. If the user does not show the right “passport”, the server will not even listen to him/her. Such certificates are typical in corporate environments and/or with security-conscious developers.

When doing the Oauth2 connection to Gitea/Gogs, drone plays the server role towards the user, but it plays the client role towards Gitea/Gogs. So if the Gitea/Gogs server asks for a client certificate, drone must be able to show one, otherwise Gitea/Gogs will not even listen to what drone is asking.

I can eventually implement this myself and do a PR, but wanted to check with the developers beforehand, as instructed in your source code, because it involves adding new configuration parameters.

The solution I am proposing is for client connections to a remote server (I think I gave the wrong path, it should be /etc/ssl/cert.pem). The solution you are proposing is going to be insufficient because the git client (running inside a separate clone container) needs to be able to connect to your Gitea server as well. Instead you need to add the cert to your system cert pool on the host and mount as a volume into the server and as a global volume in your pipeline containers.

Here are the default locations that Go looks for certificates:
https://golang.org/src/crypto/x509/root_linux.go

I also recommend reaching out to members of the Gitea community if you need any assistance. I am sure someone can provide you with an example configuration or tips to get this working, since I believe using Drone + Gitea with self-signed certificates is pretty common.

Thanks again, and sorry but again this is not correct. All the paths in the link you mention refer to ca-certificates, which are Certificate Authorities and have little to do with client certificates. Please trust me on this, I’ve pulled enough hair due to TLS authentication in my career :slight_smile: (Or look it up yourself under the keywords “TLS mutual authentication” if you don’t believe me - Example: [1] )

The situation has nothing to do with self signed certificates either. Self-signed may be used as a server certificate or as a client certificate, but the self-signed part plays absolutely no role and makes no difference in this.

Git already includes the ability to specify client certificates in the .gitconfig file with the parameters sslCert and sslKey. (And even if my proposal is insufficient, it is a step in the right direction.)

Finally, there is no point in reaching out to anybody from Gitea or anywhere else. As I said, the Gitea server will typically be behind a reverse proxy. Gitea itself will not even know that the reverse proxy requires a client certificate from the client, which in all cases is drone. That’s why the solution has to come from the drone side.

[1] https://www.jscape.com/blog/client-certificate-authentication

I realize this has nothing to do with Gitea specifically, however, it is very common for teams to run Gitea behind nginx with self-signed certificates. These teams have been able to integrate with Drone without code changes, so perhaps it make sense to reach out to learn more about how this was done.

sorry, re-read your post and see that you mentioned it has nothing to do with self-signed certificates. I guess I am not familiar with the configuration you are using. It sounds like you have a configuration that is atypical of what we normally see.

Git already includes the ability to specify client certificates in the .gitconfig file with the parameters sslCert and sslKey. (And even if my proposal is insufficient, it is a step in the right direction.)

again, I am not familiar with this type of configuration, but generally speaking we would not want to merge, maintain and support an incomplete solution.