#Settings New Architecture + Server Auth

dev-linux
Ivan Maslov 5 years ago
parent e438b6e0c6
commit 35f761736f

@ -21,7 +21,7 @@ logging.basicConfig(filename="Reports\ReportRun_"+datetime.datetime.now().strfti
#Единый глобальный словарь (За основу взять из Settings.py) #Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict global mGlobalDict
mGlobalDict = Settings.mDict mGlobalDict = Settings.Settings()
Processor.mGlobalDict = mGlobalDict Processor.mGlobalDict = mGlobalDict
Timer.mGlobalDict = mGlobalDict Timer.mGlobalDict = mGlobalDict
Timer.Processor.mGlobalDict = mGlobalDict Timer.Processor.mGlobalDict = mGlobalDict
@ -38,12 +38,12 @@ lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict)
lThreadServer.start() lThreadServer.start()
#Вечный цикл #Вечный цикл
while True: while True:
lCurrentDateTime=datetime.datetime.now() lCurrentDateTime = datetime.datetime.now()
#Циклический обход правил #Циклический обход правил
lFlagSearchActivityType=True lFlagSearchActivityType=True
for lIndex, lItem in enumerate(mGlobalDict["Scheduler"]["ActivityTimeList"]): for lIndex, lItem in enumerate(mGlobalDict["Scheduler"]["ActivityTimeList"]):
#Проверка дней недели, в рамках которых можно запускать активность #Проверка дней недели, в рамках которых можно запускать активность
lItemWeekdayList=lItem.get("WeekdayList",[0,1,2,3,4,5,6]) lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
if lCurrentDateTime.weekday() in lItemWeekdayList: if lCurrentDateTime.weekday() in lItemWeekdayList:
if lFlagSearchActivityType: if lFlagSearchActivityType:
#Лог #Лог

@ -4,11 +4,16 @@ from threading import Thread
import Processor import Processor
import importlib import importlib
import pdb import pdb
import base64
import uuid
import datetime
from http import cookies
from desktopmagic.screengrab_win32 import ( from desktopmagic.screengrab_win32 import (
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages) getRectAsImage, getDisplaysAsImages)
global mGlobalDict global mGlobalDict
def SaveScreenshot(inFilePath): def SaveScreenshot(inFilePath):
# grab fullscreen # grab fullscreen
# Save the entire virtual screen as a PNG # Save the entire virtual screen as a PNG
@ -35,15 +40,87 @@ class RobotDaemonServer(Thread):
print('running server...') print('running server...')
httpd.serve_forever() httpd.serve_forever()
#Authenticate function ()
# return dict
# {
# "Domain": "", #Empty if Auth is not success
# "User": "" #Empty if Auth is not success
# }
def AuthenticateVerify(inRequest):
lResult={"Domain": "", "User": ""}
######################################
#Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
if lCookieAuthToken:
#Find AuthToken in GlobalDict
if lCookieAuthToken in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}):
#Auth Token Has Been Founded
lResult["Domain"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
#Exit earlier
return lResult
######################################
#Way 2 - try to logon
lHeaderAuthorization = inRequest.headers.get("Authorization", "").split(" ")
if len(lHeaderAuthorization) == 2:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split(
":")
lUser = llHeaderAuthorizationDecodedUserPasswordList[0]
lPassword = llHeaderAuthorizationDecodedUserPasswordList[1]
lDomain = None
if "\\" in lUser:
lDomain = lUser.split("\\")[0]
lUser = lUser.split("\\")[1]
#Try to logon - use processor
lLogonResult = Processor.Activity(
{
"Type": "WindowsLogon",
"Domain": lDomain,
"User": lUser,
"Password": lPassword
}
)
#Check result
if lLogonResult["Result"]:
lResult["Domain"] = lLogonResult["Domain"]
lResult["User"] = lLogonResult["User"]
#Create token
lAuthToken=str(uuid.uuid1())
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie
inRequest.OpenRPA={}
inRequest.OpenRPA["AuthToken"] = lAuthToken
#inRequest.OpenRPAResponse["Set-Cookie"]=[]lResult["Set-Cookie"] = lAuthToken
#pdb.set_trace()
#inRequest.send_header("Set-Cookie:", f"AuthToken={lAuthToken}")
######################################
return lResult
def AuthenticateBlock(inRequest):
# Send response status code
inRequest.send_response(401)
# Send headers
inRequest.send_header('Content-type', 'text/html')
inRequest.send_header('WWW-Authenticate', 'Basic') # Always ask login pass
inRequest.end_headers()
# Write content as utf-8 data
inRequest.wfile.write(bytes("", "utf8"))
# HTTPRequestHandler class # HTTPRequestHandler class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#ResponseContentTypeFile #ResponseContentTypeFile
def SendResponseContentTypeFile(self,inContentType,inFilePath): def SendResponseContentTypeFile(self, inContentType, inFilePath):
# Send response status code # Send response status code
self.send_response(200) self.send_response(200)
# Send headers # Send headers
self.send_header('Content-type',inContentType) self.send_header('Content-type', inContentType)
#Check if var exist
if hasattr(self, "OpenRPA"):
self.send_header("Set-Cookie", f"AuthToken={self.OpenRPA['AuthToken']}")
self.end_headers() self.end_headers()
lFileObject = open(inFilePath, "rb") lFileObject = open(inFilePath, "rb")
# Write content as utf-8 data # Write content as utf-8 data
@ -52,9 +129,23 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lFileObject.close() lFileObject.close()
# GET # GET
def do_GET(self): def do_GET(self):
#####################################
#Do authentication
#Check if authentication is turned on
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
else:
#Мост между файлом и http запросом (новый формат) #Мост между файлом и http запросом (новый формат)
if self.path == "/": if self.path == "/":
self.SendResponseContentTypeFile('text/html',"Web\\Index.xhtml") self.SendResponseContentTypeFile('text/html', "Web\\Index.xhtml")
#Мост между файлом и http запросом (новый формат) #Мост между файлом и http запросом (новый формат)
if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.css': if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.css':
self.SendResponseContentTypeFile('text/css',"..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css") self.SendResponseContentTypeFile('text/css',"..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css")
@ -111,7 +202,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lModuleImportName = lItem["RenderFunctionModuleName"] lModuleImportName = lItem["RenderFunctionModuleName"]
lModule=importlib.import_module(lModuleImportName) lModule=importlib.import_module(lModuleImportName)
#Найти функцию #Найти функцию
lFunction=getattr(lModule,lItem["RenderFunctionName"]) lFunction=getattr(lModule, lItem["RenderFunctionName"])
#Выполнить вызов и записать результат #Выполнить вызов и записать результат
lItemResultDict=lFunction(mGlobalDict) lItemResultDict=lFunction(mGlobalDict)
#RunFunction #RunFunction
@ -127,32 +218,22 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
if lFileURL.lower() in mGlobalDict["FileManager"]["FileURLFilePathDict"]: if lFileURL.lower() in mGlobalDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream',mGlobalDict["FileManager"]["FileURLFilePathDict"][lFileURL]) self.SendResponseContentTypeFile('application/octet-stream',mGlobalDict["FileManager"]["FileURLFilePathDict"][lFileURL])
# Auth function # Auth function
if self.path.lower().startswith('/auth'):
# Send response status code
self.send_response(401)
# Send headers
self.send_header('Content-type','text/html')
self.send_header('WWW-Authenticate', 'Basic') #Always ask login pass
lFlagIsKerberos=False
lHeaderAuthorization = self.headers.get("Authorization","").split(" ")
import base64
if len(lHeaderAuthorization) == 2:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split(":")
lUser = llHeaderAuthorizationDecodedUserPasswordList[0]
lPassword = llHeaderAuthorizationDecodedUserPasswordList[1]
lDomain = None
if "\\" in lUser:
lDomain = lUser.split("\\")[0]
lUser = lUser.split("\\")[1]
#print(f"Header Authorization, domain: {lDomain}, login: {lUser}, password: {lPassword}")
#self.send_header('Vary', 'negotiative')
#self.send_header('TCN', 'choice')
self.end_headers()
# Write content as utf-8 data
self.wfile.write(bytes("", "utf8"))
#pdb.set_trace()
# POST # POST
def do_POST(self): def do_POST(self):
#####################################
#Do authentication
#Check if authentication is turned on
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
else:
#Централизованная функция получения запросов/отправки #Централизованная функция получения запросов/отправки
if self.path == '/Utils/Processor': if self.path == '/Utils/Processor':
#ReadRequest #ReadRequest
@ -172,5 +253,3 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data # Write content as utf-8 data
self.wfile.write(bytes(message, "utf8")) self.wfile.write(bytes(message, "utf8"))
return return
#print(ChildProcessReadWaitString(p))

@ -64,19 +64,34 @@ def CheckIfProcessRunning(processName):
return False; return False;
#Orchestrator settings #Orchestrator settings
mDict = { def Settings():
"Server":{ mDict = {
"ListenPort_":"Порт, по которому можно подключиться к демону", "Server": {
"ListenPort":8081, "ListenPort_": "Порт, по которому можно подключиться к демону",
"ListenURLList":[ "ListenPort": 8081,
"ListenURLList": [
{ {
"Description":"Local machine test", "Description": "Local machine test",
"URL_":"Сетевое расположение сервера демона", "URL_": "Сетевое расположение сервера демона",
"URL":"http://127.0.0.1:8081" "URL": "http://127.0.0.1:8081"
}
],
"AccessUsers": {
"FlagCredentialsAsk": True, #Turn on Authentication
"FlagNoRulesBlock": True, #Block request, if user has no rules for requested URL (if FlagCredentialAsk is turned on)
"UserDict": {
#("Domain", "User"): {
# "FunctionDict": {
# # ("Method|GET|POST", "Match type|BeginWith|Contains", "URL"): def function (inRequest, inGlobalDict, inAuthenticateDict)
# }
#}
},
"AuthTokensDict": {
#"<AuthToken>":{"User":"", "Domain":"", "TokenDatetime":<Datetime>}
}
} }
]
}, },
"Scheduler":{ "Scheduler": {
"ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий "ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий
"ActivityTimeList":[ "ActivityTimeList":[
{ {
@ -137,4 +152,23 @@ mDict = {
"Robot_R01_help":"Robot data storage in orchestrator env", "Robot_R01_help":"Robot data storage in orchestrator env",
"Robot_R01":{} "Robot_R01":{}
} }
} }
###################################
#Init .py files from Settings folder
####################################
#Get file list from Settings folder
import os
import pdb
lSettingsPath = os.path.join(os.getcwd(), "Settings")
#pdb.set_trace()
#Lambda function to get files .py from settings folder except Settings.py
lFileList = [f for f in os.listdir(lSettingsPath) if os.path.isfile(os.path.join(lSettingsPath, f)) and f.split(".")[-1]=="py" and f != "Settings.py"]
#TODO Import files as python module and call SettingsUpdate()
import importlib.util
for lModuleFilePathItem in lFileList
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
#spec.loader.exec_module(foo)
#foo.MyClass()
#Return Global settings
return mDict

@ -0,0 +1,2 @@
def SettingsUpdate():
print("Everything is ok!")
Loading…
Cancel
Save