tower_credential: expect ssh_key_data to be a string instead of path (#45158)
* expect ssh_key_data to be a string instead of path ssh_key_data should be a string filled with the private key the old behavior can be archived with a lookup Fixes #45119 * clarifies ssh_key_data description, adds newline
This commit is contained in:
parent
ac4e611f9d
commit
2f6b8591b1
4 changed files with 81 additions and 44 deletions
3
changelogs/fragments/tower_credential_ssh_key_data.yaml
Normal file
3
changelogs/fragments/tower_credential_ssh_key_data.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- tower_credential - Expect ssh_key_data to be the content of a ssh_key file instead of the path to the file (https://github.com/ansible/ansible/pull/45158)
|
|
@ -51,6 +51,9 @@ The following modules will be removed in Ansible 2.12. Please update your playbo
|
||||||
Noteworthy module changes
|
Noteworthy module changes
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
* The ``tower_credential`` module originally required the ``ssh_key_data`` to be the path to a ssh_key_file.
|
||||||
|
In order to work like Tower/AWX, ``ssh_key_data`` now contains the content of the file.
|
||||||
|
The previous behavior can be achieved with ``lookup('file', '/path/to/file')``.
|
||||||
|
|
||||||
Plugins
|
Plugins
|
||||||
=======
|
=======
|
||||||
|
|
|
@ -58,7 +58,8 @@ options:
|
||||||
- Password for this credential. Use ASK for prompting. secret_key for AWS. api_key for RAX.
|
- Password for this credential. Use ASK for prompting. secret_key for AWS. api_key for RAX.
|
||||||
ssh_key_data:
|
ssh_key_data:
|
||||||
description:
|
description:
|
||||||
- Path to SSH private key.
|
- SSH private key content. To extract the content from a file path, use the lookup function (see examples).
|
||||||
|
required: False
|
||||||
ssh_key_unlock:
|
ssh_key_unlock:
|
||||||
description:
|
description:
|
||||||
- Unlock password for ssh_key. Use ASK for prompting.
|
- Unlock password for ssh_key. Use ASK for prompting.
|
||||||
|
@ -123,6 +124,17 @@ EXAMPLES = '''
|
||||||
organization: test-org
|
organization: test-org
|
||||||
state: present
|
state: present
|
||||||
tower_config_file: "~/tower_cli.cfg"
|
tower_config_file: "~/tower_cli.cfg"
|
||||||
|
|
||||||
|
- name: Create a valid SCM credential from a private_key file
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: scm
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
ssh_key_data: "{{ lookup('file', '/tmp/id_rsa') }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -187,7 +199,7 @@ def main():
|
||||||
host=dict(),
|
host=dict(),
|
||||||
username=dict(),
|
username=dict(),
|
||||||
password=dict(no_log=True),
|
password=dict(no_log=True),
|
||||||
ssh_key_data=dict(no_log=True, type='path'),
|
ssh_key_data=dict(no_log=True, type='str'),
|
||||||
ssh_key_unlock=dict(no_log=True),
|
ssh_key_unlock=dict(no_log=True),
|
||||||
authorize=dict(type='bool', default=False),
|
authorize=dict(type='bool', default=False),
|
||||||
authorize_password=dict(no_log=True),
|
authorize_password=dict(no_log=True),
|
||||||
|
@ -254,13 +266,18 @@ def main():
|
||||||
params['team'] = team['id']
|
params['team'] = team['id']
|
||||||
|
|
||||||
if module.params.get('ssh_key_data'):
|
if module.params.get('ssh_key_data'):
|
||||||
filename = module.params.get('ssh_key_data')
|
data = module.params.get('ssh_key_data')
|
||||||
if not os.path.exists(filename):
|
if os.path.exists(data):
|
||||||
module.fail_json(msg='file not found: %s' % filename)
|
module.deprecate(
|
||||||
if os.path.isdir(filename):
|
msg='ssh_key_data should be a string, not a path to a file. Use lookup(\'file\', \'/path/to/file\') instead',
|
||||||
module.fail_json(msg='attempted to read contents of directory: %s' % filename)
|
version="2.12"
|
||||||
with open(filename, 'rb') as f:
|
)
|
||||||
module.params['ssh_key_data'] = to_text(f.read())
|
if os.path.isdir(data):
|
||||||
|
module.fail_json(msg='attempted to read contents of directory: %s' % data)
|
||||||
|
with open(data, 'rb') as f:
|
||||||
|
module.params['ssh_key_data'] = to_text(f.read())
|
||||||
|
else:
|
||||||
|
module.params['ssh_key_data'] = data
|
||||||
|
|
||||||
for key in ('authorize', 'authorize_password', 'client',
|
for key in ('authorize', 'authorize_password', 'client',
|
||||||
'security_token', 'secret', 'tenant', 'subscription',
|
'security_token', 'secret', 'tenant', 'subscription',
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
- name: Generate a local SSH key
|
- name: Generate a local SSH key
|
||||||
local_action: "shell ssh-keygen -b 2048 -t rsa -f {{ tempdir.stdout }}/id_rsa -q -N 'passphrase'"
|
local_action: "shell ssh-keygen -b 2048 -t rsa -f {{ tempdir.stdout }}/id_rsa -q -N 'passphrase'"
|
||||||
|
|
||||||
|
- name: Read the generated key
|
||||||
|
set_fact:
|
||||||
|
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
|
||||||
|
|
||||||
- name: Create a User-specific credential
|
- name: Create a User-specific credential
|
||||||
tower_credential:
|
tower_credential:
|
||||||
name: SSH Credential
|
name: SSH Credential
|
||||||
|
@ -43,6 +47,46 @@
|
||||||
become_method: sudo
|
become_method: sudo
|
||||||
become_username: superuser
|
become_username: superuser
|
||||||
become_password: supersecret
|
become_password: supersecret
|
||||||
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SSH credential from lookup source
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential from lookup source
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example SSH credential from lookup source
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
become_method: sudo
|
||||||
|
become_username: superuser
|
||||||
|
become_password: supersecret
|
||||||
|
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SSH credential from file source
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential from file source
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example SSH credential from file source
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
become_method: sudo
|
||||||
|
become_username: superuser
|
||||||
|
become_password: supersecret
|
||||||
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
||||||
ssh_key_unlock: "passphrase"
|
ssh_key_unlock: "passphrase"
|
||||||
register: result
|
register: result
|
||||||
|
@ -50,6 +94,8 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- "result is changed"
|
- "result is changed"
|
||||||
|
- "result is not failed"
|
||||||
|
- "'ssh_key_data should be a string, not a path to a file.' in result.deprecations[0].msg"
|
||||||
|
|
||||||
- name: Create an invalid SSH credential (passphrase required)
|
- name: Create an invalid SSH credential (passphrase required)
|
||||||
tower_credential:
|
tower_credential:
|
||||||
|
@ -58,7 +104,7 @@
|
||||||
state: present
|
state: present
|
||||||
kind: ssh
|
kind: ssh
|
||||||
username: joe
|
username: joe
|
||||||
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
|
@ -67,38 +113,6 @@
|
||||||
- "result is failed"
|
- "result is failed"
|
||||||
- "'must be set when SSH key is encrypted' in result.module_stderr"
|
- "'must be set when SSH key is encrypted' in result.module_stderr"
|
||||||
|
|
||||||
- name: Create an invalid SSH credential (ssh_key_data file is missing)
|
|
||||||
tower_credential:
|
|
||||||
name: SSH Credential
|
|
||||||
organization: Default
|
|
||||||
state: present
|
|
||||||
kind: ssh
|
|
||||||
username: joe
|
|
||||||
ssh_key_data: "{{ tempdir.stdout }}/not_a_valid_file"
|
|
||||||
ignore_errors: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result is failed"
|
|
||||||
- "'file not found' in result.msg"
|
|
||||||
|
|
||||||
- name: Create an invalid SSH credential (ssh_key_data is a directory)
|
|
||||||
tower_credential:
|
|
||||||
name: SSH Credential
|
|
||||||
organization: Default
|
|
||||||
state: present
|
|
||||||
kind: ssh
|
|
||||||
username: joe
|
|
||||||
ssh_key_data: "{{ tempdir.stdout }}"
|
|
||||||
ignore_errors: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result is failed"
|
|
||||||
- "'attempted to read contents of directory' in result.msg"
|
|
||||||
|
|
||||||
- name: Create an invalid SSH credential (Organization not found)
|
- name: Create an invalid SSH credential (Organization not found)
|
||||||
tower_credential:
|
tower_credential:
|
||||||
name: SSH Credential
|
name: SSH Credential
|
||||||
|
@ -202,7 +216,7 @@
|
||||||
kind: scm
|
kind: scm
|
||||||
username: joe
|
username: joe
|
||||||
password: secret
|
password: secret
|
||||||
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
ssh_key_unlock: "passphrase"
|
ssh_key_unlock: "passphrase"
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
|
@ -338,7 +352,7 @@
|
||||||
kind: gce
|
kind: gce
|
||||||
username: joe
|
username: joe
|
||||||
project: ABC123
|
project: ABC123
|
||||||
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
|
|
Loading…
Reference in a new issue