One very common use case with Windows is trying to access a file from a network location, for example installing a project from a network path, or copying application settings from a central file share. When trying to do a similar action when logged on interactively, things typically just work, but trying to do the same thing in Red Hat Ansible Automation Platform might fail.
A specific example in Ansible would be trying to copy a file from a UNC path to a local directory using ansible.windows.win_copy:
- name: Copy application config file
win_copy:
src: \\fs\share\app\app.config
dest: C:\app\app.config
remote_src: true
Running the above example would fail with:
fatal: [win-host]: FAILED! =>
changed: false
dest: C:\app\app.config
msg: 'Unhandled exception while executing module: Access is denied'
src: \\fs\share\app\app.config
The culprit behind this problem is something called credential delegation and is also known as the double hop problem. This post will try to explain the reason why this fails and ways we can get it working.
Windows authentication
To understand this problem, we first need to understand how authentication works in Windows. A basic workflow of the win_copy example from above is:
When Ansible Automation Platform authenticates with a remote Windows host, it typically uses an authentication protocol like Kerberos, NTLM or CredSSP, among others. These protocols typically rely on proving to the Windows server that we know a secret only the user can know, for example a Kerberos ticket derived from their password, or the SSH private key pair. Some protocols provide enough information to the server that allows it to generate new tokens for subsequent authentication attempts whereas others do not. If the logon session does not have this information, it cannot then re-authenticate itself with the File Server resulting in an Access is denied error message.
The Windows server cannot re-use the token provided by Ansible because that is scoped just for Ansible to authenticate with Windows Server. That means to overcome this problem we have to provide enough information for the Windows server to be able to re-authenticate the user with file server. With Ansible Automation Platform, we have a few possible solutions to this problem:
- Using become on the task
- Using a connection authentication protocol that supports delegation
- Providing explicit credentials if the module/script supports it
Become
The simplest solution to this problem is to use Ansible Automation Platform’s become implementation, as it requires no changes to the connection used by Ansible Automation Platform. For Windows we can use the ansible.builtin.runas become plugin that will run the module task either as a different user or with explicit credentials used for outbound authentication. Using our win_copy example here, we can use runas to set credentials for delegation:
- name: Copy application config file
win_copy:
src: \\fs\share\app\app.config
dest: C:\app\app.config
remote_src: true
become: true
become_method: runas
become_flags: logon_type=new_credentials logon_flags=netcredentials_only
vars:
ansible_become_user: '{{ ansible_user }}'
ansible_become_pass: '{{ ansible_password }}'
Breaking down the above example, we can see the following task directives have been added.
become: true
This enables become on this specific task.
become_method: runas
This sets the become plugin that is run for this task to be the runas plugin. The runas plugin is specifically designed to work with Windows hosts. The become plugin can also be set through the ansible_become_method variable on the host/group vars simplifying the task definition.
become_flags: logon_type=new_credentials logon_flags=netcredentials_only
These are special flags for runas which tells it to only use the credentials specified for any outbound authentication attempts, for example when accessing a file server. The default behavior without these flags would be to run the whole module process as the user specified. For just solving the double hop problem, we only need it for outbound authentication, so the become flags limit the scope in which the credentials are used.
vars:
ansible_become_user: '{{ ansible_user }}'
ansible_become_pass: '{{ ansible_password }}'
Provide the explicit username and password for the become plugin through specific variables on that task. These will be the credentials used to authenticate with the target file server fs in this example. The username and password can be set to any value that is relevant for our environment. In this case, we are just re-using the same connection variables to solve the double hop problem.
It is important that the Windows host Ansible Automation Platform is connecting to is trusted to handle the become credentials, as it is a form of unconstrained delegation. If the Windows host is compromised, it could theoretically re-use the credentials provided and pretend to be that user for other tasks. To avoid this problem, we will need to use a form of constrained delegation through a connection based solution.
Connection-based delegation
It is possible to solve the double hop problem by using features that are part of the connection plugin Ansible uses. As these features are specific to the connection plugin, there is no one option available in all cases. For example, the builtin connection plugins that work with Windows can be used with the following authentication protocols for credential delegation:
Protocol | Connection Plugin | Delegation Type |
---|---|---|
CredSSP | winrm, psrp | Unconstrained |
Plaintext Password | ssh | Unconstrained |
Kerberos | winrm, psrp, ssh | Unconstrained and Constrained |
The CredSSP and SSH plaintext password authentication protocols solve the problem in a similar way to how become works by sending the explicit username and password to the Windows server. In delegation terms, this is called unconstrained delegation as it allows the server to authenticate with any target it wishes using those credentials.
The Kerberos protocol also has a way to achieve unconstrained delegation, but it can also be used with constrained delegation. Constrained delegation is ideal, as it restricts how the server can re-use the user’s identity, but it requires extra configuration in the Active Directory environment before it can work. How to use Kerberos delegation is a complex topic in itself and will be the focus of a future blog post.
Context specific credentials
The final option available to Ansible Automation Platform for solving the double hop problem is to provide credentials as part of a module specific option. For example, the microsoft.ad.user module has a domain_username and domain_password option that can be used to authenticate to the Active Directory server with specific credentials.
- name: Create domain user
microsoft.ad.user:
name: MyUser
state: present
password: '{{ user_password }}'
domain_username: '{{ ad_username }}'
domain_password: '{{ ad_password }}'
In the above example, the microsoft.ad.user module will authenticate with the username/password specified by the ad_username and ad_password variables respectively. Being able to provide a credential in this manner is dependent on the module that is being used and whether it exposes such an option. In the case of running custom PowerShell code through ansible.builtin.script, ansible.windows.win_powershell or ansible.windows.win_shell it requires the cmdlet being used to expose the functionality through a parameter like -Credential.
It is important in the above examples that the task is run with no_log: true so the credentials are not persisted in any logging mechanism accidentally:
- name: Run win_powershell example with explicit credentials
ansible.windows.win_powershell:
script: |
param($UserName, $Password)
$cred = [PSCredential]::new($UserName, (ConvertTo-SecureString -AsPlainText -Force $Password))
Get-CmdletExample -Credential $cred
parameters:
UserName: MyUser
Password: '{{ script_password }}'
no_log: true
Next steps
With all this information we should now be able to identify when a double hop problem can occur as well as how to workaround the issue. By using become, connection authentication settings or utilizing existing available module options, we easily workaround this issue and write tasks that work in the same way that it does when running it interactively.
To learn more about automating Linux and Windows in the cloud read this brief.
For hands-on self-paced labs on Ansible Automation Platform, please visit this page or try this lab on getting started with Windows automation.
저자 소개
I am currently a Senior Software Engineer for Red Hat working on the Ansible Core product. Ansible, if you haven’t heard, is a popular open source tool that handles configuration-management, application deployment, cloud provisioning, and much more. Within this team I mostly focus on the Windows integration and have had years of experience on working on a Microsoft stack. I try to be active on various community boards and on IRC, if you see someone talking under jborean93 that would be me. In the past I’ve worked as a system analyst in the financial industry and worked with applications that spanned hundreds of servers and had to deal with things like AWS, PCI DSS, Spring Boot applications, among other things.
유사한 검색 결과
채널별 검색
오토메이션
기술, 팀, 인프라를 위한 IT 자동화 최신 동향
인공지능
고객이 어디서나 AI 워크로드를 실행할 수 있도록 지원하는 플랫폼 업데이트
오픈 하이브리드 클라우드
하이브리드 클라우드로 더욱 유연한 미래를 구축하는 방법을 알아보세요
보안
환경과 기술 전반에 걸쳐 리스크를 감소하는 방법에 대한 최신 정보
엣지 컴퓨팅
엣지에서의 운영을 단순화하는 플랫폼 업데이트
인프라
세계적으로 인정받은 기업용 Linux 플랫폼에 대한 최신 정보
애플리케이션
복잡한 애플리케이션에 대한 솔루션 더 보기
오리지널 쇼
엔터프라이즈 기술 분야의 제작자와 리더가 전하는 흥미로운 스토리
제품
- Red Hat Enterprise Linux
- Red Hat OpenShift Enterprise
- Red Hat Ansible Automation Platform
- 클라우드 서비스
- 모든 제품 보기
툴
체험, 구매 & 영업
커뮤니케이션
Red Hat 소개
Red Hat은 Linux, 클라우드, 컨테이너, 쿠버네티스 등을 포함한 글로벌 엔터프라이즈 오픈소스 솔루션 공급업체입니다. Red Hat은 코어 데이터센터에서 네트워크 엣지에 이르기까지 다양한 플랫폼과 환경에서 기업의 업무 편의성을 높여 주는 강화된 기능의 솔루션을 제공합니다.