def newAdmin(): """ Create a new admin account using valid session """ log.debug(f"<{request.remote_addr}> creating new admin account") if missingParams := missing(request, data=["username", "password", "name"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def registerNewAgent(): """ Register a new agent with the commander server """ log.debug(f"<{request.remote_addr}> registering a new agent") if missingParams := missing(request, data=["registrationKey", "hostname", "os"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def updateCredentials(): """ Authenticate an admin and update that admin's credentials """ log.debug(f"<{request.remote_addr}> updating credentials") if missingParams := missing(request, data=["username", "password", "newPassword"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def sendExecutable(): """ Send executable or script to the agent for execution """ log.debug(f"<{request.remote_addr}> sending executable") if missingParams := missing(request, headers=["Agent-ID"], data=["filename"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def agentCheckin(ws): """ Agent checking in -- send file to be executed if a job is waiting """ log.debug(f"<{ws.sock.getpeername()[0]}> agent checking in") # get agent ID from socket while True: data = ws.receive() # validate that json data was sent try: jsonData = json.loads(data) except Exception: log.warning( f"[{ws.sock.getpeername()[0]}] invalid json data received from agent during checkin" ) ws.close( 400, json.dumps({"error": "message was not a valid json object"})) return {"error": "message was not a valid json object"} # convert data to request-like object for missing() request = SimpleNamespace(**{ "headers": jsonData, "remote_addr": ws.sock.getpeername()[0] }) # check if the Agent ID was provided in the json data if missingParams := missing(request, headers=["Agent-ID"]): log.warning(f"<{request.remote_addr}> {missingParams}") ws.close(400, json.dumps({"error": missingParams})) return {"error": missingParams} # make sure Agent ID exists in the DB agentQuery = Agent.objects(agentID__exact=request.headers["Agent-ID"]) if not agentQuery: log.warning( f"<{request.remote_addr}> agentID not found in database") ws.close( 400, json.dumps({ "error": "agent ID not found, please check ID or register" })) return {"error": "agent ID not found, please check ID or register"} break
def login(): """ Authenticate an admin and return a new session token if successful """ log.debug(f"<{request.remote_addr}> logging in") if missingParams := missing(request, data=["username", "password"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def deleteJob(): """ Delete an entry and its corresponding file from the commander library """ log.debug(f"<{request.remote_addr}> deleting job") if missingParams := missing(request, data=["filename"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def updateJob(): """ Update the file or description of an existing entry in the commander library """ log.debug(f"<{request.remote_addr}> updating job") if missingParams := missingJobForm(request, data=["filename"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def addNewJob(): """ Add a new executable to the Commander library """ log.debug(f"<{request.remote_addr}> adding new job") if missingParams := missingJobForm(request, data=["job", "file"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def postJobResults(): """ Job has been executed -- save output and return code """ log.debug(f"<{request.remote_addr}> saving job results") if missingParams := missing(request, headers=["Agent-ID"], data=["job"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def getJobResults(): """ Get all jobs that have executed in the last 7 days, or optionally specify a different amount of time """ log.debug(f"<{request.remote_addr}> getting job results") if missingParams := missing(request, data=["agentID"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def sendAgentInstaller(): """ Fetch or generate an agent installer for the given operating system """ log.debug(f"<{request.remote_addr}> requesting an agent installer") if missingParams := missing(request, data=["os"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
def assignJob(): """ Admin submitting a job -- add job to the specified agent's queue """ log.debug(f"<{request.remote_addr}> {get_jwt_identity()} assigning a job") if missingParams := missing(request, data=["agentID", "filename", "argv"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400
@app.post("/agent/register") def registerNewAgent(): """ Register a new agent with the commander server """ log.debug(f"<{request.remote_addr}> registering a new agent") if missingParams := missing(request, data=["registrationKey", "hostname", "os"]): log.warning(f"<{request.remote_addr}> {missingParams}") return {"error": missingParams}, 400 # check registration key regKey = RegistrationKey.objects().first() if not regKey: log.error("no agent registration key found") return {"error": "no registration key has been generated yet"}, 500 if regKey["regKey"] != request.json["registrationKey"]: log.warning(f"<{request.remote_addr}> invalid registration key") return {"error": "invalild registration key"}, 401 # TODO: make sure OS is valid # create agent doc and add it to the db newAgent = Agent(hostname=request.json["hostname"], agentID=str(uuid4()), os=request.json["os"], lastCheckin=utcNowTimestamp()) newAgent.save() # return agent ID log.info( f"<{request.remote_addr}> registered new agent {newAgent['agentID']}") return {"agentID": newAgent["agentID"]} @sock.route("/agent/checkin")