IAM gives you two tools for auditing and tightening access control — one covers your whole account, the other zooms in on individual users.
📊 IAM Credentials Report — (Account Level Tool)
<div class="infographic-credreport">
<style>
.infographic-credreport {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f6f4ef;
--accent: #2e5077;
--accent-soft:#e6ecf3;
--line: #ddd6c9;
--ok: #1e8e5a;
--ok-soft: #e2f6ec;
--warn: #b8860b;
--warn-soft: #fbf1d9;
--bad: #c0392b;
--bad-soft: #fbe9e7;
--display-font: Georgia, 'Iowan Old Style', serif;
--mono-font: 'SF Mono', Menlo, Consolas, monospace;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--ink);
background: var(--paper);
padding: 2rem 1.25rem 2.5rem;
max-width: 760px;
margin: 0 auto;
border-radius: 14px;
box-sizing: border-box;
}
.infographic-credreport[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #7ea6d6;
--accent-soft:#1c2740;
--line: #2c313d;
--ok: #4fbf87;
--ok-soft: #143024;
--warn: #e0b03e;
--warn-soft: #3a3010;
--bad: #e57373;
--bad-soft: #3a2222;
}
.infographic-credreport * { box-sizing: border-box; }
.cr-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.3rem; }
.cr-header .icon { font-size: 1.6rem; }
.cr-title { font-family: var(--display-font); font-size: 1.35rem; margin: 0; }
.cr-title .tag { font-family: -apple-system, sans-serif; font-weight: 400; font-size: 0.85rem; color: var(--ink-soft); }
.cr-sub { color: var(--ink-soft); font-size: 0.86rem; margin: 0 0 1.4rem; padding-bottom: 1rem;
border-bottom: 1px solid var(--line); }
.cr-table-wrap { overflow-x: auto; }
.cr-table { width: 100%; border-collapse: collapse; font-size: 0.86rem; min-width: 500px; }
.cr-table thead th { background: var(--accent); color: #fff; text-align: left; padding: 0.6rem 0.8rem;
font-weight: 700; font-size: 0.78rem; }
.cr-table thead th:not(:first-child) { text-align: center; }
.cr-table tbody td { padding: 0.65rem 0.8rem; border-bottom: 1px solid var(--line); }
.cr-table tbody td:not(:first-child) { text-align: center; }
.cr-table tbody tr { cursor: pointer; transition: background 0.15s; }
.cr-table tbody tr:hover { background: var(--paper-alt); }
.cr-table tbody tr.is-open { background: var(--accent-soft); }
.cr-user { font-weight: 700; color: var(--accent); }
.cr-yes { color: var(--ok); font-weight: 700; }
.cr-no { color: var(--bad); font-weight: 700; }
.cr-date { font-weight: 600; }
.cr-date.fresh { color: var(--ok); }
.cr-date.warn { color: var(--warn); }
.cr-date.stale { color: var(--bad); }
.cr-verdict-row td { padding: 0; border-bottom: 1px solid var(--line); }
.cr-verdict { display: none; padding: 0.6rem 0.9rem; font-size: 0.8rem; }
.cr-verdict.show { display: block; }
.cr-verdict.ok { color: var(--ok); }
.cr-verdict.warn { color: var(--warn); }
.cr-verdict.bad { color: var(--bad); }
.cr-legend { display: flex; gap: 1.1rem; flex-wrap: wrap; margin-top: 1.1rem; font-size: 0.74rem;
color: var(--ink-soft); }
.cr-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }
.cr-legend .dot { width: 9px; height: 9px; border-radius: 50%; }
.cr-legend .dot.fresh { background: var(--ok); }
.cr-legend .dot.warn { background: var(--warn); }
.cr-legend .dot.stale { background: var(--bad); }
@media (prefers-reduced-motion: reduce) {
.infographic-credreport * { transition-duration: 0.001ms !important; }
}
</style>
<p class="cr-sub">Shows every IAM user and their credential status. Click a row to see the audit read.</p>
<div class="cr-table-wrap">
<table class="cr-table">
<thead>
<tr>
<th>User</th>
<th>Password Enabled</th>
<th>Access Key 1 Last Used</th>
<th>Access Key 2 Last Used</th>
</tr>
</thead>
<tbody>
<tr class="cr-row" data-u="user1">
<td class="cr-user">user1</td>
<td class="cr-yes">Yes</td>
<td class="cr-date fresh">2 days ago</td>
<td class="cr-date">N/A</td>
</tr>
<tr class="cr-verdict-row"><td colspan="4"><div class="cr-verdict" data-v="user1"></div></td></tr>
<tr class="cr-row" data-u="user2">
<td class="cr-user">user2</td>
<td class="cr-no">No</td>
<td class="cr-date stale">Never</td>
<td class="cr-date stale">6 months ago</td>
</tr>
<tr class="cr-verdict-row"><td colspan="4"><div class="cr-verdict" data-v="user2"></div></td></tr>
<tr class="cr-row" data-u="user3">
<td class="cr-user">user3</td>
<td class="cr-yes">Yes</td>
<td class="cr-date fresh">15 days ago</td>
<td class="cr-date warn">4 months ago</td>
</tr>
<tr class="cr-verdict-row"><td colspan="4"><div class="cr-verdict" data-v="user3"></div></td></tr>
</tbody>
</table>
</div>
<div class="cr-legend">
<span><span class="dot fresh"></span> Used recently</span>
<span><span class="dot warn"></span> Getting stale</span>
<span><span class="dot stale"></span> Unused / never used</span>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-credreport')
|| document.querySelector('.infographic-credreport');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const verdicts = {
user1: { cls: 'ok', text: '✅ Healthy — password and key both used recently. No action needed.' },
user2: { cls: 'bad', text: '⚠️ High risk — password unused, one key never used, the other idle for 6 months. Remove or rotate.' },
user3: { cls: 'warn', text: '🟡 Mostly fine — but Access Key 2 hasn\u2019t been touched in 4 months. Worth reviewing.' }
};
wrapper.querySelectorAll('.cr-row').forEach(row => {
row.addEventListener('click', () => {
const key = row.dataset.u;
const verdictEl = wrapper.querySelector('.cr-verdict[data-v="' + key + '"]');
const wasOpen = row.classList.contains('is-open');
wrapper.querySelectorAll('.cr-row').forEach(r => r.classList.remove('is-open'));
wrapper.querySelectorAll('.cr-verdict').forEach(v => v.classList.remove('show'));
if (!wasOpen) {
row.classList.add('is-open');
const v = verdicts[key];
verdictEl.textContent = v.text;
verdictEl.className = 'cr-verdict show ' + v.cls;
}
});
});
})();
</script>
</div>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});This report covers every IAM user in your account at once.
What's in it:
Password usage
Access key status
Recent credential activity
It's a full security snapshot of everyone in one place. We'll generate one shortly and walk through what it shows.
👤 IAM Access Advisor — (User Level Tool)
<div class="infographic-leastpriv">
<style>
.infographic-leastpriv {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f6f4ef;
--accent: #2e5077;
--line: #ddd6c9;
--ok: #3a9d5c;
--ok-soft: #e2f6ec;
--bad: #c0392b;
--bad-soft: #fbe9e7;
--display-font: Georgia, 'Iowan Old Style', serif;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--ink);
background: var(--paper);
padding: 2rem 1.25rem 2.5rem;
max-width: 620px;
margin: 0 auto;
border-radius: 14px;
box-sizing: border-box;
}
.infographic-leastpriv[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #7ea6d6;
--line: #2c313d;
--ok: #4fbf87;
--ok-soft: #143024;
--bad: #e57373;
--bad-soft: #3a2222;
}
.infographic-leastpriv * { box-sizing: border-box; }
.lp-header { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.3rem; }
.lp-header .icon { font-size: 1.6rem; flex-shrink: 0; }
.lp-title { font-family: var(--display-font); font-size: 1.3rem; margin: 0; color: var(--accent); line-height: 1.25; }
.lp-sub { color: var(--ink-soft); font-size: 0.86rem; margin: 0 0 1.75rem; padding-bottom: 1rem;
border-bottom: 1px solid var(--line); }
.lp-btns { display: flex; justify-content: center; gap: 0.6rem; margin-bottom: 2rem; flex-wrap: wrap; }
.lp-btns button { font: inherit; font-size: 0.82rem; font-weight: 700; padding: 0.5rem 1rem;
border-radius: 999px; cursor: pointer; border: 1.5px solid var(--line); background: var(--paper-alt); color: var(--ink); }
.lp-btns button:hover { border-color: var(--ink-soft); }
.lp-btns button.trim { border-color: var(--ok); color: var(--ok); }
.lp-diagram { display: flex; flex-direction: column; align-items: center; gap: 0; }
.lp-user { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; }
.lp-user .box { font-size: 2.3rem; line-height: 1; }
.lp-user .lbl { font-size: 0.78rem; font-weight: 700; color: var(--ink-soft); }
.lp-down { font-size: 1.1rem; color: var(--ink-soft); margin: 0.15rem 0; }
.lp-rows { display: flex; flex-direction: column; gap: 0.8rem; width: 100%; }
.lp-row { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap;
transition: opacity 0.4s, transform 0.4s; }
.lp-row.is-trimmed { opacity: 0; transform: scale(0.8); height: 0; margin: 0; pointer-events: none; overflow: hidden; }
.lp-pill { flex: 1 1 170px; max-width: 220px; text-align: center; padding: 0.6rem 0.85rem; border-radius: 999px;
color: #fff; font-weight: 700; font-size: 0.8rem; }
.lp-pill.necessary { background: var(--ok); }
.lp-pill.unnecessary { background: var(--bad); }
.lp-row .arrow { color: var(--ink-soft); font-size: 1.1rem; flex-shrink: 0; }
.lp-cloud { display: flex; flex-direction: column; align-items: center; gap: 0.15rem; flex-shrink: 0; }
.lp-cloud .icon { font-size: 1.7rem; line-height: 1; }
.lp-cloud .lbl { font-size: 0.68rem; font-weight: 700; color: var(--ink-soft); white-space: nowrap; }
.lp-result { text-align: center; margin-top: 1.6rem; font-size: 0.83rem; color: var(--ink-soft); min-height: 1.3em; }
.lp-result b { color: var(--ok); }
@media (max-width: 380px) {
.lp-row { gap: 0.4rem; }
.lp-pill { flex-basis: 140px; font-size: 0.74rem; padding: 0.55rem 0.6rem; }
}
@media (prefers-reduced-motion: reduce) {
.infographic-leastpriv * { transition-duration: 0.001ms !important; }
}
</style>
<div class="lp-btns">
<button class="trim" id="lp-trim">🧹 Apply least privilege</button>
<button id="lp-reset">↺ Reset</button>
</div>
<div class="lp-diagram">
<div class="lp-user"><span class="box">🧑</span><span class="lbl">User</span></div>
<div class="lp-down">↓</div>
<div class="lp-rows">
<div class="lp-row" id="lp-row-necessary">
<span class="lp-pill necessary">Necessary Permissions</span>
<span class="arrow">→</span>
<div class="lp-cloud"><span class="icon">☁️</span><span class="lbl">Services Used</span></div>
</div>
<div class="lp-row" id="lp-row-unnecessary">
<span class="lp-pill unnecessary">Unnecessary Permissions</span>
<span class="arrow">→</span>
<div class="lp-cloud"><span class="icon">☁️</span><span class="lbl">Services Unused</span></div>
</div>
</div>
</div>
<p class="lp-result" id="lp-result"> </p>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-leastpriv')
|| document.querySelector('.infographic-leastpriv');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const rowU = wrapper.querySelector('#lp-row-unnecessary');
const result = wrapper.querySelector('#lp-result');
wrapper.querySelector('#lp-trim').addEventListener('click', () => {
rowU.classList.add('is-trimmed');
result.innerHTML = '<b>Unnecessary permissions removed</b> — the user now only reaches what they actually use.';
});
wrapper.querySelector('#lp-reset').addEventListener('click', () => {
rowU.classList.remove('is-trimmed');
result.innerHTML = ' ';
});
})();
</script>
</div>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});This one zooms in on a single user instead. It shows which AWS services they have permission to use, and when each was last actually accessed.
Why it matters: this is your tool for enforcing least privilege. It surfaces permissions nobody's using, so you can strip them out and keep access aligned with what people actually do — tighter security, smaller attack surface.