The requirements describe a classic attribute-based access control (ABAC) model using AWS IAM. The company already has consistent tagging across users and resources, which is ideal for ABAC and least-privilege enforcement at scale.
First, Option A is required because IAM roles should represent job functions (developer vs. database administrator) and be scoped per project. Creating separate roles per project and job function allows permissions to be isolated cleanly and prevents cross-project access.
Second, Option B enforces project-level isolation at the policy level. By modifying the existing job-function policies to include a StringEquals condition that compares aws:ResourceTag/Project with aws:PrincipalTag/Project, access is automatically limited to only those resources that belong to the same project as the user. This is an AWS-recommended ABAC pattern and avoids policy sprawl.
Third, Option C is required so users can assume roles only when their tags match the role’s tags. An IAM policy attached to users that allows sts:AssumeRole only if both project and job function tags match ensures users cannot assume roles outside their assigned scope.
Options D, E, and F either misapply policies to the wrong entities, misuse tagging on policies (which IAM does not evaluate for authorization), or introduce unnecessary group-based management that conflicts with the ABAC design.
Therefore, A, B, and C together provide least privilege, project isolation, and scalable access control with minimal ongoing administration.