mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-26 21:59:38 -07:00 
			
		
		
		
	Use semantic markup (modules k-l) (#6678)
* Use semantic markup.
* Use option instead of alias.
(cherry picked from commit c694abbdf9)
Co-authored-by: Felix Fontein <felix@fontein.de>
		
	
			
		
			
				
	
	
		
			826 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			826 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| # Copyright (c) 2017, Eike Frost <ei@kefro.st>
 | |
| # Copyright (c) 2021, Christophe Gilles <christophe.gilles54@gmail.com>
 | |
| # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| from __future__ import absolute_import, division, print_function
 | |
| __metaclass__ = type
 | |
| 
 | |
| DOCUMENTATION = '''
 | |
| ---
 | |
| module: keycloak_realm
 | |
| 
 | |
| short_description: Allows administration of Keycloak realm via Keycloak API
 | |
| 
 | |
| version_added: 3.0.0
 | |
| 
 | |
| description:
 | |
|     - This module allows the administration of Keycloak realm via the Keycloak REST API. It
 | |
|       requires access to the REST API via OpenID Connect; the user connecting and the realm being
 | |
|       used must have the requisite access rights. In a default Keycloak installation, admin-cli
 | |
|       and an admin user would work, as would a separate realm definition with the scope tailored
 | |
|       to your needs and a user having the expected roles.
 | |
| 
 | |
|     - The names of module options are snake_cased versions of the camelCase ones found in the
 | |
|       Keycloak API and its documentation at U(https://www.keycloak.org/docs-api/8.0/rest-api/index.html).
 | |
|       Aliases are provided so camelCased versions can be used as well.
 | |
| 
 | |
|     - The Keycloak API does not always sanity check inputs e.g. you can set
 | |
|       SAML-specific settings on an OpenID Connect client for instance and vice versa. Be careful.
 | |
|       If you do not specify a setting, usually a sensible default is chosen.
 | |
| 
 | |
| attributes:
 | |
|     check_mode:
 | |
|         support: full
 | |
|     diff_mode:
 | |
|         support: full
 | |
| 
 | |
| options:
 | |
|     state:
 | |
|         description:
 | |
|             - State of the realm.
 | |
|             - On V(present), the realm will be created (or updated if it exists already).
 | |
|             - On V(absent), the realm will be removed if it exists.
 | |
|         choices: ['present', 'absent']
 | |
|         default: 'present'
 | |
|         type: str
 | |
| 
 | |
|     id:
 | |
|         description:
 | |
|             - The realm to create.
 | |
|         type: str
 | |
|     realm:
 | |
|         description:
 | |
|             - The realm name.
 | |
|         type: str
 | |
|     access_code_lifespan:
 | |
|         description:
 | |
|             - The realm access code lifespan.
 | |
|         aliases:
 | |
|             - accessCodeLifespan
 | |
|         type: int
 | |
|     access_code_lifespan_login:
 | |
|         description:
 | |
|             - The realm access code lifespan login.
 | |
|         aliases:
 | |
|             - accessCodeLifespanLogin
 | |
|         type: int
 | |
|     access_code_lifespan_user_action:
 | |
|         description:
 | |
|             - The realm access code lifespan user action.
 | |
|         aliases:
 | |
|             - accessCodeLifespanUserAction
 | |
|         type: int
 | |
|     access_token_lifespan:
 | |
|         description:
 | |
|             - The realm access token lifespan.
 | |
|         aliases:
 | |
|             - accessTokenLifespan
 | |
|         type: int
 | |
|     access_token_lifespan_for_implicit_flow:
 | |
|         description:
 | |
|             - The realm access token lifespan for implicit flow.
 | |
|         aliases:
 | |
|             - accessTokenLifespanForImplicitFlow
 | |
|         type: int
 | |
|     account_theme:
 | |
|         description:
 | |
|             - The realm account theme.
 | |
|         aliases:
 | |
|             - accountTheme
 | |
|         type: str
 | |
|     action_token_generated_by_admin_lifespan:
 | |
|         description:
 | |
|             - The realm action token generated by admin lifespan.
 | |
|         aliases:
 | |
|             - actionTokenGeneratedByAdminLifespan
 | |
|         type: int
 | |
|     action_token_generated_by_user_lifespan:
 | |
|         description:
 | |
|             - The realm action token generated by user lifespan.
 | |
|         aliases:
 | |
|             - actionTokenGeneratedByUserLifespan
 | |
|         type: int
 | |
|     admin_events_details_enabled:
 | |
|         description:
 | |
|             - The realm admin events details enabled.
 | |
|         aliases:
 | |
|             - adminEventsDetailsEnabled
 | |
|         type: bool
 | |
|     admin_events_enabled:
 | |
|         description:
 | |
|             - The realm admin events enabled.
 | |
|         aliases:
 | |
|             - adminEventsEnabled
 | |
|         type: bool
 | |
|     admin_theme:
 | |
|         description:
 | |
|             - The realm admin theme.
 | |
|         aliases:
 | |
|             - adminTheme
 | |
|         type: str
 | |
|     attributes:
 | |
|         description:
 | |
|             - The realm attributes.
 | |
|         type: dict
 | |
|     browser_flow:
 | |
|         description:
 | |
|             - The realm browser flow.
 | |
|         aliases:
 | |
|             - browserFlow
 | |
|         type: str
 | |
|     browser_security_headers:
 | |
|         description:
 | |
|             - The realm browser security headers.
 | |
|         aliases:
 | |
|             - browserSecurityHeaders
 | |
|         type: dict
 | |
|     brute_force_protected:
 | |
|         description:
 | |
|             - The realm brute force protected.
 | |
|         aliases:
 | |
|             - bruteForceProtected
 | |
|         type: bool
 | |
|     client_authentication_flow:
 | |
|         description:
 | |
|             - The realm client authentication flow.
 | |
|         aliases:
 | |
|             - clientAuthenticationFlow
 | |
|         type: str
 | |
|     client_scope_mappings:
 | |
|         description:
 | |
|             - The realm client scope mappings.
 | |
|         aliases:
 | |
|             - clientScopeMappings
 | |
|         type: dict
 | |
|     default_default_client_scopes:
 | |
|         description:
 | |
|             - The realm default default client scopes.
 | |
|         aliases:
 | |
|             - defaultDefaultClientScopes
 | |
|         type: list
 | |
|         elements: str
 | |
|     default_groups:
 | |
|         description:
 | |
|             - The realm default groups.
 | |
|         aliases:
 | |
|             - defaultGroups
 | |
|         type: list
 | |
|         elements: str
 | |
|     default_locale:
 | |
|         description:
 | |
|             - The realm default locale.
 | |
|         aliases:
 | |
|             - defaultLocale
 | |
|         type: str
 | |
|     default_optional_client_scopes:
 | |
|         description:
 | |
|             - The realm default optional client scopes.
 | |
|         aliases:
 | |
|             - defaultOptionalClientScopes
 | |
|         type: list
 | |
|         elements: str
 | |
|     default_roles:
 | |
|         description:
 | |
|             - The realm default roles.
 | |
|         aliases:
 | |
|             - defaultRoles
 | |
|         type: list
 | |
|         elements: str
 | |
|     default_signature_algorithm:
 | |
|         description:
 | |
|             - The realm default signature algorithm.
 | |
|         aliases:
 | |
|             - defaultSignatureAlgorithm
 | |
|         type: str
 | |
|     direct_grant_flow:
 | |
|         description:
 | |
|             - The realm direct grant flow.
 | |
|         aliases:
 | |
|             - directGrantFlow
 | |
|         type: str
 | |
|     display_name:
 | |
|         description:
 | |
|             - The realm display name.
 | |
|         aliases:
 | |
|             - displayName
 | |
|         type: str
 | |
|     display_name_html:
 | |
|         description:
 | |
|             - The realm display name HTML.
 | |
|         aliases:
 | |
|             - displayNameHtml
 | |
|         type: str
 | |
|     docker_authentication_flow:
 | |
|         description:
 | |
|             - The realm docker authentication flow.
 | |
|         aliases:
 | |
|             - dockerAuthenticationFlow
 | |
|         type: str
 | |
|     duplicate_emails_allowed:
 | |
|         description:
 | |
|             - The realm duplicate emails allowed option.
 | |
|         aliases:
 | |
|             - duplicateEmailsAllowed
 | |
|         type: bool
 | |
|     edit_username_allowed:
 | |
|         description:
 | |
|             - The realm edit username allowed option.
 | |
|         aliases:
 | |
|             - editUsernameAllowed
 | |
|         type: bool
 | |
|     email_theme:
 | |
|         description:
 | |
|             - The realm email theme.
 | |
|         aliases:
 | |
|             - emailTheme
 | |
|         type: str
 | |
|     enabled:
 | |
|         description:
 | |
|             - The realm enabled option.
 | |
|         type: bool
 | |
|     enabled_event_types:
 | |
|         description:
 | |
|             - The realm enabled event types.
 | |
|         aliases:
 | |
|             - enabledEventTypes
 | |
|         type: list
 | |
|         elements: str
 | |
|     events_enabled:
 | |
|         description:
 | |
|             - Enables or disables login events for this realm.
 | |
|         aliases:
 | |
|             - eventsEnabled
 | |
|         type: bool
 | |
|         version_added: 3.6.0
 | |
|     events_expiration:
 | |
|         description:
 | |
|             - The realm events expiration.
 | |
|         aliases:
 | |
|             - eventsExpiration
 | |
|         type: int
 | |
|     events_listeners:
 | |
|         description:
 | |
|             - The realm events listeners.
 | |
|         aliases:
 | |
|             - eventsListeners
 | |
|         type: list
 | |
|         elements: str
 | |
|     failure_factor:
 | |
|         description:
 | |
|             - The realm failure factor.
 | |
|         aliases:
 | |
|             - failureFactor
 | |
|         type: int
 | |
|     internationalization_enabled:
 | |
|         description:
 | |
|             - The realm internationalization enabled option.
 | |
|         aliases:
 | |
|             - internationalizationEnabled
 | |
|         type: bool
 | |
|     login_theme:
 | |
|         description:
 | |
|             - The realm login theme.
 | |
|         aliases:
 | |
|             - loginTheme
 | |
|         type: str
 | |
|     login_with_email_allowed:
 | |
|         description:
 | |
|             - The realm login with email allowed option.
 | |
|         aliases:
 | |
|             - loginWithEmailAllowed
 | |
|         type: bool
 | |
|     max_delta_time_seconds:
 | |
|         description:
 | |
|             - The realm max delta time in seconds.
 | |
|         aliases:
 | |
|             - maxDeltaTimeSeconds
 | |
|         type: int
 | |
|     max_failure_wait_seconds:
 | |
|         description:
 | |
|             - The realm max failure wait in seconds.
 | |
|         aliases:
 | |
|             - maxFailureWaitSeconds
 | |
|         type: int
 | |
|     minimum_quick_login_wait_seconds:
 | |
|         description:
 | |
|             - The realm minimum quick login wait in seconds.
 | |
|         aliases:
 | |
|             - minimumQuickLoginWaitSeconds
 | |
|         type: int
 | |
|     not_before:
 | |
|         description:
 | |
|             - The realm not before.
 | |
|         aliases:
 | |
|             - notBefore
 | |
|         type: int
 | |
|     offline_session_idle_timeout:
 | |
|         description:
 | |
|             - The realm offline session idle timeout.
 | |
|         aliases:
 | |
|             - offlineSessionIdleTimeout
 | |
|         type: int
 | |
|     offline_session_max_lifespan:
 | |
|         description:
 | |
|             - The realm offline session max lifespan.
 | |
|         aliases:
 | |
|             - offlineSessionMaxLifespan
 | |
|         type: int
 | |
|     offline_session_max_lifespan_enabled:
 | |
|         description:
 | |
|             - The realm offline session max lifespan enabled option.
 | |
|         aliases:
 | |
|             - offlineSessionMaxLifespanEnabled
 | |
|         type: bool
 | |
|     otp_policy_algorithm:
 | |
|         description:
 | |
|             - The realm otp policy algorithm.
 | |
|         aliases:
 | |
|             - otpPolicyAlgorithm
 | |
|         type: str
 | |
|     otp_policy_digits:
 | |
|         description:
 | |
|             - The realm otp policy digits.
 | |
|         aliases:
 | |
|             - otpPolicyDigits
 | |
|         type: int
 | |
|     otp_policy_initial_counter:
 | |
|         description:
 | |
|             - The realm otp policy initial counter.
 | |
|         aliases:
 | |
|             - otpPolicyInitialCounter
 | |
|         type: int
 | |
|     otp_policy_look_ahead_window:
 | |
|         description:
 | |
|             - The realm otp policy look ahead window.
 | |
|         aliases:
 | |
|             - otpPolicyLookAheadWindow
 | |
|         type: int
 | |
|     otp_policy_period:
 | |
|         description:
 | |
|             - The realm otp policy period.
 | |
|         aliases:
 | |
|             - otpPolicyPeriod
 | |
|         type: int
 | |
|     otp_policy_type:
 | |
|         description:
 | |
|             - The realm otp policy type.
 | |
|         aliases:
 | |
|             - otpPolicyType
 | |
|         type: str
 | |
|     otp_supported_applications:
 | |
|         description:
 | |
|             - The realm otp supported applications.
 | |
|         aliases:
 | |
|             - otpSupportedApplications
 | |
|         type: list
 | |
|         elements: str
 | |
|     password_policy:
 | |
|         description:
 | |
|             - The realm password policy.
 | |
|         aliases:
 | |
|             - passwordPolicy
 | |
|         type: str
 | |
|     permanent_lockout:
 | |
|         description:
 | |
|             - The realm permanent lockout.
 | |
|         aliases:
 | |
|             - permanentLockout
 | |
|         type: bool
 | |
|     quick_login_check_milli_seconds:
 | |
|         description:
 | |
|             - The realm quick login check in milliseconds.
 | |
|         aliases:
 | |
|             - quickLoginCheckMilliSeconds
 | |
|         type: int
 | |
|     refresh_token_max_reuse:
 | |
|         description:
 | |
|             - The realm refresh token max reuse.
 | |
|         aliases:
 | |
|             - refreshTokenMaxReuse
 | |
|         type: int
 | |
|     registration_allowed:
 | |
|         description:
 | |
|             - The realm registration allowed option.
 | |
|         aliases:
 | |
|             - registrationAllowed
 | |
|         type: bool
 | |
|     registration_email_as_username:
 | |
|         description:
 | |
|             - The realm registration email as username option.
 | |
|         aliases:
 | |
|             - registrationEmailAsUsername
 | |
|         type: bool
 | |
|     registration_flow:
 | |
|         description:
 | |
|             - The realm registration flow.
 | |
|         aliases:
 | |
|             - registrationFlow
 | |
|         type: str
 | |
|     remember_me:
 | |
|         description:
 | |
|             - The realm remember me option.
 | |
|         aliases:
 | |
|             - rememberMe
 | |
|         type: bool
 | |
|     reset_credentials_flow:
 | |
|         description:
 | |
|             - The realm reset credentials flow.
 | |
|         aliases:
 | |
|             - resetCredentialsFlow
 | |
|         type: str
 | |
|     reset_password_allowed:
 | |
|         description:
 | |
|             - The realm reset password allowed option.
 | |
|         aliases:
 | |
|             - resetPasswordAllowed
 | |
|         type: bool
 | |
|     revoke_refresh_token:
 | |
|         description:
 | |
|             - The realm revoke refresh token option.
 | |
|         aliases:
 | |
|             - revokeRefreshToken
 | |
|         type: bool
 | |
|     smtp_server:
 | |
|         description:
 | |
|             - The realm smtp server.
 | |
|         aliases:
 | |
|             - smtpServer
 | |
|         type: dict
 | |
|     ssl_required:
 | |
|         description:
 | |
|             - The realm ssl required option.
 | |
|         choices: ['all', 'external', 'none']
 | |
|         aliases:
 | |
|             - sslRequired
 | |
|         type: str
 | |
|     sso_session_idle_timeout:
 | |
|         description:
 | |
|             - The realm sso session idle timeout.
 | |
|         aliases:
 | |
|             - ssoSessionIdleTimeout
 | |
|         type: int
 | |
|     sso_session_idle_timeout_remember_me:
 | |
|         description:
 | |
|             - The realm sso session idle timeout remember me.
 | |
|         aliases:
 | |
|             - ssoSessionIdleTimeoutRememberMe
 | |
|         type: int
 | |
|     sso_session_max_lifespan:
 | |
|         description:
 | |
|             - The realm sso session max lifespan.
 | |
|         aliases:
 | |
|             - ssoSessionMaxLifespan
 | |
|         type: int
 | |
|     sso_session_max_lifespan_remember_me:
 | |
|         description:
 | |
|             - The realm sso session max lifespan remember me.
 | |
|         aliases:
 | |
|             - ssoSessionMaxLifespanRememberMe
 | |
|         type: int
 | |
|     supported_locales:
 | |
|         description:
 | |
|             - The realm supported locales.
 | |
|         aliases:
 | |
|             - supportedLocales
 | |
|         type: list
 | |
|         elements: str
 | |
|     user_managed_access_allowed:
 | |
|         description:
 | |
|             - The realm user managed access allowed option.
 | |
|         aliases:
 | |
|             - userManagedAccessAllowed
 | |
|         type: bool
 | |
|     verify_email:
 | |
|         description:
 | |
|             - The realm verify email option.
 | |
|         aliases:
 | |
|             - verifyEmail
 | |
|         type: bool
 | |
|     wait_increment_seconds:
 | |
|         description:
 | |
|             - The realm wait increment in seconds.
 | |
|         aliases:
 | |
|             - waitIncrementSeconds
 | |
|         type: int
 | |
| 
 | |
| extends_documentation_fragment:
 | |
|     - community.general.keycloak
 | |
|     - community.general.attributes
 | |
| 
 | |
| author:
 | |
|     - Christophe Gilles (@kris2kris)
 | |
| '''
 | |
| 
 | |
| EXAMPLES = '''
 | |
| - name: Create or update Keycloak realm (minimal example)
 | |
|   community.general.keycloak_realm:
 | |
|     auth_client_id: admin-cli
 | |
|     auth_keycloak_url: https://auth.example.com/auth
 | |
|     auth_realm: master
 | |
|     auth_username: USERNAME
 | |
|     auth_password: PASSWORD
 | |
|     id: realm
 | |
|     realm: realm
 | |
|     state: present
 | |
| 
 | |
| - name: Delete a Keycloak realm
 | |
|   community.general.keycloak_realm:
 | |
|     auth_client_id: admin-cli
 | |
|     auth_keycloak_url: https://auth.example.com/auth
 | |
|     auth_realm: master
 | |
|     auth_username: USERNAME
 | |
|     auth_password: PASSWORD
 | |
|     id: test
 | |
|     state: absent
 | |
| 
 | |
| '''
 | |
| 
 | |
| RETURN = '''
 | |
| msg:
 | |
|     description: Message as to what action was taken.
 | |
|     returned: always
 | |
|     type: str
 | |
|     sample: "Realm testrealm has been updated"
 | |
| 
 | |
| proposed:
 | |
|     description: Representation of proposed realm.
 | |
|     returned: always
 | |
|     type: dict
 | |
|     sample: {
 | |
|       id: "test"
 | |
|     }
 | |
| 
 | |
| existing:
 | |
|     description: Representation of existing realm (sample is truncated).
 | |
|     returned: always
 | |
|     type: dict
 | |
|     sample: {
 | |
|         "adminUrl": "http://www.example.com/admin_url",
 | |
|         "attributes": {
 | |
|             "request.object.signature.alg": "RS256",
 | |
|         }
 | |
|     }
 | |
| 
 | |
| end_state:
 | |
|     description: Representation of realm after module execution (sample is truncated).
 | |
|     returned: on success
 | |
|     type: dict
 | |
|     sample: {
 | |
|         "adminUrl": "http://www.example.com/admin_url",
 | |
|         "attributes": {
 | |
|             "request.object.signature.alg": "RS256",
 | |
|         }
 | |
|     }
 | |
| '''
 | |
| 
 | |
| from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
 | |
|     keycloak_argument_spec, get_token, KeycloakError
 | |
| from ansible.module_utils.basic import AnsibleModule
 | |
| 
 | |
| 
 | |
| def sanitize_cr(realmrep):
 | |
|     """ Removes probably sensitive details from a realm representation.
 | |
| 
 | |
|     :param realmrep: the realmrep dict to be sanitized
 | |
|     :return: sanitized realmrep dict
 | |
|     """
 | |
|     result = realmrep.copy()
 | |
|     if 'secret' in result:
 | |
|         result['secret'] = '********'
 | |
|     if 'attributes' in result:
 | |
|         if 'saml.signing.private.key' in result['attributes']:
 | |
|             result['attributes'] = result['attributes'].copy()
 | |
|             result['attributes']['saml.signing.private.key'] = '********'
 | |
|     return result
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     """
 | |
|     Module execution
 | |
| 
 | |
|     :return:
 | |
|     """
 | |
|     argument_spec = keycloak_argument_spec()
 | |
| 
 | |
|     meta_args = dict(
 | |
|         state=dict(default='present', choices=['present', 'absent']),
 | |
| 
 | |
|         id=dict(type='str'),
 | |
|         realm=dict(type='str'),
 | |
|         access_code_lifespan=dict(type='int', aliases=['accessCodeLifespan']),
 | |
|         access_code_lifespan_login=dict(type='int', aliases=['accessCodeLifespanLogin']),
 | |
|         access_code_lifespan_user_action=dict(type='int', aliases=['accessCodeLifespanUserAction']),
 | |
|         access_token_lifespan=dict(type='int', aliases=['accessTokenLifespan'], no_log=False),
 | |
|         access_token_lifespan_for_implicit_flow=dict(type='int', aliases=['accessTokenLifespanForImplicitFlow'], no_log=False),
 | |
|         account_theme=dict(type='str', aliases=['accountTheme']),
 | |
|         action_token_generated_by_admin_lifespan=dict(type='int', aliases=['actionTokenGeneratedByAdminLifespan'], no_log=False),
 | |
|         action_token_generated_by_user_lifespan=dict(type='int', aliases=['actionTokenGeneratedByUserLifespan'], no_log=False),
 | |
|         admin_events_details_enabled=dict(type='bool', aliases=['adminEventsDetailsEnabled']),
 | |
|         admin_events_enabled=dict(type='bool', aliases=['adminEventsEnabled']),
 | |
|         admin_theme=dict(type='str', aliases=['adminTheme']),
 | |
|         attributes=dict(type='dict'),
 | |
|         browser_flow=dict(type='str', aliases=['browserFlow']),
 | |
|         browser_security_headers=dict(type='dict', aliases=['browserSecurityHeaders']),
 | |
|         brute_force_protected=dict(type='bool', aliases=['bruteForceProtected']),
 | |
|         client_authentication_flow=dict(type='str', aliases=['clientAuthenticationFlow']),
 | |
|         client_scope_mappings=dict(type='dict', aliases=['clientScopeMappings']),
 | |
|         default_default_client_scopes=dict(type='list', elements='str', aliases=['defaultDefaultClientScopes']),
 | |
|         default_groups=dict(type='list', elements='str', aliases=['defaultGroups']),
 | |
|         default_locale=dict(type='str', aliases=['defaultLocale']),
 | |
|         default_optional_client_scopes=dict(type='list', elements='str', aliases=['defaultOptionalClientScopes']),
 | |
|         default_roles=dict(type='list', elements='str', aliases=['defaultRoles']),
 | |
|         default_signature_algorithm=dict(type='str', aliases=['defaultSignatureAlgorithm']),
 | |
|         direct_grant_flow=dict(type='str', aliases=['directGrantFlow']),
 | |
|         display_name=dict(type='str', aliases=['displayName']),
 | |
|         display_name_html=dict(type='str', aliases=['displayNameHtml']),
 | |
|         docker_authentication_flow=dict(type='str', aliases=['dockerAuthenticationFlow']),
 | |
|         duplicate_emails_allowed=dict(type='bool', aliases=['duplicateEmailsAllowed']),
 | |
|         edit_username_allowed=dict(type='bool', aliases=['editUsernameAllowed']),
 | |
|         email_theme=dict(type='str', aliases=['emailTheme']),
 | |
|         enabled=dict(type='bool'),
 | |
|         enabled_event_types=dict(type='list', elements='str', aliases=['enabledEventTypes']),
 | |
|         events_enabled=dict(type='bool', aliases=['eventsEnabled']),
 | |
|         events_expiration=dict(type='int', aliases=['eventsExpiration']),
 | |
|         events_listeners=dict(type='list', elements='str', aliases=['eventsListeners']),
 | |
|         failure_factor=dict(type='int', aliases=['failureFactor']),
 | |
|         internationalization_enabled=dict(type='bool', aliases=['internationalizationEnabled']),
 | |
|         login_theme=dict(type='str', aliases=['loginTheme']),
 | |
|         login_with_email_allowed=dict(type='bool', aliases=['loginWithEmailAllowed']),
 | |
|         max_delta_time_seconds=dict(type='int', aliases=['maxDeltaTimeSeconds']),
 | |
|         max_failure_wait_seconds=dict(type='int', aliases=['maxFailureWaitSeconds']),
 | |
|         minimum_quick_login_wait_seconds=dict(type='int', aliases=['minimumQuickLoginWaitSeconds']),
 | |
|         not_before=dict(type='int', aliases=['notBefore']),
 | |
|         offline_session_idle_timeout=dict(type='int', aliases=['offlineSessionIdleTimeout']),
 | |
|         offline_session_max_lifespan=dict(type='int', aliases=['offlineSessionMaxLifespan']),
 | |
|         offline_session_max_lifespan_enabled=dict(type='bool', aliases=['offlineSessionMaxLifespanEnabled']),
 | |
|         otp_policy_algorithm=dict(type='str', aliases=['otpPolicyAlgorithm']),
 | |
|         otp_policy_digits=dict(type='int', aliases=['otpPolicyDigits']),
 | |
|         otp_policy_initial_counter=dict(type='int', aliases=['otpPolicyInitialCounter']),
 | |
|         otp_policy_look_ahead_window=dict(type='int', aliases=['otpPolicyLookAheadWindow']),
 | |
|         otp_policy_period=dict(type='int', aliases=['otpPolicyPeriod']),
 | |
|         otp_policy_type=dict(type='str', aliases=['otpPolicyType']),
 | |
|         otp_supported_applications=dict(type='list', elements='str', aliases=['otpSupportedApplications']),
 | |
|         password_policy=dict(type='str', aliases=['passwordPolicy'], no_log=False),
 | |
|         permanent_lockout=dict(type='bool', aliases=['permanentLockout']),
 | |
|         quick_login_check_milli_seconds=dict(type='int', aliases=['quickLoginCheckMilliSeconds']),
 | |
|         refresh_token_max_reuse=dict(type='int', aliases=['refreshTokenMaxReuse'], no_log=False),
 | |
|         registration_allowed=dict(type='bool', aliases=['registrationAllowed']),
 | |
|         registration_email_as_username=dict(type='bool', aliases=['registrationEmailAsUsername']),
 | |
|         registration_flow=dict(type='str', aliases=['registrationFlow']),
 | |
|         remember_me=dict(type='bool', aliases=['rememberMe']),
 | |
|         reset_credentials_flow=dict(type='str', aliases=['resetCredentialsFlow']),
 | |
|         reset_password_allowed=dict(type='bool', aliases=['resetPasswordAllowed'], no_log=False),
 | |
|         revoke_refresh_token=dict(type='bool', aliases=['revokeRefreshToken']),
 | |
|         smtp_server=dict(type='dict', aliases=['smtpServer']),
 | |
|         ssl_required=dict(choices=["external", "all", "none"], aliases=['sslRequired']),
 | |
|         sso_session_idle_timeout=dict(type='int', aliases=['ssoSessionIdleTimeout']),
 | |
|         sso_session_idle_timeout_remember_me=dict(type='int', aliases=['ssoSessionIdleTimeoutRememberMe']),
 | |
|         sso_session_max_lifespan=dict(type='int', aliases=['ssoSessionMaxLifespan']),
 | |
|         sso_session_max_lifespan_remember_me=dict(type='int', aliases=['ssoSessionMaxLifespanRememberMe']),
 | |
|         supported_locales=dict(type='list', elements='str', aliases=['supportedLocales']),
 | |
|         user_managed_access_allowed=dict(type='bool', aliases=['userManagedAccessAllowed']),
 | |
|         verify_email=dict(type='bool', aliases=['verifyEmail']),
 | |
|         wait_increment_seconds=dict(type='int', aliases=['waitIncrementSeconds']),
 | |
|     )
 | |
| 
 | |
|     argument_spec.update(meta_args)
 | |
| 
 | |
|     module = AnsibleModule(argument_spec=argument_spec,
 | |
|                            supports_check_mode=True,
 | |
|                            required_one_of=([['id', 'realm', 'enabled'],
 | |
|                                              ['token', 'auth_realm', 'auth_username', 'auth_password']]),
 | |
|                            required_together=([['auth_realm', 'auth_username', 'auth_password']]))
 | |
| 
 | |
|     result = dict(changed=False, msg='', diff={}, proposed={}, existing={}, end_state={})
 | |
| 
 | |
|     # Obtain access token, initialize API
 | |
|     try:
 | |
|         connection_header = get_token(module.params)
 | |
|     except KeycloakError as e:
 | |
|         module.fail_json(msg=str(e))
 | |
| 
 | |
|     kc = KeycloakAPI(module, connection_header)
 | |
| 
 | |
|     realm = module.params.get('realm')
 | |
|     state = module.params.get('state')
 | |
| 
 | |
|     # convert module parameters to realm representation parameters (if they belong in there)
 | |
|     params_to_ignore = list(keycloak_argument_spec().keys()) + ['state']
 | |
| 
 | |
|     # Filter and map the parameters names that apply to the role
 | |
|     realm_params = [x for x in module.params
 | |
|                     if x not in params_to_ignore and
 | |
|                     module.params.get(x) is not None]
 | |
| 
 | |
|     # See whether the realm already exists in Keycloak
 | |
|     before_realm = kc.get_realm_by_id(realm=realm)
 | |
| 
 | |
|     if before_realm is None:
 | |
|         before_realm = {}
 | |
| 
 | |
|     # Build a proposed changeset from parameters given to this module
 | |
|     changeset = {}
 | |
| 
 | |
|     for realm_param in realm_params:
 | |
|         new_param_value = module.params.get(realm_param)
 | |
|         changeset[camel(realm_param)] = new_param_value
 | |
| 
 | |
|     # Prepare the desired values using the existing values (non-existence results in a dict that is save to use as a basis)
 | |
|     desired_realm = before_realm.copy()
 | |
|     desired_realm.update(changeset)
 | |
| 
 | |
|     result['proposed'] = sanitize_cr(changeset)
 | |
|     before_realm_sanitized = sanitize_cr(before_realm)
 | |
|     result['existing'] = before_realm_sanitized
 | |
| 
 | |
|     # Cater for when it doesn't exist (an empty dict)
 | |
|     if not before_realm:
 | |
|         if state == 'absent':
 | |
|             # Do nothing and exit
 | |
|             if module._diff:
 | |
|                 result['diff'] = dict(before='', after='')
 | |
|             result['changed'] = False
 | |
|             result['end_state'] = {}
 | |
|             result['msg'] = 'Realm does not exist, doing nothing.'
 | |
|             module.exit_json(**result)
 | |
| 
 | |
|         # Process a creation
 | |
|         result['changed'] = True
 | |
| 
 | |
|         if 'id' not in desired_realm:
 | |
|             module.fail_json(msg='id needs to be specified when creating a new realm')
 | |
| 
 | |
|         if module._diff:
 | |
|             result['diff'] = dict(before='', after=sanitize_cr(desired_realm))
 | |
| 
 | |
|         if module.check_mode:
 | |
|             module.exit_json(**result)
 | |
| 
 | |
|         # create it
 | |
|         kc.create_realm(desired_realm)
 | |
|         after_realm = kc.get_realm_by_id(desired_realm['id'])
 | |
| 
 | |
|         result['end_state'] = sanitize_cr(after_realm)
 | |
| 
 | |
|         result['msg'] = 'Realm %s has been created.' % desired_realm['id']
 | |
|         module.exit_json(**result)
 | |
| 
 | |
|     else:
 | |
|         if state == 'present':
 | |
|             # Process an update
 | |
| 
 | |
|             # doing an update
 | |
|             result['changed'] = True
 | |
|             if module.check_mode:
 | |
|                 # We can only compare the current realm with the proposed updates we have
 | |
|                 if module._diff:
 | |
|                     result['diff'] = dict(before=before_realm_sanitized,
 | |
|                                           after=sanitize_cr(desired_realm))
 | |
|                 result['changed'] = (before_realm != desired_realm)
 | |
| 
 | |
|                 module.exit_json(**result)
 | |
| 
 | |
|             # do the update
 | |
|             kc.update_realm(desired_realm, realm=realm)
 | |
| 
 | |
|             after_realm = kc.get_realm_by_id(realm=realm)
 | |
| 
 | |
|             if before_realm == after_realm:
 | |
|                 result['changed'] = False
 | |
| 
 | |
|             result['end_state'] = sanitize_cr(after_realm)
 | |
| 
 | |
|             if module._diff:
 | |
|                 result['diff'] = dict(before=before_realm_sanitized,
 | |
|                                       after=sanitize_cr(after_realm))
 | |
| 
 | |
|             result['msg'] = 'Realm %s has been updated.' % desired_realm['id']
 | |
|             module.exit_json(**result)
 | |
| 
 | |
|         else:
 | |
|             # Process a deletion (because state was not 'present')
 | |
|             result['changed'] = True
 | |
| 
 | |
|             if module._diff:
 | |
|                 result['diff'] = dict(before=before_realm_sanitized, after='')
 | |
| 
 | |
|             if module.check_mode:
 | |
|                 module.exit_json(**result)
 | |
| 
 | |
|             # delete it
 | |
|             kc.delete_realm(realm=realm)
 | |
| 
 | |
|             result['proposed'] = {}
 | |
|             result['end_state'] = {}
 | |
| 
 | |
|             result['msg'] = 'Realm %s has been deleted.' % before_realm['id']
 | |
| 
 | |
|     module.exit_json(**result)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |