mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #44324 from benediktwerner/accept-minions-from-grains
Automatically accept minion keys based on grains
This commit is contained in:
commit
95d9eb5744
@ -36,7 +36,7 @@
|
||||
|
||||
# The root directory prepended to these options: pki_dir, cachedir,
|
||||
# sock_dir, log_file, autosign_file, autoreject_file, extension_modules,
|
||||
# key_logfile, pidfile:
|
||||
# key_logfile, pidfile, autosign_grains_dir:
|
||||
#root_dir: /
|
||||
|
||||
# The path to the master's configuration file.
|
||||
@ -351,6 +351,11 @@
|
||||
# the autosign_file and the auto_accept setting.
|
||||
#autoreject_file: /etc/salt/autoreject.conf
|
||||
|
||||
# If the autosign_grains_dir is specified, incoming keys from minons with grain
|
||||
# values matching those defined in files in this directory will be accepted
|
||||
# automatically. This is insecure. Minions need to be configured to send the grains.
|
||||
#autosign_grains_dir: /etc/salt/autosign_grains
|
||||
|
||||
# Enable permissive access to the salt keys. This allows you to run the
|
||||
# master or minion as root, but have a non-root group be given access to
|
||||
# your pki_dir. To make the access explicit, root must belong to the group
|
||||
@ -1297,4 +1302,3 @@
|
||||
# use OS defaults, typically 75 seconds on Linux, see
|
||||
# /proc/sys/net/ipv4/tcp_keepalive_intvl.
|
||||
#tcp_keepalive_intvl: -1
|
||||
|
||||
|
@ -666,6 +666,12 @@
|
||||
# certfile: <path_to_certfile>
|
||||
# ssl_version: PROTOCOL_TLSv1_2
|
||||
|
||||
# Grains to be sent to the master on authentication to check if the minion's key
|
||||
# will be accepted automatically. Needs to be configured on the master.
|
||||
#autosign_grains:
|
||||
# - uuid
|
||||
# - server_id
|
||||
|
||||
|
||||
###### Reactor Settings #####
|
||||
###########################################
|
||||
|
@ -37,7 +37,7 @@ syndic_user: salt
|
||||
|
||||
# The root directory prepended to these options: pki_dir, cachedir,
|
||||
# sock_dir, log_file, autosign_file, autoreject_file, extension_modules,
|
||||
# key_logfile, pidfile:
|
||||
# key_logfile, pidfile, autosign_grains_dir:
|
||||
#root_dir: /
|
||||
|
||||
# The path to the master's configuration file.
|
||||
@ -320,6 +320,11 @@ syndic_user: salt
|
||||
# the autosign_file and the auto_accept setting.
|
||||
#autoreject_file: /etc/salt/autoreject.conf
|
||||
|
||||
# If the autosign_grains_dir is specified, incoming keys from minons with grain
|
||||
# values matching those defined in files in this directory will be accepted
|
||||
# automatically. This is insecure. Minions need to be configured to send the grains.
|
||||
#autosign_grains_dir: /etc/salt/autosign_grains
|
||||
|
||||
# Enable permissive access to the salt keys. This allows you to run the
|
||||
# master or minion as root, but have a non-root group be given access to
|
||||
# your pki_dir. To make the access explicit, root must belong to the group
|
||||
@ -1248,4 +1253,3 @@ syndic_user: salt
|
||||
# use OS defaults, typically 75 seconds on Linux, see
|
||||
# /proc/sys/net/ipv4/tcp_keepalive_intvl.
|
||||
#tcp_keepalive_intvl: -1
|
||||
|
||||
|
@ -140,7 +140,8 @@ an alternative root.
|
||||
This directory is prepended to the following options:
|
||||
:conf_master:`pki_dir`, :conf_master:`cachedir`, :conf_master:`sock_dir`,
|
||||
:conf_master:`log_file`, :conf_master:`autosign_file`,
|
||||
:conf_master:`autoreject_file`, :conf_master:`pidfile`.
|
||||
:conf_master:`autoreject_file`, :conf_master:`pidfile`,
|
||||
:conf_master:`autosign_grains_dir`.
|
||||
|
||||
.. conf_master:: conf_file
|
||||
|
||||
@ -1321,6 +1322,32 @@ minion IDs for which keys will automatically be rejected. Will override both
|
||||
membership in the :conf_master:`autosign_file` and the
|
||||
:conf_master:`auto_accept` setting.
|
||||
|
||||
.. conf_master:: autosign_grains_dir
|
||||
|
||||
``autosign_grains_dir``
|
||||
-----------------------
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
Default: ``not defined``
|
||||
|
||||
If the ``autosign_grains_dir`` is specified, incoming keys from minions with
|
||||
grain values that match those defined in files in the autosign_grains_dir
|
||||
will be accepted automatically. Grain values that should be accepted automatically
|
||||
can be defined by creating a file named like the corresponding grain in the
|
||||
autosign_grains_dir and writing the values into that file, one value per line.
|
||||
Lines starting with a ``#`` will be ignored.
|
||||
Minion must be configured to send the corresponding grains on authentication.
|
||||
This should still be considered a less than secure option, due to the fact
|
||||
that trust is based on just the requesting minion.
|
||||
|
||||
Please see the :ref:`Autoaccept Minions from Grains <tutorial-autoaccept-grains>`
|
||||
documentation for more infomation.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
autosign_grains_dir: /etc/salt/autosign_grains
|
||||
|
||||
.. conf_master:: permissive_pki_access
|
||||
|
||||
``permissive_pki_access``
|
||||
|
@ -2423,6 +2423,27 @@ minion's pki directory.
|
||||
|
||||
master_sign_key_name: <filename_without_suffix>
|
||||
|
||||
.. conf_minion:: autosign_grains
|
||||
|
||||
``autosign_grains``
|
||||
-------------------
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
Default: ``not defined``
|
||||
|
||||
The grains that should be sent to the master on authentication to decide if
|
||||
the minion's key should be accepted automatically.
|
||||
|
||||
Please see the :ref:`Autoaccept Minions from Grains <tutorial-autoaccept-grains>`
|
||||
documentation for more infomation.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
autosign_grains:
|
||||
- uuid
|
||||
- server_id
|
||||
|
||||
.. conf_minion:: always_verify_signature
|
||||
|
||||
``always_verify_signature``
|
||||
|
44
doc/topics/tutorials/autoaccept_grains.rst
Normal file
44
doc/topics/tutorials/autoaccept_grains.rst
Normal file
@ -0,0 +1,44 @@
|
||||
.. _tutorial-autoaccept-grains:
|
||||
|
||||
==============================
|
||||
Autoaccept minions from Grains
|
||||
==============================
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
To automatically accept minions based on certain characteristics, e.g. the ``uuid``
|
||||
you can specify certain grain values on the salt master. Minions with matching grains
|
||||
will have their keys automatically accepted.
|
||||
|
||||
1. Configure the autosign_grains_dir in the master config file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
autosign_grains_dir: /etc/salt/autosign_grains
|
||||
|
||||
|
||||
2. Configure the grain values to be accepted
|
||||
|
||||
Place a file named like the grain in the autosign_grains_dir and write the values that
|
||||
should be accepted automatically inside that file. For example to automatically
|
||||
accept minions based on their ``uuid`` create a file named ``/etc/salt/autosign_grains/uuid``:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
8f7d68e2-30c5-40c6-b84a-df7e978a03ee
|
||||
1d3c5473-1fbc-479e-b0c7-877705a0730f
|
||||
|
||||
The master is now setup to accept minions with either of the two specified uuids.
|
||||
Multiple values must always be written into separate lines.
|
||||
Lines starting with a ``#`` are ignored.
|
||||
|
||||
|
||||
3. Configure the minion to send the specific grains to the master in the minion config file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
autosign_grains:
|
||||
- uuid
|
||||
|
||||
Now you should be able to start salt-minion and run ``salt-call
|
||||
state.apply`` or any other salt commands that require master authentication.
|
@ -35,3 +35,4 @@ Tutorials Index
|
||||
* :ref:`Multi-cloud orchestration with Apache Libcloud <tutorial-libcloud>`
|
||||
* :ref:`Running Salt States and Commands in Docker Containers <docker-sls>`
|
||||
* :ref:`Preseed Minion with Accepted Key <tutorial-preseed-key>`
|
||||
* :ref:`Autoaccept Minions from Grains <tutorial-autoaccept-grains>`
|
||||
|
@ -2444,7 +2444,7 @@ def syndic_config(master_config_path,
|
||||
# Prepend root_dir to other paths
|
||||
prepend_root_dirs = [
|
||||
'pki_dir', 'key_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'autosign_file', 'autoreject_file', 'token_dir'
|
||||
'autosign_file', 'autoreject_file', 'token_dir', 'autosign_grains_dir'
|
||||
]
|
||||
for config_key in ('log_file', 'key_logfile', 'syndic_log_file'):
|
||||
# If this is not a URI and instead a local path
|
||||
@ -3852,7 +3852,7 @@ def apply_master_config(overrides=None, defaults=None):
|
||||
prepend_root_dirs = [
|
||||
'pki_dir', 'key_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'autosign_file', 'autoreject_file', 'token_dir', 'syndic_dir',
|
||||
'sqlite_queue_dir'
|
||||
'sqlite_queue_dir', 'autosign_grains_dir'
|
||||
]
|
||||
|
||||
# These can be set to syslog, so, not actual paths on the system
|
||||
|
@ -740,6 +740,11 @@ class AsyncAuth(object):
|
||||
payload = {}
|
||||
payload[u'cmd'] = u'_auth'
|
||||
payload[u'id'] = self.opts[u'id']
|
||||
if u'autosign_grains' in self.opts:
|
||||
autosign_grains = {}
|
||||
for grain in self.opts[u'autosign_grains']:
|
||||
autosign_grains[grain] = self.opts[u'grains'].get(grain, None)
|
||||
payload[u'autosign_grains'] = autosign_grains
|
||||
try:
|
||||
pubkey_path = os.path.join(self.opts[u'pki_dir'], self.mpub)
|
||||
with salt.utils.files.fopen(pubkey_path) as f:
|
||||
|
@ -348,6 +348,33 @@ class AutoKey(object):
|
||||
os.remove(stub_file)
|
||||
return True
|
||||
|
||||
def check_autosign_grains(self, autosign_grains):
|
||||
'''
|
||||
Check for matching grains in the autosign_grains_dir.
|
||||
'''
|
||||
if not autosign_grains or u'autosign_grains_dir' not in self.opts:
|
||||
return False
|
||||
|
||||
autosign_grains_dir = self.opts[u'autosign_grains_dir']
|
||||
for root, dirs, filenames in os.walk(autosign_grains_dir):
|
||||
for grain in filenames:
|
||||
if grain in autosign_grains:
|
||||
grain_file = os.path.join(autosign_grains_dir, grain)
|
||||
|
||||
if not self.check_permissions(grain_file):
|
||||
message = 'Wrong permissions for {0}, ignoring content'
|
||||
log.warning(message.format(grain_file))
|
||||
continue
|
||||
|
||||
with salt.utils.files.fopen(grain_file, u'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith(u'#'):
|
||||
continue
|
||||
if autosign_grains[grain] == line:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_autoreject(self, keyid):
|
||||
'''
|
||||
Checks if the specified keyid should automatically be rejected.
|
||||
@ -357,7 +384,7 @@ class AutoKey(object):
|
||||
self.opts.get('autoreject_file', None)
|
||||
)
|
||||
|
||||
def check_autosign(self, keyid):
|
||||
def check_autosign(self, keyid, autosign_grains=None):
|
||||
'''
|
||||
Checks if the specified keyid should automatically be signed.
|
||||
'''
|
||||
@ -367,6 +394,8 @@ class AutoKey(object):
|
||||
return True
|
||||
if self.check_autosign_dir(keyid):
|
||||
return True
|
||||
if self.check_autosign_grains(autosign_grains):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
@ -211,7 +211,7 @@ class AESReqServerMixin(object):
|
||||
|
||||
# Check if key is configured to be auto-rejected/signed
|
||||
auto_reject = self.auto_key.check_autoreject(load['id'])
|
||||
auto_sign = self.auto_key.check_autosign(load['id'])
|
||||
auto_sign = self.auto_key.check_autosign(load['id'], load.get(u'autosign_grains', None))
|
||||
|
||||
pubfn = os.path.join(self.opts['pki_dir'],
|
||||
'minions',
|
||||
|
@ -838,6 +838,8 @@ class TestDaemon(object):
|
||||
opts_dict['ext_pillar'].append(
|
||||
{'cmd_yaml': 'cat {0}'.format(os.path.join(FILES, 'ext.yaml'))})
|
||||
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
for opts_dict in (master_opts, syndic_master_opts):
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
@ -851,6 +853,14 @@ class TestDaemon(object):
|
||||
)
|
||||
opts_dict['extension_modules'] = os.path.join(opts_dict['root_dir'], 'extension_modules')
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
new_autosign_file_path = os.path.join(opts_dict['root_dir'], 'autosign_file')
|
||||
shutil.copyfile(
|
||||
os.path.join(INTEGRATION_TEST_DIR, 'files', 'autosign_file'),
|
||||
new_autosign_file_path
|
||||
)
|
||||
os.chmod(new_autosign_file_path, autosign_file_permissions)
|
||||
|
||||
# Point the config values to the correct temporary paths
|
||||
for name in ('hosts', 'aliases'):
|
||||
optname = '{0}.file'.format(name)
|
||||
|
1
tests/integration/daemons/__init__.py
Normal file
1
tests/integration/daemons/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
79
tests/integration/daemons/test_masterapi.py
Normal file
79
tests/integration/daemons/test_masterapi.py
Normal file
@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ShellCase
|
||||
from tests.support.paths import TMP, INTEGRATION_TEST_DIR
|
||||
|
||||
# Import 3rd-party libs
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.files
|
||||
|
||||
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
autosign_file_path = os.path.join(TMP, 'rootdir', 'autosign_file')
|
||||
|
||||
|
||||
class AutosignGrainsTest(ShellCase):
|
||||
'''
|
||||
Test autosigning minions based on grain values.
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
shutil.copyfile(
|
||||
os.path.join(INTEGRATION_TEST_DIR, 'files', 'autosign_grains', 'autosign_file'),
|
||||
autosign_file_path
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
self.run_key('-d minion -y')
|
||||
self.run_call('test.ping -l quiet') # get minon to try to authenticate itself again
|
||||
|
||||
if 'minion' in self.run_key('-l acc'):
|
||||
self.tearDown()
|
||||
self.skipTest('Could not deauthorize minion')
|
||||
if 'minion' not in self.run_key('-l un'):
|
||||
self.tearDown()
|
||||
self.skipTest('minion did not try to reauthenticate itself')
|
||||
|
||||
self.autosign_grains_dir = os.path.join(self.master_opts['autosign_grains_dir'])
|
||||
if not os.path.isdir(self.autosign_grains_dir):
|
||||
os.makedirs(self.autosign_grains_dir)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.copyfile(
|
||||
os.path.join(INTEGRATION_TEST_DIR, 'files', 'autosign_file'),
|
||||
autosign_file_path
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
self.run_call('test.ping -l quiet') # get minon to authenticate itself again
|
||||
|
||||
if os.path.isdir(self.autosign_grains_dir):
|
||||
shutil.rmtree(self.autosign_grains_dir)
|
||||
|
||||
def test_autosign_grains_accept(self):
|
||||
grain_file_path = os.path.join(self.autosign_grains_dir, 'test_grain')
|
||||
with salt.utils.files.fopen(grain_file_path, 'w') as f:
|
||||
f.write('#invalid_value\ncheese')
|
||||
os.chmod(grain_file_path, autosign_file_permissions)
|
||||
|
||||
self.run_call('test.ping -l quiet') # get minon to try to authenticate itself again
|
||||
self.assertIn('minion', self.run_key('-l acc'))
|
||||
|
||||
def test_autosign_grains_fail(self):
|
||||
grain_file_path = os.path.join(self.autosign_grains_dir, 'test_grain')
|
||||
with salt.utils.files.fopen(grain_file_path, 'w') as f:
|
||||
f.write('#cheese\ninvalid_value')
|
||||
os.chmod(grain_file_path, autosign_file_permissions)
|
||||
|
||||
self.run_call('test.ping -l quiet') # get minon to try to authenticate itself again
|
||||
self.assertNotIn('minion', self.run_key('-l acc'))
|
||||
self.assertIn('minion', self.run_key('-l un'))
|
2
tests/integration/files/autosign_file
Normal file
2
tests/integration/files/autosign_file
Normal file
@ -0,0 +1,2 @@
|
||||
# match everything
|
||||
*
|
2
tests/integration/files/autosign_grains/autosign_file
Normal file
2
tests/integration/files/autosign_grains/autosign_file
Normal file
@ -0,0 +1,2 @@
|
||||
# match everything except 'minion'
|
||||
^(?!minion$)
|
@ -8,7 +8,6 @@ worker_threads: 3
|
||||
pidfile: master.pid
|
||||
sock_dir: master_sock
|
||||
timeout: 12
|
||||
open_mode: True
|
||||
fileserver_list_cache_time: 0
|
||||
file_buffer_size: 8192
|
||||
file_recv: True
|
||||
@ -97,3 +96,6 @@ libcloud_dns:
|
||||
key: 12345
|
||||
secret: mysecret
|
||||
shopper_id: 12345
|
||||
|
||||
autosign_grains_dir: autosign_grains
|
||||
autosign_file: autosign_file
|
||||
|
@ -103,3 +103,6 @@ osenv:
|
||||
cmd_blacklist_glob:
|
||||
- 'bad_command *'
|
||||
- 'second_bad_command *'
|
||||
|
||||
autosign_grains:
|
||||
- test_grain
|
||||
|
@ -169,6 +169,9 @@ TEST_SUITES = {
|
||||
'external_api':
|
||||
{'display_name': 'ExternalAPIs',
|
||||
'path': 'integration/externalapi'},
|
||||
'daemons':
|
||||
{'display_name': 'Daemon',
|
||||
'path': 'integration/daemons'},
|
||||
}
|
||||
|
||||
|
||||
@ -468,6 +471,14 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
|
||||
default=False,
|
||||
help='Run venafi runner tests'
|
||||
)
|
||||
self.test_selection_group.add_option(
|
||||
'--daemons',
|
||||
'--daemon-tests',
|
||||
dest='daemons',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Run salt/daemons/*.py tests'
|
||||
)
|
||||
|
||||
def validate_options(self):
|
||||
if self.options.cloud_provider or self.options.external_api:
|
||||
|
@ -3,6 +3,7 @@
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
from functools import wraps
|
||||
import io
|
||||
import stat
|
||||
|
||||
# Import Salt libs
|
||||
@ -58,7 +59,8 @@ class AutoKeyTest(TestCase):
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
opts = {'user': 'test_user'}
|
||||
opts = salt.config.master_config(None)
|
||||
opts[u'user'] = u'test_user'
|
||||
self.auto_key = masterapi.AutoKey(opts)
|
||||
self.stats = {}
|
||||
|
||||
@ -135,6 +137,93 @@ class AutoKeyTest(TestCase):
|
||||
self.stats['testfile'] = {'mode': gen_permissions('w', '', ''), 'gid': 0}
|
||||
self.assertTrue(self.auto_key.check_permissions('testfile'))
|
||||
|
||||
def _test_check_autosign_grains(self,
|
||||
test_func,
|
||||
file_content=u'test_value',
|
||||
file_name=u'test_grain',
|
||||
autosign_grains_dir=u'test_dir',
|
||||
permissions_ret=True):
|
||||
'''
|
||||
Helper function for testing autosign_grains().
|
||||
|
||||
Patches ``os.walk`` to return only ``file_name`` and ``salt.utils.files.fopen`` to open a
|
||||
mock file with ``file_content`` as content. Optionally sets ``opts`` values.
|
||||
Then executes test_func. The ``os.walk`` and ``salt.utils.files.fopen`` mock objects
|
||||
are passed to the function as arguments.
|
||||
'''
|
||||
if autosign_grains_dir:
|
||||
self.auto_key.opts[u'autosign_grains_dir'] = autosign_grains_dir
|
||||
mock_file = io.StringIO(file_content)
|
||||
mock_dirs = [(None, None, [file_name])]
|
||||
|
||||
with patch('os.walk', MagicMock(return_value=mock_dirs)) as mock_walk, \
|
||||
patch('salt.utils.files.fopen', MagicMock(return_value=mock_file)) as mock_open, \
|
||||
patch('salt.daemons.masterapi.AutoKey.check_permissions',
|
||||
MagicMock(return_value=permissions_ret)) as mock_permissions:
|
||||
test_func(mock_walk, mock_open, mock_permissions)
|
||||
|
||||
def test_check_autosign_grains_no_grains(self):
|
||||
'''
|
||||
Asserts that autosigning from grains fails when no grain values are passed.
|
||||
'''
|
||||
def test_func(mock_walk, mock_open, mock_permissions):
|
||||
self.assertFalse(self.auto_key.check_autosign_grains(None))
|
||||
self.assertEqual(mock_walk.call_count, 0)
|
||||
self.assertEqual(mock_open.call_count, 0)
|
||||
self.assertEqual(mock_permissions.call_count, 0)
|
||||
|
||||
self.assertFalse(self.auto_key.check_autosign_grains({}))
|
||||
self.assertEqual(mock_walk.call_count, 0)
|
||||
self.assertEqual(mock_open.call_count, 0)
|
||||
self.assertEqual(mock_permissions.call_count, 0)
|
||||
|
||||
self._test_check_autosign_grains(test_func)
|
||||
|
||||
def test_check_autosign_grains_no_autosign_grains_dir(self):
|
||||
'''
|
||||
Asserts that autosigning from grains fails when the \'autosign_grains_dir\' config option
|
||||
is undefined.
|
||||
'''
|
||||
def test_func(mock_walk, mock_open, mock_permissions):
|
||||
self.assertFalse(self.auto_key.check_autosign_grains({u'test_grain': u'test_value'}))
|
||||
self.assertEqual(mock_walk.call_count, 0)
|
||||
self.assertEqual(mock_open.call_count, 0)
|
||||
self.assertEqual(mock_permissions.call_count, 0)
|
||||
|
||||
self._test_check_autosign_grains(test_func, autosign_grains_dir=None)
|
||||
|
||||
def test_check_autosign_grains_accept(self):
|
||||
'''
|
||||
Asserts that autosigning from grains passes when a matching grain value is in an
|
||||
autosign_grain file.
|
||||
'''
|
||||
def test_func(*args):
|
||||
self.assertTrue(self.auto_key.check_autosign_grains({u'test_grain': u'test_value'}))
|
||||
|
||||
file_content = u'#test_ignore\ntest_value'
|
||||
self._test_check_autosign_grains(test_func, file_content=file_content)
|
||||
|
||||
def test_check_autosign_grains_accept_not(self):
|
||||
'''
|
||||
Asserts that autosigning from grains fails when the grain value is not in the
|
||||
autosign_grain files.
|
||||
'''
|
||||
def test_func(*args):
|
||||
self.assertFalse(self.auto_key.check_autosign_grains({u'test_grain': u'test_invalid'}))
|
||||
|
||||
file_content = u'#test_invalid\ntest_value'
|
||||
self._test_check_autosign_grains(test_func, file_content=file_content)
|
||||
|
||||
def test_check_autosign_grains_invalid_file_permissions(self):
|
||||
'''
|
||||
Asserts that autosigning from grains fails when the grain file has the wrong permissions.
|
||||
'''
|
||||
def test_func(*args):
|
||||
self.assertFalse(self.auto_key.check_autosign_grains({u'test_grain': u'test_value'}))
|
||||
|
||||
file_content = u'#test_ignore\ntest_value'
|
||||
self._test_check_autosign_grains(test_func, file_content=file_content, permissions_ret=False)
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class LocalFuncsTestCase(TestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user