support authentication with TLS client certificates #451

Open
opened 6 months ago by pgnd · 5 comments
pgnd commented 6 months ago

I've set up a gitea server,

gitea -v
    Gitea version 1.15.9 built with GNU Make 4.1, go1.16.12 : bindata, sqlite, sqlite_unlock_notify

It's local; uses self-signed SSL certs, signed by my local CA. Certs are correctly added to system/OS ssl store.
The gitea instance sits behind an nginx frontend -- UI via https:// in browser works great. As does ssh:// push & clone.

Next, I installed 'tea' cli

tea -v
    0.8.0

When I exec a login add,

tea login add \
 --url https://gitea.example.loc \
 --name myadmin \
 --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7

    2022/01/10 10:38:31 Get "https://gitea.example.loc/api/v1/version": x509: certificate signed by unknown authority

tea login add \
 --url https://gitea.example.loc \
 --name myadmin \
 --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7 \
 --insecure

    2022/01/10 10:39:23 Unknown API Error: 400
    Request: '/api/v1/version' with 'GET' method 'map[Authorization:[token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7]]' header and '<html>
    <head><title>400 No required SSL certificate was sent</title></head>
    <body>
    <center><h1>400 Bad Request</h1></center>
    <center>No required SSL certificate was sent</center>
    <hr><center>nginx</center>
    </body>
    </html>
    ' body

Seems I need to convince tea to use system ssl cert store &/or pass specific CA/cert paths.
Afaict, no option's available, per tea login add --help

How do I get tea+SSL for my instance?

I've set up a gitea server, ``` gitea -v Gitea version 1.15.9 built with GNU Make 4.1, go1.16.12 : bindata, sqlite, sqlite_unlock_notify ``` It's local; uses self-signed SSL certs, signed by my local CA. Certs are correctly added to system/OS ssl store. The gitea instance sits behind an nginx frontend -- UI via https:// in browser works great. As does ssh:// push & clone. Next, I installed 'tea' cli ``` tea -v 0.8.0 ``` When I exec a `login add`, ``` tea login add \ --url https://gitea.example.loc \ --name myadmin \ --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7 2022/01/10 10:38:31 Get "https://gitea.example.loc/api/v1/version": x509: certificate signed by unknown authority tea login add \ --url https://gitea.example.loc \ --name myadmin \ --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7 \ --insecure 2022/01/10 10:39:23 Unknown API Error: 400 Request: '/api/v1/version' with 'GET' method 'map[Authorization:[token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7]]' header and '<html> <head><title>400 No required SSL certificate was sent</title></head> <body> <center><h1>400 Bad Request</h1></center> <center>No required SSL certificate was sent</center> <hr><center>nginx</center> </body> </html> ' body ``` Seems I need to convince `tea` to use system ssl cert store &/or pass specific CA/cert paths. Afaict, no option's available, per `tea login add --help` How do I get tea+SSL for my instance?
Collaborator
discussion not relevant to the feature proposal tea gives you two options:
  • add your CA to the trusted-cert store of your OS
  • edit your login (tea login edit) to disable certificate validation using the insecure: true parameter

If you really need to add this cert to tea only, you could implement that, by adding an option to load a custom cert here

edit: I see you used the --insecure flag when registering the login. Are you sure that worked as intended? You may need to specify --insecure true instead.

edit2: Are you saying, that the cert added to the system store was not recognized by tea? That indeed might be an issue. Which OS are you running tea on?

<details><summary>discussion not relevant to the feature proposal</summary> tea gives you two options: - add your CA to the trusted-cert store of your OS - edit your login (`tea login edit`) to disable certificate validation using the `insecure: true` parameter If you really need to add this cert to tea only, you could implement that, by adding an option to load a custom cert [here](https://gitea.com/gitea/tea/src/branch/master/modules/config/login.go#L167-L176) edit: I see you used the `--insecure` flag when registering the login. Are you sure that worked as intended? You may need to specify `--insecure true` instead. edit2: Are you saying, that the cert added to the system store was not recognized by tea? That indeed might be an issue. Which OS are you running tea on? </details>
Poster
discussion not relevant to the feature proposal @noerw

add your CA to the trusted-cert store of your OS

as mentioned,

Certs are correctly added to system/OS ssl store.

They are already.

They're widely used here locally by other tools.
My certs are visible/correct/updated in the trusted store, and usable to fully verify server/app certs

openssl s_client -showcerts -connect gitea.example.loc:443
	CONNECTED(00000003)
	depth=2 O = example.loc, OU = example.loc_CA, L = NYC, ST = NY, C = US, emailAddress = ssl@example.loc, CN = example.loc_CA_ROOT
	verify return:1
	depth=1 C = US, ST = NY, O = example.loc, OU = example.loc_CA, CN = example.loc_CA_INT, emailAddress = ssl@example.loc
	verify return:1
	depth=0 C = US, ST = NY, L = NYC, O = example.loc, OU = example.loc_CA, CN = gitea.example.loc, emailAddress = ssl@example.loc
	verify return:1
	---
	Certificate chain
	...

Are you sure that worked as intended? You may need to specify --insecure true instead.

reading the help

tea login add --help
	NAME:
	   tea logins add - Add a Gitea login

	USAGE:
	   tea logins add [command options] [arguments...]

	DESCRIPTION:
	   Add a Gitea login, without args it will create one interactively

	OPTIONS:
	   --name value, -n value         Login name
	   --url value, -u value          Server URL (default: "https://gitea.com") [$GITEA_SERVER_URL]
	   --token value, -t value        Access token. Can be obtained from Settings > Applications [$GITEA_SERVER_TOKEN]
	   --user value                   User for basic auth (will create token) [$GITEA_SERVER_USER]
	   --password value, --pwd value  Password for basic auth (will create token) [$GITEA_SERVER_PASSWORD]
	   --ssh-key value, -s value      Path to a SSH key to use, overrides auto-discovery
-->	   --insecure, -i                 Disable TLS verification (default: false)
	   --help, -h                     show help (default: false)

doesn't require a value.

& checking, just to be certain,

tea login add \
 --url https://gitea.example.loc \
 --name myadmin \
 --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7 \
 --insecure true

returns the same error as reported above

<details><summary>discussion not relevant to the feature proposal</summary> @noerw > add your CA to the trusted-cert store of your OS as mentioned, >> Certs are correctly added to system/OS ssl store. They are already. They're widely used here locally by other tools. My certs are visible/correct/updated in the trusted store, and usable to fully verify server/app certs ``` openssl s_client -showcerts -connect gitea.example.loc:443 CONNECTED(00000003) depth=2 O = example.loc, OU = example.loc_CA, L = NYC, ST = NY, C = US, emailAddress = ssl@example.loc, CN = example.loc_CA_ROOT verify return:1 depth=1 C = US, ST = NY, O = example.loc, OU = example.loc_CA, CN = example.loc_CA_INT, emailAddress = ssl@example.loc verify return:1 depth=0 C = US, ST = NY, L = NYC, O = example.loc, OU = example.loc_CA, CN = gitea.example.loc, emailAddress = ssl@example.loc verify return:1 --- Certificate chain ... ``` > Are you sure that worked as intended? You may need to specify --insecure true instead. reading the help ``` tea login add --help NAME: tea logins add - Add a Gitea login USAGE: tea logins add [command options] [arguments...] DESCRIPTION: Add a Gitea login, without args it will create one interactively OPTIONS: --name value, -n value Login name --url value, -u value Server URL (default: "https://gitea.com") [$GITEA_SERVER_URL] --token value, -t value Access token. Can be obtained from Settings > Applications [$GITEA_SERVER_TOKEN] --user value User for basic auth (will create token) [$GITEA_SERVER_USER] --password value, --pwd value Password for basic auth (will create token) [$GITEA_SERVER_PASSWORD] --ssh-key value, -s value Path to a SSH key to use, overrides auto-discovery --> --insecure, -i Disable TLS verification (default: false) --help, -h show help (default: false) ``` doesn't require a value. & checking, just to be certain, ``` tea login add \ --url https://gitea.example.loc \ --name myadmin \ --token 9e441b3e8ab29a9d4254a859b456bbceb43ea9d7 \ --insecure true ``` returns the same error as reported above </details>
Collaborator

x509: certificate signed by unknown authority

If you added your CA to one of these locations (assuming you're on linux), this should not occur, and you shouldn't be needing to specify --insecure.
Maybe you're hitting the same issue as this person, they also require a client side cert and use a local CA.
This hints either at an issue with your certificates, or maybe, maybe with the golang TLS client in this specific configuration. idk, that's far outside my area.

400 Bad Request - No required SSL certificate was sent

I just now understood what you're asking for (derived only from the quoted bit above; it would be helpful to be more explicit about your environment and the thing you want to achieve next time).

So you have configured your nginx proxy to require clients to authenticate with a client cert by setting ssl_verify_client. And expect tea to send that client certificate to your nginx host.

That's indeed not supported:
Turns out, golang's TLS client doesn't implement looking up matching client certs in truststores, they need to be specified manually.
A quick search didn't yield any golang NSS implementations (and we try to avoid using cgo / C dependencies), so I don't think we'll implement that functionality.
(I don't know what trust store you put your client cert into, I'll assume it's NSS).

With much less effort, we could of course add a flag where logins can specify a path to a client certificate.

--insecure doesn't require a value.

indeed, sorry for confusing that


aside: you posted a sensitive gitea access_token above, you may want to cycle that.

> `x509: certificate signed by unknown authority` If you added your CA to [one of these locations](https://go.dev/src/crypto/x509/root_linux.go) (assuming you're on linux), this should not occur, and you shouldn't be needing to specify `--insecure`. Maybe you're hitting the same issue as [this person](https://stackoverflow.com/questions/57763465/go-code-how-to-connect-a-self-signed-cert-ssl-site-without-insecureskipverify), they also require a client side cert and use a local CA. This hints either at an issue with your certificates, or maybe, maybe with the golang TLS client in this specific configuration. idk, that's far outside my area. > `400 Bad Request - No required SSL certificate was sent` I just now understood what you're asking for (derived only from the quoted bit above; it would be helpful to be more explicit about your environment and the thing you want to achieve next time). So you have configured your nginx proxy to require clients to authenticate with a client cert by setting `ssl_verify_client`. And expect tea to send that client certificate to your nginx host. That's indeed not supported: Turns out, golang's TLS client doesn't implement looking up matching client certs in truststores, [they need to be specified manually](https://pkg.go.dev/crypto/tls#Config.Certificates). A quick search didn't yield any golang NSS implementations (and we try to avoid using cgo / C dependencies), so I don't think we'll implement that functionality. (I don't know what trust store you put your client cert into, I'll assume it's NSS). With much less effort, we could of course add a flag where logins can specify a path to a client certificate. > `--insecure` doesn't require a value. indeed, sorry for confusing that --- aside: you posted a sensitive gitea access_token above, you may want to cycle that.
Poster

@noerw

A quick search didn't yield any golang NSS implementations

this looks like a start

https://github.com/protosam/go-libnss

With much less effort, we could of course add a flag where logins can specify a path to a client certificate.

that'd be more than good enough.
as long as you can pass the client cert at cmd line, and get the tea login working -- and, eventually (in milestone 0.9.0?) tea clone, etc.

&/or perhaps parsing already-existing, host-specific section in ~/.gitconfig,

[http "https://gitea.example.com"]
	username = gitea
	sslVerify = true
	sslCertPasswordProtected = false
	sslCAInfo = /etc/git/sec/myCA.CHAIN.crt.pem
	sslCert   = /etc/git/sec/example.com.client.EC.crt.pem
	sslKey    = /etc/git/sec/example.com.client.EC.key.pem

or a similar tea-specific app.ini with similar config ...

aside: you posted a sensitive gitea access_token above, you may want to cycle that.

heh, no worries. at this stage, randomized AND completely sacrificial ;-)

@noerw > A quick search didn't yield any golang NSS implementations this looks like a start https://github.com/protosam/go-libnss > With much less effort, we could of course add a flag where logins can specify a path to a client certificate. that'd be more than good enough. as long as you can pass the client cert at cmd line, and get the `tea login` working -- and, eventually (in milestone 0.9.0?) `tea clone`, etc. &/or perhaps parsing already-existing, host-specific section in `~/.gitconfig`, ``` [http "https://gitea.example.com"] username = gitea sslVerify = true sslCertPasswordProtected = false sslCAInfo = /etc/git/sec/myCA.CHAIN.crt.pem sslCert = /etc/git/sec/example.com.client.EC.crt.pem sslKey = /etc/git/sec/example.com.client.EC.key.pem ``` or a similar `tea`-specific `app.ini` with similar config ... > aside: you posted a sensitive gitea access_token above, you may want to cycle that. heh, no worries. at this stage, randomized AND completely sacrificial ;-)
Collaborator

Ideally we don't introduce another config location for this stuff, so the NSS aproach would be best in that regard.

Either way, support needs to be added in 2 components:

Ideally we don't introduce another config location for this stuff, so the NSS aproach would be best in that regard. Either way, support needs to be added in 2 components: - [ ] gitea API client (https://gitea.com/gitea/go-sdk) - [ ] go-git for git operations (it currently [only supports addding custom root-CAs](https://github.com/go-git/go-git/blob/1b1a61a/plumbing/transport/client/client.go#L66-L68))
noerw changed title from ssl cert submission mechanism missing for tea? to support authentication with TLS client certificates 6 months ago
noerw added the
kind/feature
label 6 months ago
noerw added the
kind/proposal
upstream/sdk
labels 6 months ago
Sign in to join this conversation.
Loading…
There is no content yet.