1#!/usr/local/bin/python3.8 2# This file is part of Ansible 3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 5from __future__ import (absolute_import, division, print_function) 6__metaclass__ = type 7 8 9DOCUMENTATION = ''' 10--- 11module: iam_policy_info 12version_added: 1.0.0 13short_description: Retrieve inline IAM policies for users, groups, and roles 14description: 15 - Supports fetching of inline IAM policies for IAM users, groups and roles. 16options: 17 iam_type: 18 description: 19 - Type of IAM resource you wish to retrieve inline policies for. 20 required: yes 21 choices: [ "user", "group", "role"] 22 type: str 23 iam_name: 24 description: 25 - Name of IAM resource you wish to retrieve inline policies for. In other words, the user name, group name or role name. 26 required: yes 27 type: str 28 policy_name: 29 description: 30 - Name of a specific IAM inline policy you with to retrieve. 31 required: no 32 type: str 33 34author: 35 - Mark Chappell (@tremble) 36 37extends_documentation_fragment: 38- amazon.aws.aws 39- amazon.aws.ec2 40 41''' 42 43EXAMPLES = ''' 44- name: Describe all inline IAM policies on an IAM User 45 community.aws.iam_policy_info: 46 iam_type: user 47 iam_name: example_user 48 49- name: Describe a specific inline policy on an IAM Role 50 community.aws.iam_policy_info: 51 iam_type: role 52 iam_name: example_role 53 policy_name: example_policy 54 55''' 56RETURN = ''' 57policies: 58 description: A list containing the matching IAM inline policy names and their data 59 returned: success 60 type: complex 61 contains: 62 policy_name: 63 description: The Name of the inline policy 64 returned: success 65 type: str 66 policy_document: 67 description: The JSON document representing the inline IAM policy 68 returned: success 69 type: list 70policy_names: 71 description: A list of matching names of the IAM inline policies on the queried object 72 returned: success 73 type: list 74all_policy_names: 75 description: A list of names of all of the IAM inline policies on the queried object 76 returned: success 77 type: list 78''' 79 80try: 81 import botocore 82except ImportError: 83 pass 84 85from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule 86from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code 87from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry 88 89 90class Policy: 91 92 def __init__(self, client, name, policy_name): 93 self.client = client 94 self.name = name 95 self.policy_name = policy_name 96 self.changed = False 97 98 @staticmethod 99 def _iam_type(): 100 return '' 101 102 def _list(self, name): 103 return {} 104 105 def list(self): 106 return self._list(self.name).get('PolicyNames', []) 107 108 def _get(self, name, policy_name): 109 return '{}' 110 111 def get(self, policy_name): 112 return self._get(self.name, policy_name)['PolicyDocument'] 113 114 def get_all(self): 115 policies = list() 116 for policy in self.list(): 117 policies.append({"policy_name": policy, "policy_document": self.get(policy)}) 118 return policies 119 120 def run(self): 121 policy_list = self.list() 122 ret_val = { 123 'changed': False, 124 self._iam_type() + '_name': self.name, 125 'all_policy_names': policy_list 126 } 127 if self.policy_name is None: 128 ret_val.update(policies=self.get_all()) 129 ret_val.update(policy_names=policy_list) 130 elif self.policy_name in policy_list: 131 ret_val.update(policies=[{ 132 "policy_name": self.policy_name, 133 "policy_document": self.get(self.policy_name)}]) 134 ret_val.update(policy_names=[self.policy_name]) 135 return ret_val 136 137 138class UserPolicy(Policy): 139 140 @staticmethod 141 def _iam_type(): 142 return 'user' 143 144 def _list(self, name): 145 return self.client.list_user_policies(aws_retry=True, UserName=name) 146 147 def _get(self, name, policy_name): 148 return self.client.get_user_policy(aws_retry=True, UserName=name, PolicyName=policy_name) 149 150 151class RolePolicy(Policy): 152 153 @staticmethod 154 def _iam_type(): 155 return 'role' 156 157 def _list(self, name): 158 return self.client.list_role_policies(aws_retry=True, RoleName=name) 159 160 def _get(self, name, policy_name): 161 return self.client.get_role_policy(aws_retry=True, RoleName=name, PolicyName=policy_name) 162 163 164class GroupPolicy(Policy): 165 166 @staticmethod 167 def _iam_type(): 168 return 'group' 169 170 def _list(self, name): 171 return self.client.list_group_policies(aws_retry=True, GroupName=name) 172 173 def _get(self, name, policy_name): 174 return self.client.get_group_policy(aws_retry=True, GroupName=name, PolicyName=policy_name) 175 176 177def main(): 178 argument_spec = dict( 179 iam_type=dict(required=True, choices=['user', 'group', 'role']), 180 iam_name=dict(required=True), 181 policy_name=dict(default=None, required=False), 182 ) 183 184 module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) 185 186 args = dict( 187 client=module.client('iam', retry_decorator=AWSRetry.jittered_backoff()), 188 name=module.params.get('iam_name'), 189 policy_name=module.params.get('policy_name'), 190 ) 191 iam_type = module.params.get('iam_type') 192 193 try: 194 if iam_type == 'user': 195 policy = UserPolicy(**args) 196 elif iam_type == 'role': 197 policy = RolePolicy(**args) 198 elif iam_type == 'group': 199 policy = GroupPolicy(**args) 200 201 module.exit_json(**(policy.run())) 202 except is_boto3_error_code('NoSuchEntity') as e: 203 module.exit_json(changed=False, msg=e.response['Error']['Message']) 204 except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except 205 module.fail_json_aws(e) 206 207 208if __name__ == '__main__': 209 main() 210