Connecting via SSH Proxy
Axidian Privilege supports connecting Ansible to resources through a proxy server. In this scenario, Ansible connects to the SSH Proxy component, which provides access to resources via SSH, SCP, and SFTP protocols.
The component establishes a connection to the resource on behalf of the specified account, controls access to it, and logs all actions on the resource in the Events, Active Sessions, and All Sessions journals.
Two-factor authentication is not supported in the Ansible via SSH Proxy scenario.
Requirements
The following is required to use Ansible via SSH Proxy:
- Ansible 2.14 or higher
- Access to the Axidian Privilege SSH Proxy component
- An Axidian Privilege user account with access to the target resource
- AAPM license, if using Ansible Lookup Plugin
Connection Configuration
To configure a connection from an Ansible playbook through SSH Proxy:
Construct the SSH Proxy connection string in UTF-8 encoding using the following template:
<pam_user>#<resource_address>#<account_name>#[reason]pam_user— Axidian Privilege username for authentication in SSH Proxyresource_address— IP address or DNS name of the target resourceaccount_name— account name used to connect to the target resourcereason— reason for connecting to the resource, if required by the policy
Example:
pam.admin#192.168.0.100#PAM.LOCAL\pam-admin#MaintenanceConfigure Ansible for connecting to Axidian Privilege in one of the following files:
Ansible playbook — specify the parameters in the
varssection.inventory.yml — specify the parameters in the
hostssection.Configuration parameters
Parameter Requirement Description ansible_hostRequired DNS name or IP address of the SSH Proxy component ansible_portRequired SSH Proxy component port.
Default port:2222ansible_userRequired SSH Proxy connection string.
Example:pam.admin#10.0.0.1#DOMAIN\admin.ansible_passwordOptional PAM user password. Specify if password authentication is configured. It is recommended to encrypt the password using Ansible Vault. ansible_ssh_private_key_fileOptional Path to the PAM user SSH key. Specify if SSH key authentication is configured.
Example:/home/user/.ssh/id_rsa.ansible_ssh_retriesOptional Number of connection retry attempts. Specify to reconnect after a connection drop or session closure from the administrator console. ansible_ssh_extra_argsOptional Allows passing additional command-line arguments to the SSH client. Use to configure SCP and SFTP connections. Examples
- Ansible playbook
- inventory file
- name: Execute command via PAM SSH Proxy
hosts: all
gather_facts: false
vars:
ansible_host: "pam.company.com"
ansible_port: 2222
ansible_user: "pam.admin#192.168.0.100#DOMAIN\\admin"
ansible_password: "{{ pam_password }}"
tasks:
- name: Get system information
ansible.builtin.raw: uname -a
register: result
changed_when: false
- name: Show result
ansible.builtin.debug:
msg: "{{ result.stdout | trim }}"Single resource---
all:
hosts:
target_server:
ansible_host: pam.company.com
ansible_port: 2222
ansible_user: "pam.admin#192.168.0.100#DOMAIN\\admin"
ansible_password: "{{ vault_pam_password }}"Multiple resources---
all:
vars:
ansible_port: 2222
ansible_host: pam.company.com
ansible_password: "{{ vault_pam_password }}"
hosts:
web_server:
ansible_user: "pam.admin#10.11.5.10#DOMAIN\\web-admin"
db_server:
ansible_user: "pam.admin#10.11.5.20#DOMAIN\\db-admin"
app_server:
ansible_user: "pam.admin#190.160.1.100#LINUX-SERVER\\db-admin#Maintenance"
Running a Scenario
To start a session, open a terminal and run the command to connect to the resource
ansible-playbook <playbook> [-i <inventory>] [-e <variable>]
playbook— name of the Ansible playbookinventory— name of the configuration file with connection settingsvariable— name of the environment variable
Launch command examples
ansible-playbook playbook.yml
ansible-playbook playbook.yml -i inventory.yml
ansible-playbook playbook.yml -i inventory.yml -e "pam_password=${PAM_PASSWORD}"
Using Ansible Vault
It is recommended to encrypt credentials using the Ansible Vault component rather than storing them in plain text.
To encrypt the PAM user password:
Open a terminal and run the command to encrypt the password:
ansible-vault encrypt_string --ask-vault-pass '<password>' --name '<variable>'password— the Axidian Privilege user password to encryptvariable— the variable name for encryption
Enter the password that will be used to decrypt the variable when running the playbook.
As a result, the encrypted variable will be displayed in the terminal.Create a file in YAML or JSON format and save the command output to it.
- YAML
- JSON
vault_pam_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
31643864386664376639656162346664313937633035346638656139376138656163376638656164
6337663961383964666137633930626439656637666137660a313233343536373839306162636465{
"vault_pam_password": "$ANSIBLE_VAULT;1.1;AES256\n31643864386664376639656162346664313937633035346638656139376138656163376638656164\n6337663961383964666137633930626439656637666137660a313233343536373839306"
}Specify the variable in the playbook:
- For the
vars_filesparameter, specify the path to the file containing the encrypted variable. - For the
passwordparameter, specify the variable name.
Example
---
- name: Execute command via PAM SSH Proxy using Ansible Vault
hosts: all
gather_facts: false
vars_files:
- ./vault.yml
vars:
ansible_host: "pam.company.com"
ansible_port: 2222
ansible_user: "pam.admin#192.168.0.100#PAM.LOCAL\\pam-admin"
ansible_password: "{{ vault_pam_password }}"
tasks:
- name: Verify connection
ansible.builtin.raw: id
register: result
changed_when: false
no_log: true- For the
File Transfer via SCP and SFTP
Files can be transferred from the host running the playbook to an SSH resource using the following protocols:
- SCP — for quick transfer of a single file to the resource
- SFTP — for CI/CD automation or transferring multiple files to the resource
Use the ansible.builtin.shell module and the sshpass utility to transfer files.
The ansible.builtin.copy module is not suitable for file transfer via SSH Proxy. The module creates a temporary directory on the resource, uploads the file there, moves it to the target directory, sets access permissions, and removes the temporary directory. This requires a separate communication channel, but SSH Proxy only allows file transfer via SCP and SFTP and terminates the session immediately after the file is transferred.
Prerequisites
In the Axidian Privilege administration console, perform the following steps:
- Go to the Policies section and click on the required policy.
- Go to the SSH → Data Transfer subsection.
- For the SCP and SFTP protocols, select the Allowed to resource only or Allowed in both directions option.
- Click Save.
Host Configuration
On the host from which you plan to connect to the SSH resource, perform the following steps:
Install the sshpass utility, which allows automatically filling in the password for SSH connections.
- RPM
- DEB
sudo dnf install sshpasssudo apt install sshpassConfigure the connection to the SSH resource using one of the following methods:
Specify the parameters in the ssh_config file and pass the file path in the
ansible_ssh_extra_argsvariable — the recommended method. This allows you to avoid escaping the connection string.Specify the parameters directly in
ansible_ssh_extra_argsin the inventory.yml file or Ansible playbook.Escaping Special CharactersThe SSH Proxy connection string contains special characters
#and\that must be escaped. When configuring in a YAML file, specify the connection string in single quotes.When substituting variables into a command, such as
src_fileoransible_user, use thequotefilter to handle spaces and special characters.Parameters
Parameter DescriptionHostNameDNS name or IP address of the SSH Proxy component.
Can be specified in theansible_hostparameter in inventory.yml or in the playbook.PortSSH Proxy component port. Default port: 2222.
Can be specified in theansible_portparameter in inventory.yml or in the playbook.UserSSH Proxy connection string.
Example:pamadmin@pam.local#ssh-host.example.com#RESOURCE\user##.
Can be specified in theansible_userparameter in inventory.yml or in the playbook.PreferredAuthenticationsPriority order of authentication methods used when connecting to the proxy server. Possible values: keyboard-interactive— interactive authentication (challenge-response)password— password authenticationpublickey— SSH key authentication
publickey,keyboard-interactive— the SSH key is checked first; if it does not match, the server requests a password.KbdInteractiveAuthenticationEnable interactive authentication using the keyboard-interactivemethod. Possible values:truefalse
PubkeyAuthenticationEnable SSH key authentication. Possible values: truefalse
NumberOfPasswordPromptsNumber of password entry attempts. If exceeded, the connection to the proxy server is terminated. UserKnownHostsFilePath to the known_hosts file StrictHostKeyCheckingServer SSH key verification: yes— strict verification. If the server key is not found in the known_hosts file or does not match the saved key for this host, the connection is terminated with an error.no— verification disabled. If the key is not in the known_hosts file, it is added automatically.accept-new— verification for new hosts only. If the key is not in known_hosts, it is added automatically and the connection is established. If the specified key does not match the key in known_hosts, the connection is terminated.
ConnectTimeoutTimeout (in seconds) for establishing a TCP connection to the server Examples
- inventory.yml
- ansible.cfg
- Ansible playbook
Parameters defined in inventory.ymlall:
hosts:
pam_target:
ansible_connection: ssh
ansible_host: pam.example.com
ansible_port: 2222
ansible_user: 'pamadmin@pam.local#ssh-host.example.com#RESOURCE\pam-user##'
ansible_password: "{{ vault_pam_password }}"
ansible_ssh_extra_args: >-
-tt
-o PreferredAuthentications=keyboard-interactive,password
-o KbdInteractiveAuthentication=yes
-o PubkeyAuthentication=no
-o NumberOfPasswordPrompts=1
-o StrictHostKeyChecking=yes
-o UserKnownHostsFile=./known_hosts
-o ConnectTimeout=10Path to ssh_config specified in inventory.ymlall:
hosts:
pam_target:
ansible_connection: ssh
ansible_password: "{{ vault_pam_password }}"
ansible_ssh_extra_args: '-tt -F ./ssh_config'Path to ssh_config specified in ansible.cfg[defaults]
inventory = ./inventory.yml
[ssh_connection]
pipelining = False
ssh_args = -F ./ssh_configParameters specified in the playbook- block:
- name: Transfer file via SSH Proxy using SFTP protocol
delegate_to: localhost
environment:
SSHPASS: "{{ ansible_password }}"
ansible.builtin.shell: >-
sshpass -e sftp
-P {{ ansible_port }}
-o PreferredAuthentications=keyboard-interactive,password
-o KbdInteractiveAuthentication=yes
-o PubkeyAuthentication=no
-o NumberOfPasswordPrompts=1
-o StrictHostKeyChecking=accept-new
-o UserKnownHostsFile=./known_hosts
-o ConnectTimeout=10
-o BatchMode=no
-b {{ sftp_batch_file.path | quote }}
{{ ansible_user | quote }}@{{ ansible_host }}
register: sftp_result
no_log: truePath to ssh_config specified in the playbookansible.builtin.shell: >-
sshpass -e sftp
-F ./ssh_config
-o BatchMode=no
-b {{ sftp_batch_file.path | quote }}
{{ inventory_hostname }}ssh_config file exampleHost pam_target
HostName pam.example.com
Port 2222
User pamadmin@pam.local#ssh-host.example.com#RESOURCE\pam-user##
PreferredAuthentications keyboard-interactive,password
KbdInteractiveAuthentication yes
PubkeyAuthentication no
NumberOfPasswordPrompts 1
UserKnownHostsFile ./known_hosts
StrictHostKeyChecking yes
ConnectTimeout 10
Add the public key of the SSH Proxy component to the known_hosts file.
cautionThis step is required if
StrictHostKeyCheckingis set toyes. If the proxy server fingerprint is not recorded before the first run, the playbook will fail with an error.ssh-keyscan [-p <port>] <host> >> ./known_hostsport— SSH Proxy component porthost— DNS name or IP address of the SSH Proxy component
To confirm the fingerprint, type
yesin the terminal.Run the playbook to transfer files from the host to the SSH resource using the selected protocol.
ansible-playbook <playbook> \
-e src_file=<source_path> \
-e dest_dir=<destination_dir> \
--ask-vault-passplaybook— name of the Ansible playbooksource_path— path to the file to be transferred from the host to the target resourcedest_dir— directory on the target resource where the file will be transferredask-vault-pass— prompt for the password to decrypt variables in the playbook
Playbook example
- SCP
- SFTP
---
- name: Transfer file via SSH Proxy using SCP protocol
hosts: all
gather_facts: false
vars:
src_file: /tmp/file.txt
dest_dir: /home/user
dest_file: "{{ dest_dir }}/{{ src_file | basename }}"
tasks:
- name: Transfer file via SSH Proxy using SCP protocol
delegate_to: localhost
environment:
SSHPASS: "{{ ansible_password }}"
ansible.builtin.shell: >-
sshpass -e scp
-F ./ssh_config
-O
{{ src_file | quote }}
{{ inventory_hostname }}:{{ dest_file | quote }}
register: scp_result
failed_when: false
- name: Verify file exists on target
ansible.builtin.raw: "test -f {{ dest_file | quote }} && echo OK"
register: verify_result
changed_when: false
failed_when: "'OK' not in verify_result.stdout"---
- name: Transfer file via SSH Proxy using SFTP protocol
hosts: all
gather_facts: false
vars:
src_file: /tmp/file.txt
dest_dir: /home/user
dest_file: "{{ dest_dir }}/{{ src_file | basename }}"
tasks:
- name: Create temporary batch file
delegate_to: localhost
ansible.builtin.tempfile:
state: file
suffix: .sftp
register: sftp_batch_file
- name: Write SFTP batch commands
delegate_to: localhost
ansible.builtin.copy:
dest: "{{ sftp_batch_file.path }}"
content: "put {{ src_file }} {{ dest_file }}\n"
- block:
- name: Transfer file via SSH Proxy using SFTP protocol
delegate_to: localhost
environment:
SSHPASS: "{{ ansible_password }}"
ansible.builtin.shell: >-
sshpass -e sftp
-F ./ssh_config
-o BatchMode=no
-b {{ sftp_batch_file.path | quote }}
{{ inventory_hostname }}
register: sftp_result
no_log: true
- name: Verify file exists on target
ansible.builtin.raw: "test -f {{ dest_file | quote }} && echo OK"
register: verify_result
changed_when: false
failed_when: "'OK' not in verify_result.stdout"
always:
- name: Remove temporary batch file
delegate_to: localhost
ansible.builtin.file:
path: "{{ sftp_batch_file.path }}"
state: absent
Security Recommendations
For server authentication and automation scenarios, before the first connection to PAM, add the public key of
the SSH Proxy component to the known_hosts file:ssh-keyscan [-p <port>] <host> >> ~/.ssh/known_hostsport— SSH Proxy component porthost— DNS name or IP address of the SSH Proxy component
cautionVerify the key authenticity: the
ssh-keyscancommand uses the Trust on first use (TOFU) mechanism, where the key is added without verification.When configuring the connection, enable public key verification: set the
StrictHostKeyCheckingparameter toyes.Do not store passwords in plain text — use Ansible Vault to encrypt credentials.
Use the
no_log: trueparameter to prevent credentials from appearing in Ansible logs when a task completes.In CI/CD scenarios, pass the password and SSH key through environment variables.
The ssh_config file contains connection data. It is recommended to restrict file permissions using the command:
chmod 600 ~/.ssh/configTo enhance security, it is recommended to use the following parameters:
gather_facts: false— disables host information gathering, which prevents Python script launch commands from appearing in logs.no_log: true— disables output to the console and Ansible logs. Use for tasks involving credentials.become: trueandbecome_method: sudo— elevates privileges for executing commands that requirerootpermissions.rawmodule — allows executing commands through SSH Proxy without installing Python on the target resource and enables displaying an informative log in the session profile in the administrator console.Scenario example
---
- name: Execute command via PAM SSH Proxy
hosts: all
gather_facts: false
become: true
become_method: sudo
vars:
ansible_host: "pam.company.com"
ansible_port: 2222
ansible_user: "pam.admin#10.10.5.190#PAM.LOCAL\\pam-admin"
ansible_password: "{{ pam_password }}"
tasks:
- name: Execute command (credentials hidden)
ansible.builtin.raw: uname -a
register: result
changed_when: false
no_log: true
- name: Show command result (log displayed)
ansible.builtin.debug:
msg: "{{ result.stdout | trim }}"
no_log: false