Monday, December 14, 2015

Getting Ansible to run in both Linux - all versions and Windows using playbooks inside of Ansible

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…

Step 6:  find this:



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:


Step 5:  Now once that is done you can run any preformatted powershell script you created….



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