# This file is automatically generated by botocraft.  Do not edit directly.
# mypy: disable-error-code="index, override, assignment, union-attr, misc"
from botocraft.mixins.iam import IAMPolicyManagerMixin
from botocraft.mixins.tags import TagsDictMixin
from collections import OrderedDict
from botocraft.mixins.iam import iam_attached_policies_only
from typing import ClassVar, Type, Optional, Literal, Dict, List, Union, Any, cast
from botocraft.mixins.iam import group_inline_policies_only
from datetime import datetime
from pydantic import Field
from botocraft.mixins.iam import role_attached_policies_only
from botocraft.mixins.iam import IAMPolicyMixin
from .abstract import PrimaryBoto3ModelQuerySet
from botocraft.mixins.iam import role_inline_policies_only
from botocraft.mixins.iam import group_attached_policies_only
from .abstract import (
    Boto3Model,
    ReadonlyBoto3Model,
    PrimaryBoto3Model,
    ReadonlyPrimaryBoto3Model,
    Boto3ModelManager,
    ReadonlyBoto3ModelManager,
)
from functools import cached_property

# ===============
# Managers
# ===============


class IAMAccessKeyManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(
        self, model: "IAMAccessKey", UserName: str | None = None
    ) -> "IAMAccessKey":
        """
        Create an AWS Access Key for a user.

        Args:
            model: The :py:class:`AccessKey` to create.

        Keyword Args:
            UserName: The name of the IAM user that the new key will belong to.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(UserName=self.serialize(UserName))
        _response = self.client.create_access_key(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateAccessKeyResponse(**_response)

        self.sessionize(response.AccessKey)
        return cast("IAMAccessKey", response.AccessKey)

    def delete(self, AccessKeyId: str, *, UserName: str | None = None) -> None:
        """
        Delete an AWS Access Key from a user.

        Args:
            AccessKeyId: The access key ID for the access key ID and secret access key you want to delete.

        Keyword Args:
            UserName: The name of the user whose access key pair you want to delete.
        """
        args: Dict[str, Any] = dict(
            AccessKeyId=self.serialize(AccessKeyId), UserName=self.serialize(UserName)
        )
        self.client.delete_access_key(
            **{k: v for k, v in args.items() if v is not None}
        )

    def list(
        self, *, UserName: str | None = None, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Returns information about the access key IDs associated with the specified IAM
        user. If there is none, the operation returns an empty list.

        Keyword Args:
            UserName: The name of the user.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_access_keys")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListAccessKeysResponse(**_response)
            if response.AccessKeyMetadata:
                results.extend(response.AccessKeyMetadata)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def update(self, model: "IAMAccessKey") -> None:
        """
        Changes the status of the specified access key from Active to Inactive, or vice
        versa. This operation can be used to disable a user's key as part of a key
        rotation workflow.

        Args:
            model: The :py:class:`AccessKey` to update.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            AccessKeyId=data.get("AccessKeyId"),
            Status=data.get("Status"),
            UserName=data.get("UserName"),
        )
        self.client.update_access_key(
            **{k: v for k, v in args.items() if v is not None}
        )

    def last_used(self, AccessKeyId: str) -> "GetAccessKeyLastUsedResponse":
        """
        Retrieves information about when the specified access key was last used. The
        information includes the date and time of last use, along with the Amazon Web
        Services service and Region that were specified in the last request made with
        that key.

        Args:
            AccessKeyId: The identifier of an access key.
        """
        args: Dict[str, Any] = dict(AccessKeyId=self.serialize(AccessKeyId))
        _response = self.client.get_access_key_last_used(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetAccessKeyLastUsedResponse(**_response)

        results: "GetAccessKeyLastUsedResponse" = None
        if response is not None:
            results = response

        self.sessionize(results)
        return cast("GetAccessKeyLastUsedResponse", results)


class IAMGroupManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMGroup") -> "IAMGroup":
        """
        Create an IAM group.

        Args:
            model: The :py:class:`Group` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(GroupName=data.get("GroupName"), Path=data.get("Path"))
        _response = self.client.create_group(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateGroupResponse(**_response)

        self.sessionize(response.Group)
        return cast("IAMGroup", response.Group)

    def delete(self, GroupName: str) -> None:
        """
        Delete an IAM group.

        Args:
            GroupName: The name of the IAM group to delete.
        """
        args: Dict[str, Any] = dict(GroupName=self.serialize(GroupName))
        self.client.delete_group(**{k: v for k, v in args.items() if v is not None})

    def delete_policy(self, GroupName: str, PolicyName: str) -> "None":
        """
        Delete a policy from a group.

        Args:
            GroupName: The name (friendly name, not ARN) identifying the group that the policy is embedded in.
            PolicyName: The name identifying the policy document to delete.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), PolicyName=self.serialize(PolicyName)
        )
        self.client.delete_group_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def detach_policy(self, GroupName: str, PolicyArn: str) -> "None":
        """
        Detach a policy from a group.

        Args:
            GroupName: The name (friendly name, not ARN) of the IAM group to detach the policy from.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to detach.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.detach_group_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(
        self, GroupName: str, *, MaxItems: int | None = None
    ) -> Optional["IAMGroup"]:
        """
        Get an IAM group.

        Args:
            GroupName: The name of the group.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), MaxItems=self.serialize(MaxItems)
        )
        _response = self.client.get_group(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetGroupResponse(**_response)

        if response and response.Group:
            self.sessionize(response.Group)
            return response.Group
        return None

    def get_policy(self, GroupName: str, PolicyName: str) -> "GetGroupPolicyResponse":
        """
        Retrieves the specified inline policy document that is embedded in the specified
        IAM group.

        Args:
            GroupName: The name of the group the policy is associated with.
            PolicyName: The name of the policy document to get.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), PolicyName=self.serialize(PolicyName)
        )
        _response = self.client.get_group_policy(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetGroupPolicyResponse(**_response)

        results: "GetGroupPolicyResponse" = None
        if response is not None:
            results = response

        self.sessionize(results)
        return cast("GetGroupPolicyResponse", results)

    def list(
        self, *, PathPrefix: str | None = None, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists the IAM groups that have the specified path prefix.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. For example, the prefix ``/division_abc/subdivision_xyz/``
                gets all groups whose path starts with ``/division_abc/subdivision_xyz/``.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_groups")
        args: Dict[str, Any] = dict(
            PathPrefix=self.serialize(PathPrefix), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListGroupsResponse(**_response)
            if response.Groups:
                results.extend(response.Groups)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def list_for_user(
        self, UserName: str, *, MaxItems: int | None = None
    ) -> List["IAMGroup"]:
        """
        Lists the IAM groups that the specified IAM user belongs to.

        Args:
            UserName: The name of the user to list groups for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_groups_for_user")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["IAMGroup"] = []

        for _response in response_iterator:
            response = ListGroupsForUserResponse(**_response)
            if response.Groups is not None:
                results.extend(response.Groups)
            else:
                break

        self.sessionize(results)
        return cast("List[IAMGroup]", results)

    @group_inline_policies_only
    def list_policies(
        self, GroupName: str, *, MaxItems: int | None = None
    ) -> List[str]:
        """
        Lists the names of the inline policies that are embedded in the specified IAM
        group.

        Args:
            GroupName: The name of the group to list policies for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_group_policies")
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List[str] = []

        for _response in response_iterator:
            response = ListGroupPoliciesResponse(**_response)
            if response.PolicyNames is not None:
                results.extend(response.PolicyNames)
            else:
                break

        self.sessionize(results)
        return cast("List[str]", results)

    @group_attached_policies_only
    def list_attached_policies(
        self,
        GroupName: str,
        *,
        PathPrefix: str | None = None,
        MaxItems: int | None = None,
    ) -> List["AttachedPolicy"]:
        """
        Lists all managed policies that are attached to the specified IAM group.

        Args:
            GroupName: The name (friendly name, not ARN) of the group to list attached policies for.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it
                defaults to a slash (/), listing all policies.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_attached_group_policies")
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName),
            PathPrefix=self.serialize(PathPrefix),
            MaxItems=self.serialize(MaxItems),
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["AttachedPolicy"] = []

        for _response in response_iterator:
            response = ListAttachedGroupPoliciesResponse(**_response)
            if response.AttachedPolicies is not None:
                results.extend(response.AttachedPolicies)
            else:
                break

        self.sessionize(results)
        return cast("List[AttachedPolicy]", results)

    def update(
        self,
        model: "IAMGroup",
        NewPath: str | None = None,
        NewGroupName: str | None = None,
    ) -> None:
        """
        Update an IAM group.

        Args:
            model: The :py:class:`Group` to update.

        Keyword Args:
            NewPath: New path for the IAM group. Only include this if changing the group's path.
            NewGroupName: New name for the IAM group. Only include this if changing the group's name.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            GroupName=data.get("GroupName"),
            NewPath=self.serialize(NewPath),
            NewGroupName=self.serialize(NewGroupName),
        )
        self.client.update_group(**{k: v for k, v in args.items() if v is not None})

    def attach_policy(self, GroupName: str, PolicyArn: str) -> "None":
        """
        Attach a policy to a group.

        Args:
            GroupName: The name (friendly name, not ARN) of the group to attach the policy to.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to attach.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.attach_group_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def put_policy(
        self, GroupName: str, PolicyName: str, PolicyDocument: str
    ) -> "None":
        """
        Attach a policy to a group.

        Args:
            GroupName: The name of the group to associate the policy with.
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName),
            PolicyName=self.serialize(PolicyName),
            PolicyDocument=self.serialize(PolicyDocument),
        )
        self.client.put_group_policy(**{k: v for k, v in args.items() if v is not None})

    def add_user(self, GroupName: str, UserName: str) -> "None":
        """
        Add a user to a group.

        Args:
            GroupName: The name of the group to update.
            UserName: The name of the user to add.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), UserName=self.serialize(UserName)
        )
        self.client.add_user_to_group(
            **{k: v for k, v in args.items() if v is not None}
        )

    def remove_user(self, GroupName: str, UserName: str) -> "None":
        """
        Remove a user from a group.

        Args:
            GroupName: The name of the group to update.
            UserName: The name of the user to remove.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), UserName=self.serialize(UserName)
        )
        self.client.remove_user_from_group(
            **{k: v for k, v in args.items() if v is not None}
        )


class InstanceProfileManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "InstanceProfile") -> "InstanceProfile":
        """
        Create an IAM instance profile.

        Args:
            model: The :py:class:`InstanceProfile` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            InstanceProfileName=data.get("InstanceProfileName"),
            Path=data.get("Path"),
            Tags=data.get("Tags"),
        )
        _response = self.client.create_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateInstanceProfileResponse(**_response)

        self.sessionize(response.InstanceProfile)
        return cast("InstanceProfile", response.InstanceProfile)

    def delete(self, InstanceProfileName: str) -> None:
        """
        Delete an IAM instance profile.

        Args:
            InstanceProfileName: The name of the instance profile to delete.
        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName)
        )
        self.client.delete_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(self, InstanceProfileName: str) -> Optional["InstanceProfile"]:
        """
        Retrieves information about the specified instance profile, including the instance profile's path, GUID, ARN, and role.
        For more information about instance profiles, see `Using instance
        profiles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html>`_ in the
        *IAM User Guide*.

        Args:
            InstanceProfileName: The name of the instance profile to get information about.

        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName)
        )
        _response = self.client.get_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetInstanceProfileResponse(**_response)

        if response and response.InstanceProfile:
            self.sessionize(response.InstanceProfile)
            return response.InstanceProfile
        return None

    def list(
        self, *, PathPrefix: str | None = None, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists the instance profiles that have the specified path prefix. If there are none, the operation returns an empty list.
        For more information about instance profiles, see `Using instance
        profiles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html>`_ in the
        *IAM User Guide*.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. For example, the prefix ``/application_abc/component_xyz/``
                gets all instance profiles whose path starts with ``/application_abc/component_xyz/``.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.

        """
        paginator = self.client.get_paginator("list_instance_profiles")
        args: Dict[str, Any] = dict(
            PathPrefix=self.serialize(PathPrefix), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListInstanceProfilesResponse(**_response)
            if response.InstanceProfiles:
                results.extend(response.InstanceProfiles)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def list_for_role(
        self, RoleName: str, *, MaxItems: int | None = None
    ) -> List["InstanceProfile"]:
        """
        Lists the instance profiles that have the specified associated IAM role. If there are none, the operation returns an
        empty list. For more information about instance profiles, go to `Using instance
        profiles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html>`_ in the
        *IAM User Guide*.

        Args:
            RoleName: The name of the role to list instance profiles for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.

        """
        paginator = self.client.get_paginator("list_instance_profiles_for_role")
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["InstanceProfile"] = []

        for _response in response_iterator:
            response = ListInstanceProfilesForRoleResponse(**_response)
            if response.InstanceProfiles is not None:
                results.extend(response.InstanceProfiles)
            else:
                break

        self.sessionize(results)
        return cast("List[InstanceProfile]", results)

    def add_role(self, InstanceProfileName: str, RoleName: str) -> "None":
        """
        Add a role to an instance profile.

        Args:
            InstanceProfileName: The name of the instance profile to update.
            RoleName: The name of the role to add.
        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName),
            RoleName=self.serialize(RoleName),
        )
        self.client.add_role_to_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )

    def remove_role(self, InstanceProfileName: str, RoleName: str) -> "None":
        """
        Remove a role from an instance profile.

        Args:
            InstanceProfileName: The name of the instance profile to update.
            RoleName: The name of the role to remove.
        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName),
            RoleName=self.serialize(RoleName),
        )
        self.client.remove_role_from_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )


class IAMLoginProfileManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMLoginProfile") -> "IAMLoginProfile":
        """
        Create a login profile for a user.

        Args:
            model: The :py:class:`LoginProfile` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"),
            Password=data.get("Password"),
            PasswordResetRequired=data.get("PasswordResetRequired"),
        )
        _response = self.client.create_login_profile(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateLoginProfileResponse(**_response)

        self.sessionize(response.LoginProfile)
        return cast("IAMLoginProfile", response.LoginProfile)

    def delete(self, UserName: str) -> None:
        """
        Delete a login profile for a user.

        Args:
            UserName: The name of the user whose password you want to delete.
        """
        args: Dict[str, Any] = dict(UserName=self.serialize(UserName))
        self.client.delete_login_profile(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(self, UserName: str) -> Optional["IAMLoginProfile"]:
        """
        Retrieves the user name for the specified IAM user. A login profile is created
        when you create a password for the user to access the Amazon Web Services
        Management Console. If the user does not exist or does not have a password, the
        operation returns a 404 (``NoSuchEntity``) error.

        Args:
            UserName: The name of the user whose login profile you want to retrieve.
        """
        args: Dict[str, Any] = dict(UserName=self.serialize(UserName))
        _response = self.client.get_login_profile(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetLoginProfileResponse(**_response)

        if response and response.LoginProfile:
            self.sessionize(response.LoginProfile)
            return response.LoginProfile
        return None

    def update(self, model: "IAMLoginProfile", Password: str | None = None) -> None:
        """
        Update a login profile for a user.

        Args:
            model: The :py:class:`LoginProfile` to update.

        Keyword Args:
            Password: The new password for the specified IAM user.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"),
            Password=self.serialize(Password),
            PasswordResetRequired=data.get("PasswordResetRequired"),
        )
        self.client.update_login_profile(
            **{k: v for k, v in args.items() if v is not None}
        )


class IAMPolicyManager(IAMPolicyManagerMixin, Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMPolicy") -> "IAMPolicy":
        """
        Create a policy.

        Args:
            model: The :py:class:`Policy` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            PolicyName=data.get("PolicyName"),
            PolicyDocument=data.get("PolicyDocument"),
            Path=data.get("Path"),
            Description=data.get("Description"),
            Tags=data.get("Tags"),
        )
        _response = self.client.create_policy(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreatePolicyResponse(**_response)

        self.sessionize(response.Policy)
        return cast("IAMPolicy", response.Policy)

    def delete(self, PolicyArn: str) -> None:
        """
        Delete a policy.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to delete.
        """
        args: Dict[str, Any] = dict(PolicyArn=self.serialize(PolicyArn))
        self.client.delete_policy(**{k: v for k, v in args.items() if v is not None})

    def get(self, PolicyArn: str) -> Optional["IAMPolicy"]:
        """
        Retrieves information about the specified managed policy, including the policy's default version and the total number of
        IAM users, groups, and roles to which the policy is attached. To retrieve the list of the specific users, groups, and
        roles that the policy is attached to, use
        `ListEntitiesForPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html>`_. This
        operation returns metadata about the policy. To retrieve the actual policy document for a specific version of the
        policy, use `GetPolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html>`_.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the managed policy that you want information about.

        """
        args: Dict[str, Any] = dict(PolicyArn=self.serialize(PolicyArn))
        _response = self.client.get_policy(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetPolicyResponse(**_response)

        if response and response.Policy:
            self.sessionize(response.Policy)
            return response.Policy
        return None

    def list(
        self,
        *,
        Scope: Literal["All", "AWS", "Local"] | None = None,
        OnlyAttached: bool | None = None,
        PathPrefix: str | None = None,
        PolicyUsageFilter: Literal["PermissionsPolicy", "PermissionsBoundary"] | None = None,
        MaxItems: int | None = None,
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists all the managed policies that are available in your Amazon Web Services
        account, including your own customer- defined managed policies and all Amazon
        Web Services managed policies.

        Keyword Args:
            Scope: The scope to use for filtering the results.
            OnlyAttached: A flag to filter the results to only the attached policies.
            PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it
                defaults to a slash (/), listing all policies. This parameter allows (through its `regex pattern
                <http://wikipedia.org/wiki/regex>`_) a string of characters consisting of either a forward slash (/) by itself or a
                string that must begin and end with forward slashes. In addition, it can contain any ASCII character from the !
                (``u0021``) through the DEL character (``u007F``), including most punctuation characters, digits, and upper and
                lowercased letters.
            PolicyUsageFilter: The policy usage method to use for filtering the results.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_policies")
        args: Dict[str, Any] = dict(
            Scope=self.serialize(Scope),
            OnlyAttached=self.serialize(OnlyAttached),
            PathPrefix=self.serialize(PathPrefix),
            PolicyUsageFilter=self.serialize(PolicyUsageFilter),
            MaxItems=self.serialize(MaxItems),
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListPoliciesResponse(**_response)
            if response.Policies:
                results.extend(response.Policies)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def list_entities(
        self,
        PolicyArn: str,
        *,
        EntityFilter: Literal["User", "Role", "Group", "LocalManagedPolicy", "AWSManagedPolicy"] | None = None,
        PathPrefix: str | None = None,
        PolicyUsageFilter: Literal["PermissionsPolicy", "PermissionsBoundary"] | None = None,
        MaxItems: int | None = None,
    ) -> "ListEntitiesForPolicyResponse":
        """
        Lists all IAM users, groups, and roles that the specified managed policy is
        attached to.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy for which you want the versions.

        Keyword Args:
            EntityFilter: The entity type to use for filtering the results.
            PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it
                defaults to a slash (/), listing all entities.
            PolicyUsageFilter: The policy usage method to use for filtering the results.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_entities_for_policy")
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn),
            EntityFilter=self.serialize(EntityFilter),
            PathPrefix=self.serialize(PathPrefix),
            PolicyUsageFilter=self.serialize(PolicyUsageFilter),
            MaxItems=self.serialize(MaxItems),
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: "ListEntitiesForPolicyResponse" = []

        for _response in response_iterator:
            response = ListEntitiesForPolicyResponse(**_response)
            results.append(response)

        self.sessionize(results)
        return cast("ListEntitiesForPolicyResponse", results)

    def list_versions(
        self, PolicyArn: str, *, MaxItems: int | None = None
    ) -> List["IAMPolicyVersion"]:
        """
        Lists information about the versions of the specified managed policy, including
        the version that is currently set as the policy's default version.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy for which you want the versions.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_policy_versions")
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["IAMPolicyVersion"] = []

        for _response in response_iterator:
            response = ListPolicyVersionsResponse(**_response)
            if response.Versions is not None:
                results.extend(response.Versions)
            else:
                break

        self.sessionize(results)
        return cast("List[IAMPolicyVersion]", results)

    def set_default_version(self, PolicyArn: str, VersionId: str) -> "None":
        """
        Sets the specified version of the specified policy as the policy's default
        (operative) version.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy whose default version you want to set.
            VersionId: The version of the policy to set as the default (operative) version.
        """
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), VersionId=self.serialize(VersionId)
        )
        self.client.set_default_policy_version(
            **{k: v for k, v in args.items() if v is not None}
        )


class IAMPolicyVersionManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(
        self, model: "IAMPolicyVersion", SetAsDefault: bool | None = None
    ) -> "IAMPolicyVersion":
        """
        Creates a new version of the specified managed policy. To update a managed policy, you create a new policy version. A
        managed policy can have up to five versions. If the policy has five versions, you must delete an existing version using
        `DeletePolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeletePolicyVersion.html>`_ before you
        create a new version.

        Args:
            model: The :py:class:`PolicyVersion` to create.

        Keyword Args:
            SetAsDefault: Specifies whether to set this version as the policy's default version.

        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            PolicyArn=data.get("PolicyArn"),
            PolicyDocument=data.get("PolicyDocument"),
            SetAsDefault=self.serialize(SetAsDefault),
        )
        _response = self.client.create_policy_version(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreatePolicyVersionResponse(**_response)

        self.sessionize(response.PolicyVersion)
        return cast("IAMPolicyVersion", response.PolicyVersion)

    def delete(self, PolicyArn: str, VersionId: str) -> None:
        """
        Deletes the specified version from the specified managed policy.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy from which you want to delete a version.
            VersionId: The policy version to delete.
        """
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), VersionId=self.serialize(VersionId)
        )
        self.client.delete_policy_version(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(self, PolicyArn: str, VersionId: str) -> Optional["IAMPolicyVersion"]:
        """
        Retrieves information about the specified version of the specified managed
        policy, including the policy document.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the managed policy that you want information about.
            VersionId: Identifies the policy version to retrieve.
        """
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), VersionId=self.serialize(VersionId)
        )
        _response = self.client.get_policy_version(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetPolicyVersionResponse(**_response)

        if response and response.PolicyVersion:
            self.sessionize(response.PolicyVersion)
            return response.PolicyVersion
        return None

    def list(
        self, PolicyArn: str, *, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists information about the versions of the specified managed policy, including
        the version that is currently set as the policy's default version.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy for which you want the versions.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_policy_versions")
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListPolicyVersionsResponse(**_response)
            if response.Versions:
                results.extend(response.Versions)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def set_default(self, PolicyArn: str, VersionId: str) -> "None":
        """
        Sets the specified version of the specified policy as the policy's default
        (operative) version.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy whose default version you want to set.
            VersionId: The version of the policy to set as the default (operative) version.
        """
        args: Dict[str, Any] = dict(
            PolicyArn=self.serialize(PolicyArn), VersionId=self.serialize(VersionId)
        )
        self.client.set_default_policy_version(
            **{k: v for k, v in args.items() if v is not None}
        )


class IAMRoleManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMRole") -> "IAMRole":
        """
        Create a role.

        Args:
            model: The :py:class:`Role` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            RoleName=data.get("RoleName"),
            AssumeRolePolicyDocument=data.get("AssumeRolePolicyDocument"),
            Path=data.get("Path"),
            Description=data.get("Description"),
            MaxSessionDuration=data.get("MaxSessionDuration"),
            PermissionsBoundary=data.get("PermissionsBoundary"),
            Tags=data.get("Tags"),
        )
        _response = self.client.create_role(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateRoleResponse(**_response)

        self.sessionize(response.Role)
        return cast("IAMRole", response.Role)

    def create_service_linked_role(
        self,
        AWSServiceName: str,
        *,
        Description: str | None = None,
        CustomSuffix: str | None = None,
    ) -> "IAMRole":
        """
        Create a service linked role.

        Args:
            AWSServiceName: The service principal for the Amazon Web Services service to which this role is attached. You use a
                string similar to a URL but without the http:// in front. For example: ``elasticbeanstalk.amazonaws.com``.

        Keyword Args:
            Description: The description of the role.
            CustomSuffix: A string that you provide, which is combined with the service-provided prefix to form the complete
                role name. If you make multiple requests for the same service, then you must supply a different ``CustomSuffix`` for
                each request. Otherwise the request fails with a duplicate role name error. For example, you could add ``-1`` or
                ``-debug`` to the suffix.
        """
        args: Dict[str, Any] = dict(
            AWSServiceName=self.serialize(AWSServiceName),
            Description=self.serialize(Description),
            CustomSuffix=self.serialize(CustomSuffix),
        )
        _response = self.client.create_service_linked_role(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateServiceLinkedRoleResponse(**_response)

        results: "IAMRole" = None
        if response is not None:
            results = response.Role

        self.sessionize(results)
        return cast("IAMRole", results)

    def delete_service_linked_role(self, RoleName: str) -> str:
        """
        Delete a service linked role.

        Args:
            RoleName: The name of the service-linked role to be deleted.
        """
        args: Dict[str, Any] = dict(RoleName=self.serialize(RoleName))
        _response = self.client.delete_service_linked_role(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DeleteServiceLinkedRoleResponse(**_response)

        results: str = None
        if response is not None:
            results = response.DeletionTaskId

        self.sessionize(results)
        return cast("str", results)

    def delete(self, RoleName: str) -> None:
        """
        Delete a role.

        Args:
            RoleName: The name of the role to delete.
        """
        args: Dict[str, Any] = dict(RoleName=self.serialize(RoleName))
        self.client.delete_role(**{k: v for k, v in args.items() if v is not None})

    def delete_role_permissions_boundary(self, RoleName: str) -> "None":
        """
        Deletes the permissions boundary for the specified IAM role.

        Args:
            RoleName: The name (friendly name, not ARN) of the IAM role from which you want to remove the permissions boundary.
        """
        args: Dict[str, Any] = dict(RoleName=self.serialize(RoleName))
        self.client.delete_role_permissions_boundary(
            **{k: v for k, v in args.items() if v is not None}
        )

    def delete_policy(self, RoleName: str, PolicyName: str) -> "None":
        """
        Delete an inline policy from a role.

        Args:
            RoleName: The name (friendly name, not ARN) identifying the role that the policy is embedded in.
            PolicyName: The name of the inline policy to delete from the specified IAM role.
        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), PolicyName=self.serialize(PolicyName)
        )
        self.client.delete_role_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(self, RoleName: str) -> Optional["IAMRole"]:
        """
        Retrieves information about the specified role, including the role's path, GUID, ARN, and the role's trust policy that
        grants permission to assume the role. For more information about roles, see `IAM
        roles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html>`_ in the *IAM User Guide*.

        Args:
            RoleName: The name of the IAM role to get information about.

        """
        args: Dict[str, Any] = dict(RoleName=self.serialize(RoleName))
        _response = self.client.get_role(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetRoleResponse(**_response)

        if response and response.Role:
            self.sessionize(response.Role)
            return response.Role
        return None

    def get_policy(self, RoleName: str, PolicyName: str) -> "GetRolePolicyResponse":
        """
        Get an inline policy from a role.

        Args:
            RoleName: The name of the role associated with the policy.
            PolicyName: The name of the policy document to get.
        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), PolicyName=self.serialize(PolicyName)
        )
        _response = self.client.get_role_policy(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetRolePolicyResponse(**_response)

        results: "GetRolePolicyResponse" = None
        if response is not None:
            results = response

        self.sessionize(results)
        return cast("GetRolePolicyResponse", results)

    def list(
        self, *, PathPrefix: str | None = None, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists the IAM roles that have the specified path prefix. If there are none, the operation returns an empty list. For
        more information about roles, see `IAM roles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html>`_ in the
        *IAM User Guide*.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. For example, the prefix ``/application_abc/component_xyz/``
                gets all roles whose path starts with ``/application_abc/component_xyz/``.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.

        """
        paginator = self.client.get_paginator("list_roles")
        args: Dict[str, Any] = dict(
            PathPrefix=self.serialize(PathPrefix), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListRolesResponse(**_response)
            if response.Roles:
                results.extend(response.Roles)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    @role_inline_policies_only
    def list_policies(
        self, RoleName: str, *, MaxItems: int | None = None
    ) -> List[str]:
        """
        List the inline policies attached to a role.

        Args:
            RoleName: The name of the role to list policies for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_role_policies")
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List[str] = []

        for _response in response_iterator:
            response = ListRolePoliciesResponse(**_response)
            if response.PolicyNames is not None:
                results.extend(response.PolicyNames)
            else:
                break

        self.sessionize(results)
        return cast("List[str]", results)

    @role_attached_policies_only
    def list_attached_policies(
        self,
        RoleName: str,
        *,
        PathPrefix: str | None = None,
        MaxItems: int | None = None,
    ) -> List["AttachedPolicy"]:
        """
        List the attached IAM policies for a role.

        Args:
            RoleName: The name (friendly name, not ARN) of the role to list attached policies for.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it
                defaults to a slash (/), listing all policies.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_attached_role_policies")
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName),
            PathPrefix=self.serialize(PathPrefix),
            MaxItems=self.serialize(MaxItems),
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["AttachedPolicy"] = []

        for _response in response_iterator:
            response = ListAttachedRolePoliciesResponse(**_response)
            if response.AttachedPolicies is not None:
                results.extend(response.AttachedPolicies)
            else:
                break

        self.sessionize(results)
        return cast("List[AttachedPolicy]", results)

    def list_instance_profiles(
        self, RoleName: str, *, MaxItems: int | None = None
    ) -> List["InstanceProfile"]:
        """
        Lists the instance profiles that have the specified associated IAM role. If there are none, the operation returns an
        empty list. For more information about instance profiles, go to `Using instance
        profiles <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html>`_ in the
        *IAM User Guide*.

        Args:
            RoleName: The name of the role to list instance profiles for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.

        """
        paginator = self.client.get_paginator("list_instance_profiles_for_role")
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["InstanceProfile"] = []

        for _response in response_iterator:
            response = ListInstanceProfilesForRoleResponse(**_response)
            if response.InstanceProfiles is not None:
                results.extend(response.InstanceProfiles)
            else:
                break

        self.sessionize(results)
        return cast("List[InstanceProfile]", results)

    def update(self, model: "IAMRole") -> None:
        """
        Update a role.

        Args:
            model: The :py:class:`Role` to update.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            RoleName=data.get("RoleName"),
            Description=data.get("Description"),
            MaxSessionDuration=data.get("MaxSessionDuration"),
        )
        self.client.update_role(**{k: v for k, v in args.items() if v is not None})

    def update_assume_role_policy(self, RoleName: str, PolicyDocument: str) -> "None":
        """
        Updates the policy that grants an IAM entity permission to assume a role. This is typically referred to as the "role
        trust policy". For more information about roles, see `Using roles to delegate permissions and federate
        identities <https://docs.aws.amazon.com/IAM/latest/UserGuide/roles-toplevel.html>`_.

        Args:
            RoleName: The name of the role to update with the new policy.
            PolicyDocument: The policy that grants an entity permission to assume the role.

        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName),
            PolicyDocument=self.serialize(PolicyDocument),
        )
        self.client.update_assume_role_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def update_description(
        self, RoleName: str, Description: str
    ) -> "UpdateRoleDescriptionResponse":
        """
        Use `UpdateRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateRole.html>`_ instead.

        Args:
            RoleName: The name of the role that you want to modify.
            Description: The new description that you want to apply to the specified role.

        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), Description=self.serialize(Description)
        )
        _response = self.client.update_role_description(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = UpdateRoleDescriptionResponse(**_response)

        results: "UpdateRoleDescriptionResponse" = None
        if response is not None:
            results = response

        self.sessionize(results)
        return cast("UpdateRoleDescriptionResponse", results)

    def add_to_instance_profile(
        self, InstanceProfileName: str, RoleName: str
    ) -> "None":
        """
        Adds the specified IAM role to the specified instance profile. An instance profile can contain only one role, and this
        quota cannot be increased. You can remove the existing role and then add a different role to an instance profile. You
        must then wait for the change to appear across all of Amazon Web Services because of `eventual
        consistency <https://en.wikipedia.org/wiki/Eventual_consistency>`_. To force the change, you must `disassociate the
        instance profile <https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DisassociateIamInstanceProfile.html>`_ and
        then `associate the instance
        profile <https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AssociateIamInstanceProfile.html>`_, or you can stop
        your instance and then restart it.

        Args:
            InstanceProfileName: The name of the instance profile to update.
            RoleName: The name of the role to add.

        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName),
            RoleName=self.serialize(RoleName),
        )
        self.client.add_role_to_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )

    def remove_from_instance_profile(
        self, InstanceProfileName: str, RoleName: str
    ) -> "None":
        """
        Removes the specified IAM role from the specified Amazon EC2 instance profile.

        Args:
            InstanceProfileName: The name of the instance profile to update.
            RoleName: The name of the role to remove.
        """
        args: Dict[str, Any] = dict(
            InstanceProfileName=self.serialize(InstanceProfileName),
            RoleName=self.serialize(RoleName),
        )
        self.client.remove_role_from_instance_profile(
            **{k: v for k, v in args.items() if v is not None}
        )

    def attach_policy(self, RoleName: str, PolicyArn: str) -> "None":
        """
        Attach an IAM policy to a role.

        Args:
            RoleName: The name (friendly name, not ARN) of the role to attach the policy to.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to attach.
        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.attach_role_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def detach_policy(self, RoleName: str, PolicyArn: str) -> "None":
        """
        Detach an IAM policy from a role.

        Args:
            RoleName: The name (friendly name, not ARN) of the IAM role to detach the policy from.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to detach.
        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.detach_role_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def put_policy(self, RoleName: str, PolicyName: str, PolicyDocument: str) -> "None":
        """
        Attach an inline policy to a role.

        Args:
            RoleName: The name of the role to associate the policy with.
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """
        args: Dict[str, Any] = dict(
            RoleName=self.serialize(RoleName),
            PolicyName=self.serialize(PolicyName),
            PolicyDocument=self.serialize(PolicyDocument),
        )
        self.client.put_role_policy(**{k: v for k, v in args.items() if v is not None})


class IAMUserManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMUser") -> "IAMUser":
        """
        Create a user.

        Args:
            model: The :py:class:`User` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"),
            Path=data.get("Path"),
            PermissionsBoundary=data.get("PermissionsBoundary"),
            Tags=data.get("Tags"),
        )
        _response = self.client.create_user(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateUserResponse(**_response)

        self.sessionize(response.User)
        return cast("IAMUser", response.User)

    def delete(self, UserName: str) -> None:
        """
        Delete a user.

        Args:
            UserName: The name of the user to delete.
        """
        args: Dict[str, Any] = dict(UserName=self.serialize(UserName))
        self.client.delete_user(**{k: v for k, v in args.items() if v is not None})

    def get(self, UserName: str) -> Optional["IAMUser"]:
        """
        Retrieves information about the specified IAM user, including the user's
        creation date, path, unique ID, and ARN.

        Args:
            UserName: The name of the user to get information about.
        """
        args: Dict[str, Any] = dict(UserName=self.serialize(UserName))
        _response = self.client.get_user(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetUserResponse(**_response)

        if response and response.User:
            self.sessionize(response.User)
            return response.User
        return None

    def get_policy(self, UserName: str, PolicyName: str) -> "GetUserPolicyResponse":
        """
        Get an inline policy from a user.

        Args:
            UserName: The name of the user who the policy is associated with.
            PolicyName: The name of the policy document to get.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), PolicyName=self.serialize(PolicyName)
        )
        _response = self.client.get_user_policy(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetUserPolicyResponse(**_response)

        results: "GetUserPolicyResponse" = None
        if response is not None:
            results = response

        self.sessionize(results)
        return cast("GetUserPolicyResponse", results)

    def list(
        self, *, PathPrefix: str | None = None, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        Lists the IAM users that have the specified path prefix. If no path prefix is
        specified, the operation returns all users in the Amazon Web Services account.
        If there are none, the operation returns an empty list.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. For example: ``/division_abc/subdivision_xyz/``, which would
                get all user names whose path starts with ``/division_abc/subdivision_xyz/``.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_users")
        args: Dict[str, Any] = dict(
            PathPrefix=self.serialize(PathPrefix), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListUsersResponse(**_response)
            if response.Users:
                results.extend(response.Users)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def update(
        self,
        model: "IAMUser",
        NewPath: str | None = None,
        NewUserName: str | None = None,
    ) -> None:
        """
        Update a user.

        Args:
            model: The :py:class:`User` to update.

        Keyword Args:
            NewPath: New path for the IAM user. Include this parameter only if you're changing the user's path.
            NewUserName: New name for the user. Include this parameter only if you're changing the user's name.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"),
            NewPath=self.serialize(NewPath),
            NewUserName=self.serialize(NewUserName),
        )
        self.client.update_user(**{k: v for k, v in args.items() if v is not None})

    def add_to_group(self, GroupName: str, UserName: str) -> "None":
        """
        Add a user to a group.

        Args:
            GroupName: The name of the group to update.
            UserName: The name of the user to add.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), UserName=self.serialize(UserName)
        )
        self.client.add_user_to_group(
            **{k: v for k, v in args.items() if v is not None}
        )

    def remove_from_group(self, GroupName: str, UserName: str) -> "None":
        """
        Remove a user from a group.

        Args:
            GroupName: The name of the group to update.
            UserName: The name of the user to remove.
        """
        args: Dict[str, Any] = dict(
            GroupName=self.serialize(GroupName), UserName=self.serialize(UserName)
        )
        self.client.remove_user_from_group(
            **{k: v for k, v in args.items() if v is not None}
        )

    def list_groups(
        self, UserName: str, *, MaxItems: int | None = None
    ) -> List["IAMGroup"]:
        """
        Lists the IAM groups that the specified IAM user belongs to.

        Args:
            UserName: The name of the user to list groups for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_groups_for_user")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["IAMGroup"] = []

        for _response in response_iterator:
            response = ListGroupsForUserResponse(**_response)
            if response.Groups is not None:
                results.extend(response.Groups)
            else:
                break

        self.sessionize(results)
        return cast("List[IAMGroup]", results)

    def attach_policy(self, UserName: str, PolicyArn: str) -> "None":
        """
        Attach an IAM policy to a user.

        Args:
            UserName: The name (friendly name, not ARN) of the IAM user to attach the policy to.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to attach.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.attach_user_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def detach_policy(self, UserName: str, PolicyArn: str) -> "None":
        """
        Detach an IAM policy from a user.

        Args:
            UserName: The name (friendly name, not ARN) of the IAM user to detach the policy from.
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to detach.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), PolicyArn=self.serialize(PolicyArn)
        )
        self.client.detach_user_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def list_policies(
        self, UserName: str, *, MaxItems: int | None = None
    ) -> List[str]:
        """
        Lists the names of the inline policies embedded in the specified IAM user.

        Args:
            UserName: The name of the user to list policies for.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_user_policies")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List[str] = []

        for _response in response_iterator:
            response = ListUserPoliciesResponse(**_response)
            if response.PolicyNames is not None:
                results.extend(response.PolicyNames)
            else:
                break

        self.sessionize(results)
        return cast("List[str]", results)

    @iam_attached_policies_only
    def list_attached_policies(
        self,
        UserName: str,
        *,
        PathPrefix: str | None = None,
        MaxItems: int | None = None,
    ) -> List["AttachedPolicy"]:
        """
        Lists all managed policies that are attached to the specified IAM user.

        Args:
            UserName: The name (friendly name, not ARN) of the user to list attached policies for.

        Keyword Args:
            PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it
                defaults to a slash (/), listing all policies.
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_attached_user_policies")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName),
            PathPrefix=self.serialize(PathPrefix),
            MaxItems=self.serialize(MaxItems),
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )

        results: List["AttachedPolicy"] = []

        for _response in response_iterator:
            response = ListAttachedUserPoliciesResponse(**_response)
            if response.AttachedPolicies is not None:
                results.extend(response.AttachedPolicies)
            else:
                break

        self.sessionize(results)
        return cast("List[AttachedPolicy]", results)

    def put_policy(self, UserName: str, PolicyName: str, PolicyDocument: str) -> "None":
        """
        Attach an inline policy to a user.

        Args:
            UserName: The name of the user to associate the policy with.
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName),
            PolicyName=self.serialize(PolicyName),
            PolicyDocument=self.serialize(PolicyDocument),
        )
        self.client.put_user_policy(**{k: v for k, v in args.items() if v is not None})

    def delete_policy(self, UserName: str, PolicyName: str) -> "None":
        """
        Delete an inline policy from a user.

        Args:
            UserName: The name (friendly name, not ARN) identifying the user that the policy is embedded in.
            PolicyName: The name identifying the policy document to delete.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), PolicyName=self.serialize(PolicyName)
        )
        self.client.delete_user_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def put_permission_boundary(
        self, UserName: str, PermissionsBoundary: str
    ) -> "None":
        """
        Attach a permissions boundary to a user.

        Args:
            UserName: The name (friendly name, not ARN) of the IAM user for which you want to set the permissions boundary.
            PermissionsBoundary: The ARN of the managed policy that is used to set the permissions boundary for the user.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName),
            PermissionsBoundary=self.serialize(PermissionsBoundary),
        )
        self.client.put_user_permissions_boundary(
            **{k: v for k, v in args.items() if v is not None}
        )

    def delete_permission_boundary(self, UserName: str) -> "None":
        """
        Delete a permissions boundary from a user.

        Args:
            UserName: The name (friendly name, not ARN) of the IAM user from which you want to remove the permissions boundary.
        """
        args: Dict[str, Any] = dict(UserName=self.serialize(UserName))
        self.client.delete_user_permissions_boundary(
            **{k: v for k, v in args.items() if v is not None}
        )


class IAMSSHPublicKeyManager(Boto3ModelManager):
    service_name: str = "iam"

    def create(self, model: "IAMSSHPublicKey") -> "IAMSSHPublicKey":
        """
        Upload an SSH public key.

        Args:
            model: The :py:class:`SSHPublicKey` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"), SSHPublicKeyBody=data.get("SSHPublicKeyBody")
        )
        _response = self.client.upload_ssh_public_key(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = UploadSSHPublicKeyResponse(**_response)

        self.sessionize(response.SSHPublicKey)
        return cast("IAMSSHPublicKey", response.SSHPublicKey)

    def delete(self, UserName: str, SSHPublicKeyId: str) -> None:
        """
        Delete an SSH public key.

        Args:
            UserName: The name of the IAM user associated with the SSH public key.
            SSHPublicKeyId: The unique identifier for the SSH public key.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName),
            SSHPublicKeyId=self.serialize(SSHPublicKeyId),
        )
        self.client.delete_ssh_public_key(
            **{k: v for k, v in args.items() if v is not None}
        )

    def get(
        self, UserName: str, SSHPublicKeyId: str, Encoding: Literal["SSH", "PEM"]
    ) -> Optional["IAMSSHPublicKey"]:
        """
        Get an SSH public key.

        Args:
            UserName: The name of the IAM user associated with the SSH public key.
            SSHPublicKeyId: The unique identifier for the SSH public key.
            Encoding: Specifies the public key encoding format to use in the response. To retrieve the public key in ssh-rsa
                format, use ``SSH``. To retrieve the public key in PEM format, use ``PEM``.
        """
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName),
            SSHPublicKeyId=self.serialize(SSHPublicKeyId),
            Encoding=self.serialize(Encoding),
        )
        _response = self.client.get_ssh_public_key(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = GetSSHPublicKeyResponse(**_response)

        if response and response.SSHPublicKey:
            self.sessionize(response.SSHPublicKey)
            return response.SSHPublicKey
        return None

    def list(
        self, UserName: str, *, MaxItems: int | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        List SSH public keys.

        Args:
            UserName: The name of the IAM user to list SSH public keys for. If none is specified, the ``UserName`` field is
                determined implicitly based on the Amazon Web Services access key used to sign the request.

        Keyword Args:
            MaxItems: Use this only when paginating results to indicate the maximum number of items you want in the response. If
                additional items exist beyond the maximum you specify, the ``IsTruncated`` response element is ``true``.
        """
        paginator = self.client.get_paginator("list_ssh_public_keys")
        args: Dict[str, Any] = dict(
            UserName=self.serialize(UserName), MaxItems=self.serialize(MaxItems)
        )
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListSSHPublicKeysResponse(**_response)
            if response.SSHPublicKeys:
                results.extend(response.SSHPublicKeys)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def update(self, model: "IAMSSHPublicKey") -> None:
        """
        Update an SSH public key.

        Args:
            model: The :py:class:`SSHPublicKey` to update.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            UserName=data.get("UserName"),
            SSHPublicKeyId=data.get("SSHPublicKeyId"),
            Status=data.get("Status"),
        )
        self.client.update_ssh_public_key(
            **{k: v for k, v in args.items() if v is not None}
        )


# ==============
# Service Models
# ==============


class IAMAccessKey(PrimaryBoto3Model):
    """
    Contains information about an Amazon Web Services access key.

    This data type is used as a response element in the
    `CreateAccessKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html>`_ and
    `ListAccessKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html>`_ operations.

    The ``SecretAccessKey`` value is returned only in response to
    `CreateAccessKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html>`_. You can get a secret
    access key only when you first create an access key; you cannot recover the secret access key later. If you lose a
    secret access key, you must create a new access key.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMAccessKeyManager

    UserName: str
    """
    The name of the IAM user that the access key is associated with.
    """
    AccessKeyId: str
    """
    The ID for this access key.
    """
    Status: Literal["Active", "Inactive", "Expired"]
    """
    The status of the access key.

    ``Active`` means that the key is valid for API calls, while ``Inactive`` means it is not.
    """
    SecretAccessKey: str = Field(frozen=True)
    """
    The secret key used to sign requests.
    """
    CreateDate: datetime = Field(default=None, frozen=True)
    """
    The date when the access key was created.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`AccessKeyId` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.AccessKeyId

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`AccessKeyId`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.AccessKeyId

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`AccessKeyId` attribute.
        """
        return hash(self.AccessKeyId)

    @cached_property
    def user(self) -> Optional["IAMUser"]:
        """
        Return the :py:class:`User` object that this access key belongs to.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "UserName": self.UserName,
                }
            )
        except AttributeError:
            return None
        return IAMUser.objects.using(self.session).get(**pk)  # type: ignore[arg-type]

    def last_used(self) -> "GetAccessKeyLastUsedResponse":
        """
        Return the :py:class:`AccessKeyLastUsed` object that this access key was last
        used.
        """

        return (
            cast("IAMAccessKeyManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .last_used(
                cast("str", self.AccessKeyId),
            )
        )


class IAMGroup(PrimaryBoto3Model):
    """
    Contains information about an IAM group entity.

    This data type is used as a response element in the following operations:

    * `CreateGroup <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateGroup.html>`_
    * `GetGroup <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetGroup.html>`_
    * `ListGroups <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListGroups.html>`_
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMGroupManager

    Path: str
    """
    The path to the group.

    For more information about paths, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    GroupName: str
    """
    The friendly name that identifies the group.
    """
    GroupId: str = Field(frozen=True)
    """
    The stable and unique string identifying the group.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    Arn: str = Field(frozen=True)
    """
    The Amazon Resource Name (ARN) specifying the group.

    For more information about ARNs and how to use them in policies, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    CreateDate: datetime = Field(frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the group was created.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`GroupName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.GroupName

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`GroupName`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.GroupName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`GroupName` attribute.
        """
        return hash(self.GroupName)

    @cached_property
    def users(self) -> List["IAMUser"] | None:
        """
        Return the :py:class:`User` objects that are members of this group.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "GroupName": self.GroupName,
                }
            )
        except AttributeError:
            return []
        return IAMUser.objects.using(self.session).list(**pk)  # type: ignore[arg-type]

    def add_user(self, UserName: str) -> "None":
        """
        Add a user to this group.

        Args:
            UserName: The name of the user to add.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .add_user(
                cast("str", self.GroupName),
                UserName,
            )
        )

    def remove_user(self, UserName: str) -> "None":
        """
        Remove a user from this group.

        Args:
            UserName: The name of the user to remove.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .remove_user(
                cast("str", self.GroupName),
                UserName,
            )
        )

    def attach_policy(self, PolicyArn: str) -> "None":
        """
        Attach a policy to this group.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to attach.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .attach_policy(
                cast("str", self.GroupName),
                PolicyArn,
            )
        )

    def detach_policy(self, PolicyArn: str) -> "None":
        """
        Detach a policy from this group.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to detach.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .detach_policy(
                cast("str", self.GroupName),
                PolicyArn,
            )
        )

    def put_inline_policy(self, PolicyName: str, PolicyDocument: str) -> "None":
        """
        Put an inline policy to this group.

        Args:
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .put_policy(
                cast("str", self.GroupName),
                PolicyName,
                PolicyDocument,
            )
        )

    def remove_inline_policy(self, PolicyName: str) -> "None":
        """
        Remove an inline policy from this group.

        Args:
            PolicyName: The name identifying the policy document to delete.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .delete_policy(
                cast("str", self.GroupName),
                PolicyName,
            )
        )

    def attached_policies(self) -> List["AttachedPolicy"]:
        """
        Return the :py:class:`Policy` objects that are attached to this group.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_attached_policies(
                cast("str", self.GroupName),
            )
        )

    def inline_policies(self) -> "List[str]":
        """
        Return the :py:class:`Policy` objects that are inline policies of this group.
        """

        return (
            cast("IAMGroupManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_policies(
                cast("str", self.GroupName),
            )
        )


class IAMTag(Boto3Model):
    """
    A structure that represents user-provided metadata that can be associated with an
    IAM resource.

    For more information about tagging, see
    `Tagging IAM resources <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html>`_
    in the *IAM
    User Guide*.
    """

    Key: str
    """
    The key name that can be used to look up or retrieve the associated value.

    For example, ``Department`` or ``Cost
    Center`` are common choices.
    """
    Value: str
    """
    The value associated with this tag.

    For example, tags with a key name of ``Department`` could have values such as
    ``Human Resources``, ``Accounting``, and ``Support``. Tags with a key name of ``Cost Center`` might have values that
    consist of the number associated with the different cost centers in your company. Typically, many resources have tags
    with the same key name but with different values.
    """


class InstanceProfile(TagsDictMixin, PrimaryBoto3Model):
    """
    Contains information about an instance profile.

    This data type is used as a response element in the following operations:

    * `CreateInstanceProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateInstanceProfile.html>`_
    * `GetInstanceProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetInstanceProfile.html>`_
    * `ListInstanceProfiles <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListInstanceProfiles.html>`_
    *
      `ListInstanceProfilesForRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListInstanceProfilesForRole.html>`_
    """

    tag_class: ClassVar[Type] = IAMTag
    manager_class: ClassVar[Type[Boto3ModelManager]] = InstanceProfileManager

    Path: str
    """
    The path to the instance profile.

    For more information about paths, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    InstanceProfileName: str
    """
    The name identifying the instance profile.
    """
    InstanceProfileId: str = Field(frozen=True)
    """
    The stable and unique string identifying the instance profile.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    Arn: str = Field(frozen=True)
    """
    The Amazon Resource Name (ARN) specifying the instance profile.

    For more information about ARNs and how to use them in policies, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM
    User Guide*.
    """
    CreateDate: datetime = Field(frozen=True)
    """
    The date when the instance profile was created.
    """
    Roles: List["IAMRole"] = Field(frozen=True)
    """
    The role associated with the instance profile.
    """
    Tags: List["IAMTag"] | None = None
    """
    A list of tags that are attached to the instance profile.

    For more information about tagging, see
    `Tagging IAM resources <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html>`_
    in the *IAM User Guide*.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`InstanceProfileName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.InstanceProfileName

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the
        :py:attr:`InstanceProfileName` attribute.

        Returns:
            The name of the model instance.
        """
        return self.InstanceProfileName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`InstanceProfileName` attribute.
        """
        return hash(self.InstanceProfileName)


class IAMLoginProfile(PrimaryBoto3Model):
    """
    Contains the user name and password create date for a user.

    This data type is used as a response element in the
    `CreateLoginProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html>`_
    and
    `GetLoginProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetLoginProfile.html>`_
    operations.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMLoginProfileManager

    UserName: str
    """
    The name of the user, which can be used for signing in to the Amazon Web Services
    Management Console.
    """
    CreateDate: datetime = Field(frozen=True)
    """
    The date when the password for the user was created.
    """
    PasswordResetRequired: bool | None = None
    """
    Specifies whether the user is required to set a new password on next sign-in.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`UserName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.UserName

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`UserName`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.UserName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`UserName` attribute.
        """
        return hash(self.UserName)


class IAMPolicy(TagsDictMixin, IAMPolicyMixin, PrimaryBoto3Model):
    """
    Contains information about a managed policy.

    This data type is used as a response element in the
    `CreatePolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html>`_,
    `GetPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html>`_,
    and
    `ListPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicies.html>`_
    operations.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    tag_class: ClassVar[Type] = IAMTag
    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMPolicyManager

    PolicyName: str | None = None
    """
    The friendly name (not ARN) identifying the policy.
    """
    PolicyId: str = Field(default=None, frozen=True)
    """
    The stable and unique string identifying the policy.
    """
    Arn: str = Field(default=None, frozen=True)
    """
    The Amazon Resource Name (ARN).

    ARNs are unique identifiers for Amazon Web Services resources.
    """
    Path: str | None = None
    """
    The path to the policy.
    """
    DefaultVersionId: str = Field(default=None, frozen=True)
    """
    The identifier for the version of the policy that is set as the default version.
    """
    AttachmentCount: int = Field(default=None, frozen=True)
    """
    The number of entities (users, groups, and roles) that the policy is attached to.
    """
    PermissionsBoundaryUsageCount: int = Field(default=None, frozen=True)
    """
    The number of entities (users and roles) for which the policy is used to set the
    permissions boundary.
    """
    IsAttachable: bool = Field(default=None, frozen=True)
    """
    Specifies whether the policy can be attached to an IAM user, group, or role.
    """
    Description: str | None = None
    """
    A friendly description of the policy.
    """
    CreateDate: datetime = Field(default=None, frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the policy was created.
    """
    UpdateDate: datetime = Field(default=None, frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the policy was last updated.
    """
    Tags: List["IAMTag"] | None = None
    """
    A list of tags that are attached to the instance profile.

    For more information about tagging, see
    `Tagging IAM resources <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html>`_
    in the *IAM User Guide*.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.Arn

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`PolicyName`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.PolicyName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`Arn` attribute.
        """
        return hash(self.Arn)

    def entities(self) -> "ListEntitiesForPolicyResponse":
        """
        Return the :py:class:`Entity` objects that are entities of this policy.
        """

        return (
            cast("IAMPolicyManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_entities(
                cast("str", self.Arn),
            )
        )

    def versions(self) -> List["IAMPolicyVersion"]:
        """
        Return the :py:class:`PolicyVersion` objects that are versions of this policy.
        """

        return (
            cast("IAMPolicyManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_versions(
                cast("str", self.Arn),
            )
        )

    def set_default_version(self, VersionId: str) -> "None":
        """
        Set the default version of this policy.

        Args:
            VersionId: The version of the policy to set as the default (operative) version.
        """

        return (
            cast("IAMPolicyManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .set_default_version(
                cast("str", self.Arn),
                VersionId,
            )
        )


class IAMPolicyVersion(PrimaryBoto3Model):
    """
    Contains information about a version of a managed policy.

    This data type is used as a response element in the
    `CreatePolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicyVersion.html>`_,
    `GetPolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html>`_,
    `ListPolicyVersions <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html>`_,
    and
    `GetAccountAu thorizationDetails <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccountAuthorizationDetails.html>`_
     operations.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMPolicyVersionManager

    Document: str = Field(default=None, frozen=True)
    """
    The policy document.
    """
    VersionId: str = Field(default=None, frozen=True)
    """
    The identifier for the policy version.
    """
    IsDefaultVersion: bool = Field(default=None, frozen=True)
    """
    Specifies whether the policy version is set as the policy's default version.
    """
    CreateDate: datetime = Field(default=None, frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the policy version was created.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`VersionId` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.VersionId

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`VersionId`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.VersionId

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`VersionId` attribute.
        """
        return hash(self.VersionId)


class AttachedPermissionsBoundary(Boto3Model):
    """
    Contains information about an attached permissions boundary.

    An attached permissions boundary is a managed policy that has been attached to a
    user or role to set the permissions boundary.

    For more information about permissions boundaries, see
    `Permissions boundaries for IAM identities <https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html>`_
    in the *IAM User Guide*.
    """

    PermissionsBoundaryType: Literal["PermissionsBoundaryPolicy"] | None = None
    """
    The permissions boundary usage type that indicates what type of IAM resource is used
    as the permissions boundary for an entity.

    This data type can only have a value of ``Policy``.
    """
    PermissionsBoundaryArn: str | None = None
    """
    The ARN of the policy used to set the permissions boundary for the user or role.
    """


class IAMRoleLastUsed(Boto3Model):
    """Contains information about the last time that an IAM role was used. This includes the date and time and the Region in
    which the role was last used. Activity is only reported for the trailing 400 days. This period can be shorter if your
    Region began supporting these features within the last year. The role might have been used more than 400 days ago. For
    more information, see `Regions where data is
    tracked <https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html#access-advisor_tracking-
    period>`_ in the *IAM user Guide*.

    This data type is returned as a response element in the
    `GetRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html>`_ and `GetAccountAuthorizationDetails <htt
    ps://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccountAuthorizationDetails.html>`_ operations.
    """

    LastUsedDate: datetime | None = None
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_ that the role was last used.
    """
    Region: str | None = None
    """
    The name of the Amazon Web Services Region in which the role was last used.
    """


class IAMRole(TagsDictMixin, PrimaryBoto3Model):
    """
    Contains information about an IAM role.

    This structure is returned as a response element in several API operations that
    interact with roles.
    """

    tag_class: ClassVar[Type] = IAMTag
    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMRoleManager

    AssumeRolePolicyDocument: dict[str, Any] | None = None
    """
    The policy that grants an entity permission to assume the role.
    """
    Path: str
    """
    The path to the role.

    For more information about paths, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    RoleName: str
    """
    The friendly name that identifies the role.
    """
    RoleId: str = Field(frozen=True)
    """
    The stable and unique string identifying the role.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    Arn: str = Field(frozen=True)
    """
    The Amazon Resource Name (ARN) specifying the role.

    For more information about ARNs and how to use them in policies, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*
    guide.
    """
    CreateDate: datetime = Field(frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the role was created.
    """
    Description: str | None = None
    """
    A description of the role that you provide.
    """
    MaxSessionDuration: int | None = None
    """
    The maximum session duration (in seconds) for the specified role.

    Anyone who uses the CLI, or API to assume the role can
    specify the duration using the optional ``DurationSeconds`` API parameter or ``duration-seconds`` CLI parameter.
    """
    PermissionsBoundary: AttachedPermissionsBoundary | None = None
    """
    The ARN of the policy used to set the permissions boundary for the role.
    """
    Tags: List["IAMTag"] | None = None
    """
    A list of tags that are attached to the role.

    For more information about tagging, see
    `Tagging IAM resources <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html>`_
    in the *IAM User Guide*.
    """
    RoleLastUsed: IAMRoleLastUsed = Field(default=None, frozen=True)
    """
    Contains information about the last time that an IAM role was used.

    This includes the date and time and the Region in which the role was last used.
    Activity is only reported for the trailing 400 days. This period can be shorter if
    your Region began supporting these features within the last year. The role might
    have been used more than 400 days ago. For more information, see
    `Regions where data is tracked <https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html#access-advisor_tracking-
    period>`_ in the *IAM user Guide*.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`RoleName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.RoleName

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`RoleName`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.RoleName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`RoleName` attribute.
        """
        return hash(self.RoleName)

    def attached_policies(self) -> List["AttachedPolicy"]:
        """
        Return the :py:class:`Policy` objects that are attached to this role.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_attached_policies(
                cast("str", self.RoleName),
            )
        )

    def inline_policies(self) -> "List[str]":
        """
        Return the :py:class:`Policy` objects that are inline policies of this role.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_policies(
                cast("str", self.RoleName),
            )
        )

    def instance_profiles(self) -> List["InstanceProfile"]:
        """
        Return the :py:class:`InstanceProfile` objects that are instance profiles of
        this role.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_instance_profiles(
                cast("str", self.RoleName),
            )
        )

    def update_assume_role_policy(self, PolicyDocument: str) -> "None":
        """
        Update the assume role policy of this role.

        Args:
            PolicyDocument: The policy that grants an entity permission to assume the role.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .update_assume_role_policy(
                cast("str", self.RoleName),
                PolicyDocument,
            )
        )

    def attach_policy(self, PolicyArn: str) -> "None":
        """
        Attach a policy to this role.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to attach.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .attach_policy(
                cast("str", self.RoleName),
                PolicyArn,
            )
        )

    def detach_policy(self, PolicyArn: str) -> "None":
        """
        Detach a policy from this role.

        Args:
            PolicyArn: The Amazon Resource Name (ARN) of the IAM policy you want to detach.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .detach_policy(
                cast("str", self.RoleName),
                PolicyArn,
            )
        )

    def add_policy(self, PolicyName: str, PolicyDocument: str) -> "None":
        """
        Put an inline policy to this role.

        Args:
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .put_policy(
                cast("str", self.RoleName),
                PolicyName,
                PolicyDocument,
            )
        )

    def remove_policy(self, PolicyName: str) -> "None":
        """
        Remove an inline policy from this role.

        Args:
            PolicyName: The name of the inline policy to delete from the specified IAM role.
        """

        return (
            cast("IAMRoleManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .delete_policy(
                cast("str", self.RoleName),
                PolicyName,
            )
        )


class IAMUser(TagsDictMixin, PrimaryBoto3Model):
    """
    Contains information about an IAM user entity.

    This data type is used as a response element in the following operations:

    * `CreateUser <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html>`_
    * `GetUser <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUser.html>`_
    * `ListUsers <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html>`_
    """

    tag_class: ClassVar[Type] = IAMTag
    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMUserManager

    Path: str
    """
    The path to the user.

    For more information about paths, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    UserName: str
    """
    The friendly name identifying the user.
    """
    UserId: str = Field(frozen=True)
    """
    The stable and unique string identifying the user.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM User Guide*.
    """
    Arn: str = Field(frozen=True)
    """
    The Amazon Resource Name (ARN) that identifies the user.

    For more information about ARNs and how to use ARNs in policies, see
    `IAM Identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html>`_
    in the *IAM
    User Guide*.
    """
    CreateDate: datetime = Field(frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the user was created.
    """
    PasswordLastUsed: datetime = Field(default=None, frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the user's password was last
used to sign in to an Amazon Web Services website. For a list of Amazon Web Services websites that capture a user's last
sign-in time, see the `Credential reports <https://docs.aws.amazon.com/IAM/latest/UserGuide/credential-reports.html>`_
topic in the *IAM User Guide*. If a password is used more than once in a five-minute span, only the first use is
returned in this field. If the field is null (no value), then it indicates that they never signed in with a password.
This can be because:
    """
    PermissionsBoundary: AttachedPermissionsBoundary | None = None
    """
For more information about permissions boundaries, see `Permissions boundaries for IAM
identities <https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html>`_  in the *IAM User Guide*.
    """
    Tags: List["IAMTag"] | None = None
    """
    A list of tags that are associated with the user.

    For more information about tagging, see
    `Tagging IAM resources <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html>`_
    in the *IAM User Guide*.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the
        :py:attr:`UserName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.UserName

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the :py:attr:`UserName`
        attribute.

        Returns:
            The name of the model instance.
        """
        return self.UserName

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`UserName` attribute.
        """
        return hash(self.UserName)

    def groups(self) -> List["IAMGroup"]:
        """
        Return the :py:class:`Group` objects that are groups of this user.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_groups(
                cast("str", self.UserName),
            )
        )

    def add_to_group(self, GroupName: str) -> "None":
        """
        Add a user to a group.

        Args:
            GroupName: The name of the group to update.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .add_to_group(
                cast("str", self.UserName),
                GroupName,
            )
        )

    def remove_from_group(self, GroupName: str) -> "None":
        """
        Remove a user from a group.

        Args:
            GroupName: The name of the group to update.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .remove_from_group(
                cast("str", self.UserName),
                GroupName,
            )
        )

    def attached_policies(self) -> List["AttachedPolicy"]:
        """
        Return the :py:class:`Policy` objects that are attached to this user.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_attached_policies(
                cast("str", self.UserName),
            )
        )

    def inline_policies(self) -> "List[str]":
        """
        Return the :py:class:`Policy` objects that are inline policies of this user.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .list_policies(
                cast("str", self.UserName),
            )
        )

    def add_policy(self, PolicyName: str, PolicyDocument: str) -> "None":
        """
        Put an inline policy to this user.

        Args:
            PolicyName: The name of the policy document.
            PolicyDocument: The policy document.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .put_policy(
                cast("str", self.UserName),
                PolicyName,
                PolicyDocument,
            )
        )

    def remove_policy(self, PolicyName: str) -> "None":
        """
        Remove an inline policy from this user.

        Args:
            PolicyName: The name identifying the policy document to delete.
        """

        return (
            cast("IAMUserManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .delete_policy(
                cast("str", self.UserName),
                PolicyName,
            )
        )


class IAMSSHPublicKey(PrimaryBoto3Model):
    """
    Contains information about an SSH public key.

    This data type is used as a response element in the
    `GetSSHPublicKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetSSHPublicKey.html>`_
    and
    `UploadSSHPublicKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadSSHPublicKey.html>`_
    operations.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = IAMSSHPublicKeyManager

    UserName: str
    """
    The name of the IAM user associated with the SSH public key.
    """
    SSHPublicKeyId: str
    """
    The unique identifier for the SSH public key.
    """
    Fingerprint: str = Field(frozen=True)
    """
    The MD5 message digest of the SSH public key.
    """
    SSHPublicKeyBody: str
    """
    The SSH public key.
    """
    Status: Literal["Active", "Inactive", "Expired"]
    """
    The status of the SSH public key.

    ``Active`` means that the key can be used for authentication with an CodeCommit
    repository. ``Inactive`` means that the key cannot be used.
    """
    UploadDate: datetime = Field(default=None, frozen=True)
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the SSH public key was uploaded.
    """

    @property
    def name(self) -> str | None:
        """
        Return the name of the model.   This is the value of the
        :py:attr:`SSHPublicKeyId` attribute.

        Returns:
            The name of the model instance.
        """
        return self.SSHPublicKeyId

    @property
    def pk(self) -> OrderedDict[str, Any]:
        return OrderedDict(
            {
                "UserName": self.UserName,
                "SSHPublicKeyId": self.SSHPublicKeyId,
            }
        )


# =======================
# Request/Response Models
# =======================


class CreateAccessKeyResponse(Boto3Model):
    """Contains the response to a successful
    `CreateAccessKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html>`_ request.
    """

    AccessKey: IAMAccessKey
    """
    A structure with details about the access key.
    """


class AccessKeyMetadata(Boto3Model):
    """
    Contains information about an Amazon Web Services access key, without its secret
    key.

    This data type is used as a response element in the
    `ListAccessKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html>`_
    operation.
    """

    UserName: str | None = None
    """
    The name of the IAM user that the key is associated with.
    """
    AccessKeyId: str | None = None
    """
    The ID for this access key.
    """
    Status: Literal["Active", "Inactive", "Expired"] | None = None
    """
    The status of the access key.

    ``Active`` means that the key is valid for API calls; ``Inactive`` means it is not.
    """
    CreateDate: datetime | None = None
    """
    The date when the access key was created.
    """


class ListAccessKeysResponse(Boto3Model):
    """Contains the response to a successful
    `ListAccessKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html>`_ request.
    """

    AccessKeyMetadata: List["AccessKeyMetadata"]
    """
    A list of objects containing metadata about the access keys.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class IAMAccessKeyLastUsed(Boto3Model):
    """
    Contains information about the last time an Amazon Web Services access key was used
    since IAM began tracking this information on April 22, 2015.

    This data type is used as a response element in the
    `GetAccessKeyLastUsed <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccessKeyLastUsed.html>`_
    operation.
    """

    LastUsedDate: datetime | None = None
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the access key was most recently
used. This field is null in the following situations:
    """
    ServiceName: str
    """
    The name of the Amazon Web Services service with which this access key was most
    recently used.

    The value of this field is "N/A" in the following situations:
    """
    Region: str
    """
    The Amazon Web Services Region where this access key was most recently used.

    The value for this field is "N/A" in the
    following situations:
    """


class GetAccessKeyLastUsedResponse(Boto3Model):
    """Contains the response to a successful
    `GetAccessKeyLastUsed <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccessKeyLastUsed.html>`_ request. It is
    also returned as a member of the
    `AccessKeyMetaData <https://docs.aws.amazon.com/IAM/latest/APIReference/API_AccessKeyMetaData.html>`_ structure returned
    by the `ListAccessKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html>`_ action.
    """

    UserName: str | None = None
    """
    The name of the IAM user that owns this access key.
    """
    AccessKeyLastUsed: IAMAccessKeyLastUsed | None = None
    """
    Contains information about the last time the access key was used.
    """


class CreateGroupResponse(Boto3Model):
    """Contains the response to a successful
    `CreateGroup <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateGroup.html>`_ request.
    """

    Group: IAMGroup
    """
    A structure containing details about the new group.
    """


class GetGroupResponse(Boto3Model):
    """Contains the response to a successful `GetGroup <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetGroup.html>`_
    request.
    """

    Group: IAMGroup
    """
    A structure that contains details about the group.
    """
    Users: List["IAMUser"]
    """
    A list of users in the group.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class GetGroupPolicyResponse(Boto3Model):
    """Contains the response to a successful
    `GetGroupPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetGroupPolicy.html>`_ request.
    """

    GroupName: str
    """
    The group the policy is associated with.
    """
    PolicyName: str
    """
    The name of the policy.
    """
    PolicyDocument: str
    """
    The policy document.
    """


class ListGroupsResponse(Boto3Model):
    """Contains the response to a successful
    `ListGroups <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListGroups.html>`_ request.
    """

    Groups: List["IAMGroup"]
    """
    A list of groups.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListGroupsForUserResponse(Boto3Model):
    """Contains the response to a successful
    `ListGroupsForUser <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListGroupsForUser.html>`_ request.
    """

    Groups: List["IAMGroup"]
    """
    A list of groups.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListGroupPoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListGroupPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListGroupPolicies.html>`_ request.
    """

    PolicyNames: List[str]
    """
    A list of policy names.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class AttachedPolicy(Boto3Model):
    """
    Contains information about an attached policy.

    An attached policy is a managed policy that has been attached to a user, group, or
    role. This data type is used as a response element in the
    `ListAttachedGroupPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedGroupPolicies.html>`_,
    `ListAttachedRolePolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html>`_,
    `ListAttachedUserPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedUserPolicies.html>`_,
    and `    GetAccountAuthorizationDetails <https://docs.aws.amazon.com/IAM/latest/APIR
    eference/API_GetAccountAuthorizationDetails.h    tml>`_ operations.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    PolicyName: str | None = None
    """
    The friendly name of the attached policy.
    """
    PolicyArn: str | None = None
    """
    The Amazon Resource Name (ARN).

    ARNs are unique identifiers for Amazon Web Services resources.
    """


class ListAttachedGroupPoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListAttachedGroupPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedGroupPolicies.html>`_
    request.
    """

    AttachedPolicies: List["AttachedPolicy"] | None = None
    """
    A list of the attached policies.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class CreateInstanceProfileResponse(Boto3Model):
    """Contains the response to a successful
    `CreateInstanceProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateInstanceProfile.html>`_ request.
    """

    InstanceProfile: "InstanceProfile"
    """
    A structure containing details about the new instance profile.
    """


class GetInstanceProfileResponse(Boto3Model):
    """Contains the response to a successful
    `GetInstanceProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetInstanceProfile.html>`_ request.
    """

    InstanceProfile: "InstanceProfile"
    """
    A structure containing details about the instance profile.
    """


class ListInstanceProfilesResponse(Boto3Model):
    """Contains the response to a successful
    `ListInstanceProfiles <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListInstanceProfiles.html>`_ request.
    """

    InstanceProfiles: List["InstanceProfile"]
    """
    A list of instance profiles.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListInstanceProfilesForRoleResponse(Boto3Model):
    """Contains the response to a successful
    `ListInstanceProfilesForRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListInstanceProfilesForRole.html>`_
    request.
    """

    InstanceProfiles: List["InstanceProfile"]
    """
    A list of instance profiles.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class CreateLoginProfileResponse(Boto3Model):
    """Contains the response to a successful
    `CreateLoginProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html>`_ request.
    """

    LoginProfile: IAMLoginProfile
    """
    A structure containing the user name and password create date.
    """


class GetLoginProfileResponse(Boto3Model):
    """Contains the response to a successful
    `GetLoginProfile <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetLoginProfile.html>`_ request.
    """

    LoginProfile: IAMLoginProfile
    """
    A structure containing the user name and the profile creation date for the user.
    """


class CreatePolicyResponse(Boto3Model):
    """Contains the response to a successful
    `CreatePolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html>`_ request.
    """

    Policy: IAMPolicy | None = None
    """
    A structure containing details about the new policy.
    """


class GetPolicyResponse(Boto3Model):
    """Contains the response to a successful
    `GetPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html>`_ request.
    """

    Policy: IAMPolicy | None = None
    """
    A structure containing details about the policy.
    """


class ListPoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicies.html>`_ request.
    """

    Policies: List["IAMPolicy"] | None = None
    """
    A list of policies.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class PolicyGroup(Boto3Model):
    """
    Contains information about a group that a managed policy is attached to.

    This data type is used as a response element in the
    `ListEntitiesForPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html>`_
    operation.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    GroupName: str | None = None
    """
    The name (friendly name, not ARN) identifying the group.
    """
    GroupId: str | None = None
    """
    The stable and unique string identifying the group.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html>`_
    in the *IAM User Guide*.
    """


class PolicyUser(Boto3Model):
    """
    Contains information about a user that a managed policy is attached to.

    This data type is used as a response element in the
    `ListEntitiesForPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html>`_
    operation.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    UserName: str | None = None
    """
    The name (friendly name, not ARN) identifying the user.
    """
    UserId: str | None = None
    """
    The stable and unique string identifying the user.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html>`_
    in the *IAM User Guide*.
    """


class PolicyRole(Boto3Model):
    """
    Contains information about a role that a managed policy is attached to.

    This data type is used as a response element in the
    `ListEntitiesForPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html>`_
    operation.

    For more information about managed policies, refer to
    `Managed policies and inline policies <https://docs.aws.amazon.com/IAM/latest/UserGuide/policies-managed-vs-inline.html>`_
    in the *IAM User Guide*.
    """

    RoleName: str | None = None
    """
    The name (friendly name, not ARN) identifying the role.
    """
    RoleId: str | None = None
    """
    The stable and unique string identifying the role.

    For more information about IDs, see
    `IAM identifiers <https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html>`_
    in the *IAM User Guide*.
    """


class ListEntitiesForPolicyResponse(Boto3Model):
    """Contains the response to a successful
    `ListEntitiesForPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListEntitiesForPolicy.html>`_ request.
    """

    PolicyGroups: List["PolicyGroup"] | None = None
    """
    A list of IAM groups that the policy is attached to.
    """
    PolicyUsers: List["PolicyUser"] | None = None
    """
    A list of IAM users that the policy is attached to.
    """
    PolicyRoles: List["PolicyRole"] | None = None
    """
    A list of IAM roles that the policy is attached to.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListPolicyVersionsResponse(Boto3Model):
    """Contains the response to a successful
    `ListPolicyVersions <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html>`_ request.
    """

    Versions: List["IAMPolicyVersion"] | None = None
    """
    A list of policy versions.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class CreatePolicyVersionResponse(Boto3Model):
    """Contains the response to a successful
    `CreatePolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicyVersion.html>`_ request.
    """

    PolicyVersion: IAMPolicyVersion | None = None
    """
    A structure containing details about the new policy version.
    """


class GetPolicyVersionResponse(Boto3Model):
    """Contains the response to a successful
    `GetPolicyVersion <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html>`_ request.
    """

    PolicyVersion: IAMPolicyVersion | None = None
    """
    A structure containing details about the policy version.
    """


class CreateRoleResponse(Boto3Model):
    """Contains the response to a successful
    `CreateRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateRole.html>`_ request.
    """

    Role: IAMRole
    """
    A structure containing details about the new role.
    """


class CreateServiceLinkedRoleResponse(Boto3Model):
    Role: IAMRole | None = None
    """
A `Role <https://docs.aws.amazon.com/IAM/latest/APIReference/API_Role.html>`_ object that contains details about the newly
created role.
    """


class DeleteServiceLinkedRoleResponse(Boto3Model):
    DeletionTaskId: str
    """
    The deletion task identifier that you can use to check the status of the deletion.

    This identifier is returned in the
    format ``task/aws-service-role/<service-principal-name>/<role-name>/<task-uuid>``.
    """


class GetRoleResponse(Boto3Model):
    """Contains the response to a successful `GetRole <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html>`_
    request.
    """

    Role: IAMRole
    """
    A structure containing details about the IAM role.
    """


class GetRolePolicyResponse(Boto3Model):
    """Contains the response to a successful
    `GetRolePolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html>`_ request.
    """

    RoleName: str
    """
    The role the policy is associated with.
    """
    PolicyName: str
    """
    The name of the policy.
    """
    PolicyDocument: str
    """
    The policy document.
    """


class ListRolesResponse(Boto3Model):
    """Contains the response to a successful
    `ListRoles <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRoles.html>`_ request.
    """

    Roles: List["IAMRole"]
    """
    A list of roles.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListRolePoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListRolePolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html>`_ request.
    """

    PolicyNames: List[str]
    """
    A list of policy names.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListAttachedRolePoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListAttachedRolePolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html>`_
    request.
    """

    AttachedPolicies: List["AttachedPolicy"] | None = None
    """
    A list of the attached policies.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class UpdateRoleDescriptionResponse(Boto3Model):
    Role: IAMRole | None = None
    """
    A structure that contains details about the modified role.
    """


class CreateUserResponse(Boto3Model):
    """Contains the response to a successful
    `CreateUser <https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html>`_ request.
    """

    User: IAMUser | None = None
    """
    A structure with details about the new IAM user.
    """


class GetUserResponse(Boto3Model):
    """Contains the response to a successful `GetUser <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUser.html>`_
    request.
    """

    User: IAMUser
    """
    A structure containing details about the IAM user.
    """


class GetUserPolicyResponse(Boto3Model):
    """Contains the response to a successful
    `GetUserPolicy <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUserPolicy.html>`_ request.
    """

    UserName: str
    """
    The user the policy is associated with.
    """
    PolicyName: str
    """
    The name of the policy.
    """
    PolicyDocument: str
    """
    The policy document.
    """


class ListUsersResponse(Boto3Model):
    """Contains the response to a successful
    `ListUsers <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html>`_ request.
    """

    Users: List["IAMUser"]
    """
    A list of users.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListUserPoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListUserPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUserPolicies.html>`_ request.
    """

    PolicyNames: List[str]
    """
    A list of policy names.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class ListAttachedUserPoliciesResponse(Boto3Model):
    """Contains the response to a successful
    `ListAttachedUserPolicies <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedUserPolicies.html>`_
    request.
    """

    AttachedPolicies: List["AttachedPolicy"] | None = None
    """
    A list of the attached policies.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """


class UploadSSHPublicKeyResponse(Boto3Model):
    """Contains the response to a successful
    `UploadSSHPublicKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadSSHPublicKey.html>`_ request.
    """

    SSHPublicKey: IAMSSHPublicKey | None = None
    """
    Contains information about the SSH public key.
    """


class GetSSHPublicKeyResponse(Boto3Model):
    """Contains the response to a successful
    `GetSSHPublicKey <https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetSSHPublicKey.html>`_ request.
    """

    SSHPublicKey: IAMSSHPublicKey | None = None
    """
    A structure containing details about the SSH public key.
    """


class SSHPublicKeyMetadata(Boto3Model):
    """
    Contains information about an SSH public key, without the key's body or fingerprint.

    This data type is used as a response element in the
    `ListSSHPublicKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListSSHPublicKeys.html>`_
    operation.
    """

    UserName: str
    """
    The name of the IAM user associated with the SSH public key.
    """
    SSHPublicKeyId: str
    """
    The unique identifier for the SSH public key.
    """
    Status: Literal["Active", "Inactive", "Expired"]
    """
    The status of the SSH public key.

    ``Active`` means that the key can be used for authentication with an CodeCommit
    repository. ``Inactive`` means that the key cannot be used.
    """
    UploadDate: datetime
    """
The date and time, in `ISO 8601 date-time format <http://www.iso.org/iso/iso8601>`_, when the SSH public key was uploaded.
    """


class ListSSHPublicKeysResponse(Boto3Model):
    """Contains the response to a successful
    `ListSSHPublicKeys <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListSSHPublicKeys.html>`_ request.
    """

    SSHPublicKeys: List["SSHPublicKeyMetadata"] | None = None
    """
    A list of the SSH public keys assigned to IAM user.
    """
    IsTruncated: bool | None = None
    """
    A flag that indicates whether there are more items to return.

    If your results were truncated, you can make a subsequent
    pagination request using the ``Marker`` request parameter to retrieve more items. Note that IAM might return fewer than
    the ``MaxItems`` number of results even when there are more results available. We recommend that you check
    ``IsTruncated`` after every call to ensure that you receive all your results.
    """
    Marker: str | None = None
    """
    When ``IsTruncated`` is ``true``, this element is present and contains the value to
    use for the ``Marker`` parameter in a subsequent pagination request.
    """
