mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #43097 from twangboy/win_fix_group
Fix `group.present` for Windows
This commit is contained in:
commit
e9ccaa61d2
3 changed files with 196 additions and 59 deletions
|
@ -12,6 +12,7 @@ from __future__ import absolute_import
|
|||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
import salt.utils.win_functions
|
||||
|
||||
|
||||
try:
|
||||
|
@ -35,10 +36,18 @@ def __virtual__():
|
|||
return (False, "Module win_groupadd: module only works on Windows systems")
|
||||
|
||||
|
||||
def add(name, gid=None, system=False):
|
||||
def add(name, **kwargs):
|
||||
'''
|
||||
Add the specified group
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group to add
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of results
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -57,29 +66,32 @@ def add(name, gid=None, system=False):
|
|||
compObj = nt.GetObject('', 'WinNT://.,computer')
|
||||
newGroup = compObj.Create('group', name)
|
||||
newGroup.SetInfo()
|
||||
ret['changes'].append((
|
||||
'Successfully created group {0}'
|
||||
).format(name))
|
||||
ret['changes'].append('Successfully created group {0}'.format(name))
|
||||
except pywintypes.com_error as com_err:
|
||||
ret['result'] = False
|
||||
if len(com_err.excepinfo) >= 2:
|
||||
friendly_error = com_err.excepinfo[2].rstrip('\r\n')
|
||||
ret['comment'] = (
|
||||
'Failed to create group {0}. {1}'
|
||||
).format(name, friendly_error)
|
||||
ret['comment'] = 'Failed to create group {0}. {1}' \
|
||||
''.format(name, friendly_error)
|
||||
else:
|
||||
ret['result'] = None
|
||||
ret['comment'] = (
|
||||
'The group {0} already exists.'
|
||||
).format(name)
|
||||
ret['comment'] = 'The group {0} already exists.'.format(name)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def delete(name):
|
||||
def delete(name, **kwargs):
|
||||
'''
|
||||
Remove the named group
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group to remove
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of results
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -118,6 +130,14 @@ def info(name):
|
|||
'''
|
||||
Return information about a group
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group for which to get information
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of information about the group
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -151,6 +171,17 @@ def getent(refresh=False):
|
|||
'''
|
||||
Return info on all groups
|
||||
|
||||
Args:
|
||||
|
||||
refresh (bool):
|
||||
Refresh the info for all groups in ``__context__``. If False only
|
||||
the groups in ``__context__`` wil be returned. If True the
|
||||
``__context__`` will be refreshed with current data and returned.
|
||||
Default is False
|
||||
|
||||
Returns:
|
||||
A list of groups and their information
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -182,16 +213,26 @@ def getent(refresh=False):
|
|||
return ret
|
||||
|
||||
|
||||
def adduser(name, username):
|
||||
def adduser(name, username, **kwargs):
|
||||
'''
|
||||
add a user to a group
|
||||
Add a user to a group
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group to modify
|
||||
|
||||
username (str):
|
||||
The name of the user to add to the group
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of results
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' group.adduser foo username
|
||||
|
||||
'''
|
||||
|
||||
ret = {'name': name,
|
||||
|
@ -209,7 +250,7 @@ def adduser(name, username):
|
|||
'/', '\\').encode('ascii', 'backslashreplace').lower())
|
||||
|
||||
try:
|
||||
if __fixlocaluser(username.lower()) not in existingMembers:
|
||||
if salt.utils.win_functions.get_sam_name(username) not in existingMembers:
|
||||
if not __opts__['test']:
|
||||
groupObj.Add('WinNT://' + username.replace('\\', '/'))
|
||||
|
||||
|
@ -231,16 +272,26 @@ def adduser(name, username):
|
|||
return ret
|
||||
|
||||
|
||||
def deluser(name, username):
|
||||
def deluser(name, username, **kwargs):
|
||||
'''
|
||||
remove a user from a group
|
||||
Remove a user from a group
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group to modify
|
||||
|
||||
username (str):
|
||||
The name of the user to remove from the group
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of results
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' group.deluser foo username
|
||||
|
||||
'''
|
||||
|
||||
ret = {'name': name,
|
||||
|
@ -258,7 +309,7 @@ def deluser(name, username):
|
|||
'/', '\\').encode('ascii', 'backslashreplace').lower())
|
||||
|
||||
try:
|
||||
if __fixlocaluser(username.lower()) in existingMembers:
|
||||
if salt.utils.win_functions.get_sam_name(username) in existingMembers:
|
||||
if not __opts__['test']:
|
||||
groupObj.Remove('WinNT://' + username.replace('\\', '/'))
|
||||
|
||||
|
@ -280,16 +331,27 @@ def deluser(name, username):
|
|||
return ret
|
||||
|
||||
|
||||
def members(name, members_list):
|
||||
def members(name, members_list, **kwargs):
|
||||
'''
|
||||
remove a user from a group
|
||||
Ensure a group contains only the members in the list
|
||||
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the group to modify
|
||||
|
||||
members_list (str):
|
||||
A single user or a comma separated list of users. The group will
|
||||
contain only the users specified in this list.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of results
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' group.members foo 'user1,user2,user3'
|
||||
|
||||
'''
|
||||
|
||||
ret = {'name': name,
|
||||
|
@ -297,7 +359,7 @@ def members(name, members_list):
|
|||
'changes': {'Users Added': [], 'Users Removed': []},
|
||||
'comment': []}
|
||||
|
||||
members_list = [__fixlocaluser(thisMember) for thisMember in members_list.lower().split(",")]
|
||||
members_list = [salt.utils.win_functions.get_sam_name(m) for m in members_list.split(",")]
|
||||
if not isinstance(members_list, list):
|
||||
ret['result'] = False
|
||||
ret['comment'].append('Members is not a list object')
|
||||
|
@ -364,27 +426,26 @@ def members(name, members_list):
|
|||
return ret
|
||||
|
||||
|
||||
def __fixlocaluser(username):
|
||||
'''
|
||||
prefixes a username w/o a backslash with the computername
|
||||
|
||||
i.e. __fixlocaluser('Administrator') would return 'computername\administrator'
|
||||
'''
|
||||
if '\\' not in username:
|
||||
username = ('{0}\\{1}').format(__salt__['grains.get']('host'), username)
|
||||
|
||||
return username.lower()
|
||||
|
||||
|
||||
def list_groups(refresh=False):
|
||||
'''
|
||||
Return a list of groups
|
||||
|
||||
Args:
|
||||
|
||||
refresh (bool):
|
||||
Refresh the info for all groups in ``__context__``. If False only
|
||||
the groups in ``__context__`` wil be returned. If True, the
|
||||
``__context__`` will be refreshed with current data and returned.
|
||||
Default is False
|
||||
|
||||
Returns:
|
||||
list: A list of groups on the machine
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' group.getent
|
||||
salt '*' group.list_groups
|
||||
'''
|
||||
if 'group.list_groups' in __context__ and not refresh:
|
||||
return __context__['group.getent']
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
r'''
|
||||
Management of user groups
|
||||
=========================
|
||||
|
||||
The group module is used to create and manage unix group settings, groups
|
||||
can be either present or absent:
|
||||
The group module is used to create and manage group settings, groups can be
|
||||
either present or absent. User/Group names can be passed to the ``adduser``,
|
||||
``deluser``, and ``members`` parameters. ``adduser`` and ``deluser`` can be used
|
||||
together but not with ``members``.
|
||||
|
||||
In Windows, if no domain is specified in the user or group name (ie:
|
||||
`DOMAIN\username``) the module will assume a local user or group.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -36,6 +41,10 @@ import sys
|
|||
# Import 3rd-party libs
|
||||
import salt.ext.six as six
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils
|
||||
import salt.utils.win_functions
|
||||
|
||||
|
||||
def _changes(name,
|
||||
gid=None,
|
||||
|
@ -50,6 +59,18 @@ def _changes(name,
|
|||
if not lgrp:
|
||||
return False
|
||||
|
||||
# User and Domain names are not case sensitive in Windows. Let's make them
|
||||
# all lower case so we can compare properly
|
||||
if salt.utils.is_windows():
|
||||
if lgrp['members']:
|
||||
lgrp['members'] = [user.lower() for user in lgrp['members']]
|
||||
if members:
|
||||
members = [salt.utils.win_functions.get_sam_name(user) for user in members]
|
||||
if addusers:
|
||||
addusers = [salt.utils.win_functions.get_sam_name(user) for user in addusers]
|
||||
if delusers:
|
||||
delusers = [salt.utils.win_functions.get_sam_name(user) for user in delusers]
|
||||
|
||||
change = {}
|
||||
if gid:
|
||||
if lgrp['gid'] != gid:
|
||||
|
@ -57,7 +78,7 @@ def _changes(name,
|
|||
|
||||
if members:
|
||||
# -- if new member list if different than the current
|
||||
if set(lgrp['members']) ^ set(members):
|
||||
if set(lgrp['members']).symmetric_difference(members):
|
||||
change['members'] = members
|
||||
|
||||
if addusers:
|
||||
|
@ -79,31 +100,58 @@ def present(name,
|
|||
addusers=None,
|
||||
delusers=None,
|
||||
members=None):
|
||||
'''
|
||||
r'''
|
||||
Ensure that a group is present
|
||||
|
||||
name
|
||||
The name of the group to manage
|
||||
Args:
|
||||
|
||||
gid
|
||||
The group id to assign to the named group; if left empty, then the next
|
||||
available group id will be assigned
|
||||
name (str):
|
||||
The name of the group to manage
|
||||
|
||||
system
|
||||
Whether or not the named group is a system group. This is essentially
|
||||
the '-r' option of 'groupadd'.
|
||||
gid (str):
|
||||
The group id to assign to the named group; if left empty, then the
|
||||
next available group id will be assigned. Ignored on Windows
|
||||
|
||||
addusers
|
||||
List of additional users to be added as a group members.
|
||||
system (bool):
|
||||
Whether or not the named group is a system group. This is essentially
|
||||
the '-r' option of 'groupadd'. Ignored on Windows
|
||||
|
||||
delusers
|
||||
Ensure these user are removed from the group membership.
|
||||
addusers (list):
|
||||
List of additional users to be added as a group members. Cannot
|
||||
conflict with names in delusers. Cannot be used in conjunction with
|
||||
members.
|
||||
|
||||
members
|
||||
Replace existing group members with a list of new members.
|
||||
delusers (list):
|
||||
Ensure these user are removed from the group membership. Cannot
|
||||
conflict with names in addusers. Cannot be used in conjunction with
|
||||
members.
|
||||
|
||||
Note: Options 'members' and 'addusers/delusers' are mutually exclusive and
|
||||
can not be used together.
|
||||
members (list):
|
||||
Replace existing group members with a list of new members. Cannot be
|
||||
used in conjunction with addusers or delusers.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Adds DOMAIN\db_admins and Administrators to the local db_admin group
|
||||
# Removes Users
|
||||
db_admin:
|
||||
group.present:
|
||||
- addusers:
|
||||
- DOMAIN\db_admins
|
||||
- Administrators
|
||||
- delusers:
|
||||
- Users
|
||||
|
||||
# Ensures only DOMAIN\domain_admins and the local Administrator are
|
||||
# members of the local Administrators group. All other users are
|
||||
# removed
|
||||
Administrators:
|
||||
group.present:
|
||||
- members:
|
||||
- DOMAIN\domain_admins
|
||||
- Administrator
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -233,8 +281,17 @@ def absent(name):
|
|||
'''
|
||||
Ensure that the named group is absent
|
||||
|
||||
name
|
||||
The name of the group to remove
|
||||
Args:
|
||||
name (str):
|
||||
The name of the group to remove
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Removes the local group `db_admin`
|
||||
db_admin:
|
||||
group.absent
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
|
|
@ -4,6 +4,9 @@ Various functions to be used by windows during start up and to monkey patch
|
|||
missing functions in other modules
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
# Import 3rd Party Libs
|
||||
|
@ -138,3 +141,19 @@ def get_current_user():
|
|||
return False
|
||||
|
||||
return user_name
|
||||
|
||||
|
||||
def get_sam_name(username):
|
||||
'''
|
||||
Gets the SAM name for a user. It basically prefixes a username without a
|
||||
backslash with the computer name. If the username contains a backslash, it
|
||||
is returned as is.
|
||||
|
||||
Everything is returned lower case
|
||||
|
||||
i.e. salt.utils.fix_local_user('Administrator') would return 'computername\administrator'
|
||||
'''
|
||||
if '\\' not in username:
|
||||
username = '{0}\\{1}'.format(platform.node(), username)
|
||||
|
||||
return username.lower()
|
||||
|
|
Loading…
Add table
Reference in a new issue