Skip to content

Commit

Permalink
expose deleting orphaned assignments and orphaned eligible assignments
Browse files Browse the repository at this point in the history
  • Loading branch information
demoray authored Jul 11, 2024
1 parent b03ef64 commit a0669e5
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 119 deletions.
87 changes: 76 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Usage: az-pim [OPTIONS] <COMMAND>
Commands:
list List active or eligible assignments
activate Activate roles
deactivate Deactivate roles
activate Activate eligible role assignments
deactivate Deactivate eligible role assignments
delete Delete eligible role assignments
role Manage Azure role-based access control (Azure RBAC)
init Setup shell tab completions
Expand Down Expand Up @@ -103,7 +104,7 @@ $
## az-pim activate

```
Activate roles
Activate eligible role assignments
Usage: activate [OPTIONS] <COMMAND>
Expand Down Expand Up @@ -291,7 +292,7 @@ Options:
## az-pim deactivate

```
Deactivate roles
Deactivate eligible role assignments
Usage: deactivate [OPTIONS] <COMMAND>
Expand Down Expand Up @@ -414,6 +415,67 @@ Options:
-h, --help
Print help (see a summary with '-h')
```
## az-pim delete

```
Delete eligible role assignments
Usage: delete [OPTIONS] <COMMAND>
Commands:
orphaned-entries Delete assignments that objects in Microsoft Graph cannot be found
Options:
--verbose...
Increase logging verbosity. Provide repeatedly to increase the verbosity
--quiet
Only show errors
-h, --help
Print help
```
### az-pim delete orphaned-entries

```
Delete assignments that objects in Microsoft Graph cannot be found
Usage: orphaned-entries [OPTIONS]
Options:
--subscription <SUBSCRIPTION>
Subscription
--verbose...
Increase logging verbosity. Provide repeatedly to increase the verbosity
--quiet
Only show errors
--resource-group <RESOURCE_GROUP>
Resource Group
This argument requires `subscription` to be set.
--provider <PROVIDER>
Provider
This argument requires `subscription` and `resource_group` to be set.
--scope <SCOPE>
Specify scope directly
--nested
Delete nested assignments
--yes
Always respond yes to confirmations
-h, --help
Print help (see a summary with '-h')
```
## az-pim role

Expand Down Expand Up @@ -446,10 +508,10 @@ Manage role assignments
Usage: assignment [OPTIONS] <COMMAND>
Commands:
list List assignments
delete Delete an assignment
delete-set Delete a set of assignments
delete-orphan-entries Delete assignments that objects in Microsoft Graph cannot be found
list List assignments
delete Delete an assignment
delete-set Delete a set of assignments
delete-orphaned-entries Delete assignments that objects in Microsoft Graph cannot be found
Options:
--verbose...
Expand Down Expand Up @@ -597,12 +659,12 @@ $ az-pim role assignment list --subscription 00000000-0000-0000-0000-00000000000
$
```

#### az-pim role assignment delete-orphan-entries
#### az-pim role assignment delete-orphaned-entries

```
Delete assignments that objects in Microsoft Graph cannot be found
Usage: delete-orphan-entries [OPTIONS]
Usage: delete-orphaned-entries [OPTIONS]
Options:
--subscription <SUBSCRIPTION>
Expand All @@ -627,6 +689,9 @@ Options:
--scope <SCOPE>
Specify scope directly
--nested
Delete nested assignments
--yes
Always respond yes to confirmations
Expand All @@ -637,7 +702,7 @@ Options:
##### Example Usage

```
$ az-pim role assignment delete-orphan-entries --subscription 00000000-0000-0000-0000-000000000001
$ az-pim role assignment delete-orphaned-entries --subscription 00000000-0000-0000-0000-000000000001
2024-07-09T19:54:45.843289Z INFO azure_pim_cli: listing assignments
2024-07-09T19:54:48.142932Z INFO azure_pim_cli: listing role definitions
2024-07-09T19:54:48.421671Z INFO az_pim: Are you sure you want to delete role: "Storage Queue Data Contributor" principal:00000000-0000-0000-0000-000000000000 (type: ServicePrincipal) scope:/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.Storage/storageAccounts/mystorageaccount? (y/n):
Expand Down
82 changes: 25 additions & 57 deletions examples/cleanup-orphaned-assignments.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use anyhow::{Context, Result};
use anyhow::Result;
use azure_pim_cli::{models::roles::RoleAssignments, ListFilter, PimClient};
use clap::Parser;
use std::{
io::{stderr, stdin},
time::Duration,
};
use tracing::{debug, info, level_filters::LevelFilter, warn};
use std::{collections::BTreeSet, io::stderr, time::Duration};
use tracing::{info, level_filters::LevelFilter};
use tracing_subscriber::{fmt, EnvFilter};

/// Cleanup orphaned role assignments for an arbitrary set of subscriptions
Expand All @@ -16,23 +13,6 @@ struct Args {
yes: bool,
}

fn choice(msg: &str) -> bool {
info!("Are you sure you want to {msg}? (y/n): ");
loop {
let mut input = String::new();
let Ok(_) = stdin().read_line(&mut input) else {
continue;
};
match input.trim().to_lowercase().as_str() {
"y" => break true,
"n" => break false,
_ => {
warn!("Please enter 'y' or 'n': ");
}
}
}
}

fn main() -> Result<()> {
fmt()
.with_env_filter(
Expand All @@ -50,6 +30,9 @@ fn main() -> Result<()> {
let mut total = client.list_eligible_role_assignments(None, Some(ListFilter::AsTarget))?;
total.0.extend(active.0.clone());

let mut to_activate = RoleAssignments::default();

let mut scopes = BTreeSet::new();
for role_assignment in total.0 {
if role_assignment.scope.subscription().is_none() {
continue;
Expand All @@ -60,46 +43,31 @@ fn main() -> Result<()> {
{
continue;
}

info!("checking {}", role_assignment.scope_name);

if !active.0.contains(&role_assignment) {
client.activate_role_assignment(
&role_assignment,
"cleaning up orphaned resources",
Duration::from_secs(60 * 60 * 8),
)?;
let mut set = RoleAssignments::default();
set.insert(role_assignment.clone());
client.wait_for_role_activation(&set, Duration::from_secs(60 * 5))?;
to_activate.insert(role_assignment.clone());
}

let mut objects = client
.role_assignments(&role_assignment.scope)
.context("unable to list active assignments")?;
let definitions = client.role_definitions(&role_assignment.scope)?;
debug!("{} total entries", objects.len());
objects.retain(|x| x.object.is_none());
debug!("{} orphaned entries", objects.len());
for entry in objects {
let definition = definitions
.iter()
.find(|x| x.id == entry.properties.role_definition_id);
let value = format!(
"role:\"{}\" principal:{} (type: {}) scope:{}",
definition.map_or(entry.name.as_str(), |x| x.properties.role_name.as_str()),
entry.properties.principal_id,
entry.properties.principal_type,
entry.properties.scope
);
if !yes && !choice(&format!("delete {value}")) {
info!("skipping {value}");
continue;
}
scopes.insert(role_assignment.scope);
}

client
.delete_role_assignment(&entry.properties.scope, &entry.name)
.context("unable to delete assignment")?;
}
if !to_activate.is_empty() {
client.activate_role_assignment_set(
&to_activate,
"cleaning up orphaned resources",
Duration::from_secs(60 * 60 * 8),
5,
)?;
client.wait_for_role_activation(&to_activate, Duration::from_secs(60 * 5))?;
}

for scope in scopes {
info!("deleting orphaned role assignments for {scope}");
client.delete_orphaned_role_assignments(&scope, yes, true)?;
info!("deleting orphaned eligible role assignments for {scope}");
client.delete_orphaned_eligible_role_assignments(&scope, yes, true)?;
}

Ok(())
Expand Down
Loading

0 comments on commit a0669e5

Please sign in to comment.