Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

1Password User Activity Monitoring: From CLI to Email Reports

If you have a corporate password manager, keeping track of who's actually using your security tools becomes crucial.

I needed a way to monitor user activity and identify potential security risks from inactive accounts. Here's how I built an automated solution using 1Password CLI and PowerShell to generate professional email reports.

The Challenge

I thought it would be a good idea to get regular visibility into:

  • Which users haven't logged into 1Password recently
  • Automated reporting without manual data collection

The built-in 1Password web interface provides some reporting, but I needed something more automated and customizable for our specific risk categories.

Visual Results

This is the main header of the email with the overview:


Then you have all the users broken down with "risk" as below:


Part 1: Extracting Data with 1Password CLI

Understanding the Data Structure

The first step was understanding what data 1Password CLI actually provides. You need to authenticate first, then the key insight is that op user list doesn't include login timestamps - you need to query individual users.

# First, authenticate to 1Password
eval $(op signin)

# This gives you basic user info but NO login data
op user list --format=json

# This gives you detailed user info INCLUDING last_auth_at
op user get "user@croucher.cloud" --format=json

When I ran op user get on a single user, I discovered the last_auth_at field:

{
  "id": "K4KF334T35F3JBAO4DTUOZXXA4",
  "name": "Lee Croucher",
  "email": “Lee.Croucher@croucher.cloud",
  "type": "MEMBER",
  "state": "ACTIVE",
  "created_at": "2024-06-20T15:39:37Z",
  "updated_at": "2024-07-19T09:06:54Z",
  "last_auth_at": "2024-07-15T08:24:20Z"
}

Building the Data Collection Script

The script follows a simple process:

  1. Authenticate to 1Password
  2. Get all user emails from the user list
  3. Query each user individually to get their authentication data
#!/bin/bash

# Step 1: Authenticate
eval $(op signin)

# Step 2: Get user list and extract emails
users=$(op user list --format=json)
mapfile -t emails < <(echo "$users" | sed -n 's/.*"email"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')

# Step 3: Process each user
for email in "${emails[@]}"; do
    echo "Processing: $email"
    
    user_data=$(op user get "$email" --format=json)
    last_auth=$(echo "$user_data" | sed -n 's/.*"last_auth_at"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
    
    # Calculate days since last login
    if [[ -z "$last_auth" ]]; then
        last_auth="Never"
        days_since="Never"
    else
        current_date=$(date +%s)
        last_date=$(date -d "$last_auth" +%s)
        days_since=$(( (current_date - last_date) / 86400 ))
    fi
    
    # Write to CSV
    echo "\"$email\",\"$last_auth\",\"$days_since\"" >> "$OUTPUT_FILE"
done

Part 2: Professional Email Reporting with PowerShell

I thought up four risk categories based on login patterns:

  • Low Risk (< 15 days): Active users, no immediate concern
  • Medium Risk (15-60 days): May need a gentle reminder
  • High Risk (61-100 days): Potential security concern - where were the passwords being stored?
  • Not Using 1Password (101+ days/Never): High security risk

Reading and Processing the Data

The PowerShell script automatically finds the latest CSV file and processes it:

# Find the latest CSV file
$csvFiles = Get-ChildItem -Path $Path -Filter "user_login_report_*.csv" | Sort-Object LastWriteTime -Descending
$latestCSV = $csvFiles[0]

# Read and enhance the data with risk assessment
$userData = Import-Csv -Path $latestCSV.FullName
$processedData = $userData | ForEach-Object {
    $risk = Get-RiskLevel -DaysString $_.'Days Since Last Login'
    [PSCustomObject]@{
        Email = $_.Email
        'Last Authentication' = $_.'Last Authentication'
        'Days Since Last Login' = $_.'Days Since Last Login'
        'Risk Level' = $risk
        'Risk Color' = Get-RiskColor -Risk $risk
    }
}

Creating Professional HTML Reports

Rather than plain text emails, I would choose to generate HTML reports with:

Executive Summary Table:

$summaryTable = @"
<table style="border-collapse: collapse; width: 100%;">
    <tr>
        <td style="background-color: #28a745; color: white;">Low</td>
        <td>$lowRisk users</td>
        <td>$([math]::Round(($lowRisk / $totalUsers) * 100, 1))%</td>
    </tr>
    <!-- More rows for other risk levels -->
</table>
"@

Detailed User Table: Shows every user with color-coded risk levels, sorted with highest risk first.

Running the Complete Solution

I typically run both scripts in sequence:

# Generate the data (authentication happens within the script)
./onepassword_report.sh

# Send the email report
./Send-1PasswordReport.ps1 -SMTPServer "mail.croucher.cloud" -FromEmail "security@croucher.cloud" -ToEmail "team@croucher.cloud"
Previous Post Next Post

نموذج الاتصال