Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
5f1e4f7
fix(rotation): default NULL-policy certs to the 'default' rotation po…
evan-datadog Aug 12, 2026
580195c
config: set LEMUR_DEFAULT_ROTATION_INTERVAL=60 and unify on the singl…
evan-datadog Aug 12, 2026
3e26ff6
refactor(rotation): split getter from sync; fire sync before rotation…
evan-datadog Aug 12, 2026
00cf889
refactor(rotation): consolidate into get_rotation_policy_from_config
evan-datadog Aug 12, 2026
474bc22
config: move LEMUR_DEFAULT_ROTATION_INTERVAL to lemur.conf.py via env…
evan-datadog Aug 12, 2026
cf33bd3
revert: restore lemur/default.conf.py to master
evan-datadog Aug 12, 2026
1e77c21
Update service.py
evan-datadog Aug 12, 2026
9f45a3a
refactor(rotation): rename to update_default_rotation_policy; consoli…
evan-datadog Aug 12, 2026
ba71df6
refactor(rotation): call update_default_rotation_policy at boot via i…
evan-datadog Aug 12, 2026
0dd2a90
refactor(rotation): give configure_default_rotation_policy its own me…
evan-datadog Aug 12, 2026
6b3e345
log create vs update in update_default_rotation_policy
evan-datadog Aug 12, 2026
73fddb2
Clean up formatting in factory.py
evan-datadog Aug 12, 2026
6831cf8
fix(rotation): guard configure_default_rotation_policy against missin…
evan-datadog Aug 12, 2026
898b636
fix(rotation): catch OperationalError instead of inspecting table exi…
evan-datadog Aug 12, 2026
2ca9244
fix(rotation): catch ProgrammingError; guard Certificate.__init__ query
evan-datadog Aug 12, 2026
6d33127
Update models.py
evan-datadog Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lemur/certificates/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def __init__(self, **kwargs):
self.roles = list(set(kwargs.get("roles", [])))
self.replaces = kwargs.get("replaces", [])
self.rotation = kwargs.get("rotation")
self.rotation_policy = kwargs.get("rotation_policy")
self.rotation_policy = kwargs.get("rotation_policy") or RotationPolicy.query.filter_by(name="default").first()
self.key_type = kwargs.get("key_type")
self.signing_algorithm = defaults.signing_algorithm(cert)
self.bits = defaults.bitstrength(cert)
Expand Down
23 changes: 23 additions & 0 deletions lemur/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def create_app(app_name=None, blueprints=None, config=None):
configure_logging(app)
configure_database(app)
install_plugins(app)
configure_default_rotation_policy(app)

@app.teardown_appcontext
def teardown(exception=None):
Expand All @@ -77,6 +78,28 @@ def teardown(exception=None):
return app


def configure_default_rotation_policy(app):
"""
Ensures the named "default" RotationPolicy exists and its days are in sync
with LEMUR_DEFAULT_ROTATION_INTERVAL. Called once at boot via create_app()
so every process (web, celery worker, celery beat) starts with the policy
matching the configured value.
"""
from lemur.policies import service as policy_service
from sqlalchemy.exc import OperationalError, ProgrammingError

with app.app_context():
try:
policy_service.update_default_rotation_policy()
except (OperationalError, ProgrammingError):
# rotation_policies table doesn't exist yet (fresh DB / migrations
# not yet run, or test DB before create_all). Safe to skip — the
# policy will be synced on the next boot after migrations complete.
app.logger.debug(
"Skipping default rotation policy sync: table not ready"
)


def from_file(file_path, silent=False):
"""
Updates the values in the config from a Python file. This function
Expand Down
19 changes: 1 addition & 18 deletions lemur/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,24 +282,7 @@ def run(self, password):
"DEFAULT_SECURITY", recipients=recipients
)

_DEFAULT_ROTATION_INTERVAL = "default"
default_rotation_interval = policy_service.get_by_name(
_DEFAULT_ROTATION_INTERVAL
)

if default_rotation_interval:
sys.stdout.write(
"[-] Default rotation interval policy already created, skipping...!\n"
)
else:
days = current_app.config.get("LEMUR_DEFAULT_ROTATION_INTERVAL", 30)
sys.stdout.write(
"[+] Creating default certificate rotation policy of {days} days before issuance.\n".format(
days=days
)
)
policy_service.create(days=days, name=_DEFAULT_ROTATION_INTERVAL)

policy_service.update_default_rotation_policy()
sys.stdout.write("[/] Done!\n")


Expand Down
27 changes: 27 additions & 0 deletions lemur/policies/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,37 @@
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""

from flask import current_app

from lemur import database
from lemur.policies.models import RotationPolicy


def update_default_rotation_policy():
"""
Return the named "default" RotationPolicy, keeping it in sync with
Comment thread
evan-datadog marked this conversation as resolved.
LEMUR_DEFAULT_ROTATION_INTERVAL: creates it if missing, updates its days
if the config has changed. This policy is the NULL-policy fallback in
Certificate.__init__.
The default rotation policy is refreshed as a part of the pre-query sync
in get_all_pending_reissue.
"""
days = current_app.config.get("LEMUR_DEFAULT_ROTATION_INTERVAL", 60)
policies = get_by_name("default")
if not policies:
current_app.logger.info(
"[+] Creating default rotation policy: days=%d", days
)
return create(days=days, name="default")
policy = policies[0]
if policy.days != days:
current_app.logger.info(
"[~] Updating default rotation policy: days %d -> %d", policy.days, days
)
update(policy.id, days=days)
return policy


def get(policy_id):
"""
Retrieves policy by its ID.
Expand Down
1 change: 1 addition & 0 deletions lemur/tests/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def get_random_secret(length):
LEMUR_DEFAULT_LOCATION = "Los Gatos"
LEMUR_DEFAULT_ORGANIZATION = "Example, Inc."
LEMUR_DEFAULT_ORGANIZATIONAL_UNIT = "Example"
LEMUR_DEFAULT_ROTATION_INTERVAL = 60

LEMUR_ALLOW_WEEKEND_EXPIRATION = False

Expand Down
3 changes: 3 additions & 0 deletions local/src/lemur.conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ def get_random_secret(length):
LEMUR_DEFAULT_ORGANIZATIONAL_UNIT = str(
os.environ.get("LEMUR_DEFAULT_ORGANIZATIONAL_UNIT", "")
)
LEMUR_DEFAULT_ROTATION_INTERVAL = int(
os.environ.get("LEMUR_DEFAULT_ROTATION_INTERVAL", 60)
)

LEMUR_DEFAULT_AUTHORITY = str(os.environ.get("LEMUR_DEFAULT_AUTHORITY", "ExampleCa"))

Expand Down
Loading