MSP

AWS-IAM-access-control-security

8 min read
Share:

Locking Down the Front Door: IAM and Access Control in AWS

Most AWS breaches don’t start with a zero-day exploit. They start with an over-permissioned role, a leaked access key, or a policy that grants *:* (a wildcard meaning “every action, on every resource”) because it was faster than scoping it properly. Identity and Access Management (IAM) is AWS’s system for controlling who — and what — can do what inside your account. It’s the control plane for everything else you build in AWS, which makes it the highest-leverage place to invest your security effort. This post walks through the practices
that actually move the needle, from root account hygiene to automated least-privilege enforcement, and explains the key terms along the way so it’s useful whether you’re new to AWS or you’ve been running it in production for years.

A Quick Primer, If You’re New to IAM

Feel free to skip this section if you already know the vocabulary.
An AWS account has an identity for every person or system that needs to act on it: a user (a person, historically with their own long-lived credentials), a role (a set of permissions that something can assume temporarily rather than own permanently), or a federated identity (a person logging in through an outside identity provider like Okta or Microsoft Entra, without ever holding standing AWS credentials). A policy is a JSON document that states what an identity is allowed — or explicitly denied — to do, usually written as a combination of an action (like s3:GetObject, meaning “read an object from S3”) and a resource, identified by its ARN (Amazon Resource Name, a unique address for that specific AWS resource). MFA is multi-factor authentication — a second proof of identity beyond a password, like a code from a hardware key or an authenticator app. STS (Security Token Service) is what issues shortlived, temporary credentials when a role is assumed, instead of a password-like key that lives forever. CloudTrail is AWS’s activity log, recording who called which API and when. Least privilege is the principle of granting only the permissions an identity actually needs, nothing more. With that vocabulary in hand, the rest of this post should read clearly regardless of your starting point.

Start With the Root Account

Every AWS account has one root user, created automatically when the account is set up, with unrestricted access to everything in it. Because it’s so powerful, the root user should not be used for everyday work — use it only for the handful of tasks that specifically require root, such as closing an account or changing a support plan.
• Enable MFA on the root user immediately, using a hardware key or virtual MFA device (an app like Google Authenticator).
• Remove root access keys if they exist. Root should never authenticate programmatically (i.e., from scripts or code).
• Set a strong, unique password and store it in a password manager, not a shared doc.
• If you manage multiple AWS accounts under AWS Organizations (AWS’s tool for centrally managing a group of accounts), consider its centralized root access management for member accounts. Where it fits your setup, you can remove standing root credentials from member accounts entirely and recover access only when a root-only task is actually required, plus layer on Service Control Policy guardrails, explained further down.
If you haven’t audited this in the last quarter, it’s worth ten minutes now.

Humans Get Federated Access, Workloads Get Roles

For human access — the engineers and admins who log in — prefer IAM Identity Center (AWS’s built-in single sign-on service) or federation with an outside identity provider, backed by temporary credentials rather than a permanent password-like key. For workloads — the applications running on services like EC2 (virtual servers), Lambda (serverless functions), or ECS (containers) — prefer IAM roles with temporary credentials rather than embedding a long-lived access key inside the application’s code or config.

This isn’t an absolute ban on IAM users (the older model of giving a person their own standing AWS credentials). AWS recommends them only for specific cases federation doesn’t cover — certain break-glass scenarios (emergency access when normal login paths are down), some third-party tooling, or legacy systems that can’t do federated login. If an IAM user is genuinely necessary, minimize its permissions, enable MFA on it, and remove its credentials the moment they’re no longer in use. The default path for everyone else should still be federation and temporary credentials, because static IAM access keys are one of the most common sources of AWS compromise — they get committed to GitHub repos, embedded in CI/CD configs, or left in .env files that outlive the engineer who created them.

For the humans on your team, IAM Identity Center lets you manage permission sets (reusable bundles of permissions, similar to a policy template) centrally and map them to groups in your identity provider. You can assign multiple permission sets to the same person, so someone might get a broad read-only set for daily work and a separate, tightly scoped set for the rare occasions they need elevated access, rather than living in an admin role
permanently.

iam_access_diagram

iam_access

Figure : Human access flows through federation/IAM Identity Center to a scoped permission
set; workload access flows through an IAM role with temporary STS credentials

Cross-Account Access and Third-Party Vendors

If you run more than one AWS account (common practice, for isolating environments like dev and prod), use IAM roles and STS for access between them rather than sharing longlived access keys. When a third-party vendor needs to assume a role into your account, use an ExternalId (a shared secret value included in the role trust setup) where appropriate — this helps address the “confused deputy” problem, where a vendor’s own AWS account could otherwise be tricked into acting on your resources on someone else’s behalf. Keep the role’s trust policy (the part of a role that defines who is allowed to assume it) narrowly scoped to the specific accounts or principals that should be able to use it.

Least Privilege Is a Continuous Process

“Least privilege” gets treated like a one-time checkbox, but it’s really an ongoing discipline that needs to track how applications actually change over time.

Scope both the action and the resource. Instead of granting s3:GetObject on every object in the account, scope the resource ARN down to the specific bucket and folder path a role actually needs, whenever that’s practical.

Use IAM Access Analyzer’s full toolset, not just one feature of it. Access Analyzer is a free AWS tool with several distinct capabilities worth knowing individually: it identifies resources shared with accounts outside your own, analyzes unused access (permissions granted but never actually exercised), validates policies against AWS best practices before you deploy them, and can generate a draft least-privilege policy based on activity it observes in CloudTrail.
A practical workflow, useful for a beginner setting this up for the first time: start with a controlled baseline policy (something reasonably scoped, even if not perfect), let the workload run through representative activity, review the Access Analyzer findings, generate or refine a least-privilege policy from that activity, test it against real usage, deploy it, and repeat the review periodically. There’s no fixed observation window here — how long you need to
capture “representative activity” depends entirely on the workload’s usage pattern; a batch job that runs monthly needs a longer window than an API that sees traffic every minute.

least-privilege review workflow

least-privilege review workflow

 

Guardrails for Sensitive Actions

Not all permissions carry equal risk. Destructive or sensitive actions — deleting a database, changing billing, modifying IAM itself — deserve additional controls layered on top of your normal policies.

An MFA-based condition using aws:MultiFactorAuthPresent (a policy condition that checks whether the caller authenticated with MFA) in an explicit deny statement can be a useful guardrail, but it needs to be tested carefully rather than assumed to work uniformly. This condition behaves differently depending on the authentication path and credential type involved — IAM users, federated identities, and assumed roles don’t all carry MFA context the
same way. Validate the condition against each identity type you actually use before rolling out a broad deny, and make sure it doesn’t accidentally block legitimate automation or a breakglass procedure. In IAM’s evaluation logic, an explicit deny always overrides any allow, which is exactly why a poorly scoped one can cause an outage as easily as it prevents a breach.

Use Service Control Policies, or SCPs, at the AWS Organizations level as an additional layer of guardrails across accounts. It’s worth being precise about what SCPs actually do: they define the maximum permissions available to identities in the accounts they apply to, but they never grant permissions on their own — they only restrict what a given account’s own IAM policies
are allowed to permit. Typical uses include restricting AWS Regions your organization doesn’t operate in, or preventing specific security-control changes, like disabling CloudTrail.

REFERENCE

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user-access-management.html

Tag

aws cloud IAM

Leave a Reply

Your email address will not be published. Required fields are marked *