I am using the python nmap module to do certificate discovery and monitoring.
import nmap
import time
import datetime
from contextlib import redirect_stdout
from datetime import date
import itertools
This is the function that manages the nmap scan.
SSLmonitor = nmap.PortScanner()
def SSLmon(IPaddress):
now = datetime.datetime.now()
filename = now.strftime("/results/%Y-%m-%dSSLmonWeekly.txt", "r")
filename2 = now.strftime("/results/%Y-%m-%dSSLmonWeeklyExpiring.txt", "r")
results = SSLmonitor.scan(hosts=IPaddress, arguments='--script=ssl-cert -p 443')
# If statement checks to see if last scanned address has ['scan'].
#print(results.keys())
if 'scan' in results:
hosts = results['scan']
#print(hosts)
# If host had cert on 443 try, else do pass.
try:
for host in hosts: # Chunk through the tuple.
try:
# Get the information for each host in the tuple
cert = hosts[host]['tcp'][443]['script']['ssl-cert']
try:
for host in hosts: # Chunk through the dictionary to get the key value pairs we want.
try:
# Get the information for each host in the hecka-dictionary.
cert = hosts[host]['tcp'][443]['script']['ssl-cert']
cert2 = cert.replace('Not valid after: ', '~')
indexed = cert2.index('~')
if datetime.date(int(cert2[indexed+1:indexed+5]), int(cert2[indexed+6:indexed+8]), int(cert2[indexed+9:indexed+11])) - datetime.date.today()
with open(filename, 'a') as f:
with redirect_stdout(f):
print("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'))
else:
with open(filename2, 'a') as e:
with redirect_stdout(e):
print("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'))
except Exception:
pass
except Exception:
pass
I looping through a list of IP addresses I know have certs
on port 443, and running them through the scanner.
#--------------------------------------------------------------
# Iterate through list of hosts with discovered certs
#--------------------------------------------------------------
with open("/weeklyscanlist/DiscoveredCertsByIP.txt", "r") as text_file:
for line in itertools.islice(text_file, 1, 4250):
SSLmon(str(line))
When I was handling output like this
if datetime.date(int(expDate[0]), int(expDate[1]), int(expDate[2])) - datetime.date.today() < datetime.timedelta(days = 30):
print("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'), "this cert is expiring soon)
else:
print("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'), "this cert is good for a while)
And it was working fine, so I know it the way I am handling writing the output to a file, but I can't find a way to handle this.
I've also tried
if datetime.date(int(expDate[0]), int(expDate[1]), int(expDate[2])) - datetime.date.today() < datetime.timedelta(days = 30):
fn = open(filename2, 'a')
fn.write("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'))
fn.close()
else:
f = open(filename, 'a')
f.write("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n'))
f.close()
without success.
Here is what you should do, following up on deweyredman’s sage advice to use string formatting:
Use string formatting to generate the output line of the file
Use an if-then to pick the filename
Only use one file write block to stay DRY
dt_diff = datetime.date(int(expDate[0]), int(expDate[1]), int(expDate[2])) - datetime.date.today()
which_filename = filename if dt_diff < datetime.timedelta(days = 30) else filename2
with open(which_filename, 'a') as f:
line = '\n%s %s' % (
IPaddress,
cert.replace(':', '='
).replace('commonName=', '\ncommonName='
).replace('/', '\n'),)
f.write(line)
It seems your args to f.write are incorrect...try:
if datetime.date(int(expDate[0]), int(expDate[1]), int(expDate[2])) - datetime.date.today() < datetime.timedelta(days = 30):
fn = open(filename2, 'a')
fn.write("{} {} {}".format("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n')))
fn.close()
else:
f = open(filename, 'a')
f.write("{} {} {}".format("\n", IPaddress, cert.replace(':', '=').replace('commonName=', '\ncommonName=').replace('/', '\n')))
f.close()
f.write takes one argument...you're passing it three.
Related
I wrote a python code for my project that stores file name of files on the SFTP server in a list and does the same for local directory and compares the 2 lists and then download the uncommon files. code takes its server credentials from a separate text file of format
CONTENTS OF TEXT FILE (config9.txt)
127.0.0.1,username,password,log22.txt,/new45,C:\Users\udit\Desktop\ftp2\bob16
my program executed one by one for different IP's. I wanted it to run it parallely for all IP's using multithreading. I modified my code but it still executes it one by one. Whats the error in it?
import os
import pysftp
import csv
import socket
from stat import S_IMODE, S_ISDIR, S_ISREG
import time
import threading
from threading import Thread
from time import sleep
import os.path
import shutil
import fileinput
import lock
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
def mainprocess():
with open("config9.txt", "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for row in csv_reader:
print(row)
IP=row[0]
myUsername=row[1]
myPassword=row[2]
txtfile=row[3]
remotepath=row[4]
localpath=row[5]
with pysftp.Connection(host=IP, username=myUsername, password=myPassword, cnopts=cnopts) as sftp:
r = str(socket.gethostbyaddr(IP))
print("connection successful with " + r)
def get_file2(sftp, remotedir):
result = []
for entry in sftp.listdir_attr(remotedir):
remotepath = remotedir + "/" + entry.filename
mode = entry.st_mode
if S_ISDIR(mode):
result += get_file2(sftp, remotepath)
elif S_ISREG(mode):
if (time.time() - entry.st_mtime) // (24 * 3600) > 0:
result.append(entry.filename)
return result
remote_path = remotepath
d = get_file2(sftp, remote_path)
def process():
myName = []
with open(filename, 'r+') as f:
for name in f.readlines():
while '\n' in name:
name = name.replace('\n', '')
myName.append(name)
print(myName)
print(len(myName))
import os
filtered_list = [string for string in d if string not in myName]
print("filtered list:", filtered_list)
print(len(filtered_list))
local_path =localpath
def compare_files(sftp, remotedir, remotefile, localdir, preserve_mtime=True):
remotepath = remotedir + "/" + remotefile
localpath = os.path.join(localdir, remotefile)
mode = sftp.stat(remotepath).st_mode
if S_ISDIR(mode):
try:
os.mkdir(localpath, mode=777)
except OSError:
pass
compare_files(sftp, remotepath, localpath, preserve_mtime)
elif S_ISREG(mode):
sftp.get(remotepath, localpath, preserve_mtime=True)
for file in filtered_list:
compare_files(sftp, remote_path, file, local_path, preserve_mtime=False)
with open(filename, 'a') as f:
for item in filtered_list:
f.write("%s\n" % item)
filename=txtfile
try:
file = open(filename, 'r')
process()
except IOError:
file = open(filename, 'w')
process()
t=time.time()
t1=threading.Thread(target=mainprocess(),args=())
t1.start()
t1.join()
I have a log file which consists the capacity of 1TB. I am uncertain that how to run this python script in the command line. I use the sys library but still my csv data is not added.
Below is my python code.
import re
import sys
from csv import writer
import datetime
log_file = '/Users/kiya/Desktop/mysql/ipscan/ip.txt'
output_file = '/Users/kiya/Desktop/mysql/ipscan/output.csv'
try:
ip_file =sys.argv[1]
except Exception:
print("usage: pythone3 {} [ip file]".format(sys.argv[0]))
sys.exit()
name_to_check = 'MBX_AUTHENTICATION_FAILED'
with open(log_file,encoding="utf-8") as infile:
for line in infile:
if name_to_check in line:
username = re.search(r'(?<=userName=)(.*)(?=,)', line)
username = username.group()
ip = re.search(r'(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])',line)
ip = ip.group()
with open(output_file, 'a') as outfile:
outfile.write('{username},{ip}\n'.format(username=username, ip=ip))
try this it work well and if the problem persist check your search regex :
from sys import argv
log_file = ""
if len(argv) > 0 :
log_file = argv[1]
else :
quit("No log_file specified, exiting script.")
with open(log_file, encoding="utf-8") as infile:
for line in infile:
if name_to_check in line:
username = re.search(r'(?<=userName=)(.*)(?=,)', line)
username = username.group()
date = re.search(r'(?P<date>\d{8})\s+(?P<time>\d{9})\+(?P<zone>\d{4})', line)
date = datetime.datetime.strptime(date.group('date'), "%Y%m%d").strftime("%Y-%m-%d")
print(date)
time = re.search(r'(?P<date>\d{8})\s+(?P<time>\d{9})\+(?P<zone>\d{4})', line)
time = datetime.datetime.strptime(time.group('time'), "%H%M%S%f").strftime("%H:%M:%S")
print(time)
ip = re.search(r'(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])',line)
with open(output_file, "ab", buffering=0) as outfile:
outfile.write( ("{},{},{},{}\n".format(username, date, time, ip)).encode() )
I want to make a replacement script.
It should replace str1 to str2.
My file has xml-based structure.
For example, I have:
...word1'#13#10'word2'#13#10'word3... = ...word1'#13#10'word3...
I want to remove some part of string.
I use this in a script:
Lines[i] = Lines[i].replace(key, DataBase[key])
I've already checked that "key" and "DataBase[key]" are correctly defined. If I print them into console with "print()" - it looks just like it has to.
But then script is executing it don't change sequences like this - with '#13#10'. Pairs of keys without any specific simbols works fine.
What can I do? And why it doesn't works well?
Full script:
import configparser
#import time
config = configparser.ConfigParser() # init configparser
config.optionxform = str
config.read("SocratToCortesExpress.cfg") # config file
print("Config file - readed")
filePath = config.get("PATH", "old_file") # config file - with names of files, pairs of words
DataStrings = config.items("DATA") # read pairs
DataBase = dict() # initialization of dictionary
print("Dictionary - initialized")
for Dstr in DataStrings: # old and new words for a replacement
SocratName = Dstr[0]
CortesName = Dstr[1]
DataBase[SocratName] = CortesName
print("Dictionary - fulfilled")
with open(filePath, "r", encoding='utf-8-sig') as ResultFile: # input file Lines = ResultFile.readlines()
print("Old file - uploaded")
f1 = open('logkeys.txt', 'w')
for key in DataBase.keys():
try:
f1.write('\n'+key+'\n'+DataBase[key]+'\n')
except Exception as e: #errors
f2 = open('log.txt', 'w')
f2.write('An exceptional thing happed - %s' %e)
f2.close()
f1.close()
for i in range(len(Lines)): # brutforce - all over input file
#Lines[i] = Lines[i].replace('\ufeff', '') #some weird symbol
for key in DataBase.keys():
try:
Lines[i] = Lines[i].replace(key, DataBase[key]) #replacing
except Exception as e: #errors
f2 = open('log.txt', 'w')
f2.write('An exceptional thing happed - %s' %e)
f2.close()
print("Sequences - replaced")
outFileName = config.get("PATH", "new_file") # define output file
print("Exit file - initialized")
with open(outFileName, "a", encoding='utf-8-sig') as outFile: # save
for line in Lines:
outFile.write(line)
print("OK")
Have you tried this?
>>> s = "word1'#13#10'word2'#13#10'word3"
>>> s.replace("'word2'#13#10'", '')
"word1'#13#10word3"
I have a script that basically pssh into multiple hosts for some information and checks a file to see if the information matches or not. The script runs fine when run directly from the Jenkins node. But when I try to run it via Jenkins, it hangs. It does create the output file, I added debug statements and see that the hosts from the file.txt are getting printed on Jenkins, but otherwise it just hangs.
I'm passing the file name as one of the arg. On Jenkins, I used to string parameter to pass the file. What am I doing wrong?
Thanks in advance.
import sys
import os
import subprocess
import re
import datetime
try:
hosts_file = sys.argv[1]
with open(hosts_file, 'r') as f:
hosts = []
for line in f:
hosts.append(line.split()[0])
except IOError:
print 'Error opening hosts_file'
sys.exit(1)
for host in hosts:
cmd = ('sshpass -f password pssh -A -O UserKnownHostsFile=/dev/null -O StrictHostKeyChecking=no -H ' + host + ' -l root -i "<cmd>"')
with open('file.txt', 'w') as fw:
subprocess.call(cmd, shell=True, stdout=fw)
with open('file.txt', 'r') as fr:
for line in fr:
match = re.search(r'some_word', line, re.I)
if match:
id_list.append(line.split()[-1])
model_dict[id_list[-1]] = line.strip()
if len(id_list) == 0:
print "something not found for hostname => %s" % host
with open('file.txt', 'r') as fr, open('output', 'a') as fw:
fw.write("something ==> %s" % host + "\n")
fw.write("*****************************************************************************************************************************************************************" + "\n")
for line in fr:
for item in id_list:
match = re.search(r'%s' % item, line, re.I)
if match:
my_line = model_dict[item] + ' => ' + line
fw.write(my_line)
id_list.remove(item)
if len(id_list) > 0:
with open('output', 'a') as fw:
for item in id_list:
my_line = model_dict[item] + ' => ' + 'No match found'
fw.write(my_line + "\n")
with open('models.txt', 'r') as fr, open('output', 'a') as fw:
fw.write("#### Printing Controller information ####" + "\n")
for line in fr:
match = re.search(r'vmhba', line, re.I)
if match:
fw.write(line.strip() + "\n")
os.remove('models.txt')
#I'm assuming this will print on the Jenkins console
with open('output', 'r') as fr:
for line in fr:
print line
properties = ["color", "font-size", "font-family", "width", "height"]
inPath = "style.css"
outPath = "output.txt"
#Open a file for reading
file = open(inPath, 'rU')
if file:
# read from the file
filecontents = file.read()
file.close()
else:
print "Error Opening File."
#Open a file for writing
file = open(outPath, 'wb')
if file:
for i in properties:
search = i
index = filecontents.find(search)
file.write(str(index), "\n")
file.close()
else:
print "Error Opening File."
seems to work, but:
It only searches a keyword once?
Its not writing to the output file. function takes exactly 1 argument
I don't want it to print the index actually, but the number of time the keyword appears.
Many thanks
First, you want .count(search), not .find(search), if what you're looking for is # of occurrences.
Second, .write() only takes a single parameter - if you want to write a newline, you need to concatenate it first, or call .write() twice.
Third, doing for i in properties: search = i is redundant; just use the name you want in your for loop.
for search in properties:
cnt = filecontents.count(search)
file.write(str(cnt) + "\n")
from itertools import imap
properties = ("color", "font-size", "font-family", "width", "height")
inPath = "style.css"
outPath = "output.txt"
try:
#Open a file for reading
filecontents = file(inPath).read()
except Exception as exc:
print exc
else:
#Open a file for writing
with open(outPath, 'wb') as out_file:
#for property in properties:
# out_string = "%s %s\n"
# out_file.write( out_string % (
# property, filecontents.count(property)))
outfile.write('\n'.join(
imap(str, imap(filecontents.count, properties))))