Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User-group modules #52

Merged
merged 32 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
58fc1e5
main functions defined. stil WIP
pescobar Nov 1, 2020
d46aa27
first version adding/removing groups
pescobar Nov 2, 2020
58010c1
first version adding connections to groups
pescobar Nov 2, 2020
2a47b0b
looks like it is working
gwbischof Apr 11, 2024
657e999
add read_only parameter when creating connection
gwbischof May 1, 2024
0a4c8c6
touchups
gwbischof May 21, 2024
d6e2123
working on updating guacamole_users_groups to take a permissions dict…
gwbischof May 24, 2024
e5f4d1b
Pass at making present/sync work
RobertSchaffer1 May 29, 2024
e88865f
Adding connections groups to users_group logic
RobertSchaffer1 May 29, 2024
86012c0
Adding connections groups to users_group logic p2
RobertSchaffer1 May 29, 2024
d50ebca
Adding connections groups to users_group logic p3
RobertSchaffer1 May 29, 2024
0c1d323
Adding connections groups to users_group logic p4
RobertSchaffer1 May 29, 2024
9dde1b5
Adding connections groups to users_group logic p5
RobertSchaffer1 May 29, 2024
808eb7c
Fixed users group permissions for connections groups (not needed)
RobertSchaffer1 May 29, 2024
3883d81
add code for remove user groups and connections
gwbischof May 30, 2024
cbbdde5
missing :
gwbischof May 30, 2024
09fb0bc
debugging
gwbischof May 30, 2024
990c628
debugging
gwbischof May 30, 2024
5465536
some progress
gwbischof May 30, 2024
2793c50
more progress
gwbischof May 30, 2024
db5436a
debug
gwbischof May 30, 2024
f1eef85
add guacamole_user_group_users
gwbischof May 31, 2024
b17ca55
progress
gwbischof May 31, 2024
9a5cae7
progress
gwbischof May 31, 2024
f1493f1
progress
gwbischof May 31, 2024
b626f48
progress
gwbischof May 31, 2024
d6e944f
flake8 fixes
gwbischof Jun 4, 2024
8195f6e
clean up
gwbischof Jun 4, 2024
6fcd38b
doc updates
gwbischof Jun 4, 2024
1711661
flake8 fixes
gwbischof Jun 4, 2024
4ed18d5
clean up guacamole user group users module
gwbischof Jun 4, 2024
988f0a3
touch ups
gwbischof Jun 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion plugins/modules/guacamole_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@
- Should we enable sftp transfers for this connection?
type: bool

read_only:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding read-only here allows creating a read-only connection.

description:
- True if connection should be read-only.
type: bool

sftp_port:
description:
- Port to use for sftp
Expand Down Expand Up @@ -329,6 +334,7 @@
username: vnc_user
password: vnc_pass
sftp_enable: true
read_only: false
sftp_port: 22
sftp_hostname: 192.168.11.11
sftp_server_alive_interval: 10
Expand Down Expand Up @@ -410,6 +416,7 @@ def guacamole_populate_connection_payload(module_params):
"parameters": {
"enable-sftp": module_params['sftp_enable'],
"sftp-directory": module_params['sftp_default_upload_directory'],
"read-only": module_params['read_only']
},
"attributes": {
"guacd-encryption": module_params['guacd_encryption'],
Expand Down Expand Up @@ -440,7 +447,8 @@ def guacamole_populate_connection_payload(module_params):
"sftp_root_directory",
"disable_copy",
"disable_paste",
"cursor"
"cursor",
"read_only"
)
guacamole_add_parameter(payload, module_params, parameters)

Expand Down Expand Up @@ -590,6 +598,7 @@ def main():
guacd_hostname=dict(type='str', required=False),
guacd_port=dict(type='int', required=False),
guacd_encryption=dict(type='str', required=False),
read_only=dict(type='bool', default=False),
)

result = dict(changed=False, msg='', diff={},
Expand Down
7 changes: 3 additions & 4 deletions plugins/modules/guacamole_connections_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
URL_DELETE_CONNECTIONS_GROUP = URL_UPDATE_CONNECTIONS_GROUP



def guacamole_populate_connections_group_payload(module_params):
"""
Populate the json that we send to the guaccamole API to create new connections group
Expand All @@ -174,7 +173,7 @@ def guacamole_populate_connections_group_payload(module_params):
return payload


def guacamole_add_connections_group(base_url, validate_certs, datasource, auth_token, payload):
def guacamole_add_connections_group(base_url, validate_certs, datasource, auth_token, payload):
"""
Add a new connections group to the guacamole server.
"""
Expand Down Expand Up @@ -386,7 +385,7 @@ def main():
# if the group has child connections and force_deletion=false fail and exit
else:
module.fail_json(
msg="Won't delete a group with child connections unless force_deletion=True"
msg="Won't delete a group with child connections unless force_deletion=True"
)

# if the group to delete doesn't exists we just print a message
Expand All @@ -408,7 +407,7 @@ def main():

# check if something changed (idempotence)
if guacamole_connections_groups_before != guacamole_connections_groups_after:
result['changed'] = True
result['changed'] = True

# return connections_group_info{} for the added/updated/deleted connections group
if module.params.get('state') == 'present':
Expand Down
280 changes: 280 additions & 0 deletions plugins/modules/guacamole_user_group_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
#!/usr/bin/python

# Copyright: (c) 2020, Pablo Escobar <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
import json

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import open_url
from ansible_collections.scicore.guacamole.plugins.module_utils.guacamole import GuacamoleError, \
guacamole_get_token
__metaclass__ = type

ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}

DOCUMENTATION = '''
---
module: guacamole_user_group_users

short_description: Administer guacamole user-group users using the rest API

version_added: "2.9"

description:
- "Add or remove guacamole connections groups."

options:
base_url:
description:
- Url to access the guacamole API
required: true
aliases: ['url']
type: str

auth_username:
description:
- Guacamole admin user to login to the API
required: true
type: str

auth_password:
description:
- Guacamole admin user password to login to the API
required: true
type: str

validate_certs:
description:
- Validate ssl certs?
default: true
type: bool

users:
description:
- Dictionary that maps user-groups to a list of users.
type: dict
elements: str

state:
description:
- Create, delete or sync the user-group members.
default: 'present'
type: str
choices:
- present
- absent
- sync

author:
- Pablo Escobar Lopez (@pescobar)
- Garrett Bischof (@gwbischof)
- Robert Schaffer (@RobertSchaffer1)
'''

EXAMPLES = '''

- name: Assign user 'u1' to user group 'users1'
scicore.guacamole.guacamole_user_group_users:
base_url: http://localhost/guacamole
auth_username: guacadmin
auth_password: guacadmin
users:
"{{ { 'users1': ['u1'] } }}"
state: present

- name: Remove user 'u1' from user group 'users1'
scicore.guacamole.guacamole_user_group_users:
base_url: http://localhost/guacamole
auth_username: guacadmin
auth_password: guacadmin
users:
"{{ { 'users1': ['u1'] } }}"
state: absent


- name: Assign user 'u1' to user group 'users1', and remove any other users from 'users1'.
scicore.guacamole.guacamole_user_group_users:
base_url: http://localhost/guacamole
auth_username: guacadmin
auth_password: guacadmin
users:
"{{ { 'users1': ['u1'] } }}"
state: sync

'''

RETURN = '''
message:
description: Some extra info about what the module did
type: str
returned: always
'''

URL_GET_GROUP_MEMBERS = "{url}/api/session/data/{datasource}/userGroups/{group_name}/memberUsers?token={token}"
URL_UPDATE_USERS_IN_GROUP = URL_GET_GROUP_MEMBERS


def guacamole_get_user_group_users(base_url, validate_certs, datasource, auth_token, group_name):
"""
Returns a dict of dicts.
Each dict provides the details for one of the users groups defined in guacamole
"""

url_get_users_group_permissions = URL_GET_GROUP_MEMBERS.format(
url=base_url, datasource=datasource, token=auth_token, group_name=group_name)

try:
group_permissions = json.load(open_url(url_get_users_group_permissions, method='GET',
validate_certs=validate_certs))
except ValueError as e:
raise GuacamoleError(
'API returned invalid JSON when trying to obtain group permissions from %s: %s'
% (url_get_users_group_permissions, str(e)))
except Exception as e:
raise GuacamoleError('Could not obtain group permissions from %s: %s'
% (url_get_users_group_permissions, str(e)))

return group_permissions


def guacamole_update_users_in_group(base_url, validate_certs, datasource, auth_token, group_name, user, action):
"""
Add or remove a user to a group.
Action must be "add" or "remove"
"""

if action not in ['add', 'remove']:
raise GuacamoleError("action must be 'add' or 'remove'")

url_update_users_in_group = URL_UPDATE_USERS_IN_GROUP.format(
url=base_url, datasource=datasource, token=auth_token, group_name=group_name)

payload = [{
"op": action,
"path": '/',
"value": user,
}]

try:
headers = {'Content-Type': 'application/json'}
open_url(url_update_users_in_group, method='PATCH', validate_certs=validate_certs, headers=headers,
data=json.dumps(payload))
except Exception as e:
raise GuacamoleError('Could not update users for group %s in url %s. Error msg: %s'
% (group_name, url_update_users_in_group, str(e)))


def main():

# define the available arguments/parameters that a user can pass to
# the module
module_args = dict(
base_url=dict(type='str', aliases=['url'], required=True),
auth_username=dict(type='str', required=True),
auth_password=dict(type='str', required=True, no_log=True),
validate_certs=dict(type='bool', default=True),
users=dict(type='dict', default={}),
state=dict(type='str', choices=['absent', 'present', 'sync'], default='present')
)

result = dict(changed=False, msg='')

module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=False
)

# Obtain access token, initialize API
try:
guacamole_token = guacamole_get_token(
base_url=module.params.get('base_url'),
auth_username=module.params.get('auth_username'),
auth_password=module.params.get('auth_password'),
validate_certs=module.params.get('validate_certs'),
)
except GuacamoleError as e:
module.fail_json(msg=str(e))

users = module.params.get('users')

# Add users to user-group.
if module.params.get('state') in {'present', 'sync'}:
for group_name, usernames in users.items():

# Check the existing users for the user group.
try:
existing_users = set(guacamole_get_user_group_users(
base_url=module.params.get('base_url'),
validate_certs=module.params.get('validate_certs'),
datasource=guacamole_token['dataSource'],
auth_token=guacamole_token['authToken'],
group_name=group_name
))
except GuacamoleError as e:
module.fail_json(msg=str(e))

# Find which users need to be added.
new_users = set(usernames) - existing_users

# Add new users to user-group.
for new_user in new_users:
try:
guacamole_update_users_in_group(
base_url=module.params.get('base_url'),
validate_certs=module.params.get('validate_certs'),
datasource=guacamole_token['dataSource'],
auth_token=guacamole_token['authToken'],
group_name=group_name,
user=new_user,
action='add',
)
except GuacamoleError as e:
module.fail_json(msg=str(e))

result['changed'] = True

# Remove users from user group.
if module.params.get('state') in {'absent', 'sync'}:

for group_name, usernames in users.items():

# Find which users need to be removed.
existing_users = set(guacamole_get_user_group_users(
base_url=module.params.get('base_url'),
validate_certs=module.params.get('validate_certs'),
datasource=guacamole_token['dataSource'],
auth_token=guacamole_token['authToken'],
group_name=group_name
))
if module.params.get('state') == 'absent':
remove_users = set(usernames) & existing_users
else:
remove_users = existing_users - set(usernames)

# Remove users.
for remove_user in remove_users:
try:
guacamole_update_users_in_group(
base_url=module.params.get('base_url'),
validate_certs=module.params.get('validate_certs'),
datasource=guacamole_token['dataSource'],
auth_token=guacamole_token['authToken'],
group_name=group_name,
user=remove_user,
action='remove',
)
except GuacamoleError as e:
module.fail_json(msg=str(e))

result['changed'] = True
module.exit_json(**result)


if __name__ == '__main__':
main()
Loading
Loading