access-review – Coding skill for AI agents
Conduct periodic access reviews and certifications. Implement access governance and recertification workflows. Use when managing access compliance.
Install the access-review skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/access-review-e242a.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /access-review – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/access-review-e242a.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $access-review – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/access-review-e242a.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /access-review – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/access-review-e242a.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /access-review – then describe the task you want done.
SKILL.md content
Access Review
Implement periodic access review processes for AWS IAM, GitHub, Okta, and other identity providers, including automated reporting, certification workflows, and unused permission detection.
Access Review Process
access_review_workflow:
1_scope:
actions:
- Define systems in scope for the review cycle
- Identify review owners (managers, system owners)
- Set review timeline and deadlines
- Generate access inventory from all identity sources
frequency:
privileged_access: Quarterly
standard_access: Semi-annually
service_accounts: Quarterly
api_keys: Monthly
2_extract:
actions:
- Pull current access data from all systems
- Correlate identities across platforms (SSO mapping)
- Enrich with last login and activity data
- Flag accounts for review (inactive, over-privileged, orphaned)
3_review:
actions:
- Assign review items to appropriate managers
- Manager certifies each user's access (approve/revoke/modify)
- Risk-based prioritization (privileged users reviewed first)
- Escalate non-responses after deadline
decisions:
approve: "Access is appropriate for current role"
modify: "Access needs adjustment (reduce/change scope)"
revoke: "Access is no longer needed"
4_remediate:
actions:
- Revoke access flagged for removal
- Modify access as directed by reviewers
- Document exceptions with justification
- Confirm changes with system owners
sla:
revocations: "Complete within 5 business days of decision"
modifications: "Complete within 10 business days"
exceptions: "Approved by security team, documented, time-limited"
5_report:
actions:
- Generate completion metrics (% reviewed, % on time)
- Document all decisions and actions taken
- Archive evidence for compliance audits
- Identify process improvements for next cycleReview boundaries
Confirm exact tenant/accounts, read-only credentials, review period and authorized
reviewers. Store reports privately with defined retention; proposed cadence/SLA
numbers are examples, not compliance certification. Identity joins need verified
immutable IDs, not matching display names. Owner approval and a recovery/break-glass
plan are required before modifying access; inactivity heuristics never authorize
revoking production service accounts automatically.
AWS IAM Access Review Scripts
Obtain the IAM credential report through a read-only scoped client, poll boundedly
until complete, and decode it once into a private file. Failure/unsupported values
are unknown, never zero/inactive. Use named CSV columns, not positional awk fields:
import csv
def review_console_mfa(report_path):
candidates = []
with open(report_path, newline="", encoding="utf-8") as source:
for row in csv.DictReader(source):
if row.get("password_enabled") == "true" and row.get("mfa_active") == "false":
candidates.append({"user": row["user"], "finding": "review_console_mfa"})
return candidates # Private review data, not automatic disable actions.Compare timezone-aware last-use/creation times and both access-key slots with an
agreed threshold; missing history may mean never-used, unsupported or unavailable.
Password last-use alone is not overall account inactivity. Effective privilege
requires user/group/role/inline policies, boundaries, SCPs and resource policies;
policy-name matching is only a hint. Cross-account trust needs structured principal
and condition analysis, not grep or an AWS-account substring. No key or access is
revoked solely because a report marks it stale.
GitHub Access Review
#!/usr/bin/env bash
# github-access-review.sh - Partial organization inventory
set -euo pipefail
umask 077
ORG="your-org"
OUTPUT_DIR="./access-review/github/$(date +%Y-%m)"
mkdir -p "$OUTPUT_DIR"
echo "=== GitHub Organization Access Review ==="
echo "--- Organization Members ---"
gh api orgs/$ORG/members --paginate \
--jq '.[] | [.login, .site_admin] | @csv' \
> "$OUTPUT_DIR/org-members.csv"
echo "--- Organization Owners ---"
gh api "orgs/$ORG/members?role=admin" --paginate \
--jq '.[] | .login' \
> "$OUTPUT_DIR/org-owners.txt"
echo "--- Outside Collaborators ---"
gh api orgs/$ORG/outside_collaborators --paginate \
--jq '.[] | .login' \
> "$OUTPUT_DIR/outside-collaborators.txt"
echo "--- Repository Access Per Repo ---"
for repo in $(gh api "orgs/$ORG/repos" --paginate --jq '.[].name'); do
echo "Repo: $repo"
gh api "repos/$ORG/$repo/collaborators" --paginate \
--jq '.[] | [.login, .role_name] | @csv' \
> "$OUTPUT_DIR/repo-$repo-access.csv"
done
echo "--- Team Memberships ---"
for team in $(gh api orgs/$ORG/teams --paginate --jq '.[].slug'); do
echo "Team: $team"
gh api "orgs/$ORG/teams/$team/members" --paginate \
--jq '.[] | .login' \
> "$OUTPUT_DIR/team-$team-members.txt"
done
echo "--- Pending Invitations ---"
gh api orgs/$ORG/invitations --paginate \
--jq '.[] | [.login, .email, .role, .created_at] | @csv' \
> "$OUTPUT_DIR/pending-invitations.csv"
echo "--- Deploy Keys ---"
for repo in $(gh api "orgs/$ORG/repos" --paginate --jq '.[].name'); do
keys=$(gh api "repos/$ORG/$repo/keys" --jq '.[].title' 2>/dev/null)
if [ -n "$keys" ]; then
echo "$repo: $keys"
fi
done > "$OUTPUT_DIR/deploy-keys.txt"
# Branch/ruleset enforcement needs a separate authorized read of each repository's
# actual default/protected branches, classic protection and repository/org rulesets.
# A 403/404 is unknown or absent for that API, not proof the branch is unprotected.
# site_admin is GitHub site administration, NOT an organization-owner indicator.
echo "Report generated in $OUTPUT_DIR"Okta Access Review
Use a secret-aware SDK/client against the approved Okta HTTPS domain; do not put
SSWS tokens in curl arguments. Disable unexpected redirects, set deadlines and
bounded page/retry budgets, and follow only same-origin API Link: rel=next URLs.
Enumerate users, factors, apps/assignments and admin roles with pagination; a
single limit=200 response is incomplete. Iterate structured app IDs, not CSV
rows containing quoted commas. Record permissions/errors/coverage explicitly.
Factor enrollment is not proof that the current sign-on policy requires MFA or
that a user's enrollment is usable. Compare current authenticators, policy and
assignment data before recommendations. Keep names/email inventories restricted.
Unused Permission Detection
"""
Detect unused IAM permissions using CloudTrail and IAM Access Analyzer.
Generates recommendations for right-sizing access.
"""
import boto3
import json
import time
from datetime import datetime, timedelta, timezone
def analyze_iam_usage(days_lookback=90):
"""Analyze IAM user and role activity against granted permissions."""
iam = boto3.client("iam")
report = {
"generated_at": datetime.now(timezone.utc).isoformat(),
"lookback_days": days_lookback,
"findings": [],
}
users = (user for page in iam.get_paginator("list_users").paginate() for user in page["Users"])
for user in users:
username = user["UserName"]
# Get service last accessed data
job_id = iam.generate_service_last_accessed_details(
Arn=user["Arn"]
)["JobId"]
for attempt in range(60):
result = iam.get_service_last_accessed_details(JobId=job_id)
if result["JobStatus"] == "COMPLETED":
break
if result["JobStatus"] == "FAILED":
raise RuntimeError("IAM last-access job failed")
time.sleep(2)
else:
raise TimeoutError("IAM last-access job exceeded polling budget")
services = list(result["ServicesLastAccessed"])
while result.get("IsTruncated"):
result = iam.get_service_last_accessed_details(JobId=job_id, Marker=result["Marker"])
services.extend(result["ServicesLastAccessed"])
threshold = datetime.now(timezone.utc) - timedelta(days=days_lookback)
unused_services = []
for service in services:
last_accessed = service.get("LastAuthenticated")
if last_accessed is None or last_accessed < threshold:
unused_services.append({
"service": service["ServiceNamespace"],
"last_accessed": str(last_accessed) if last_accessed else "Unknown/no recorded activity",
})
if unused_services:
report["findings"].append({
"type": "unused_permissions",
"user": username,
"arn": user["Arn"],
"unused_service_count": len(unused_services),
"unused_services": unused_services[:10],
"recommendation": "Review and remove unused service permi… (full content is in the download package)
Related skills
- api-design-principles – Master REST and GraphQL API design principles to build intuitive, scalable, and…
- cli-creator – Build a composable CLI for Codex from API docs, an OpenAPI spec, existing curl examples…
- create-plan – Create a concise plan. Use when a user explicitly asks for a plan related to a coding…
- code-review-and-quality – Conducts multi-axis code review. Use before merging any change. Use when reviewing code…
- active-directory-attacks – Assess Active Directory attack paths using scoped configuration review and controlled…
- address-github-comments – Use when you need to address review or issue comments on an open GitHub Pull Request…
- architecture-decision-records – Write and maintain Architecture Decision Records (ADRs) following best practices for…
- architecture-patterns – Implement proven backend architecture patterns including Clean Architecture, Hexagonal…