summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/general/plugins/lookup/tss.py
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/community/general/plugins/lookup/tss.py')
-rw-r--r--ansible_collections/community/general/plugins/lookup/tss.py195
1 files changed, 169 insertions, 26 deletions
diff --git a/ansible_collections/community/general/plugins/lookup/tss.py b/ansible_collections/community/general/plugins/lookup/tss.py
index 935b5f4b4..80105ff71 100644
--- a/ansible_collections/community/general/plugins/lookup/tss.py
+++ b/ansible_collections/community/general/plugins/lookup/tss.py
@@ -13,10 +13,10 @@ 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).
+ Server using token authentication with O(username) and O(password) on
+ the REST API at O(base_url).
- When using self-signed certificates the environment variable
- C(REQUESTS_CA_BUNDLE) can be set to a file containing the trusted certificates
+ E(REQUESTS_CA_BUNDLE) can be set to a file containing the trusted certificates
(in C(.pem) format).
- For example, C(export REQUESTS_CA_BUNDLE='/etc/ssl/certs/ca-bundle.trust.crt').
requirements:
@@ -26,8 +26,32 @@ options:
description: The integer ID of the secret.
required: true
type: int
+ secret_path:
+ description: Indicate a full path of secret including folder and secret name when the secret ID is set to 0.
+ required: false
+ type: str
+ version_added: 7.2.0
+ fetch_secret_ids_from_folder:
+ description:
+ - Boolean flag which indicates whether secret ids are in a folder is fetched by folder ID or not.
+ - V(true) then the terms will be considered as a folder IDs. Otherwise (default), they are considered as secret IDs.
+ required: false
+ type: bool
+ version_added: 7.1.0
+ fetch_attachments:
+ description:
+ - Boolean flag which indicates whether attached files will get downloaded or not.
+ - The download will only happen if O(file_download_path) has been provided.
+ required: false
+ type: bool
+ version_added: 7.0.0
+ file_download_path:
+ description: Indicate the file attachment download location.
+ required: false
+ type: path
+ version_added: 7.0.0
base_url:
- description: The base URL of the server, e.g. C(https://localhost/SecretServer).
+ description: The base URL of the server, for example V(https://localhost/SecretServer).
env:
- name: TSS_BASE_URL
ini:
@@ -44,7 +68,7 @@ options:
password:
description:
- The password associated with the supplied username.
- - Required when I(token) is not provided.
+ - Required when O(token) is not provided.
env:
- name: TSS_PASSWORD
ini:
@@ -54,7 +78,7 @@ options:
default: ""
description:
- The domain with which to request the OAuth2 Access Grant.
- - Optional when I(token) is not provided.
+ - Optional when O(token) is not provided.
- Requires C(python-tss-sdk) version 1.0.0 or greater.
env:
- name: TSS_DOMAIN
@@ -66,7 +90,7 @@ options:
token:
description:
- Existing token for Thycotic authorizer.
- - If provided, I(username) and I(password) are not needed.
+ - If provided, O(username) and O(password) are not needed.
- Requires C(python-tss-sdk) version 1.0.0 or greater.
env:
- name: TSS_TOKEN
@@ -157,39 +181,101 @@ EXAMPLES = r"""
tasks:
- ansible.builtin.debug:
msg: the password is {{ secret_password }}
+
+# Private key stores into certificate file which is attached with secret.
+# If fetch_attachments=True then private key file will be download on specified path
+# and file content will display in debug message.
+- hosts: localhost
+ vars:
+ secret: >-
+ {{
+ lookup(
+ 'community.general.tss',
+ 102,
+ fetch_attachments=True,
+ file_download_path='/home/certs',
+ base_url='https://secretserver.domain.com/SecretServer/',
+ token='thycotic_access_token'
+ )
+ }}
+ tasks:
+ - ansible.builtin.debug:
+ msg: >
+ the private key is {{
+ (secret['items']
+ | items2dict(key_name='slug',
+ value_name='itemValue'))['private-key']
+ }}
+
+# If fetch_secret_ids_from_folder=true then secret IDs are in a folder is fetched based on folder ID
+- hosts: localhost
+ vars:
+ secret: >-
+ {{
+ lookup(
+ 'community.general.tss',
+ 102,
+ fetch_secret_ids_from_folder=true,
+ base_url='https://secretserver.domain.com/SecretServer/',
+ token='thycotic_access_token'
+ )
+ }}
+ tasks:
+ - ansible.builtin.debug:
+ msg: >
+ the secret id's are {{
+ secret
+ }}
+
+# If secret ID is 0 and secret_path has value then secret is fetched by secret path
+- hosts: localhost
+ vars:
+ secret: >-
+ {{
+ lookup(
+ 'community.general.tss',
+ 0,
+ secret_path='\folderName\secretName'
+ base_url='https://secretserver.domain.com/SecretServer/',
+ username='user.name',
+ password='password'
+ )
+ }}
+ tasks:
+ - ansible.builtin.debug:
+ msg: >
+ the password is {{
+ (secret['items']
+ | items2dict(key_name='slug',
+ value_name='itemValue'))['password']
+ }}
"""
import abc
-
+import os
from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.module_utils import six
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
try:
- from thycotic.secrets.server import SecretServer, SecretServerError
+ from delinea.secrets.server import SecretServer, SecretServerError, PasswordGrantAuthorizer, DomainPasswordGrantAuthorizer, AccessTokenAuthorizer
HAS_TSS_SDK = True
+ HAS_DELINEA_SS_SDK = True
+ HAS_TSS_AUTHORIZER = True
except ImportError:
try:
- from delinea.secrets.server import SecretServer, SecretServerError
+ from thycotic.secrets.server import SecretServer, SecretServerError, PasswordGrantAuthorizer, DomainPasswordGrantAuthorizer, AccessTokenAuthorizer
HAS_TSS_SDK = True
+ HAS_DELINEA_SS_SDK = False
+ HAS_TSS_AUTHORIZER = True
except ImportError:
SecretServer = None
SecretServerError = None
HAS_TSS_SDK = False
-
-try:
- from thycotic.secrets.server import PasswordGrantAuthorizer, DomainPasswordGrantAuthorizer, AccessTokenAuthorizer
-
- HAS_TSS_AUTHORIZER = True
-except ImportError:
- try:
- from delinea.secrets.server import PasswordGrantAuthorizer, DomainPasswordGrantAuthorizer, AccessTokenAuthorizer
-
- HAS_TSS_AUTHORIZER = True
- except ImportError:
+ HAS_DELINEA_SS_SDK = False
PasswordGrantAuthorizer = None
DomainPasswordGrantAuthorizer = None
AccessTokenAuthorizer = None
@@ -211,13 +297,49 @@ class TSSClient(object):
else:
return TSSClientV0(**server_parameters)
- def get_secret(self, term):
+ def get_secret(self, term, secret_path, fetch_file_attachments, file_download_path):
display.debug("tss_lookup term: %s" % term)
-
secret_id = self._term_to_secret_id(term)
- display.vvv(u"Secret Server lookup of Secret with ID %d" % secret_id)
+ if secret_id == 0 and secret_path:
+ fetch_secret_by_path = True
+ display.vvv(u"Secret Server lookup of Secret with path %s" % secret_path)
+ else:
+ fetch_secret_by_path = False
+ display.vvv(u"Secret Server lookup of Secret with ID %d" % secret_id)
+
+ if fetch_file_attachments:
+ if fetch_secret_by_path:
+ obj = self._client.get_secret_by_path(secret_path, fetch_file_attachments)
+ else:
+ obj = self._client.get_secret(secret_id, fetch_file_attachments)
+ for i in obj['items']:
+ if file_download_path and os.path.isdir(file_download_path):
+ if i['isFile']:
+ try:
+ file_content = i['itemValue'].content
+ with open(os.path.join(file_download_path, str(obj['id']) + "_" + i['slug']), "wb") as f:
+ f.write(file_content)
+ except ValueError:
+ raise AnsibleOptionsError("Failed to download {0}".format(str(i['slug'])))
+ except AttributeError:
+ display.warning("Could not read file content for {0}".format(str(i['slug'])))
+ finally:
+ i['itemValue'] = "*** Not Valid For Display ***"
+ else:
+ raise AnsibleOptionsError("File download path does not exist")
+ return obj
+ else:
+ if fetch_secret_by_path:
+ return self._client.get_secret_by_path(secret_path, False)
+ else:
+ return self._client.get_secret_json(secret_id)
+
+ def get_secret_ids_by_folderid(self, term):
+ display.debug("tss_lookup term: %s" % term)
+ folder_id = self._term_to_folder_id(term)
+ display.vvv(u"Secret Server lookup of Secret id's with Folder ID %d" % folder_id)
- return self._client.get_secret_json(secret_id)
+ return self._client.get_secret_ids_by_folderid(folder_id)
@staticmethod
def _term_to_secret_id(term):
@@ -226,6 +348,13 @@ class TSSClient(object):
except ValueError:
raise AnsibleOptionsError("Secret ID must be an integer")
+ @staticmethod
+ def _term_to_folder_id(term):
+ try:
+ return int(term)
+ except ValueError:
+ raise AnsibleOptionsError("Folder ID must be an integer")
+
class TSSClientV0(TSSClient):
def __init__(self, **server_parameters):
@@ -294,6 +423,20 @@ class LookupModule(LookupBase):
)
try:
- return [tss.get_secret(term) for term in terms]
+ if self.get_option("fetch_secret_ids_from_folder"):
+ if HAS_DELINEA_SS_SDK:
+ return [tss.get_secret_ids_by_folderid(term) for term in terms]
+ else:
+ raise AnsibleError("latest python-tss-sdk must be installed to use this plugin")
+ else:
+ return [
+ tss.get_secret(
+ term,
+ self.get_option("secret_path"),
+ self.get_option("fetch_attachments"),
+ self.get_option("file_download_path"),
+ )
+ for term in terms
+ ]
except SecretServerError as error:
raise AnsibleError("Secret Server lookup failure: %s" % error.message)