mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add the Thycotic Secret Server lookup plugin. (#91)
* Add the Thycotic Secret Server lookup plugin. * Update plugins/lookup/tss.py Co-Authored-By: Felix Fontein <felix@fontein.de> * Fix import error check per code review. * Apply suggestions from code review Co-Authored-By: Felix Fontein <felix@fontein.de> * Trivial changes based on suggestions from code review. * Add a unittest for plugins/lookup/tss.py * Add copyrights. * Fixed formatting bug in test_tss.py * Fix formatting bugs in tss.py and test_tss.py * Apply suggestions from code review Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
151551b04f
commit
4c6e2f2a40
2 changed files with 174 additions and 0 deletions
131
plugins/lookup/tss.py
Normal file
131
plugins/lookup/tss.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright: (c) 2020, Adam Migus <adam@migus.org>
|
||||
# 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
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
lookup: tss
|
||||
author: Adam Migus (adam@migus.org)
|
||||
short_description: Get secrets from Thycotic Secret Server
|
||||
version_added: 1.0.0
|
||||
description:
|
||||
- Uses the Thycotic Secret Server Python SDK to get Secrets from Secret
|
||||
Server using token authentication with I(username) and I(password) on
|
||||
the REST API at I(base_url).
|
||||
requirements:
|
||||
- python-tss-sdk - https://pypi.org/project/python-tss-sdk/
|
||||
options:
|
||||
_terms:
|
||||
description: The integer ID of the secret.
|
||||
required: true
|
||||
type: int
|
||||
base_url:
|
||||
description: The base URL of the server, e.g. C(https://localhost/SecretServer).
|
||||
env:
|
||||
- name: TSS_BASE_URL
|
||||
ini:
|
||||
- section: tss_lookup
|
||||
key: base_url
|
||||
required: true
|
||||
username:
|
||||
description: The username with which to request the OAuth2 Access Grant.
|
||||
env:
|
||||
- name: TSS_USERNAME
|
||||
ini:
|
||||
- section: tss_lookup
|
||||
key: username
|
||||
required: true
|
||||
password:
|
||||
description: The password associated with the supplied username.
|
||||
env:
|
||||
- name: TSS_PASSWORD
|
||||
ini:
|
||||
- section: tss_lookup
|
||||
key: password
|
||||
required: true
|
||||
api_path_uri:
|
||||
default: /api/v1
|
||||
description: The path to append to the base URL to form a valid REST
|
||||
API request.
|
||||
env:
|
||||
- name: TSS_API_PATH_URI
|
||||
required: false
|
||||
token_path_uri:
|
||||
default: /oauth2/token
|
||||
description: The path to append to the base URL to form a valid OAuth2
|
||||
Access Grant request.
|
||||
env:
|
||||
- name: TSS_TOKEN_PATH_URI
|
||||
required: false
|
||||
"""
|
||||
|
||||
RETURN = r"""
|
||||
_list:
|
||||
description:
|
||||
- The JSON responses to C(GET /secrets/{id}).
|
||||
- See U(https://updates.thycotic.net/secretserver/restapiguide/TokenAuth/#operation--secrets--id--get).
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
- hosts: localhost
|
||||
vars:
|
||||
secret: "{{ lookup('community.general.tss', 1) }}"
|
||||
tasks:
|
||||
- debug: msg="the password is {{ (secret['items'] | items2dict(key_name='slug', value_name='itemValue'))['password'] }}"
|
||||
"""
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
|
||||
sdk_is_missing = False
|
||||
|
||||
try:
|
||||
from thycotic.secrets.server import (
|
||||
SecretServer,
|
||||
SecretServerAccessError,
|
||||
SecretServerError,
|
||||
)
|
||||
except ImportError:
|
||||
sdk_is_missing = True
|
||||
|
||||
from ansible.utils.display import Display
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
@staticmethod
|
||||
def Client(server_parameters):
|
||||
return SecretServer(**server_parameters)
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
if sdk_is_missing:
|
||||
raise AnsibleError("python-tss-sdk must be installed to use this plugin")
|
||||
|
||||
self.set_options(var_options=variables, direct=kwargs)
|
||||
|
||||
secret_server = LookupModule.Client(
|
||||
{
|
||||
"base_url": self.get_option("base_url"),
|
||||
"username": self.get_option("username"),
|
||||
"password": self.get_option("password"),
|
||||
"api_path_uri": self.get_option("api_path_uri"),
|
||||
"token_path_uri": self.get_option("token_path_uri"),
|
||||
}
|
||||
)
|
||||
result = []
|
||||
|
||||
for term in terms:
|
||||
display.debug("tss_lookup term: %s" % term)
|
||||
try:
|
||||
id = int(term)
|
||||
display.vvv(u"Secret Server lookup of Secret with ID %d" % id)
|
||||
result.append(secret_server.get_secret_json(id))
|
||||
except ValueError:
|
||||
raise AnsibleOptionsError("Secret ID must be an integer")
|
||||
except SecretServerError as error:
|
||||
raise AnsibleError("Secret Server lookup failure: %s" % error.message)
|
||||
return result
|
43
tests/unit/plugins/lookup/test_tss.py
Normal file
43
tests/unit/plugins/lookup/test_tss.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# (c) 2020, Adam Migus <adam@migus.org>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible_collections.community.general.tests.unit.compat.unittest import TestCase
|
||||
from ansible_collections.community.general.tests.unit.compat.mock import (
|
||||
patch,
|
||||
MagicMock,
|
||||
)
|
||||
from ansible_collections.community.general.plugins.lookup import tss
|
||||
from ansible.plugins.loader import lookup_loader
|
||||
|
||||
|
||||
class MockSecretServer(MagicMock):
|
||||
RESPONSE = '{"foo": "bar"}'
|
||||
|
||||
def get_secret_json(self, path):
|
||||
return self.RESPONSE
|
||||
|
||||
|
||||
class TestLookupModule(TestCase):
|
||||
def setUp(self):
|
||||
tss.sdk_is_missing = False
|
||||
self.lookup = lookup_loader.get("community.general.tss")
|
||||
|
||||
@patch(
|
||||
"ansible_collections.community.general.plugins.lookup.tss.LookupModule.Client",
|
||||
MockSecretServer(),
|
||||
)
|
||||
def test_get_secret_json(self):
|
||||
self.assertListEqual(
|
||||
[MockSecretServer.RESPONSE],
|
||||
self.lookup.run(
|
||||
[1],
|
||||
[],
|
||||
**{"base_url": "dummy", "username": "dummy", "password": "dummy", }
|
||||
),
|
||||
)
|
Loading…
Reference in a new issue