Deleting inactive Sharefile invites

Sharefile Logo

File collaboration external to a firm is always a delicate balance. Too strict a set of IT rules and staff resort to email attachments and shadow IT. Too loose and you have a bunch of external users with access to various parts of your SaaS stack. Either way, there is a clear business need and many vendors strive to meet it, from pure plays like Dropbox down to guest user features in SharePoint.

Sharefile can be a good solution in this space: user driven guest enrollment without the guests having any possible access to any other system.

One of the challenges with any guest access though, is that a certain percentage of guest invites are never accepted. From a data and cyber security hygiene perspective it’s important that these unused invites expire.

Unfortunately that doesn’t seem to be a native feature of Sharefile. Happily, the following script works nicely to do the cleanup. Run from an Azure Automation Runbook (or similar) on a schedule and you’re good to go.

I hope you find it useful.

# Retrieve all clients from Sharefile, execute a delete for any who haven't 
# accepted their invite within 60 days

$sfSecret = Get-AutomationVariable -Name "ShareFileSecret"
$sfID = Get-AutomationVariable -Name "ShareFileClientID"
$sfCredentials = Get-AutomationPSCredential -Name 'Sharefile Service Account'

$Url = "https://XXXX.sharefile.com/oauth/token"
$Body = @{
    'grant_type'='password';
    'client_id'=$sfID;
    'client_secret'=$sfSecret;
    'username'=$sfCredentials.UserName
    'password'=$sfCredentials.GetNetworkCredential().Password
}
$result = Invoke-RestMethod -Method 'GET' -Body $body `
    -Headers @{"Content-Type"="application/x-www-form-urlencoded"} -Uri $url
$headerParams = @{'Authorization'="Bearer $($result.access_token)"}
$filter = 'CreatedDate lt date('+(get-date).AddDays(-60).toString('yyyy-MM-dd')+`
    ') and IsConfirmed eq False'

$clientURI = 'https://XXXX.sf-api.com/sf/v3/Accounts/Clients'
$deleteURL = 'https://XXXX.sf-api.com/sf/v3/Users/Clients/BulkDelete'
$clientBody = @{
    '`$select'='Name,IsConfirmed,CreatedDate,Id,Email';
    '`$filter'=$filter
}
$users = Invoke-RestMethod -Header $headerParams -Method 'GET' -Body $clientBody `
    -Uri $clientURI
Write-Output "Found $($users.value.count) clients"
$toDelete = @()
$deleteCount = 0
$cutoff = (get-date).AddDays(-60)
foreach($user in $users.value){
    # make sure
    if(!$user.isConfirmed -and [DateTime]($user.CreatedDate) -lt $cutoff){ 
        $toDelete +=$user.id
        $deleteCount++
        Write-Output "Will delete $($user.email), ($($user.id)) "+`
         "created $($user.CreatedDate), confirmed $($user.isconfirmed)"
    } 
    # API only permits max 100 at a time
    if($toDelete.count -gt 99){
        $result = Invoke-RestMethod -Header $headerParams `
            -ContentType 'application/json' -Method 'POST' `
            -Body (@{'UserIDs'=$toDelete} | ConvertTo-Json) -Uri $deleteURL
        $toDelete = @()
    }
}

if($toDelete.count -gt 0){
    $result = Invoke-RestMethod -Header $headerParams `
        -ContentType 'application/json' -Method 'POST' `
        -Body (@{'UserIDs'=$toDelete}|ConvertTo-Json) -Uri $deleteURL
}

if($deleteCount -lt 1){
    Write-Output "No client users matching query, nothing deleted"
} else {
    Write-Output "Deleted $deleteCount users"
}