jozu-ai / kitops

Tools for easing the handoff between AI/ML and App/SRE teams.
https://KitOps.ml
Apache License 2.0
339 stars 34 forks source link

Add support for authenticating via client certificates #402

Closed amisevsk closed 2 months ago

amisevsk commented 2 months ago

Description

Add support for authenticating with remote registries via client certificates. This PR adds two options to most commands (anything that might contact a remote registry):

      --cert string   Path to client certificate used for authentication (can also be set via environment variable KITOPS_CLIENT_CERT)
      --key string    Path to client certificate key used for authentication (can also be set via environment variable KITOPS_CLIENT_KEY)

For convenience, values can also be set via environment variables. The env vars take precedence, if set.

Less interesting, but this PR also refactors how we pass networking options around, to use the same struct everywhere rather than creating 3 similar-but-slight-different structs we have to convert between.

Testing

I've briefly tested this with the registry image behind an nginx proxy and didn't find any issues. I used the following compose.yml and nginx.conf to test:

compose.yml ```yaml version: "3" services: registry: image: registry ports: - 5050:5050 environment: REGISTRY_HTTP_ADDR: ":5050" nginx: image: nginx ports: - "8443:8443" - "8080:8080" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:z - ./certs/server.crt:/etc/ssl/server.crt:z - ./certs/server.key:/etc/ssl/server.key:z - ./certs/ca.crt:/etc/nginx/client_certs/ca.crt:z depends_on: - registry ```
nginx.conf ```conf server { listen 8080; location / { return 301 https://$host$request_uri; } } server { listen 8443 ssl; ssl_certificate /etc/ssl/server.crt; ssl_certificate_key /etc/ssl/server.key; ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_client_certificate /etc/nginx/client_certs/ca.crt; ssl_verify_client optional; ssl_verify_depth 2; # disable any limits to avoid HTTP 413 for large image uploads client_max_body_size 0; location / { if ($ssl_client_verify != SUCCESS) { return 403; } proxy_set_header SSL_Client_Issuer $ssl_client_i_dn; proxy_set_header SSL_Client $ssl_client_s_dn; proxy_set_header SSL_Client_Verify $ssl_client_verify; proxy_pass http://registry:5050; } } ```

Linked issues

Closes #401

amisevsk commented 2 months ago

I've also disabled sorting for flags (not sure why we'd want that?) so it's a little easier to read, e.g.

Flags:
      --plain-http    Use plain HTTP when connecting to remote registries
      --tls-verify    Require TLS and verify certificates when connecting to remote registries (default true)
      --cert string   Path to client certificate used for authentication (can also be set via environment variable KITOPS_CLIENT_CERT)
      --key string    Path to client certificate key used for authentication (can also be set via environment variable KITOPS_CLIENT_KEY)
  -h, --help          help for push

Global Flags:
      --config string      Alternate path to root storage directory for CLI
      --log-level string   Log messages above specified level ('trace', 'debug', 'info', 'warn', 'error') (default 'info') (default "info")
      --progress string    Configure progress bars for longer operations (options: none, plain, fancy) (default "plain")
  -v, --verbose count      Increase verbosity of output (use -vv for more)
notniknot commented 2 months ago

@amisevsk Tested it and can confirm that it works with our reverse proxy :)