Conversation
…on-logger-4.1.0 Build(deps): Bump python-json-logger from 4.0.0 to 4.1.0
Bumps [requests](https://github.com/psf/requests) from 2.33.0 to 2.33.1. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](psf/requests@v2.33.0...v2.33.1) --- updated-dependencies: - dependency-name: requests dependency-version: 2.33.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…2.33.1 Build(deps): Bump requests from 2.33.0 to 2.33.1
Bumps [gunicorn](https://github.com/benoitc/gunicorn) from 25.2.0 to 25.3.0. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](benoitc/gunicorn@25.2.0...25.3.0) --- updated-dependencies: - dependency-name: gunicorn dependency-version: 25.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
…25.3.0 Build(deps): Bump gunicorn from 25.2.0 to 25.3.0
Bumps [types-pytz](https://github.com/python/typeshed) from 2026.1.1.20260304 to 2026.1.1.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-pytz dependency-version: 2026.1.1.20260402 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Thread the endpoint parameter through send_rotation_notification() and into send_default_notification() via **kwargs, so notification plugins can include operational context (e.g. which load balancer is being rotated) in their messages. This is backwards compatible — the endpoint parameter is optional and existing plugins that don't use it will simply ignore it via their **kwargs signature. Closes Netflix#5346 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After rotating a certificate on an endpoint, attempt to detach the old certificate via the source plugin's new remove_old_certificate() method. This prevents old certificates from accumulating on endpoints that support multiple certificates (e.g. GCP load balancers). The base SourcePlugin.remove_old_certificate() is a no-op by default, which is correct for providers like AWS ELBs that handle cert swaps atomically. Plugins for multi-cert endpoints can override this method. The cleanup is best-effort — failures are logged as warnings but do not fail the rotation itself. Closes Netflix#5348 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies that send_rotation_notification passes the endpoint kwarg through to send_default_notification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests cover: - remove_old_certificate is called with the old cert after rotation - removal is skipped when there is no old certificate - removal failure does not break the rotation itself Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getattr(script_info, 'config') raises AttributeError when the script_info object doesn't have a config attribute set yet (e.g. when running 'lemur --help' or 'lemur' without a subcommand). Use getattr with a default of None to handle this gracefully. Closes Netflix#4764 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…z-2026.1.1.20260402 Build(deps): Bump types-pytz from 2026.1.1.20260304 to 2026.1.1.20260402
Bumps [types-setuptools](https://github.com/python/typeshed) from 82.0.0.20260210 to 82.0.0.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-setuptools dependency-version: 82.0.0.20260402 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…uptools-82.0.0.20260402 Build(deps): Bump types-setuptools from 82.0.0.20260210 to 82.0.0.20260402
Bumps [types-paramiko](https://github.com/python/typeshed) from 4.0.0.20260322 to 4.0.0.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-paramiko dependency-version: 4.0.0.20260402 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…amiko-4.0.0.20260402 Build(deps): Bump types-paramiko from 4.0.0.20260322 to 4.0.0.20260402
Bumps [google-cloud-private-ca](https://github.com/googleapis/google-cloud-python) from 1.17.0 to 1.18.0. - [Release notes](https://github.com/googleapis/google-cloud-python/releases) - [Changelog](https://github.com/googleapis/google-cloud-python/blob/main/packages/google-cloud-documentai/CHANGELOG.md) - [Commits](googleapis/google-cloud-python@google-cloud-private-ca-v1.17.0...google-cloud-private-ca-v1.18.0) --- updated-dependencies: - dependency-name: google-cloud-private-ca dependency-version: 1.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
…oud-private-ca-1.18.0 Build(deps): Bump google-cloud-private-ca from 1.17.0 to 1.18.0
Bumps [mypy](https://github.com/python/mypy) from 1.19.1 to 1.20.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](python/mypy@v1.19.1...v1.20.0) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Build(deps): Bump mypy from 1.19.1 to 1.20.0
Bumps [types-deprecated](https://github.com/python/typeshed) from 1.3.1.20260130 to 1.3.1.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-deprecated dependency-version: 1.3.1.20260402 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…recated-1.3.1.20260402 Build(deps): Bump types-deprecated from 1.3.1.20260130 to 1.3.1.20260402
Bumps [botocore](https://github.com/boto/botocore) from 1.42.80 to 1.42.83. - [Commits](boto/botocore@1.42.80...1.42.83) --- updated-dependencies: - dependency-name: botocore dependency-version: 1.42.83 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…1.42.83 Build(deps): Bump botocore from 1.42.80 to 1.42.83
Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.1.7 to 3.1.8. - [Release notes](https://github.com/pallets/werkzeug/releases) - [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst) - [Commits](pallets/werkzeug@3.1.7...3.1.8) --- updated-dependencies: - dependency-name: werkzeug dependency-version: 3.1.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
…3.1.8 Build(deps): Bump werkzeug from 3.1.7 to 3.1.8
Bumps [types-protobuf](https://github.com/python/typeshed) from 6.32.1.20260221 to 7.34.1.20260403. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-protobuf dependency-version: 7.34.1.20260403 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…tobuf-7.34.1.20260403 Build(deps): Bump types-protobuf from 6.32.1.20260221 to 7.34.1.20260403
Bumps [invoke](https://github.com/pyinvoke/invoke) from 2.2.1 to 3.0.0. - [Commits](pyinvoke/invoke@2.2.1...3.0.0) --- updated-dependencies: - dependency-name: invoke dependency-version: 3.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Fix password hashing update
…ions (GHSA-54vg-pfh7-jq95) Validate CRL and OCSP URLs against RFC1918/loopback/link-local ranges before issuing outbound requests. Optionally enforce hostname allowlists via LEMUR_TRUSTED_CRL_HOSTS and LEMUR_TRUSTED_OCSP_HOSTS config keys. Bound crl_cache to 1000 entries to prevent unbounded cache poisoning. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix post-authentication SSRF via CRL/OCSP URLs in uploaded certificates (GHSA-54vg-pfh7-jq95)
Require admin permission on Roles.put, mirroring the existing decorator on Roles.delete. Previously RoleMemberPermission allowed any role member to rewrite membership, rename, or modify the role without admin privileges. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix privilege escalation in PUT /api/1/roles/<id> (GHSA-x3vf-mgxj-7785)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
JWT algo fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GHSA-v2wp-frmc-5q3v: ACME acme_url SSRF fix + key export audit enhancement
- test_role_put: non-admin users now get 403 (admin-only) before schema validation can return 400 - test_role_put_with_data_and_user: role members no longer permitted to update roles; expect 403 instead of 200 - test_verify_crl_unreachable: patch socket.gethostbyname so the new SSRF hostname validation passes, allowing the mocked Timeout to fire Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ilures-post-ghsa fix: update tests to reflect GHSA security hardening changes
# Conflicts: # Dockerfile # lemur/common/utils.py # lemur/plugins/lemur_acme/acme_handlers.py # lemur/plugins/lemur_acme/challenge_types.py # lemur/plugins/lemur_aws/plugin.py
# Conflicts: # .github/workflows/lemur-publish-release-pypi.yml # CHANGELOG.rst # README.rst # docs/administration.rst # docs/developer/index.rst # lemur/certificates/verify.py # lemur/certificates/views.py # lemur/tests/conftest.py # requirements-dev.txt # requirements-docs.txt # requirements-tests.txt # requirements.in # requirements.txt
This comment has been minimized.
This comment has been minimized.
# Conflicts: # requirements-dev.txt # requirements-docs.txt # requirements-tests.txt # requirements.txt
Upstream merge produced two identical csr_to_string functions in lemur/common/utils.py (lines 269 and 548). flake8 F811 caught the redefinition and failed the lint step. Both definitions had byte-identical bodies, so dropping the second keeps behavior unchanged. Fixes the dd-gitlab/test failure on PR #271.
The upstream merge resolution kept the pre-merge requirements*.{in,txt}
files (intentionally, to preserve the cryptography==43.0.1 FIPS pin and
other Datadog overrides). Side effect: it also undid the more recent
master-only dep bumps for cloudflare, azure-keyvault,
google-cloud-compute, and cert-manager.
Master in the meantime advanced to:
- cloudflare==4.3.1 (v3+ SDK; new `from cloudflare import Cloudflare` API)
- cert-manager==3.0.0
- azure-keyvault==4.2.0
- google-cloud-compute==1.46.0
Plugin code in wip-apr27 already uses the new APIs (matching master),
so without the bumps the plugin modules ImportError at test-collection
time and break the CI test job.
Easiest correct path: take master's requirements-base.in /
requirements-datadog.in / requirements.txt verbatim onto wip-apr27.
The cryptography==43.0.1 FIPS pin and the rest of the Datadog overlay
were already pulled forward on master, so we lose nothing.
Recompiled the four requirements*.txt files via pip-compile -U against the existing requirements*.in inputs to pull category-3 deps (the ones the upstream merge left lagging because of "kept ours") forward. Invariants verified post-recompile: - cryptography==43.0.1 stays pinned (FIPS gov-deployment requirement) - CVE overrides preserved: urllib3 2.7.0, jinja2 3.1.6, python-ldap 3.4.7, h11 0.16.0 - cloudflare bumped 4.3.1 -> 5.4.0; the top-level package still exposes `Cloudflare` (the lemur_acme plugin import path stays valid) Notable bumps: - acme/certbot: 5.4.0 -> 5.6.0 - boto3/botocore: 1.42.73 -> 1.43.31 - gunicorn: 25.1.0 -> 26.0.0 - paramiko: 4.0.0 -> 5.0.0 - requests: 2.32.5 -> 2.34.2 - sentry-sdk: 2.55.0 -> 2.63.0 - werkzeug: 3.1.6 -> 3.1.8 The Datadog-only deps (azure-*, cert-manager, google-cloud-compute, logmatic-python, simplejson, cachetools) are untouched in their pinning, just resolved to their latest compatible.
The upstream merge brought in the lemur_gcs destination plugin (Netflix PR Netflix#5210 'Add Google Cloud Storage destination plugin') but the necessary google-cloud-storage dep wasn't added to requirements-base.in during the merge. lemur_gcs/plugin.py does `from google.cloud import storage` at module load time, which means pytest's collection step ImportErrors on the plugin's test files, breaking CI. Adds google-cloud-storage to requirements-base.in (upstream-shaped dep, correct file per CLAUDE.md) and recompiles. pip-compile pulled in google-cloud-core, google-crc32c, and google-resumable-media as transitives, all consistent with what upstream Netflix resolves to.
These plugins came in from the Netflix upstream merge but were never present in Datadog's master and we have no use case for them: - lemur_gcs: GCS bucket destination plugin (upstream commit a2bec2a) - lemur_google_ca: Google Cloud Private CA issuer plugin (upstream commit 60f4f48) Removes: - lemur/plugins/lemur_gcs/ (plugin + tests, 462 lines) - lemur/plugins/lemur_google_ca/ (plugin + tests, 391 lines) - The two entry-point registrations in pyproject.toml - google-cloud-storage from requirements-base.in (added in 5cc2a5d just to keep lemur_gcs importable; no longer needed) Recompiles requirements.txt to drop google-cloud-storage and its transitives (google-cloud-core, google-crc32c, google-resumable-media). Keep the upstream merge minimal: only pull forward things that modernize what we already use, not new plugins we don't ship.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merges upstream
Netflix/lemur main(2178 commits) into the Datadog fork. Resolves 89 conflicts, recompiles pinned requirements, fixes a pre-existing missing dep, and ships a migration-tree audit doc. Tests: 864 passed, 18 skipped.Commits (first-parent)
c87a48,b02878304fa2upstream/mainintowip-apr27(89 conflicts resolved)d32e2ecachetoolsdep)beb4adrequirements{,-dev,-docs,-tests}.txt+ add migration audit docConflict resolution policy
requirements*.{in,txt}(FIPS pincryptography==43.0.1), Dockerfile, Makefile,.github/workflows/*, CODEOWNERS, dependabot,local/src/lemur.conf.py, README,docs/administration.rst,tox.ini,setup.py,setup.cfg,lemur/plugins/lemur_azure_dest/plugin.py(Datadog plugin upstream removed).Behavior changes operators / on-call should know about
CLI re-platformed:
flask_script→click(FlaskGroup)lemur/manage.py,lemur/certificates/cli.py,lemur/acme_providers/cli.py,lemur/notifications/cli.py, etc. moved fromflask_script@manager.optiontoclick. Invocation patterns likelemur ... <cmd>largely still work, but flag parsing and help output differ. Any runbooks or shell scripts invokinglemur ...subcommands need a smoke test before deploy. Datadog-only options preserved onlemur certificates ...:--region, source-based rotation, multi-cert-per-endpoint loop.Auth / SSO:
IDP_GROUPS_KEYSreplaces hard-codedgoogleGroupslemur/auth/views.pynow reads group claims from a configurable list of keys (IDP_GROUPS_KEYS) rather than always looking atgoogleGroups. Verify the staging/commercial/governmentlemur.conf.py(in k8s-resources) setsIDP_GROUPS_KEYS = ["googleGroups"](or whatever keys we use) before deploy — otherwise group-based authorization may break for SSO logins. The DatadogJWTAuthenticatorVault path is unchanged.Private-key export: stacked validation
lemur/certificates/views.pykeeps the Datadog break-glass requirement and now also runs upstream's newCERTIFICATE_EXPORT_KEY_REQUEST_VALIDATIONhook if configured. Both apply (export must satisfy break-glass and the optional validator). No-op unless we set the new config.AWS endpoint discovery: skip-region-on-failure
lemur/plugins/lemur_aws/plugin.py::get_endpointsnow wraps per-region calls in try/except — a failure in one region no longer aborts the whole sync, the failed region is skipped and logged. Affects sandbox/commercial/government source-sync runs; previously an outage in one region's API would fail the entire job.New AWS plugins available
Two new plugin classes from upstream are now registered:
AWSACMSourcePlugin(ACM source) andACMDestinationPlugin. Not enabled by default — only takes effect if listed in plugin config.AWS STS role-scoping bug fix
lemur/plugins/lemur_aws/sts.pyfixed a latent bug whererolewas referenced from outside the inner refresh closure. Took upstream. No expected user-visible change unless a refresh path was being silently broken.ACME modernization
lemur/plugins/lemur_acme/acme_handlers.pyswitched toClientV2.get_directory(...)andcryptography.x509.load_pem_x509_certificatefor revocation. Functional parity expected; revocation paths should be smoke-tested.New config callbacks (off unless set)
Upstream added several pluggable validators/filters. None are active without explicit config:
ENABLE_AUTOROTATION_FILTER,REISSUE_FILTER,DISABLE_AUTOROTATION_FILTERCERTIFICATE_CREATE_REQUEST_VALIDATION,CERTIFICATE_UPDATE_REQUEST_VALIDATION,CERTIFICATE_EXPORT_KEY_REQUEST_VALIDATIONENABLE_AUTO_ROTATE_ALL_AUTHORITIESAWS_ELB_IGNORE_TAGS,AWS_CLOUDFRONT_IGNORE_TAGS,AWS_IAM_IGNORE_TAGSNew celery task:
disable_autorotate_without_endpointUpstream added this. Default is no-op — its filter callback returns nothing unless we configure one. Verified the Datadog beat schedule in
chart/config/lemur.conf.py(k8s-resources) does not need changes; this task is opt-in.New API endpoint:
PATCH /certificates/{id}/descriptionLighter-weight description update — no need to PUT the full cert object. New endpoint; no existing endpoint changed.
Source-sync stays sequential
lemur/sources/cli.pypreserved as ours — sequential iteration. Critical (per CLAUDE.md, ref commit0ad9ef89); parallelizing floods the Celery queue. Source-sync behavior is unchanged.Datadog SNI cert sync preserved
lemur/sources/service.pykeeps the Datadog primary/SNI sync path. Upstream's get-by-name+hash fallback dropped — incompatible with our data shape.Datadog ECCPRIME256V1 reissue preserved
lemur/certificates/service.pykeeps the explicit ECCPRIME256V1 reissue block.Dependency / runtime updates
cryptography==43.0.1pin preserved (FIPS — gov build will not break).requirements.txtrecompiled — version bumps foracme,certbot,boto3/botocore,celery,google-cloud-*,msal,requests,werkzeug, etc. Critical security overrides preserved (urllib3>=2.5.0,jinja2>=3.1.6,python_ldap>=3.4.5,h11>=0.16.0).cachetoolstorequirements-datadog.in— pre-existing missing dep used bylemur/auth/vault_jwt_auth.pysince Supporting Vault Implicit OIDC Flow for User UI Login #157 (4acbeb4), never declared. Tests previously couldn't collect without it; commercial/gov runtime worked only via transitive resolution at deploy time.pip install "file://...#egg=") with modernpip install -e ".[dev]"/[tests].pyproject.toml [tool.flake8]ignoresE203(matchessetup.cfg; needed for upstream's black-formatted slices).Upstream version + Python/Postgres support matrix
__version__to1.3.dev0(was1.2.dev0).Migration tree
Zero new schema migrations introduced by the merge. The previous Datadog maintainer kept the migration chain in sync with upstream pre-merge. The single Datadog-only migration (
44d67c1988a2_.py, endpoints↔certificates m2m) remains the head, untouched.Two migration-related files modified by upstream:
lemur/migrations/versions/5770674184de_.py: cosmetic f-string conversion only. No DDL change.lemur/migrations/env.py: cleanups + dropscompare_type=Truefor autogenerate. Only affects futurelemur db migrateautogen accuracy on column-type changes — does not affect already-applied migrations or runtime. Behavior now matches upstream.Full audit:
docs/upstream-merge-migrations-2026-04-27.md.CI / build infra
.github/workflows/codeql-analysis.ymlrenamed tocodeql.yml(upstream rename).setup.py/setup.cfgkept (upstream removed in favor of purepyproject.toml); follow-up to migrate fully..github/workflows/ci.ymlkept (upstream removed in favor of newer workflows; ours is wired to Datadog CI).Test plan
make lint-python— cleanmake test-python— 864 passed, 18 skippedlemur db upgradeagainst staging — should be a no-op (no new migrations)lemur certificates rotate,lemur source sync,lemur acme dnsproviders— verify click-based invocation worksIDP_GROUPS_KEYSis set in k8s-resourceslemur.conf.pyFollow-ups (not in this PR)
setup.py/setup.cfgtopyproject.toml(upstream did; we kept ours).compare_type=Truetoenv.pyfor stricter autogenerate (default: leave as upstream).aws-sam-translatorflagged apydanticresolver warning during recompile — not blocking lemur, but worth investigating if we use SAM elsewhere.🤖 Generated with Claude Code