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

Mine minion acl master #55760

Merged
merged 26 commits into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
340cd8d
Removed mine_get from salt.utils.minions (as used only by salt.runner…
github-abcde Aug 2, 2019
ced6556
Moved code from salt.states.module:_call_function to salt.utils.funct…
github-abcde Aug 2, 2019
44a2e03
Enabled Aluminium. Edited 2-letter variable that pylint did not agree…
github-abcde Aug 2, 2019
da29e15
Rewritten most of salt.modules.mine. Moved generic functions out to s…
github-abcde Aug 2, 2019
5525864
Added minion-side ACL checks to _mine_get. Minions get no data if the…
github-abcde Aug 2, 2019
d463e3f
Added unittests.
github-abcde Aug 2, 2019
c98609a
Added documentation for the salt mine new function definition format …
github-abcde Aug 2, 2019
f1e8079
Reverted new variable name current_data (and removed typo).
github-abcde Aug 5, 2019
a011198
Replaced kwargs with func_args.
github-abcde Aug 5, 2019
2ae0f96
Merged named kwargs into **kwargs as it interferes with positional ar…
github-abcde Aug 5, 2019
c41bdeb
Added "parse_function" to make "call_function" more readable.
github-abcde Aug 5, 2019
8cc6d22
Fixed test that since 717bfb38da gets a different error.
github-abcde Aug 5, 2019
ee59024
Added Sodium release notes. Updated modules.mine docstrings.
github-abcde Aug 5, 2019
4d61da5
Added logging of denied mine requests.
github-abcde Aug 5, 2019
9885f8e
call_function: Fixed incorrect error on missing arg.
github-abcde Aug 6, 2019
7e260ae
Added unittests to avoid regression for issue 42270. Rewritten most t…
github-abcde Aug 6, 2019
9f5639a
Restore code additions that were lost during rebase-to-master
github-abcde Dec 24, 2019
8590040
Fix typo
github-abcde Dec 30, 2019
f4fb1aa
Merge branch 'master' into mine-minion-acl-master
github-abcde Dec 31, 2019
4f4c562
Remove function_definition format deprecation warnings
github-abcde Jan 3, 2020
bfee1c8
Update documentation
github-abcde Jan 3, 2020
fd480b0
Merge branch 'master' into mine-minion-acl-master
github-abcde Jan 3, 2020
d34fa64
Merge branch 'master' into mine-minion-acl-master
github-abcde Jan 5, 2020
bd8b63e
Remove broad exception catching
github-abcde Jan 6, 2020
fc62085
Merge branch 'master' into mine-minion-acl-master
github-abcde Jan 6, 2020
9318139
Merge branch 'master' into mine-minion-acl-master
github-abcde Jan 7, 2020
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
65 changes: 64 additions & 1 deletion doc/topics/mine/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,56 @@ the example below:
test.ping: []
network.ip_addrs:
interface: eth0
cidr: '10.0.0.0/8'
cidr: 10.0.0.0/8

In the example above :py:mod:`salt.modules.network.ip_addrs` has additional
filters to help narrow down the results. In the above example IP addresses
are only returned if they are on a eth0 interface and in the 10.0.0.0/8 IP
range.

.. versionchanged:: Sodium

The format to define mine_functions has been changed to allow the same format
as used for module.run. The old format (above) will still be supported.

.. code-block:: yaml

mine_functions:
test.ping: []
network.ip_addrs:
- interface: eth0
- cidr: 10.0.0.0/8
test.arg:
- isn't
- this
- fun
- this: that
- salt: stack

.. _mine_minion-side-acl:

Minion-side Access Control
--------------------------

.. versionadded:: Sodium

Mine functions can be targeted to only be available to specific minions. This
uses the same targeting parameters as :ref:`targeting` but with keywords ``allow_tgt``
and ``allow_tgt_type``. When a minion requests a function from the salt mine that
is not allowed to be requested by that minion (i.e. when looking up the combination
of ``allow_tgt`` and ``allow_tgt_type`` and the requesting minion is not in the list)
it will get no data, just as if the requested function is not present in the salt mine.

.. code-block:: yaml

mine_functions:
network.ip_addrs:
- interface: eth0
- cidr: 10.0.0.0/8
- allow_tgt: 'G@role:master'
- allow_tgt_type: 'compound'


Mine Functions Aliases
----------------------

Expand All @@ -71,6 +114,25 @@ positional and key-value arguments is not supported.
- mine_function: grains.get
- ip_interfaces

.. versionchanged:: Sodium

With the addition of the module.run-like format for defining mine_functions, the
method of adding aliases remains similar. Just add a ``mine_function`` kwarg with
the name of the real function to call, making the key below ``mine_functions``
the alias:

.. code-block:: yaml

mine_functions:
alias_name:
- mine_function: network.ip_addrs
- eth0
internal_ip_addrs:
- mine_function: network.ip_addrs
- cidr: 192.168.0.0/16
ip_list:
- mine_function: grains.get
- ip_interfaces

.. _mine_interval:

Expand Down Expand Up @@ -123,6 +185,7 @@ stored in a different location. Here is an example of a flat roster containing
of the Minion in question. This results in a non-trivial delay in
retrieving the requested data.


Minions Targeting with Mine
===========================

Expand Down
29 changes: 29 additions & 0 deletions doc/topics/releases/sodium.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:orphan:

====================================
Salt Release Notes - Codename Sodium
====================================


Salt mine updates
=================

Syntax update
-------------

The syntax for defining salt functions in config or pillar files has changed to
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also needs updating

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in bfee1c8

also support the syntax used in :py:mod:`module.run <salt.states.module.run>`.
The old syntax for the mine_function - as a dict, or as a list with dicts that
contain more than exactly one key - is still supported but discouraged in favor
of the more uniform syntax of module.run.

Minion-side ACL
---------------

Salt has had master-side ACL for the salt mine for some time, where the master
configuration contained `mine_get` that specified which minions could request
which functions. However, now you can specify which minions can access a function
in the salt mine function definition itself (or when calling :py:func:`mine.send <salt.modules.mine.send>`).
This targeting works the same as the generic minion targeting as specified
:ref:`here <targeting>`. The parameters used are ``allow_tgt`` and ``allow_tgt_type``.
See also :ref:`the documentation of the Salt Mine <mine_minion-side-acl>`.
67 changes: 56 additions & 11 deletions salt/daemons/masterapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import salt.utils.files
import salt.utils.gitfs
import salt.utils.verify
import salt.utils.mine
import salt.utils.minions
import salt.utils.gzip_util
import salt.utils.jid
Expand Down Expand Up @@ -548,6 +549,18 @@ def _mine_get(self, load, skip_verify=False):
if not skip_verify:
if any(key not in load for key in ('id', 'tgt', 'fun')):
return {}

if isinstance(load['fun'], six.string_types):
functions = list(set(load['fun'].split(',')))
_ret_dict = len(functions) > 1
elif isinstance(load['fun'], list):
functions = load['fun']
_ret_dict = True
else:
return {}

functions_allowed = []

if 'mine_get' in self.opts:
# If master side acl defined.
if not isinstance(self.opts['mine_get'], dict):
Expand All @@ -557,11 +570,18 @@ def _mine_get(self, load, skip_verify=False):
if re.match(match, load['id']):
if isinstance(self.opts['mine_get'][match], list):
perms.update(self.opts['mine_get'][match])
if not any(re.match(perm, load['fun']) for perm in perms):
for fun in functions:
if any(re.match(perm, fun) for perm in perms):
functions_allowed.append(fun)
if not functions_allowed:
return {}
else:
functions_allowed = functions

ret = {}
if not salt.utils.verify.valid_id(self.opts, load['id']):
return ret

expr_form = load.get('expr_form')
# keep both expr_form and tgt_type to ensure
# comptability between old versions of salt
Expand All @@ -580,30 +600,56 @@ def _mine_get(self, load, skip_verify=False):
greedy=False
)
minions = _res['minions']
minion_side_acl = {} # Cache minion-side ACL
for minion in minions:
fdata = self.cache.fetch('minions/{0}'.format(minion), 'mine')
if isinstance(fdata, dict):
fdata = fdata.get(load['fun'])
if fdata:
ret[minion] = fdata
mine_data = self.cache.fetch('minions/{0}'.format(minion), 'mine')
if not isinstance(mine_data, dict):
continue
for function in functions_allowed:
if function not in mine_data:
continue
mine_entry = mine_data[function]
mine_result = mine_data[function]
if isinstance(mine_entry, dict) and salt.utils.mine.MINE_ITEM_ACL_ID in mine_entry:
mine_result = mine_entry[salt.utils.mine.MINE_ITEM_ACL_DATA]
# Check and fill minion-side ACL cache
if function not in minion_side_acl.get(minion, {}):
if 'allow_tgt' in mine_entry:
# Only determine allowed targets if any have been specified.
# This prevents having to add a list of all minions as allowed targets.
salt.utils.dictupdate.set_dict_key_value(
minion_side_acl,
'{}:{}'.format(minion, function),
checker.check_minions(
mine_entry['allow_tgt'],
mine_entry.get('allow_tgt_type', 'glob')
)['minions']
)
if salt.utils.mine.minion_side_acl_denied(minion_side_acl, minion, function, load['id']):
continue
if _ret_dict:
ret.setdefault(function, {})[minion] = mine_result
else:
# There is only one function in functions_allowed.
ret[minion] = mine_result
return ret

def _mine(self, load, skip_verify=False):
'''
Return the mine data
Store/update the mine data in cache.
'''
if not skip_verify:
if 'id' not in load or 'data' not in load:
return False
if self.opts.get('minion_data_cache', False) or self.opts.get('enforce_mine_cache', False):
cbank = 'minions/{0}'.format(load['id'])
ckey = 'mine'
new_data = load['data']
if not load.get('clear', False):
data = self.cache.fetch(cbank, ckey)
if isinstance(data, dict):
data.update(load['data'])
load['data'] = data
self.cache.store(cbank, ckey, load['data'])
data.update(new_data)
self.cache.store(cbank, ckey, data)
return True

def _mine_delete(self, load):
Expand Down Expand Up @@ -703,7 +749,6 @@ def _pillar(self, load):
'''
if any(key not in load for key in ('id', 'grains')):
return False
# pillar = salt.pillar.Pillar(
log.debug('Master _pillar using ext: %s', load.get('ext'))
pillar = salt.pillar.get_pillar(
self.opts,
Expand Down
Loading