mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
[PR #7127/9a7a7a96 backport][stable-7] Add keycloak_realm_key module (#7291)
Add keycloak_realm_key module (#7127)
* Add keycloak_realm_key module
* keycloak_realm_key: make "ansible-test sanity" happy
Signed-off-by: Samuli Seppänen <samuli.seppanen@puppeteers.net>
* keycloak_realm_key: support check_mode
* keycloak_realm_key: add integration tests
* keycloak_realm_key: remove FIXME comment
* keycloak_realm_key: fix EOL in integration test variables
* keycloak_realm_key: remove unused import
* keycloak_realm_key: remove integration test realm at the end of test suite
* keycloak_realm_key: add version_added metadata
* keycloak_realm_key: add documentation for end_state
* keycloak_realm_key: support the "certificate" parameter
As with "private_key" changing the certificate after creation is not possible
because we can't compare the current value to the desired value.
* keycloak_realm_key: document default for certificate parameter
Signed-off-by: Samuli Seppänen <samuli.seppanen@puppeteers.net>
* keycloak_realm_key: implement diff mode
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* keycloak_realm_key: remove note about literal linefeeds
* keycloak_realm_key: remove defaults from priority and certificate
* keycloak_realm_key: mark diff and check modes as partially supported
* keycloak_realm_key: implement "force" parameter
This ensures that the desired state is always enforced on keys that should be,
and are, present.
* keycloak_realm_key: fix yaml parsing error in documentation
* keycloak_realm_key: document why check_mode support is partial
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
* keycloak_realm_key: documentation and metadata fixes
* keycloak_realm_key: small documentation fix
* keycloak_realm_key: change version_added to 7.5.0
* Update plugins/modules/keycloak_realm_key.py
Co-authored-by: Felix Fontein <felix@fontein.de>
---------
Signed-off-by: Samuli Seppänen <samuli.seppanen@puppeteers.net>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 9a7a7a9658
)
Co-authored-by: Samuli Seppänen <samuli.seppanen@gmail.com>
This commit is contained in:
parent
4381ac1bf3
commit
24b6441580
6 changed files with 912 additions and 0 deletions
2
.github/BOTMETA.yml
vendored
2
.github/BOTMETA.yml
vendored
|
@ -725,6 +725,8 @@ files:
|
||||||
maintainers: kris2kris
|
maintainers: kris2kris
|
||||||
$modules/keycloak_realm_info.py:
|
$modules/keycloak_realm_info.py:
|
||||||
maintainers: fynncfchen
|
maintainers: fynncfchen
|
||||||
|
$modules/keycloak_realm_key.py:
|
||||||
|
maintainers: mattock
|
||||||
$modules/keycloak_role.py:
|
$modules/keycloak_role.py:
|
||||||
maintainers: laurpaum
|
maintainers: laurpaum
|
||||||
$modules/keycloak_user.py:
|
$modules/keycloak_user.py:
|
||||||
|
|
457
plugins/modules/keycloak_realm_key.py
Normal file
457
plugins/modules/keycloak_realm_key.py
Normal file
|
@ -0,0 +1,457 @@
|
||||||
|
#!/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_key
|
||||||
|
|
||||||
|
short_description: Allows administration of Keycloak realm keys via Keycloak API
|
||||||
|
|
||||||
|
version_added: 7.5.0
|
||||||
|
|
||||||
|
description:
|
||||||
|
- This module allows the administration of Keycloak realm keys 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.
|
||||||
|
|
||||||
|
- This module is unable to detect changes to the actual cryptographic key after importing it.
|
||||||
|
However, if some other property is changed alongside the cryptographic key, then the key
|
||||||
|
will also get changed as a side-effect, as the JSON payload needs to include the private key.
|
||||||
|
This can be considered either a bug or a feature, as the alternative would be to always
|
||||||
|
update the realm key whether it has changed or not.
|
||||||
|
|
||||||
|
- If certificate is not explicitly provided it will be dynamically created by Keycloak.
|
||||||
|
Therefore comparing the current state of the certificate to the desired state (which may be
|
||||||
|
empty) is not possible.
|
||||||
|
|
||||||
|
attributes:
|
||||||
|
check_mode:
|
||||||
|
support: full
|
||||||
|
diff_mode:
|
||||||
|
support: partial
|
||||||
|
|
||||||
|
options:
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- State of the keycloak realm key.
|
||||||
|
- On V(present), the realm key will be created (or updated if it exists already).
|
||||||
|
- On V(absent), the realm key will be removed if it exists.
|
||||||
|
choices: ['present', 'absent']
|
||||||
|
default: 'present'
|
||||||
|
type: str
|
||||||
|
name:
|
||||||
|
description:
|
||||||
|
- Name of the realm key to create.
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
force:
|
||||||
|
description:
|
||||||
|
- Enforce the state of the private key and certificate. This is not automatically the
|
||||||
|
case as this module is unable to determine the current state of the private key and
|
||||||
|
thus cannot trigger an update based on an actual divergence. That said, a private key
|
||||||
|
update may happen even if force is false as a side-effect of other changes.
|
||||||
|
default: false
|
||||||
|
type: bool
|
||||||
|
parent_id:
|
||||||
|
description:
|
||||||
|
- The parent_id of the realm key. In practice the ID (name) of the realm.
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
provider_id:
|
||||||
|
description:
|
||||||
|
- The name of the "provider ID" for the key.
|
||||||
|
choices: ['rsa']
|
||||||
|
default: 'rsa'
|
||||||
|
type: str
|
||||||
|
config:
|
||||||
|
description:
|
||||||
|
- Dict specifying the key and its properties.
|
||||||
|
type: dict
|
||||||
|
suboptions:
|
||||||
|
active:
|
||||||
|
description:
|
||||||
|
- Whether they key is active or inactive. Not to be confused with the state
|
||||||
|
of the Ansible resource managed by the O(state) parameter.
|
||||||
|
default: true
|
||||||
|
type: bool
|
||||||
|
enabled:
|
||||||
|
description:
|
||||||
|
- Whether the key is enabled or disabled. Not to be confused with the state
|
||||||
|
of the Ansible resource managed by the O(state) parameter.
|
||||||
|
default: true
|
||||||
|
type: bool
|
||||||
|
priority:
|
||||||
|
description:
|
||||||
|
- The priority of the key.
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
algorithm:
|
||||||
|
description:
|
||||||
|
- Key algorithm.
|
||||||
|
default: RS256
|
||||||
|
choices: ['RS256']
|
||||||
|
type: str
|
||||||
|
private_key:
|
||||||
|
description:
|
||||||
|
- The private key as an ASCII string. Contents of the key must match O(config.algorithm)
|
||||||
|
and O(provider_id).
|
||||||
|
- Please note that the module cannot detect whether the private key specified differs from the
|
||||||
|
current state's private key. Use O(force=true) to force the module to update the private key
|
||||||
|
if you expect it to be updated.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
certificate:
|
||||||
|
description:
|
||||||
|
- A certificate signed with the private key as an ASCII string. Contents of the
|
||||||
|
key must match O(config.algorithm) and O(provider_id).
|
||||||
|
- If you want Keycloak to automatically generate a certificate using your private key
|
||||||
|
then set this to an empty string.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
notes:
|
||||||
|
- Current value of the private key cannot be fetched from Keycloak.
|
||||||
|
Therefore comparing its desired state to the current state is not
|
||||||
|
possible.
|
||||||
|
- If certificate is not explicitly provided it will be dynamically created
|
||||||
|
by Keycloak. Therefore comparing the current state of the certificate to
|
||||||
|
the desired state (which may be empty) is not possible.
|
||||||
|
- Due to the private key and certificate options the module is
|
||||||
|
B(not fully idempotent). You can use O(force=true) to force the module
|
||||||
|
to always update if you know that the private key might have changed.
|
||||||
|
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- community.general.keycloak
|
||||||
|
- community.general.attributes
|
||||||
|
|
||||||
|
author:
|
||||||
|
- Samuli Seppänen (@mattock)
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
- name: Manage Keycloak realm key (certificate autogenerated by Keycloak)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
name: custom
|
||||||
|
state: present
|
||||||
|
parent_id: master
|
||||||
|
provider_id: rsa
|
||||||
|
auth_keycloak_url: http://localhost:8080/auth
|
||||||
|
auth_username: keycloak
|
||||||
|
auth_password: keycloak
|
||||||
|
auth_realm: master
|
||||||
|
config:
|
||||||
|
private_key: "{{ private_key }}"
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 120
|
||||||
|
algorithm: RS256
|
||||||
|
- name: Manage Keycloak realm key and certificate
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
name: custom
|
||||||
|
state: present
|
||||||
|
parent_id: master
|
||||||
|
provider_id: rsa
|
||||||
|
auth_keycloak_url: http://localhost:8080/auth
|
||||||
|
auth_username: keycloak
|
||||||
|
auth_password: keycloak
|
||||||
|
auth_realm: master
|
||||||
|
config:
|
||||||
|
private_key: "{{ private_key }}"
|
||||||
|
certificate: "{{ certificate }}"
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 120
|
||||||
|
algorithm: RS256
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = '''
|
||||||
|
msg:
|
||||||
|
description: Message as to what action was taken.
|
||||||
|
returned: always
|
||||||
|
type: str
|
||||||
|
|
||||||
|
end_state:
|
||||||
|
description: Representation of the keycloak_realm_key after module execution.
|
||||||
|
returned: on success
|
||||||
|
type: dict
|
||||||
|
contains:
|
||||||
|
id:
|
||||||
|
description: ID of the realm key.
|
||||||
|
type: str
|
||||||
|
returned: when O(state=present)
|
||||||
|
sample: 5b7ec13f-99da-46ad-8326-ab4c73cf4ce4
|
||||||
|
name:
|
||||||
|
description: Name of the realm key.
|
||||||
|
type: str
|
||||||
|
returned: when O(state=present)
|
||||||
|
sample: mykey
|
||||||
|
parentId:
|
||||||
|
description: ID of the realm this key belongs to.
|
||||||
|
type: str
|
||||||
|
returned: when O(state=present)
|
||||||
|
sample: myrealm
|
||||||
|
providerId:
|
||||||
|
description: The ID of the key provider.
|
||||||
|
type: str
|
||||||
|
returned: when O(state=present)
|
||||||
|
sample: rsa
|
||||||
|
providerType:
|
||||||
|
description: The type of provider.
|
||||||
|
type: str
|
||||||
|
returned: when O(state=present)
|
||||||
|
config:
|
||||||
|
description: Realm key configuration.
|
||||||
|
type: dict
|
||||||
|
returned: when O(state=present)
|
||||||
|
sample: {
|
||||||
|
"active": ["true"],
|
||||||
|
"algorithm": ["RS256"],
|
||||||
|
"enabled": ["true"],
|
||||||
|
"priority": ["140"]
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
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
|
||||||
|
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Module execution
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
argument_spec = keycloak_argument_spec()
|
||||||
|
|
||||||
|
meta_args = dict(
|
||||||
|
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||||
|
name=dict(type='str', required=True),
|
||||||
|
force=dict(type='bool', default=False),
|
||||||
|
parent_id=dict(type='str', required=True),
|
||||||
|
provider_id=dict(type='str', default='rsa', choices=['rsa']),
|
||||||
|
config=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
active=dict(type='bool', default=True),
|
||||||
|
enabled=dict(type='bool', default=True),
|
||||||
|
priority=dict(type='int', required=True),
|
||||||
|
algorithm=dict(type='str', default='RS256', choices=['RS256']),
|
||||||
|
private_key=dict(type='str', required=True, no_log=True),
|
||||||
|
certificate=dict(type='str', required=True, no_log=True)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
argument_spec.update(meta_args)
|
||||||
|
|
||||||
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
|
supports_check_mode=True,
|
||||||
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
||||||
|
required_together=([['auth_realm', 'auth_username', 'auth_password']]))
|
||||||
|
|
||||||
|
# Initialize the result object. Only "changed" seems to have special
|
||||||
|
# meaning for Ansible.
|
||||||
|
result = dict(changed=False, msg='', end_state={}, diff=dict(before={}, after={}))
|
||||||
|
|
||||||
|
# This will include the current state of the realm key if it is already
|
||||||
|
# present. This is only used for diff-mode.
|
||||||
|
before_realm_key = {}
|
||||||
|
before_realm_key['config'] = {}
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
params_to_ignore = list(keycloak_argument_spec().keys()) + ["state", "force"]
|
||||||
|
|
||||||
|
# Filter and map the parameters names that apply to the role
|
||||||
|
component_params = [x for x in module.params
|
||||||
|
if x not in params_to_ignore and
|
||||||
|
module.params.get(x) is not None]
|
||||||
|
|
||||||
|
# We only support one component provider type in this module
|
||||||
|
provider_type = 'org.keycloak.keys.KeyProvider'
|
||||||
|
|
||||||
|
# Build a proposed changeset from parameters given to this module
|
||||||
|
changeset = {}
|
||||||
|
changeset['config'] = {}
|
||||||
|
|
||||||
|
# Generate a JSON payload for Keycloak Admin API from the module
|
||||||
|
# parameters. Parameters that do not belong to the JSON payload (e.g.
|
||||||
|
# "state" or "auth_keycloal_url") have been filtered away earlier (see
|
||||||
|
# above).
|
||||||
|
#
|
||||||
|
# This loop converts Ansible module parameters (snake-case) into
|
||||||
|
# Keycloak-compatible format (camel-case). For example private_key
|
||||||
|
# becomes privateKey.
|
||||||
|
#
|
||||||
|
# It also converts bool, str and int parameters into lists with a single
|
||||||
|
# entry of 'str' type. Bool values are also lowercased. This is required
|
||||||
|
# by Keycloak.
|
||||||
|
#
|
||||||
|
for component_param in component_params:
|
||||||
|
if component_param == 'config':
|
||||||
|
for config_param in module.params.get('config'):
|
||||||
|
changeset['config'][camel(config_param)] = []
|
||||||
|
raw_value = module.params.get('config')[config_param]
|
||||||
|
if isinstance(raw_value, bool):
|
||||||
|
value = str(raw_value).lower()
|
||||||
|
else:
|
||||||
|
value = str(raw_value)
|
||||||
|
|
||||||
|
changeset['config'][camel(config_param)].append(value)
|
||||||
|
else:
|
||||||
|
# No need for camelcase in here as these are one word parameters
|
||||||
|
new_param_value = module.params.get(component_param)
|
||||||
|
changeset[camel(component_param)] = new_param_value
|
||||||
|
|
||||||
|
# As provider_type is not a module parameter we have to add it to the
|
||||||
|
# changeset explicitly.
|
||||||
|
changeset['providerType'] = provider_type
|
||||||
|
|
||||||
|
# Make a deep copy of the changeset. This is use when determining
|
||||||
|
# changes to the current state.
|
||||||
|
changeset_copy = deepcopy(changeset)
|
||||||
|
|
||||||
|
# It is not possible to compare current keys to desired keys, because the
|
||||||
|
# certificate parameter is a base64-encoded binary blob created on the fly
|
||||||
|
# when a key is added. Moreover, the Keycloak Admin API does not seem to
|
||||||
|
# return the value of the private key for comparison. So, in effect, it we
|
||||||
|
# just have to ignore changes to the keys. However, as the privateKey
|
||||||
|
# parameter needs be present in the JSON payload, any changes done to any
|
||||||
|
# other parameters (e.g. config.priority) will trigger update of the keys
|
||||||
|
# as a side-effect.
|
||||||
|
del changeset_copy['config']['privateKey']
|
||||||
|
del changeset_copy['config']['certificate']
|
||||||
|
|
||||||
|
# Make it easier to refer to current module parameters
|
||||||
|
name = module.params.get('name')
|
||||||
|
force = module.params.get('force')
|
||||||
|
state = module.params.get('state')
|
||||||
|
enabled = module.params.get('enabled')
|
||||||
|
provider_id = module.params.get('provider_id')
|
||||||
|
parent_id = module.params.get('parent_id')
|
||||||
|
|
||||||
|
# Get a list of all Keycloak components that are of keyprovider type.
|
||||||
|
realm_keys = kc.get_components(urlencode(dict(type=provider_type, parent=parent_id)), parent_id)
|
||||||
|
|
||||||
|
# If this component is present get its key ID. Confusingly the key ID is
|
||||||
|
# also known as the Provider ID.
|
||||||
|
key_id = None
|
||||||
|
|
||||||
|
# Track individual parameter changes
|
||||||
|
changes = ""
|
||||||
|
|
||||||
|
# This tells Ansible whether the key was changed (added, removed, modified)
|
||||||
|
result['changed'] = False
|
||||||
|
|
||||||
|
# Loop through the list of components. If we encounter a component whose
|
||||||
|
# name matches the value of the name parameter then assume the key is
|
||||||
|
# already present.
|
||||||
|
for key in realm_keys:
|
||||||
|
if key['name'] == name:
|
||||||
|
key_id = key['id']
|
||||||
|
changeset['id'] = key_id
|
||||||
|
changeset_copy['id'] = key_id
|
||||||
|
|
||||||
|
# Compare top-level parameters
|
||||||
|
for param, value in changeset.items():
|
||||||
|
before_realm_key[param] = key[param]
|
||||||
|
|
||||||
|
if changeset_copy[param] != key[param] and param != 'config':
|
||||||
|
changes += "%s: %s -> %s, " % (param, key[param], changeset_copy[param])
|
||||||
|
result['changed'] = True
|
||||||
|
|
||||||
|
# Compare parameters under the "config" key
|
||||||
|
for p, v in changeset_copy['config'].items():
|
||||||
|
before_realm_key['config'][p] = key['config'][p]
|
||||||
|
if changeset_copy['config'][p] != key['config'][p]:
|
||||||
|
changes += "config.%s: %s -> %s, " % (p, key['config'][p], changeset_copy['config'][p])
|
||||||
|
result['changed'] = True
|
||||||
|
|
||||||
|
# Sanitize linefeeds for the privateKey. Without this the JSON payload
|
||||||
|
# will be invalid.
|
||||||
|
changeset['config']['privateKey'][0] = changeset['config']['privateKey'][0].replace('\\n', '\n')
|
||||||
|
changeset['config']['certificate'][0] = changeset['config']['certificate'][0].replace('\\n', '\n')
|
||||||
|
|
||||||
|
# Check all the possible states of the resource and do what is needed to
|
||||||
|
# converge current state with desired state (create, update or delete
|
||||||
|
# the key).
|
||||||
|
if key_id and state == 'present':
|
||||||
|
if result['changed']:
|
||||||
|
if module._diff:
|
||||||
|
del before_realm_key['config']['privateKey']
|
||||||
|
del before_realm_key['config']['certificate']
|
||||||
|
result['diff'] = dict(before=before_realm_key, after=changeset_copy)
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
result['msg'] = "Realm key %s would be changed: %s" % (name, changes.strip(", "))
|
||||||
|
else:
|
||||||
|
kc.update_component(changeset, parent_id)
|
||||||
|
result['msg'] = "Realm key %s changed: %s" % (name, changes.strip(", "))
|
||||||
|
elif not result['changed'] and force:
|
||||||
|
kc.update_component(changeset, parent_id)
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "Realm key %s was forcibly updated" % (name)
|
||||||
|
else:
|
||||||
|
result['msg'] = "Realm key %s was in sync" % (name)
|
||||||
|
|
||||||
|
result['end_state'] = changeset_copy
|
||||||
|
elif key_id and state == 'absent':
|
||||||
|
if module._diff:
|
||||||
|
del before_realm_key['config']['privateKey']
|
||||||
|
del before_realm_key['config']['certificate']
|
||||||
|
result['diff'] = dict(before=before_realm_key, after={})
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "Realm key %s would be deleted" % (name)
|
||||||
|
else:
|
||||||
|
kc.delete_component(key_id, parent_id)
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "Realm key %s deleted" % (name)
|
||||||
|
|
||||||
|
result['end_state'] = {}
|
||||||
|
elif not key_id and state == 'present':
|
||||||
|
if module._diff:
|
||||||
|
result['diff'] = dict(before={}, after=changeset_copy)
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "Realm key %s would be created" % (name)
|
||||||
|
else:
|
||||||
|
kc.create_component(changeset, parent_id)
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "Realm key %s created" % (name)
|
||||||
|
|
||||||
|
result['end_state'] = changeset_copy
|
||||||
|
elif not key_id and state == 'absent':
|
||||||
|
result['changed'] = False
|
||||||
|
result['msg'] = "Realm key %s not present" % (name)
|
||||||
|
result['end_state'] = {}
|
||||||
|
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
5
tests/integration/targets/keycloak_realm_key/aliases
Normal file
5
tests/integration/targets/keycloak_realm_key/aliases
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (c) Ansible Project
|
||||||
|
# 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
|
||||||
|
|
||||||
|
unsupported
|
27
tests/integration/targets/keycloak_realm_key/readme.adoc
Normal file
27
tests/integration/targets/keycloak_realm_key/readme.adoc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) Ansible Project
|
||||||
|
// 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
|
||||||
|
|
||||||
|
To be able to run these integration tests a keycloak server must be
|
||||||
|
reachable under a specific url with a specific admin user and password.
|
||||||
|
The exact values expected for these parameters can be found in
|
||||||
|
'vars/main.yml' file. A simple way to do this is to use the official
|
||||||
|
keycloak docker images like this:
|
||||||
|
|
||||||
|
----
|
||||||
|
docker run --name mykeycloak -p 8080:8080 -e KC_HTTP_RELATIVE_PATH=<url-path> -e KEYCLOAK_ADMIN=<admin_user> -e KEYCLOAK_ADMIN_PASSWORD=<admin_password> quay.io/keycloak/keycloak:20.0.2 start-dev
|
||||||
|
----
|
||||||
|
|
||||||
|
Example with concrete values inserted:
|
||||||
|
|
||||||
|
----
|
||||||
|
docker run --name mykeycloak -p 8080:8080 -e KC_HTTP_RELATIVE_PATH=/auth -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=password quay.io/keycloak/keycloak:20.0.2 start-dev
|
||||||
|
----
|
||||||
|
|
||||||
|
This test suite can run against a fresh unconfigured server instance
|
||||||
|
(no preconfiguration required) and cleans up after itself (undoes all
|
||||||
|
its config changes) as long as it runs through completly. While its active
|
||||||
|
it changes the server configuration in the following ways:
|
||||||
|
|
||||||
|
* creating, modifying and deleting some keycloak groups
|
||||||
|
|
373
tests/integration/targets/keycloak_realm_key/tasks/main.yml
Normal file
373
tests/integration/targets/keycloak_realm_key/tasks/main.yml
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
---
|
||||||
|
# Copyright (c) Ansible Project
|
||||||
|
# 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
|
||||||
|
- name: Remove Keycloak test realm to avoid failures from previous failed runs
|
||||||
|
community.general.keycloak_realm:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
realm: "{{ realm }}"
|
||||||
|
id: "{{ realm }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create Keycloak test realm
|
||||||
|
community.general.keycloak_realm:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
realm: "{{ realm }}"
|
||||||
|
id: "{{ realm }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create custom realm key (check mode)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 150
|
||||||
|
check_mode: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["150"]
|
||||||
|
- result.msg == "Realm key testkey would be created"
|
||||||
|
|
||||||
|
- name: Create custom realm key
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 150
|
||||||
|
diff: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that realm key was created
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["150"]
|
||||||
|
- result.msg == "Realm key testkey created"
|
||||||
|
|
||||||
|
- name: Create custom realm key (test for idempotency)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 150
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["150"]
|
||||||
|
- result.msg == "Realm key testkey was in sync"
|
||||||
|
|
||||||
|
- name: Update custom realm key (check mode)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 140
|
||||||
|
check_mode: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["140"]
|
||||||
|
- result.msg == "Realm key testkey would be changed: config.priority ['150'] -> ['140']"
|
||||||
|
|
||||||
|
- name: Update custom realm key
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 140
|
||||||
|
diff: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that realm key was updated
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["140"]
|
||||||
|
- result.msg == "Realm key testkey changed: config.priority ['150'] -> ['140']"
|
||||||
|
|
||||||
|
- name: Update custom realm key (test for idempotency)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 140
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["140"]
|
||||||
|
- result.msg == "Realm key testkey was in sync"
|
||||||
|
|
||||||
|
- name: Force update custom realm key
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
force: true
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key_2 }}"
|
||||||
|
certificate: ""
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 140
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that forced update ran correctly
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["140"]
|
||||||
|
- result.msg == "Realm key testkey was forcibly updated"
|
||||||
|
|
||||||
|
- name: Remove custom realm key
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: absent
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
priority: 140
|
||||||
|
diff: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that realm key was deleted
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state == {}
|
||||||
|
- result.msg == "Realm key testkey deleted"
|
||||||
|
|
||||||
|
- name: Remove custom realm key (test for idempotency)
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey
|
||||||
|
state: absent
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: ""
|
||||||
|
priority: 140
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
- result.end_state == {}
|
||||||
|
- result.msg == "Realm key testkey not present"
|
||||||
|
|
||||||
|
- name: Create custom realm key with a custom certificate
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey_with_certificate
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "{{ realm_private_key }}"
|
||||||
|
certificate: "{{ realm_certificate }}"
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 150
|
||||||
|
diff: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that realm key with custom certificate was created
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey_with_certificate"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["150"]
|
||||||
|
- result.msg == "Realm key testkey_with_certificate created"
|
||||||
|
|
||||||
|
- name: Attempt to change the private key and the certificate
|
||||||
|
community.general.keycloak_realm_key:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
name: testkey_with_certificate
|
||||||
|
state: present
|
||||||
|
parent_id: "{{ realm }}"
|
||||||
|
config:
|
||||||
|
private_key: "a different private key string"
|
||||||
|
certificate: "a different certificate string"
|
||||||
|
enabled: true
|
||||||
|
active: true
|
||||||
|
priority: 150
|
||||||
|
diff: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that nothing has changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
- result.end_state != {}
|
||||||
|
- result.end_state.name == "testkey_with_certificate"
|
||||||
|
- result.end_state.parentId == "realm_key_test"
|
||||||
|
- result.end_state.providerId == "rsa"
|
||||||
|
- result.end_state.providerType == "org.keycloak.keys.KeyProvider"
|
||||||
|
- result.end_state.config.active == ["true"]
|
||||||
|
- result.end_state.config.enabled == ["true"]
|
||||||
|
- result.end_state.config.algorithm == ["RS256"]
|
||||||
|
- result.end_state.config.priority == ["150"]
|
||||||
|
- result.msg == "Realm key testkey_with_certificate was in sync"
|
||||||
|
|
||||||
|
- name: Remove Keycloak test realm
|
||||||
|
community.general.keycloak_realm:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
realm: "{{ realm }}"
|
||||||
|
id: "{{ realm }}"
|
||||||
|
state: absent
|
48
tests/integration/targets/keycloak_realm_key/vars/main.yml
Normal file
48
tests/integration/targets/keycloak_realm_key/vars/main.yml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
# Copyright (c) Ansible Project
|
||||||
|
# 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
|
||||||
|
|
||||||
|
url: http://localhost:8080/auth
|
||||||
|
admin_realm: master
|
||||||
|
admin_user: admin
|
||||||
|
admin_password: password
|
||||||
|
realm: realm_key_test
|
||||||
|
realm_private_key_name: testkey
|
||||||
|
realm_private_key: |
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC9Mi7IKXPhqGiWGwgEYEXnqc8nytG1pHbC6QYZe1gUa43jDtGYQln36It02BGw4e5XydCUj+M26X2sH+kKaV+KHEnJtcEqdAuVX1QaDVzeiOoo1/B9HC8By6NZBsOSdxpat3EvilQ+R7NP9yi53J08+vfeZSEGyPmKV1me7nJnRh3/zcRsOi92GTsBd7gApKfP8sorDjY8m9NRuPLwleK2nh/aRvj1yK8x3UAqUIbOCVaE39bSN6VUTFK2Q/+MX3vF0Zugsk7PKKmfqcEW6wj7dtSElbX4uhrfTkGMmwIWdIiLDNRA/jVRvGxUB1SyMy6kmMC8jC2QGWpZgfkSKtHlAgMBAAECggEACWkSVh7ntmjtwM+Z47vVJkt2NBS8vxPt206DYOeXbzaVUV6mkrP0LSZKL3bi1GE8fW3am9UXWF8fQt04dm3c1G4JRojtkXrBq72Y3Y3eGWyGdx8chWCOPwDdwFsbhbC6ZRo8PUDcZVekJd1Vj38XbBXQl+WAUcnTzauAF+1kz9mhJq1gpglIbB+8l7VjMXwXeaGWJQ5OL/MSsq7r3P1elVjHwprFBM7HHA5+RTu/KY/GcEutgm5uwTRqRZNC1IBXAQtBO7HQJbuLqDPTQ3RRCPEur8R+0dk5bF+8IyzQ8Bh+Dhuou9xzfS/A7lV6L/CZSpv4Bvq1H3Uxk+orXf2Q2QKBgQDBOf1nSJB0VgQdIcdtgVpVgQ2SyWAd+N8Qk7QsyVQf9f7ZqiFLejWJbaaeY9WtfZ01D8tgHJfPqsO1/Jux255mtkyk2K2c6dav1Lsd4l+iPfidsDJNWkcd59nQqwC9BLjzWK/J4rO20apm34abLaZ9oVk8Mgz8VWJWOxTgCr+COQKBgQD6qP1lm6rzlCSIEz9eCuGPkQkVo+NIP437e3i+sxtkLlMgnmfzSwSJdVF8AKH3gXi3NyWjfBVYeAZEkm1kHF8IWOiK4U1y95Vx3uud3NX4SC+cjePc+pDPQJiz9L+zq9I6WFZWmm7n/9heTxu/l0vxI4FHaBmt95BMwLJNkzbdDQKBgCHGwUUMqjOr1YxCG1pJAkFwDa9bBDI5DsUXDKfHia0Mkz/5PVi0RCeBw15slS1+h7x+xk5GsULb1to5Df5JJadOtpcaST7koWKbDRpsN8tkidEGu8RJw6S2opyXR8nCyZHALvpbZo7Ol7rj1+PIVxIe4jpjhWGWi1oHed6wAkoBAoGAJx2F5XxEUhx1EvMF+XPzPQciBsl7Z0PbsTnUXtXuWVTNThLKH/I99AFlxNcIb2o530VwzzFG13Zra/n5rhyrS88sArgj8OPn40wpMopKraL+Iw0VWN+VB3KKIdL4s14FwWsVlhAlbHjFV/o6V0yR4kBrJSx+jWJLl16etHJbpmUCgYBUWCQwcT1aw9XHWJXiNYTnQSYg88hgGYhts1qSzhfu+n1t2BlAlxM0gu2+gez21mM8uiYsqbU2OZeG2U4as6kdai8Q4tzNQt2f1r3ZewJN/QHrkx6FT94PNa0w4ILiQ9Eu7xssaHcYjHyrI1NlbMKypVy6waDG2ajLOFAVeHGpOg==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
realm_certificate: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQDCCAiigAwIBAgIUMfPlHWcZn6xfeSjfbhgmt4yy6mMwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDAeFw0yMzA4MTgxMTU5MDFaFw0zMzA4MTUxMTU5MDFaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9Mi7IKXPhqGiWGwgEYEXnqc8nytG1pHbC6QYZe1gUa43jDtGYQln36It02BGw4e5XydCUj+M26X2sH+kKaV+KHEnJtcEqdAuVX1QaDVzeiOoo1/B9HC8By6NZBsOSdxpat3EvilQ+R7NP9yi53J08+vfeZSEGyPmKV1me7nJnRh3/zcRsOi92GTsBd7gApKfP8sorDjY8m9NRuPLwleK2nh/aRvj1yK8x3UAqUIbOCVaE39bSN6VUTFK2Q/+MX3vF0Zugsk7PKKmfqcEW6wj7dtSElbX4uhrfTkGMmwIWdIiLDNRA/jVRvGxUB1SyMy6kmMC8jC2QGWpZgfkSKtHlAgMBAAGjLjAsMAsGA1UdDwQEAwIEkDAdBgNVHQ4EFgQUcZirWRV5EzRhanUVSQ9rmAavVbEwDQYJKoZIhvcNAQELBQADggEBAIt2aFr/sxvtZfDc+Nb9tgspBuoX8f9Gf9mrS6dTdvdqSMHQrcoejSEEAZNljdSpKAhnhyR3+uCIev++WS4tixZoooQ8aYxDGNIwyry51GNEK7LKXVRmkbZFODidRuYZ1XWQORaJoaXWplaPaNtLvUr1swachz36K4n8/UIi109w/addajOHFbFGAzUmGRR4saMZPGrQCaNFje7G1o5wb/mQD1L+Jfk81Id5/F6NFBsSEIi+/O7Xs7fOWuab6cdfwI7zQQclEo55WQkLXefFLn+Ju0Ftgl023awpNEE4pjl6jD5VSEOkQ+I2sxGvymgjz7Av4zPOD/Lr05lRnMxf8dA=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
realm_private_key_2: |
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCyQ5FKuqbnWEtt
|
||||||
|
KI0FHKFvd+G/RyEI2ow29Ytjs3fZ7/gMYfXozHLLJl3jgCOvSf9Ta55arL0XnCCf
|
||||||
|
RKQb0vpgMmOTQw++A1UmNXe8atTczZMRiHMHFdLhXUvUKthcMGOrTH8xegCnm0bG
|
||||||
|
rZwimjQDog/kROMAN78Uv8SD1lMpGBxPr2DWXNl4kRF670m/jC0cM7SeDGCCKVF5
|
||||||
|
SEh6rMDgI62AxKnbtxuAbF9SOO/6kTsYv5+dc8wxDEb0aaT1jC1CLhjAVmjc6vO7
|
||||||
|
WHE0LLas+ARs4ghMONLN6VdOkJxBuEtlLqM3M+/viD1TRftZCeLarYLWdEsg8Yz9
|
||||||
|
Ufb0oawzAgMBAAECggEARqPDxWsljHNOoFj7WNU5m6RTzqpvCsUf3v96Vu3dRn1z
|
||||||
|
O+Ttv2yU6K+xcN9sRJ/8D6CLxb7Bx8NUoghfR69ZDBmrn8VpTZCgg12Yrw9efojw
|
||||||
|
CHibrGkXgbqou9CmoBGEzXKozIBeFgzQBRby0jts9SuZRImPspxkmeJMCzo5BgUg
|
||||||
|
ksNibaWikvUJYMgFc7PdXEvxhCKcWTTGC3fxJwpRxXkqKsYDa3JhdhloH8hHqynm
|
||||||
|
o7WEXeGAn4UV7C1tg3OdTciHn/ONMRItPcyonwk19meZTvsEub6ZsNjVg/5oJVBr
|
||||||
|
WG8vPZBi1VzAMayDXxDOnEAKW5eJXRSNX1vZ7EQTEQKBgQDXg5pSp9hVdVZc+eN/
|
||||||
|
Ab/1NMMdgrQdbyTeB9esjLiwNuXysQm/KaG8gTkLpiKVvJ8R7SOcxb9Y5Gt9Y5Ej
|
||||||
|
eu943V4zLDIzNt/ST4bXGW/gQ84zkMBdhKz9hKA5tartVjI1ycznjpDbgn/jAYPI
|
||||||
|
8VXGmjID2oDIJ7P+dLD8lMBDvQKBgQDTwIyimy+4EwFUuuppfWArXRsqsWUScGWD
|
||||||
|
+06xbc+Ld92LJBvakvSTdDNnS/PlYGl/fJjqQ4wq5UPREJYCi3UW9I5jtfsIg8Pl
|
||||||
|
oCnIhEYkn8xPZ7X8grU4emkM6QAPhstCDlXE6t0T202TpYVYjtEEDRQu4rKAbJ0h
|
||||||
|
gqSh5Ge2rwKBgEjrx6jWEBYCaOF20ComTmxKmQaANi+Lbt8NqkVBLDC7spymmJSt
|
||||||
|
IoOk+cdeRG+D7hLjuVwPcQpD57b6nJ5zt1mfFYOdHbNEiwEfVZGskrVAXCIIhX5f
|
||||||
|
KSVy3cAJHzfFJaIbkRB8pbkQc/M8jPnN5ucXP3scUNzoyjd8BnLAZjnFAoGAWwwY
|
||||||
|
rDYTz48EbH0uG4uYFS0kaDf8YHBJhfVBgdLYgXxZmuE8xL+ZP+mfzJOA3CiXVASr
|
||||||
|
71Z551vKzBLYnWF/SA6BRuhRdvjI+2vha2FMk6TOAXpzao59AzrG/pEUwJhRvyZQ
|
||||||
|
xKnDwyzxb0GlU02dG6PQANTisYuCCI2W4jFGUusCgYB72p5o5uBr7qrFMTdMMxxe
|
||||||
|
f/9Go/9QBR/uNYk3D/rWj0F/bXGbiYMddNMD4v3XE24NL4ZvBJn0Po64Tuz5+wtu
|
||||||
|
5ICKc6ED1l55MPsKdegVMpXGIFRjZt2TtCk4FE68m5QJpT1IIK7I9jv0+FGKjFYa
|
||||||
|
ukdTEghu13cANd8eKpxBsQ==
|
||||||
|
-----END PRIVATE KEY-----
|
Loading…
Reference in a new issue