Skip to content

Conversation

@muralibasani
Copy link
Contributor

About this change - What it does

Add configurable mTLS client auth via server_tls_client_auth and pass ssl_cert_reqs to uvicorn, enforcing client certs when set to required.

#1175

Why this way

@muralibasani muralibasani requested a review from a team as a code owner December 17, 2025 10:30
@github-actions
Copy link

github-actions bot commented Dec 17, 2025

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  src/karapace
  __main__.py
  src/karapace/backup
  cli.py
  errors.py
  src/karapace/core
  config.py 61-63, 65, 68, 222-226, 416-433
  typing.py
  src/karapace/core/kafka
  common.py
  src/karapace/kafka_rest_apis
  consumer_manager.py
Project Total  

This report was generated by python-coverage-comment-action

if config.server_tls_cafile:
ssl_context.load_verify_locations(config.server_tls_cafile)

if client_auth_mode == "required":
Copy link
Contributor

@nosahama nosahama Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit]
you could use match/case

server_tls_certfile: str | None = None
server_tls_keyfile: str | None = None
server_tls_cafile: str | None = None
server_tls_client_auth: Literal["none", "optional", "required"] = "none"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract "none", "optional", "required" into an enum, we can then use that for reference.

config = karapace_container.config()
app = create_karapace_application(config=config, lifespan=karapace_schema_registry_lifespan)
client_auth_mode = config.server_tls_client_auth.lower()
if client_auth_mode == "required":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit]
maybe you can extract this logic into a function and then use that in create_server_ssl_context() and in this file.

from tests.integration.utils.cluster import start_schema_registry_cluster


@pytest.mark.asyncio
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit]
you do not need the pytest asyncio marker.

server_cert: str,
server_key: str,
) -> None:
# Skip cleanly if test credentials are not available in the environment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is this the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

if resp.status >= 400:
failed = True
except (
aiohttp.ClientConnectorCertificateError,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we expecting such an exhaustive list of errors, just from this single API call?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually not, replaced with only client and ssl error.


client_auth = (
config.server_tls_client_auth.value
if isinstance(config.server_tls_client_auth, enum.Enum)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its good to keep it imo, as it normalizes the value just in case if it is not enum rather its a raw string. doesn't hurt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it also looks redundant, I can remove it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants