def main(self, cmd_args): """change what IAM group an IAM user is a part of""" iam_client = aws.iam_client() path_prefix = f"/{consts.NAMESPACE}/" user_name = aws.validate_user_exists(path_prefix, cmd_args.name) group_name = aws.validate_group_exists(path_prefix, cmd_args.group) old_group_names = [old_group['GroupName'] for old_group in iam_client.list_groups_for_user(UserName=user_name)['Groups']] if group_name in old_group_names and len(old_group_names) == 1: halt.err(f"{user_name} is already in the {group_name} IAM group.") if group_name not in old_group_names: iam_client.add_user_to_group( GroupName=group_name, UserName=user_name ) for old_group_name in old_group_names: if old_group_name != group_name: iam_client.remove_user_from_group( GroupName=old_group_name, UserName=user_name ) print("") print(f"{user_name}'s group set to the {group_name} IAM group.")
def _validate_user(config_dict): """validate config's IAM user access key and minimal permissions iam:GetUser, iam:SimulatePrincipalPolicy, iam:GetAccessKeyLastUsed, and ec2:DescribeRegions permissions required for successful validation. Args: config_dict (dict): Should contain config's IAM user access key. 'access_key' (dict): IAM user's access key. Access key ID (str): Secret access key. """ consts.KEY_ID = next(iter(config_dict['access_key'])) consts.KEY_SECRET = config_dict['access_key'][consts.KEY_ID] # IAM User access key must be validated before validate_perms can be used. try: iam_user = aws.iam_client().get_user()['User'] except ClientError as e: # TODO: Use client exceptions instead once they're documented if e.response['Error']['Code'] == "InvalidClientTokenId": halt.err("Access key ID is invalid.") elif e.response['Error']['Code'] == "SignatureDoesNotMatch": halt.err("Access key ID is valid, but its secret is invalid.") elif e.response['Error']['Code'] == "AccessDenied": halt.assert_empty(["iam:GetUser"]) halt.err(str(e)) # This ARN is needed for iam:SimulatePrincipalPolicy action. consts.IAM_ARN = iam_user['Arn'] consts.IAM_NAME = iam_user['UserName'] # Validate IAM user can use iam:SimulatePrincipalPolicy action. try: validate_perms.blocked(actions=["iam:GetUser"]) except ClientError as e: if e.response['Error']['Code'] == "AccessDenied": halt.assert_empty(["iam:SimulatePrincipalPolicy"]) halt.err(str(e)) # Validate IAM user can use other basic permissions needed for the script halt.assert_empty( validate_perms.blocked( actions=["iam:GetAccessKeyLastUsed", "ec2:DescribeRegions"]))
def main(self, cmd_args): """create a new IAM user under an IAM group""" iam_client = aws.iam_client() path_prefix = f"/{consts.NAMESPACE}/" aws.validate_group_exists(path_prefix, cmd_args.group) # IAM user created and added to group (given the name is unique) try: iam_client.create_user(Path=path_prefix, UserName=cmd_args.name) except ClientError as e: if e.response['Error']['Code'] == "EntityAlreadyExists": halt.err(f"IAM user \"{cmd_args.name}\" already exists.") halt.err(str(e)) iam_client.add_user_to_group(GroupName=cmd_args.group, UserName=cmd_args.name) print("") print(f"IAM user \"{cmd_args.name}\" created on AWS.") # IAM user access key generated and saved to dictionary new_key = iam_client.create_access_key( UserName=cmd_args.name)['AccessKey'] new_key = {new_key['AccessKeyId']: new_key['SecretAccessKey']} self._access_key_usable_waiter(new_key) config_dict = os2.parse_json(consts.CONFIG_JSON) if 'backup_keys' not in config_dict: config_dict['backup_keys'] = {} if cmd_args.default: # Modify existing config instead of creating new one config_dict['backup_keys'].update(config_dict['access_key']) config_dict['access_key'] = new_key os2.save_json(config_dict, consts.CONFIG_JSON) print(" User's access key set as default in config.") else: # Back up new IAM user's access key in config file config_dict['backup_keys'].update(new_key) os2.save_json(config_dict, consts.CONFIG_JSON) os2.create_configuration_zip(cmd_args.name, new_key, cmd_args.ssh_key) print(" User's zipped configuration created in config.")
def blocked(actions: List[str], resources: Optional[List[str]] = None, context: Optional[Dict[str, List]] = None) -> List[str]: """test whether IAM user is able to use specified AWS action(s) Args: actions (list): AWS action(s) to validate IAM user can use. resources (list): Check if action(s) can be used on resource(s). If None, action(s) must be usable on all resources ("*"). context (dict): Check if action(s) can be used with context(s). If None, it is expected that no context restrictions were set. Returns: list: Actions denied by IAM due to insufficient permissions. """ if not actions: return [] actions = list(set(actions)) if resources is None: resources = ["*"] _context: List[Dict] = [{}] if context is not None: # Convert context dict to list[dict] expected by ContextEntries. _context = [{ 'ContextKeyName': context_key, 'ContextKeyValues': [str(val) for val in context_values], 'ContextKeyType': "string" } for context_key, context_values in context.items()] results = aws.iam_client().simulate_principal_policy( PolicySourceArn=consts.IAM_ARN, ActionNames=actions, ResourceArns=resources, ContextEntries=_context)['EvaluationResults'] return sorted([ result['EvalActionName'] for result in results if result['EvalDecision'] != "allowed" ])
def main(self, cmd_args): """list IAM groups and their IAM users""" iam_client = aws.iam_client() path_prefix = f"/{consts.NAMESPACE}/" iam_group_names = [iam_group['GroupName'] for iam_group in iam_client.list_groups(PathPrefix=path_prefix)['Groups']] if not iam_group_names: halt.err("No namespace IAM groups found from AWS.", " Have you uploaded the AWS setup?") print("") print(f"{len(iam_group_names)} IAM group(s) found from AWS:") for group_name in iam_group_names: group_users = iam_client.get_group(GroupName=group_name)['Users'] if group_users: print(f"{group_name}: {len(group_users)} user(s) in group:") for group_user in group_users: print(f" {group_user['UserName']}") else: print(f"{group_name}: 0 users in group.")
def __init__(self, config_aws_setup): self._iam_client = aws.iam_client() self._path_prefix = f"/{consts.NAMESPACE}/" # Local IAM group setup information (names and attached policies) self._iam_group_setup = config_aws_setup['IAM']['Groups']
def __init__(self, cmd_args): self._iam_client = aws.iam_client()
def __init__(self, config_aws_setup): self._iam_client = aws.iam_client() self._policy_dir = consts.AWS_SETUP_DIR / "iam_policies" self._path_prefix = f"/{consts.NAMESPACE}/" # Local IAM policy setup information (names and descriptions) self._iam_policy_setup = config_aws_setup['IAM']['Policies']