mirror of
https://github.com/ChrispyBacon-dev/DockFlare.git
synced 2026-04-26 10:50:43 +00:00
application update before delete duplicated access policy
This commit is contained in:
parent
4bbdbf58c8
commit
b7a83e84fb
2 changed files with 80 additions and 64 deletions
21
CLI_USAGE.md
21
CLI_USAGE.md
|
|
@ -41,9 +41,10 @@ This will:
|
|||
2. **Groups policies by name** to identify duplicates
|
||||
3. **Sorts by creation date** - keeps the oldest policy for each name
|
||||
4. **Checks Access Applications** - identifies which applications are using duplicate policies
|
||||
5. **Updates Access Applications** - replaces duplicate policy IDs with the kept policy ID
|
||||
6. **Deletes newer duplicates** (only when using `--apply`)
|
||||
7. **Updates state.json** - ensures all access groups reference the correct (kept) policy ID
|
||||
5. **Updates & Deletes** - for each duplicate:
|
||||
- Updates affected applications to use the kept policy ID
|
||||
- Then deletes the duplicate policy
|
||||
6. **Updates state.json** - ensures all access groups reference the correct (kept) policy ID
|
||||
|
||||
### Example Output
|
||||
|
||||
|
|
@ -83,16 +84,13 @@ Processing: 'DockFlare-AccessGroup-idp-blocker'
|
|||
Using policy: mno345
|
||||
- App: 'DockFlare-app2.example.com' (domain: app2.example.com)
|
||||
Using policy: pqr678
|
||||
📝 Updating applications to use kept policy ID jkl012...
|
||||
✓ Updated app 'DockFlare-app1.example.com': mno345 → jkl012
|
||||
✓ Updated app 'DockFlare-app2.example.com': pqr678 → jkl012
|
||||
✗ Would delete: ID=mno345 (created: 2025-01-02T10:00:00Z)
|
||||
✗ Would delete: ID=pqr678 (created: 2025-01-03T11:00:00Z)
|
||||
|
||||
Step 6: Updating Access Applications to use kept policy IDs...
|
||||
|
||||
Updating applications for policy 'DockFlare-AccessGroup-idp-blocker' to use ID jkl012:
|
||||
Would update app 'DockFlare-app1.example.com': mno345 → jkl012
|
||||
Would update app 'DockFlare-app2.example.com': pqr678 → jkl012
|
||||
|
||||
Step 7: Updating state.json with correct policy IDs...
|
||||
Step 6: Updating state.json with correct policy IDs...
|
||||
DRY RUN: Would update state.json with the following changes:
|
||||
Group 'public-default-bypass': def456 → abc123 (policy: DockFlare-Default-Public-Access-Bypass)
|
||||
Group 'idp-blocker': mno345 → jkl012 (policy: DockFlare-AccessGroup-idp-blocker)
|
||||
|
|
@ -126,6 +124,7 @@ Policies that would be kept: 2
|
|||
|
||||
- The utility requires DockFlare to be configured with valid Cloudflare credentials
|
||||
- It operates on **all reusable policies** in your account, not just DockFlare-managed ones
|
||||
- **Automatically handles Access Applications** - The utility will update any applications using duplicate policies before deletion, ensuring no applications are left without access control
|
||||
- **Automatically handles Access Applications** - The utility detects apps using duplicate policies, updates them to use the kept policy, then safely deletes duplicates
|
||||
- **Safe execution order** - Applications are updated BEFORE policies are deleted, preventing any downtime or access control gaps
|
||||
- Always run with `--dry-run` first to preview changes
|
||||
- Deletion is permanent and cannot be undone (except by recreating policies manually)
|
||||
|
|
|
|||
|
|
@ -118,8 +118,22 @@ def cleanup_duplicate_policies(dry_run=True):
|
|||
|
||||
for app in all_apps:
|
||||
app_policies = app.get("policies", [])
|
||||
|
||||
for policy_id in policy_ids_to_delete:
|
||||
if policy_id in app_policies:
|
||||
found = False
|
||||
|
||||
if isinstance(app_policies, list):
|
||||
for policy in app_policies:
|
||||
if isinstance(policy, str):
|
||||
if policy == policy_id:
|
||||
found = True
|
||||
break
|
||||
elif isinstance(policy, dict):
|
||||
if policy.get("id") == policy_id:
|
||||
found = True
|
||||
break
|
||||
|
||||
if found:
|
||||
apps_using_duplicates.append({
|
||||
"app_id": app.get("id"),
|
||||
"app_name": app.get("name"),
|
||||
|
|
@ -135,53 +149,28 @@ def cleanup_duplicate_policies(dry_run=True):
|
|||
logging.info(f" - App: '{app_info['app_name']}' (domain: {app_info['app_domain']})")
|
||||
logging.info(f" Using policy: {app_info['old_policy_id']}")
|
||||
|
||||
for policy in policies_to_delete:
|
||||
policy_id = policy.get("id")
|
||||
policy_created = policy.get("created_at", "N/A")
|
||||
|
||||
if dry_run:
|
||||
logging.info(f" ✗ Would delete: ID={policy_id} (created: {policy_created})")
|
||||
else:
|
||||
logging.info(f" ✗ Deleting: ID={policy_id} (created: {policy_created})")
|
||||
success = reusable_policies.delete_reusable_policy(policy_id)
|
||||
if success:
|
||||
logging.info(f" → Successfully deleted policy {policy_id}")
|
||||
deleted_count += 1
|
||||
else:
|
||||
logging.error(f" → Failed to delete policy {policy_id}")
|
||||
|
||||
state_updates[name] = kept_id
|
||||
if apps_using_duplicates:
|
||||
app_updates_needed[name] = {
|
||||
"kept_id": kept_id,
|
||||
"apps": apps_using_duplicates
|
||||
}
|
||||
|
||||
logging.info("")
|
||||
|
||||
if app_updates_needed:
|
||||
logging.info("Step 6: Updating Access Applications to use kept policy IDs...")
|
||||
logging.info("")
|
||||
|
||||
for policy_name, update_info in app_updates_needed.items():
|
||||
kept_id = update_info["kept_id"]
|
||||
apps = update_info["apps"]
|
||||
|
||||
logging.info(f"Updating applications for policy '{policy_name}' to use ID {kept_id}:")
|
||||
|
||||
for app_info in apps:
|
||||
if not dry_run:
|
||||
logging.info(f" 📝 Updating applications to use kept policy ID {kept_id}...")
|
||||
from app.core import access_manager
|
||||
for app_info in apps_using_duplicates:
|
||||
app_id = app_info["app_id"]
|
||||
app_name = app_info["app_name"]
|
||||
old_policy_id = app_info["old_policy_id"]
|
||||
all_policies = app_info["all_policies"]
|
||||
|
||||
updated_policies = [kept_id if pid == old_policy_id else pid for pid in all_policies]
|
||||
|
||||
if dry_run:
|
||||
logging.info(f" Would update app '{app_name}': {old_policy_id} → {kept_id}")
|
||||
updated_policies = []
|
||||
for policy in all_policies:
|
||||
if isinstance(policy, str):
|
||||
updated_policies.append(kept_id if policy == old_policy_id else policy)
|
||||
elif isinstance(policy, dict):
|
||||
if policy.get("id") == old_policy_id:
|
||||
updated_policies.append(kept_id)
|
||||
else:
|
||||
updated_policies.append(policy.get("id") if policy.get("id") else policy)
|
||||
else:
|
||||
updated_policies.append(policy)
|
||||
|
||||
try:
|
||||
from app.core import access_manager
|
||||
app_details = access_manager.get_cloudflare_access_application(app_id)
|
||||
if app_details:
|
||||
success = access_manager.update_cloudflare_access_application(
|
||||
|
|
@ -204,13 +193,41 @@ def cleanup_duplicate_policies(dry_run=True):
|
|||
logging.error(f" ✗ Could not fetch details for app '{app_name}'")
|
||||
except Exception as e:
|
||||
logging.error(f" ✗ Error updating app '{app_name}': {e}")
|
||||
|
||||
logging.info("")
|
||||
|
||||
for policy in policies_to_delete:
|
||||
policy_id = policy.get("id")
|
||||
policy_created = policy.get("created_at", "N/A")
|
||||
|
||||
if dry_run:
|
||||
logging.info(f" ✗ Would delete: ID={policy_id} (created: {policy_created})")
|
||||
else:
|
||||
logging.info("Step 6: No Access Applications need updating")
|
||||
logging.info(f" ✗ Deleting: ID={policy_id} (created: {policy_created})")
|
||||
try:
|
||||
success = reusable_policies.delete_reusable_policy(policy_id)
|
||||
if success:
|
||||
logging.info(f" → Successfully deleted policy {policy_id}")
|
||||
deleted_count += 1
|
||||
else:
|
||||
logging.error(f" → Failed to delete policy {policy_id}")
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
if "409" in error_msg or "conflict" in error_msg.lower():
|
||||
logging.error(f" → Policy {policy_id} is still in use by applications")
|
||||
logging.error(f" → Detection may have missed some apps - please check Cloudflare dashboard")
|
||||
else:
|
||||
logging.error(f" → Failed to delete policy {policy_id}: {e}")
|
||||
|
||||
state_updates[name] = kept_id
|
||||
if apps_using_duplicates:
|
||||
app_updates_needed[name] = {
|
||||
"kept_id": kept_id,
|
||||
"apps": apps_using_duplicates
|
||||
}
|
||||
|
||||
logging.info("")
|
||||
|
||||
logging.info("Step 7: Updating state.json with correct policy IDs...")
|
||||
logging.info("Step 6: Updating state.json with correct policy IDs...")
|
||||
|
||||
if dry_run:
|
||||
logging.info("DRY RUN: Would update state.json with the following changes:")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue