Server IP : 85.214.239.14 / Your IP : 3.149.24.49 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /lib/python3/dist-packages/ansible_collections/community/aws/plugins/modules/ |
Upload File : |
#!/usr/bin/python # -*- coding: utf-8 -*- # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see <http://www.gnu.org/licenses/>. from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = ''' --- module: iam_saml_federation version_added: 1.0.0 short_description: Maintain IAM SAML federation configuration. description: - Provides a mechanism to manage AWS IAM SAML Identity Federation providers (create/update/delete metadata). options: name: description: - The name of the provider to create. required: true type: str saml_metadata_document: description: - The XML document generated by an identity provider (IdP) that supports SAML 2.0. type: str state: description: - Whether to create or delete identity provider. If 'present' is specified it will attempt to update the identity provider matching the name field. default: present choices: [ "present", "absent" ] type: str extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 - amazon.aws.boto3 author: - Tony (@axc450) - Aidan Rowe (@aidan-) ''' EXAMPLES = ''' # Note: These examples do not set authentication details, see the AWS Guide for details. # It is assumed that their matching environment variables are set. # Creates a new iam saml identity provider if not present - name: saml provider community.aws.iam_saml_federation: name: example1 # the > below opens an indented block, so no escaping/quoting is needed when in the indentation level under this key saml_metadata_document: > <?xml version="1.0"?>... <md:EntityDescriptor # Creates a new iam saml identity provider if not present - name: saml provider community.aws.iam_saml_federation: name: example2 saml_metadata_document: "{{ item }}" with_file: /path/to/idp/metdata.xml # Removes iam saml identity provider - name: remove saml provider community.aws.iam_saml_federation: name: example3 state: absent ''' RETURN = ''' saml_provider: description: Details of the SAML Identity Provider that was created/modified. type: complex returned: present contains: arn: description: The ARN of the identity provider. type: str returned: present sample: "arn:aws:iam::123456789012:saml-provider/my_saml_provider" metadata_document: description: The XML metadata document that includes information about an identity provider. type: str returned: present create_date: description: The date and time when the SAML provider was created in ISO 8601 date-time format. type: str returned: present sample: "2017-02-08T04:36:28+00:00" expire_date: description: The expiration date and time for the SAML provider in ISO 8601 date-time format. type: str returned: present sample: "2017-02-08T04:36:28+00:00" ''' try: import botocore.exceptions except ImportError: pass from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry class SAMLProviderManager: """Handles SAML Identity Provider configuration""" def __init__(self, module): self.module = module try: self.conn = module.client('iam') except botocore.exceptions.ClientError as e: self.module.fail_json_aws(e, msg="Unknown AWS SDK error") # use retry decorator for boto3 calls @AWSRetry.jittered_backoff(retries=3, delay=5) def _list_saml_providers(self): return self.conn.list_saml_providers() @AWSRetry.jittered_backoff(retries=3, delay=5) def _get_saml_provider(self, arn): return self.conn.get_saml_provider(SAMLProviderArn=arn) @AWSRetry.jittered_backoff(retries=3, delay=5) def _update_saml_provider(self, arn, metadata): return self.conn.update_saml_provider(SAMLProviderArn=arn, SAMLMetadataDocument=metadata) @AWSRetry.jittered_backoff(retries=3, delay=5) def _create_saml_provider(self, metadata, name): return self.conn.create_saml_provider(SAMLMetadataDocument=metadata, Name=name) @AWSRetry.jittered_backoff(retries=3, delay=5) def _delete_saml_provider(self, arn): return self.conn.delete_saml_provider(SAMLProviderArn=arn) def _get_provider_arn(self, name): providers = self._list_saml_providers() for p in providers['SAMLProviderList']: provider_name = p['Arn'].split('/', 1)[1] if name == provider_name: return p['Arn'] return None def create_or_update_saml_provider(self, name, metadata): if not metadata: self.module.fail_json(msg="saml_metadata_document must be defined for present state") res = {'changed': False} try: arn = self._get_provider_arn(name) except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as e: self.module.fail_json_aws(e, msg="Could not get the ARN of the identity provider '{0}'".format(name)) if arn: # see if metadata needs updating try: resp = self._get_saml_provider(arn) except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as e: self.module.fail_json_aws(e, msg="Could not retrieve the identity provider '{0}'".format(name)) if metadata.strip() != resp['SAMLMetadataDocument'].strip(): # provider needs updating res['changed'] = True if not self.module.check_mode: try: resp = self._update_saml_provider(arn, metadata) res['saml_provider'] = self._build_res(resp['SAMLProviderArn']) except botocore.exceptions.ClientError as e: self.module.fail_json_aws(e, msg="Could not update the identity provider '{0}'".format(name)) else: res['saml_provider'] = self._build_res(arn) else: # create res['changed'] = True if not self.module.check_mode: try: resp = self._create_saml_provider(metadata, name) res['saml_provider'] = self._build_res(resp['SAMLProviderArn']) except botocore.exceptions.ClientError as e: self.module.fail_json_aws(e, msg="Could not create the identity provider '{0}'".format(name)) self.module.exit_json(**res) def delete_saml_provider(self, name): res = {'changed': False} try: arn = self._get_provider_arn(name) except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as e: self.module.fail_json_aws(e, msg="Could not get the ARN of the identity provider '{0}'".format(name)) if arn: # delete res['changed'] = True if not self.module.check_mode: try: self._delete_saml_provider(arn) except botocore.exceptions.ClientError as e: self.module.fail_json_aws(e, msg="Could not delete the identity provider '{0}'".format(name)) self.module.exit_json(**res) def _build_res(self, arn): saml_provider = self._get_saml_provider(arn) return { "arn": arn, "metadata_document": saml_provider["SAMLMetadataDocument"], "create_date": saml_provider["CreateDate"].isoformat(), "expire_date": saml_provider["ValidUntil"].isoformat() } def main(): argument_spec = dict( name=dict(required=True), saml_metadata_document=dict(default=None, required=False), state=dict(default='present', required=False, choices=['present', 'absent']), ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[('state', 'present', ['saml_metadata_document'])] ) name = module.params['name'] state = module.params.get('state') saml_metadata_document = module.params.get('saml_metadata_document') sp_man = SAMLProviderManager(module) if state == 'present': sp_man.create_or_update_saml_provider(name, saml_metadata_document) elif state == 'absent': sp_man.delete_saml_provider(name) if __name__ == '__main__': main()