How to deploy Ansible on Linux
and Windows. And why it is important in your Department. The keyword today is "play books"
' Using powershell and sshwithin
Ansible Part 1 '
Note: 1 PCI updating version 1
Ansible to be deployed within Windows. *keep in mind you must be using
any version newer than 1.7
-hosts are called from the inventory file within play
books. Be sure to know all your hosts thoroughly
before defining them. Once you know your
hosts you will know what part they belong to and what playbook they should be part
of. That is why the list of servers is
so important.
Step 1: Get yourself a few cups
of coffee and find a very comfortable chair. Make sure to drown out all
exterior noise and be prepared to be here for about 30 solid minutes, however
this walkthrough will take about 1.5 hours. Remember to unblock port 5986
on the firewall
Step 2: run the following
command: yum -y python krb-devel krb5-libs krb5-workstation “Only if your using
Centos/Redhat/Suse"
Step 2-1: run the following
command if your using debian/ubuntu sudo apt-get install python-dev libkr5-de
* Note: I highly advise
against building Ansible on any Ubuntu as it has been know to cause unreliable
results and this point was brought in the installation manual as Ansible was
created on a RedHat platform. *
The above dependencies are for
Active Directory/LDAP and Kerberos
Once you installed the above you
can move to step 3:
Step 3: type pip install kerberos
Note that Mac OSX and many other
“Linux” distributions already have these dependencies installed “out of the
box"
Please note that your “Control
machine needs these installed"
Step 4: if you do not know what a
conf file is, you will need to look it up. However you will need to edit
"/etc/krb5.conf” as we need to make a few adjustments so that Keberos
understands what we are trying to do
Step 5: find this:
You need to change these
variables starting with kdc = domaincontroller1.put.your.domain.here (my.domain.com)
put your secondary domain where
controller 2 goes…
Now do the same with = each
domain you need to access
Make sure the domain you put in
is all “UPPERCASE” as it will go badly if it is not
Step 7: We need to test the
connection
Please type this: kinit
user@SOMEDOMAIN.OF.YOURS
remember to type in UPPERCASE
Step 8: Now type: klist
klist will tell you if your valid
and how long you will be valid for… This is known as a “ticket"
klist will list your tickets
Step 9: Build the windows
Inventory located at: group_vars/windows.yml
[windows_servers_PCI_AD_controllers]
Server 1….
Server 2...
Server 3….
[windows_workstations_PCI]
workstation 1….
workstation 2…
Note: Please be sure NOT to use
IP ADDRESSES
Step 10: editing the
group_vars/windows.yml
Due to the open source and
vulnerability it is advised to have Ansible enterprise and to place the
following files for both Linux and Windows within the on premise internal
database to Ansible
ansible_user: Administrator #
please remember to put it in the correct format as you did with the kinit
command
ansible_password:
A_Secr3t_password_here
ansible_port: 5986
# If your using pyth0n 2.7.x the
following must be set to ignore (I used a # because you do not need this line,
it is REMd out) so do not use it
ansible_winrm_server_cert_validation:
ignore
# note that if your kinit worked
you should be fine, however if one fails, the other will generate the unknown
error, this is why LDAP comes into place
# Within Ansible vault is
extremely powerful, people forget they are handing the keys to their Ferrari to
the cloud and its better to know who did what then to chase a cyber ghost.
So getting Ansible enterprise and LDAP in place is important for Ansible
to work as intended within Tower and the playbooks
Step 11: Using a playbook
when referencing a playbook you
need to have -ask-vault-pass this will allow you to avoid having a keylogger,
prying eyes, or problematic people from having the latest and greatest password
within Ansible our “cloud” solution. So it is advised to keep this file
extremely safe
Here is a sample playbook I
created for a friend it is like using classes within classes and referencing
them as objects from other playbooks this is know as “Dictionary Types” which
is famous in Ruby
---
- hosts: Processing
vars:
http_port: 80
max_clients: 200
remote_user: hawaiideveloper
# or whatever we use for a service account to launch the code…
Using root would be foolish
tasks:
- name: ensure apache is the
latest version
yum: httpd
state: latest
###### I will write another file
that these “Dictionary Types” can reference and that way I do not need to repeat
myself.
Now moving on
- name write the apache config
file
template:
src: /srv/httpd.js
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: restarted
Now I will write a playbook for
both DBs and Processing
----
—hosts:
webserversremote_user: hawaiideveloper@halfaway.com
tasks:
-name ensure apache or ngnix is
the latest version
yum: name=httpd state=latest
apt: name=apache2
update_cache=yes state=latest
# Here is the breakdown
- hosts: databases
remote_user: calbright
tasks:
- name: UPDATE postgresql is the
latest version(edited)
yum: name=postgresql state=latest
- name: ensure mysql is the
latest verison
yum: name=mysqld state=latest
- name: ENSURE postgresql is the
latest(edited)
service: name=postgresql # or any
sql instance
state=running
Windows updates and powershell
example part 2
Defining groups within
Ansible inventory file
Perquisites:
- You will need powershell 3.0 to
continue
-
Optional custom inventory variables are:
* ``ansible_winrm_scheme``: Specify the
connection scheme (``http`` or ``https``) to use for the WinRM connection. Ansible uses ``https`` by default unless the
port is 5985.
* ``ansible_winrm_path``: Specify an
alternate path to the WinRM endpoint.
Ansible uses ``/wsman`` by default.
* ``ansible_winrm_realm``: Specify the realm
to use for Kerberos authentication. If
the username contains ``@``, Ansible will use the part of the username after
``@`` by default.
* ``ansible_winrm_transport``: Specify one
or more transports as a comma-separated list.
By default, Ansible will use ``kerberos,plaintext`` if the ``kerberos``
module is installed and a realm is defined, otherwise ``plaintext``.
* ``ansible_winrm_server_cert_validation``:
Specify the server certificate validation mode (``ignore`` or ``validate``).
Ansible defaults to ``validate`` on Python 2.7.9 and higher, which will result
in certificate validation errors against the Windows self-signed certificates.
Unless verifiable certificates have been configured on the WinRM listeners,
this should be set to ``ignore``
-
* ``ansible_winrm_*``:
Any additional keyword arguments supported by ``winrm.Protocol`` may be
provided.
Next you will need to deploy the:
Step 1: wimRM.ps file located at the bottom of this tutorial
Step 2: Once you have copied the wimRM (windows remote
management) content file be sure to save it as: wimRM.ps
Step 3: You can now deploy updates/software on a windows
box
Step 4: type this into a browser if you want the best and
cleanest version of the file aforementioned below:
Enjoy as you can now deploy Anything using Ansible.
Stay tuned to find out how to build Ansible with Docker –
use this combination to run management Ansible without waiting for yum to
install
------------ wimRM.ps
# Configure a Windows host for remote management with Ansible
# -----------------------------------------------------------
#
# This script checks the current WinRM/PSRemoting configuration
and makes the
# necessary changes to allow Ansible to connect, authenticate and
execute
# PowerShell commands.
#
# Set $VerbosePreference = "Continue" before running
the script in order to
# see the output messages.
#
# Written by Trond Hindenes <trond@hindenes.com>
# Updated by Chris Church <cchurch@ansible.com>
#
# Version 1.0 - July 6th, 2014
# Version 1.1 - November 11th, 2014
Param (
[string]$SubjectName =
$env:COMPUTERNAME,
[int]$CertValidityDays
= 365,
$CreateSelfSignedCert =
$true
)
Function New-LegacySelfSignedCert
{
Param (
[string]$SubjectName,
[int]$ValidDays =
365
)
$name = New-Object -COM
"X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=$SubjectName", 0)
$key = New-Object -COM
"X509Enrollment.CX509PrivateKey.1"
$key.ProviderName =
"Microsoft RSA SChannel Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 1024
$key.SecurityDescriptor
= "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
$serverauthoid = New-Object
-COM "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
$ekuoids = New-Object
-COM "X509Enrollment.CObjectIds.1"
$ekuoids.Add($serverauthoid)
$ekuext = New-Object
-COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
$cert = New-Object -COM
"X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore =
(Get-Date).AddDays(-1)
$cert.NotAfter =
$cert.NotBefore.AddDays($ValidDays)
$cert.X509Extensions.Add($ekuext)
$cert.Encode()
$enrollment =
New-Object -COM "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata =
$enrollment.CreateRequest(0)
$enrollment.InstallResponse(2, $certdata, 0, "")
# Return the thumbprint
of the last installed cert.
Get-ChildItem
"Cert:\LocalMachine\my"| Sort-Object NotBefore -Descending | Select
-First 1 | Select -Expand Thumbprint
}
# Setup error handling.
Trap
{
$_
Exit 1
}
$ErrorActionPreference = "Stop"
# Detect PowerShell version.
If ($PSVersionTable.PSVersion.Major -lt 3)
{
Throw "PowerShell
version 3 or higher is required."
}
# Find and start the WinRM service.
Write-Verbose "Verifying WinRM service."
If (!(Get-Service "WinRM"))
{
Throw "Unable to
find the WinRM service."
}
ElseIf ((Get-Service "WinRM").Status -ne "Running")
{
Write-Verbose
"Starting WinRM service."
Start-Service -Name
"WinRM" -ErrorAction Stop
}
# WinRM should be running; check that we have a PS session
config.
If (!(Get-PSSessionConfiguration -Verbose:$false) -or
(!(Get-ChildItem WSMan:\localhost\Listener)))
{
Write-Verbose
"Enabling PS Remoting."
Enable-PSRemoting
-Force -ErrorAction Stop
}
Else
{
Write-Verbose "PS
Remoting is already enabled."
}
# Make sure there is a SSL listener.
$listeners = Get-ChildItem WSMan:\localhost\Listener
If (!($listeners | Where {$_.Keys -like
"TRANSPORT=HTTPS"}))
{
# HTTPS-based endpoint
does not exist.
If (Get-Command
"New-SelfSignedCertificate" -ErrorAction SilentlyContinue)
{
$cert = New-SelfSignedCertificate
-DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\My"
$thumbprint =
$cert.Thumbprint
}
Else
{
$thumbprint =
New-LegacySelfSignedCert -SubjectName $env:COMPUTERNAME
}
# Create the hashtables
of settings to be used.
$valueset = @{}
$valueset.Add('Hostname', $env:COMPUTERNAME)
$valueset.Add('CertificateThumbprint', $thumbprint)
$selectorset = @{}
$selectorset.Add('Transport', 'HTTPS')
$selectorset.Add('Address',
'*')
Write-Verbose
"Enabling SSL listener."
New-WSManInstance
-ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet
$valueset
}
Else
{
Write-Verbose "SSL
listener is already active."
}
# Check for basic authentication.
$basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth |
Where {$_.Name -eq "Basic"}
If (($basicAuthSetting.Value) -eq $false)
{
Write-Verbose
"Enabling basic auth support."
Set-Item -Path
"WSMan:\localhost\Service\Auth\Basic" -Value $true
}
Else
{
Write-Verbose
"Basic auth is already enabled."
}
# Configure firewall to allow WinRM HTTPS connections.
$fwtest1 = netsh advfirewall firewall show rule name="Allow
WinRM HTTPS"
$fwtest2 = netsh advfirewall firewall show rule name="Allow
WinRM HTTPS" profile=any
If ($fwtest1.count -lt 5)
{
Write-Verbose
"Adding firewall rule to allow WinRM HTTPS."
netsh advfirewall
firewall add rule profile=any name="Allow WinRM HTTPS" dir=in
localport=5986 protocol=TCP action=allow
}
ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5))
{
Write-Verbose
"Updating firewall rule to allow WinRM HTTPS for any profile."
netsh advfirewall
firewall set rule name="Allow WinRM HTTPS" new profile=any
}
Else
{
Write-Verbose
"Firewall rule already exists to allow WinRM HTTPS."
}
# Test a remoting connection to localhost, which should work.
$httpResult = Invoke-Command -ComputerName "localhost"
-ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction
SilentlyContinue
$httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck
-SkipRevocationCheck
$httpsResult = New-PSSession -UseSSL -ComputerName
"localhost" -SessionOption $httpsOptions -ErrorVariable httpsError
-ErrorAction SilentlyContinue
If ($httpResult -and $httpsResult)
{
Write-Verbose
"HTTP and HTTPS sessions are enabled."
}
ElseIf ($httpsResult -and !$httpResult)
{
Write-Verbose
"HTTP sessions are disabled, HTTPS session are enabled."
}
ElseIf ($httpResult -and !$httpsResult)
{
Write-Verbose
"HTTPS sessions are disabled, HTTP session are enabled."
}
Else
{
Throw "Unable to
establish an HTTP or HTTPS remoting session."
}
Write-Verbose "PS Remoting has been successfully configured
for Ansible."
I gave up on chef and puppet because this tool is robust and cloud driven. However if you want to see CHEF corey in action visit me at:
https://twitter.com/ruby4hawaii
https://twitter.com/ruby4hawaii