[python]resolve hostnames to ip address using pydns module

I wrote another script to change the desired nameserver. previously i used socket module to do resolution but i did not know how i can change the nameserver so i downloaded pydns.

This script can be extended to be used in automation script, most of the time the feeling of a layman user is neglected, users i have come across most of them have no knowledge of what ip address their server is, user will not spontaneously use nslookup to check.

from dns import resolver
import logging


logging.basicConfig(filename="dns.log", level=logging.INFO)

hostnames = []
dnsServer = input("Choose your preferred server (Default is 8.8.8.8) ")
if not dnsServer:
    dnsServer = '8.8.8.8'
    logging.info("No chosen, default {} is used".format(dnsServer))

ns = resolver.Resolver()
ns.nameservers = [dnsServer]

hostnames = input("Enter the hostnames in comma: ").split(",")
for hostname in hostnames:
    try:
        answers = ns.query(hostname, "A") # query returns an array
        logging.info("Trying to resolve {}".format(answers))
    except Exception as e:
        logging.error(e)
        exit(1)

for ip_address in answers:
    print(ip_address)
Advertisements
Posted in F5, Python, Scripting | Tagged , | Leave a comment

[python]F5 iControl API demo

Background
This demo script is to demonstrate to call F5 iCloud API with F5 SDK. The script is written in python, however I have found some limitation in using F5 SDK, best to try with direct call to the REST API by sending json template. This script took me 10hours to finish due to debugging and some exception handling for human error. The purpose is to get familiarise with the F5 SDK features.

An easier method is to use Ansible or Puppet to do auto provision on F5 bigip, with Puppet I only need to add in the json parameters which is much much easier than writing a home brew script.

What this script does?
This script can do the following:
1. Create Pool
2. Choice for user to pool member, if user skips this choice he/she can come add members later.
3. Create virtual server. You can create a VS first without assigning pool, however this option will ask user if he wants to add a pool, currently this option allows only one pool. On next update I will improve this by using an array to store the pools in order to add more than one pool to a virtual server.

Initial setting in F5 bigip
Screen Shot 2018-04-22 at 5.14.43 AM
Screen Shot 2018-04-22 at 5.15.36 AM.png
Screen Shot 2018-04-22 at 5.16.20 AM
We only have a google pool and two nodes. The following section will demonstrate auto provisioning with user’s input.

Test the script
Screen Shot 2018-04-22 at 5.18.03 AM.png
This is the ugly cli menu, I initially wanted to use tkinter, easygui, flask (as a webserver) and wtforms (form validation) modules, but I gave up as learning how to use one of them is another learning curve… I am anxious to know what F5 SDK can do so I improvised…

Pool Creation test

Screen Shot 2018-04-22 at 5.21.41 AM
I have created two nodes in a newly created pool, user can choose to create the node (pool member) later. The sub menu will loop infinitely until user press enter without putting any input.
So here is the result:
Screen Shot 2018-04-22 at 5.23.57 AM
Screen Shot 2018-04-22 at 5.24.41 AM

Pool member or node addition test
Screen Shot 2018-04-22 at 5.26.30 AM
This sub menu will check for available pools and list them for user to choose.

Screen Shot 2018-04-22 at 5.28.26 AM
So there is a third node which I just added.

Virtual server creation test
Screen Shot 2018-04-22 at 5.30.11 AM
I did not provide input for two questions as I have defaults if user just skip the questions, if no inputs from user a F5 accepted default will be used.

Screen Shot 2018-04-22 at 5.32.30 AM
Screen Shot 2018-04-22 at 5.33.28 AM.png
There are other options which I leave them as defaults, F5 SDK does not have an attribute for me to change the performance type, so when I create one VS it is always default to Standard, no attribute for Performance (Http) and Performance Layer4, there are however attributes for IP forwarding and Forward Layer2. To change the fasthttp and fastL4 profiles of a virtual server will need a request module to call the iControl API directly and supply json data.

Screen Shot 2018-04-22 at 5.36.16 AM.png

Error checking test
This script captures human error and exceptions so that the script will not crash.

Pool conflict test
Screen Shot 2018-04-22 at 5.39.12 AM
Screen Shot 2018-04-22 at 5.51.23 AM.png

Here’s the sample code, still lots of bugs to clean, making the script to work is easier if there is no user’s input sanitisation… lol… oh well… below is the sample code….

from f5.bigip import ManagementRoot
import logging, ipaddress

# enable logging with timestamp
logging.basicConfig(filename="bigip_script.log",
                    format="%(asctime)s %(levelname)s:%(message)s",
                    level=logging.INFO)

try:
    # Need to re-write this to store as an encrypted credential file
    mgmt = ManagementRoot("192.168.1.11","admin","121278")
except Exception as e:
    logging.error("Error in connecting to bigip.",e)
    print(e)
    exit(1)

ltm = mgmt.tm.ltm # LTM
vs = ltm.virtuals.virtual # Virtual Server


def choosePool():
    index = 1 # index starts from 1.
    dictPool = {} # dictionary to store the pool.name
    for pool in ltm.pools.get_collection():
        print(str(index) + ". " + pool.name)
        dictPool[index] = pool.name
        index += 1 # this index maps to the pool.name stored.
    choice = input("Which pool do you want to update? ")
    return dictPool[int(choice)] # user enters a digit, need to type cast choice to integer.


def vsMenu():
    # Simple menu to take in user input for creating vs.
    name = input("Enter virtual server name ")
    destination = input("Enter ip address of virtual server ")
    try:
        ipaddress.ip_address(destination) # check for valid ipv4 address.
    except Exception as e:
        logging.error(e)
        print("You have entered an invalid ipv4 address ", e)
        exit(1)
    port = input("Enter the service port number of {} ".format(name))
    if not port:# if user did not enter a value
        port = '0' # default port is any
    ipProtocol = input("Enter protocol of {} ".format(name))
    if not ipProtocol: # if user did not enter a value
        ipProtocol = 'tcp' # default is tcp
    source = input("Enter the source address (your expected visitor, if none just press enter) ")
    if not source: # if user did not enter a value
        source = '0.0.0.0/0' # default is any address
    pool = choosePool()
    print("Which persistence do you prefer?\n")
    print("[1] source address\n")
    print("[2] destination address\n")
    persistChoice = input("Your choice (press enter to skip): ")
    if persistChoice == '1':
        persist = 'source_addr' # session persistence based on source address
    elif persistChoice == '2':
        persist = 'dest_addr' # session persistence based on destination address
    else:
        persist = "" # default value is none.
    destination = destination + ":" + port # persist parameter accepts ip_address:port eg. 192.168.1.1:80 only.
    #print(name,destination,source,ipProtocol,pool,persist)
    createVS(name,destination,source,ipProtocol,pool,persist)


def createVS(name,destination,source,ipProtocol,pool,persist):
    if vs.exists(partition="Common", name=name):
        print("{} exists in bigip!".format(name))
    try:
        logging.info("Creating the Virtual Server {}".format(name))
        # Calling the iControl API using http-post
        vs.create(partition="Common",
                name=name,
                destination=destination,
                source=source,
                ipProtocol=ipProtocol,
                pool=pool,
                persist = persist)
    except Exception as e:
        logging.error(e)
        exit(1)


def addMember():
    poolobj = ltm.pools.pool.load(partition="Common", name=choosePool())
    createMembers(poolobj)


def createMembers(poolObj):
    members = []

    while True:
        nodeMember = input("Enter member ip address: ")
        if not nodeMember: # Quit asking if user does not put in value
            break
        try:
            ipaddress.ip_address(nodeMember) # validate if user has entered a valid ip address
            logging.debug("Collecting {}...".format(nodeMember))
        except Exception as e:
            logging.error("{} is an invalid ipv4 address: ".format(nodeMember),e)
            print("You have entered an invalid ip address: ",e)
            exit(1)
        nodeMemberPort = input("Service port of this member") # Collect server port
        if not nodeMemberPort: # Quit asking when no port is provided.
            break
        # make sure the port number is between 0 and 65535
        elif int(nodeMemberPort) >= 0 and int(nodeMemberPort) <= 65535:
            # collect the ip_address:port eg. 192.168.1.1:80 to members array.
            members.append(nodeMember + ":" + nodeMemberPort)
            logging.info("Collecting {}:{}".format(nodeMember,nodeMemberPort))
        else:
            logging.info("Unknown service port, assume quitting sub-menu...")
            break
    for member in members:
        poolObj.members_s.members.create(partition="Common", name=member)


def createPool():
    poolName = input("Enter pool name eg. pool-Gwen: ")
    # check if pool exists in bigip
    while ltm.pools.pool.exists(partition="Common",name=poolName):
        print("This pool {} is already exist! Choose another name".format(poolName))
        poolName = input("Enter pool name eg. pool-Gwen: ")
    if poolName: # Ask further for inputs if user has enter Pool Name
        print("Select load balancing method:\n")
        print("[1] Round Robin (default)\n")
        print("[2] Least Connections (Member)\n")
        print("[3] Least Connections (Node)\n")
        print("[4] Least sessions\n")
        choice = input("Enter a load balancing method: ")

        if not choice or choice is '1':
            lbMode = "round-robin" # default load balancing method, if user did not enter any value.
        elif choice is '2':
            lbMode = "least-connections-member"
        elif choice is '3':
            lbMode = "least-connections-node"
        else:
            lbMode = "least-sessions"
        try:
            poolObj = ltm.pools.pool.create(partition="Common", name=poolName, loadBalancingMode=lbMode)
            logging.info("Creating pool {} with load balancing method as {}".format(poolName,lbMode))
        except Exception as e:
            logging.error("Error in creating pool:",e)
            print(e)
            exit(1)
        choice = input("Proceed to create members? ")
        if choice.lower() == 'y':
            logging.info("User has selected to create pool members.")
            createMembers(poolObj)
        elif choice.lower() == 'n':
            logging.info("User does not want to create pool members.")
        else:
            print("You have entered an invalid choice, only y or n.\n")


# Ugly menu in CLI
def cliMenu():
    choice = 0
    while choice is not '9':
        print("Menu\n")
        print("====\n")
        print("[1]Create Pool\n")
        print("[2]Add members to existing Pool\n")
        print("[3]Create Virtual Server\n")
        print("[9]Quit\n")
        choice = input("Enter a choice: ")
        if choice == '1':
            createPool()
        elif choice == '2':
            addMember()
        elif choice == '3':
            vsMenu()
        elif choice == '9':
            print("Bye.")
        else:
            print("You have entered an invalid choice.")
            logging.error("User has entered an invalid choice in main menu.")


if __name__ == "__main__":
    cliMenu()
Posted in F5, Python, Scripting | Tagged , , , , , , , | Leave a comment

[python]Working with F5 iControl API on listing the virtual servers and pools

I am extending my demo script to demonstrate the viability to use iControl with our orchestrator for automatic F5 load balancer server provisioning.

I need to write a function to enumerate the pools and virtual servers, and here is how it is done. See the basic concept of F5 SDK here: https://f5-sdk.readthedocs.io/en/latest/userguide/basics.html

The collection has a method call get_collection() using this can easily enumerate existing pools and virtual server names.

Here’s the sample code:

from f5.bigip import ManagementRoot


try:
    ltm = ManagementRoot("192.168.1.11", "admin", "121278").tm.ltm
except Exception as e:
    print(e)
    exit(1)

# Collect the names of available pools and virtual servers.
pools = ltm.pools.get_collection()
vses = ltm.virtuals.get_collection()

# list the collections
for pool in pools:
    print(pool.name)

for vs in vses:
    print(vs.name)
Posted in F5, Python, Scripting | Tagged , , , , | Leave a comment

[powershell]Qutting com-object

I was trying to test a powershell script to read information from an excel file, I searched through the internet and found that using com object to open an excel workbook, however the close workbook and quit excel does not actually work, the excel application is still in the processes. I search through the internet and found a perfect answer to the problem, see the forum here: https://social.technet.microsoft.com/Forums/lync/en-US/81dcbbd7-f6cc-47ec-8537-db23e5ae5e2f/excel-releasecomobject-doesnt-work?forum=ITCG The solution provided by Ryan Kolter works. I used his solution and my excel closed instantaneously after the script completed.

#ignore certificate validation
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$a = 2
$src = @() # source ip address collection
$tests = @() # source hostnames collection
$xl = New-Object -ComObject Excel.Application
$xl.Visible = $false # To prevent the excel from opening visibly.
$wb = $xl.Workbooks.Open("H:\Tufin\tests\Rulebook.xlsx")


#uncomment to check the sheet in a workbook.
#$wb.Sheets | Select-Object -Property Name

$ws = $wb.Sheets.item("Rule")

#$aa = "A" + $a
while($true)
{
    if($ws.Range("A" + $a).Text -ne "") # collect until an empty cell.
    {
        $tests += $ws.Range("A" + $a).Text
    }
    else
    {
        break;
    }
    $a += 1
}
foreach($test in $tests) {
    $src += [System.Net.DNS]::GetHostEntry($test).AddressList.IPAddressToString
}


#Clean up
$xl.Workbooks.Close()
$xl.Quit()
[void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($ws)
[void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($wb)
[void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($xl)
[GC]::Collect()
Posted in Powershell, Scripting | Tagged , , , | Leave a comment

[python]Resolving a group of fqdns and store the ip addresses

Reference:http://www.pythonforbeginners.com/python/dns-lookup-python
Looking at the reference above is much easier than reading the actual socket documentation. My purpose is to find a python way to resolve a group of hostnames and return them as ip addresses.

Here’s the same code.

import logging,socket

logging.basicConfig(filename="dns.log",level=logging.INFO)
hostnames = []
answers = []

hostnames = input("Enter hostnames with comma: ").split(",")
for hostname in hostnames:
    try:
        answer = socket.gethostbyname(hostname)
        answers.append(answer)
        logging.info("Getting resolution answers from DNS for hostname {}".format(hostname))
    except Exception as e:
        logging.error(e)
        exit(1)

for i in answers:
    print(i)
    logging.info("Listing ip addresses...")

Here’s a test:

Enter hostnames with comma: http://www.google.com,www.hotmail.com,pool.ntp.org,cyruslab.net
74.125.24.105
204.79.197.212
139.99.107.37
192.0.78.24

Posted in Python, Scripting | Tagged , , | Leave a comment

[python]Creating bigip pool and pool members with F5 icontrol

I have recently downloaded the F5 SDK which helped to use the iControl REST API easily, it has a documentation here: https://f5-sdk.readthedocs.io, there are some coding example too, however not too in depth. So i started by just trying to create a new pool and iterate the pool members. This is a sample code to show it’s working, codes for checking if pool and pool members exist are required.

I have added some logging in points of event, and I must say when you start to script and have no idea where is the problem, putting loggers on points of events will help you troubleshoot and find out which point the script stops working.

Here’s the sample code:

from f5.bigip import ManagementRoot
import logging


logging.basicConfig(filename="bigip_script.log",level=logging.INFO)
poolMembers = list() # collects user input for pool members.
poolMember = '1' # initialization
poolName = input("Enter pool name: ")
print("\n")
lbMode = input("Enter load balancing method ")
print("\n")
while poolMember is not '0':
    poolMember = input("Enter member in this format ip_address:port type 0 to finish ") # creating nodes until user stops
    print("\n")
    poolMembers.append(poolMember)

try:
    mgmt = ManagementRoot("192.168.1.11","admin","p@ssw0rd") # connection to bigip
except Exception as e:
    logging.error(e)
    print(e)
    exit(1)

ltm = mgmt.tm.ltm
try:
    pool1 = ltm.pools.pool.create(name=poolName,partition="Common",loadBalancingMode=lbMode)
    logging.info("Creating pool {} with load balancing method as {}".format(poolName,lbMode))
except Exception as e:
    logging.error(e)
    print(e)
    exit(1)

for member in poolMembers:
    if member is '0': #exclude exit code, 0 is to exit the member prompt.
        logging.info("End of the pool members, exiting...")
        break

    try:
        pool1.members_s.members.create(name=member,partition="Common")
        logging.info("Creating member {}...".format(member))
    except Exception as e:
        logging.error(e)
        print(e)
        exit(1)

The logs that told me the code was successful:

INFO:root:Creating pool pool-Gwenpool with load balancing method as round-robin
INFO:root:Creating member 1.1.1.1:80...
INFO:root:Creating member 2.2.2.2:80...
INFO:root:End of the pool members, exiting...
INFO:root:Creating pool pool-Deadpool with load balancing method as least-connections-member
INFO:root:Creating member 192.168.1.100:1433...
INFO:root:Creating member 192.168.20.1:1433...
INFO:root:Creating member 192.168.30.1:1433...
INFO:root:End of the pool members, exiting...

Posted in Python, Scripting | Tagged , , , , , , | Leave a comment

[c]Question and Exercise (Tossing chance)

The requirement is to ask user to input head or tail in the program and display the number of heads and tails and the probability in percentage.
output will be like this:

Choose head or tail (valid choices is h or t): h
Choose head or tail (valid choices is h or t): h
Choose head or tail (valid choices is h or t): t
Choose head or tail (valid choices is h or t): t
Choose head or tail (valid choices is h or t): t
Choose head or tail (valid choices is h or t): t
Choose head or tail (valid choices is h or t): t
Choose head or tail (valid choices is h or t): t
Number of heads: 2
Number of tails: 6
Percent heads: 25.00%
Percent tails: 75.00%

Sample code below:

#include <stdio.h>

int main()
{
    int i,hi=0,ti=0;
    char choices;
    float headChance,tailChance;
    for(i=1;i<=8;i++)
    {
        printf("Choose head or tail (valid choices is h or t): ");
        scanf("%c%*c",&choices);
        switch(choices)
        {
            case 'h':
            case 'H':
            hi++;
            break;
            case 't':
            case 'T':
            ti++;
            break;
            default:
            printf("You have entered an invalid choice.\n");
      
        }
    }
    headChance = (float)(hi)/8 * 100;
    tailChance = (float)(ti)/8 * 100;
    printf("Number of heads: %d\n", hi);
    printf("Number of tails: %d\n", ti);
    printf("Percent heads: %.2f%%\n", headChance);
    printf("Percent tails: %.2f%%\n", tailChance);
    return 0;
}
Posted in General stuffs | 1 Comment