mirror of
				https://github.com/avatao-content/test-tutorial-framework
				synced 2025-11-04 03:52:56 +00:00 
			
		
		
		
	Initial commit, first version of test TFW project
This commit is contained in:
		
							
								
								
									
										11
									
								
								config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								config.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					version: 'v2.0.0'
 | 
				
			||||||
 | 
					difficulty: 10
 | 
				
			||||||
 | 
					enable_flag_input: false
 | 
				
			||||||
 | 
					name: 'test-tutorial-framework'
 | 
				
			||||||
 | 
					skills: []
 | 
				
			||||||
 | 
					owners: ['kristof.toth@avatao.com']
 | 
				
			||||||
 | 
					crp_config:
 | 
				
			||||||
 | 
					    controller:
 | 
				
			||||||
 | 
					        ports: ["4444/controller"]
 | 
				
			||||||
 | 
					    solvable:
 | 
				
			||||||
 | 
					        ports: ["8888/http"]
 | 
				
			||||||
							
								
								
									
										1
									
								
								controller/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								controller/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					FROM avatao/controller:ubuntu-16.04
 | 
				
			||||||
							
								
								
									
										19
									
								
								solvable/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								solvable/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					FROM baseimage-tutorial-framework
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV TFW_APP_DIR="/srv/app"                          \
 | 
				
			||||||
 | 
					    TFW_LOGIN_APP_DIR="/tmp/source_code_server"     \
 | 
				
			||||||
 | 
					    TFW_WEBIDE_WD="/home/${AVATAO_USER}/workdir"    \
 | 
				
			||||||
 | 
					    TFW_TERMINADO_WD="/home/${AVATAO_USER}/workdir"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY solvable/src/demo ${TFW_APP_DIR}/
 | 
				
			||||||
 | 
					COPY solvable/src/demo/source_code_server/server.py ${TFW_LOGIN_APP_DIR}/
 | 
				
			||||||
 | 
					COPY solvable/src/demo/source_code_server/users.db ${TFW_LOGIN_APP_DIR}/
 | 
				
			||||||
 | 
					COPY solvable/src/demo/source_code_server/login_component.py ${TFW_WEBIDE_WD}/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN chown -R ${AVATAO_USER} ${TFW_WEBIDE_WD} &&\
 | 
				
			||||||
 | 
					    chmod -R 755 ${TFW_WEBIDE_WD}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VOLUME ["/home/${AVATAO_USER}"]
 | 
				
			||||||
 | 
					USER ${AVATAO_USER}
 | 
				
			||||||
 | 
					WORKDIR /home/${AVATAO_USER}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								solvable/nginx/components/login.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								solvable/nginx/components/login.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					location = /login {
 | 
				
			||||||
 | 
					        proxy_pass http://127.0.0.1:${TFW_LOGIN_APP_PORT};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
							
								
								
									
										6
									
								
								solvable/nginx/components/terminal.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								solvable/nginx/components/terminal.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					location = /terminal {
 | 
				
			||||||
 | 
					        proxy_pass http://127.0.0.1:${TFW_TERMINADO_PORT};
 | 
				
			||||||
 | 
					        proxy_http_version 1.1;
 | 
				
			||||||
 | 
					        proxy_set_header Upgrade $http_upgrade;
 | 
				
			||||||
 | 
					        proxy_set_header Connection "upgrade";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
							
								
								
									
										21
									
								
								solvable/src/demo/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								solvable/src/demo/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import tornado
 | 
				
			||||||
 | 
					import zmq
 | 
				
			||||||
 | 
					from tornado.ioloop import IOLoop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sql_injection_fsm import SQLInjectionFSM
 | 
				
			||||||
 | 
					from tfw.networking.server.tfw_server import TFWServer
 | 
				
			||||||
 | 
					from tfw.config import tfwenv
 | 
				
			||||||
 | 
					from tfw.config.logs import logging
 | 
				
			||||||
 | 
					log = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    server = TFWServer(SQLInjectionFSM)
 | 
				
			||||||
 | 
					    server.listen(tfwenv.WEB_PORT)
 | 
				
			||||||
 | 
					    log.debug('Python version: {}'.format(sys.version[:5]))
 | 
				
			||||||
 | 
					    log.debug('Tornado version: {}'.format(tornado.version))
 | 
				
			||||||
 | 
					    log.debug('ZeroMQ version: {}'.format(zmq.zmq_version()))
 | 
				
			||||||
 | 
					    log.debug('PyZMQ version: {}'.format(zmq.pyzmq_version()))
 | 
				
			||||||
 | 
					    log.info('Tornado application listening on port {}'.format(tfwenv.WEB_PORT))
 | 
				
			||||||
 | 
					    IOLoop.instance().start()
 | 
				
			||||||
							
								
								
									
										21
									
								
								solvable/src/demo/event_handler_main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								solvable/src/demo/event_handler_main.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					from tornado.ioloop import IOLoop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tfw.components.source_code_event_handler import SourceCodeEventHandler
 | 
				
			||||||
 | 
					from tfw.components.terminado_event_handler import TerminadoEventHandler
 | 
				
			||||||
 | 
					from tfw.components.process_managing_event_handler import ProcessManagingEventHandler
 | 
				
			||||||
 | 
					from tfw.config import tfwenv
 | 
				
			||||||
 | 
					from tfw.config.logs import logging
 | 
				
			||||||
 | 
					log = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    ide = SourceCodeEventHandler(key='webide', directory=tfwenv.WEBIDE_WD, exclude=['__pycache__'])
 | 
				
			||||||
 | 
					    terminado = TerminadoEventHandler(key='shell')
 | 
				
			||||||
 | 
					    terminado.historymonitor.subscribe_callback(callback=lambda hist: log.debug('User executed command: "{}"'.format(hist[-1])))
 | 
				
			||||||
 | 
					    processmanager = ProcessManagingEventHandler(key='processmanager', dirmonitor=ide.monitor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eventhandlers = {ide, terminado, processmanager}
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        IOLoop.instance().start()
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        for eh in eventhandlers: eh.cleanup()
 | 
				
			||||||
							
								
								
									
										27
									
								
								solvable/src/demo/source_code_server/login_component.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								solvable/src/demo/source_code_server/login_component.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import sqlite3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_db():
 | 
				
			||||||
 | 
					    return sqlite3.connect('users.db')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def authorize_login(email, password):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This method checks if a user is authorized and has admin privileges.
 | 
				
			||||||
 | 
					    :param email: The email address of the user.
 | 
				
			||||||
 | 
					    :param password: The password of the user.
 | 
				
			||||||
 | 
					    :return: A tuple, the first element is the email address if the user exists,
 | 
				
			||||||
 | 
					    and None if they don't; the second element is a boolean, which is True if
 | 
				
			||||||
 | 
					    the user has admin privileges.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    conn = get_db()
 | 
				
			||||||
 | 
					    sql_statement = '''SELECT email, is_admin FROM users
 | 
				
			||||||
 | 
					                       WHERE email="{}" AND password="{}"'''
 | 
				
			||||||
 | 
					    # The problem with this approach is that it substitutes any value received
 | 
				
			||||||
 | 
					    # from the user, even if it is a valid SQL statement!
 | 
				
			||||||
 | 
					    result = conn.execute(sql_statement.format(email, password)).fetchone()
 | 
				
			||||||
 | 
					    if result is None:
 | 
				
			||||||
 | 
					        return None, False
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        email, is_admin = result
 | 
				
			||||||
 | 
					        return email, is_admin == 1
 | 
				
			||||||
							
								
								
									
										27
									
								
								solvable/src/demo/source_code_server/server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								solvable/src/demo/source_code_server/server.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import json, sys
 | 
				
			||||||
 | 
					from tornado.ioloop import IOLoop
 | 
				
			||||||
 | 
					from tornado.web import RequestHandler, Application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tfw.config import tfwenv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sys.path.append(tfwenv.WEBIDE_WD)
 | 
				
			||||||
 | 
					from login_component import authorize_login
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoginHandler(RequestHandler):
 | 
				
			||||||
 | 
					    def post(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        request = json.loads(self.request.body)
 | 
				
			||||||
 | 
					        email, is_admin = authorize_login(
 | 
				
			||||||
 | 
					            request['email'],
 | 
				
			||||||
 | 
					            request['password']
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.write({
 | 
				
			||||||
 | 
					            'email': email,
 | 
				
			||||||
 | 
					            'is_admin': is_admin
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    application = Application([(r'/login', LoginHandler)])
 | 
				
			||||||
 | 
					    application.listen(tfwenv.LOGIN_APP_PORT)
 | 
				
			||||||
 | 
					    IOLoop.instance().start()
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								solvable/src/demo/source_code_server/users.db
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								solvable/src/demo/source_code_server/users.db
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										26
									
								
								solvable/src/demo/sql_injection_fsm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								solvable/src/demo/sql_injection_fsm.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					from tfw.fsm_base import FSMBase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SQLInjectionFSM(FSMBase):
 | 
				
			||||||
 | 
					    states = [
 | 
				
			||||||
 | 
					        'start',
 | 
				
			||||||
 | 
					        'stripped_code',
 | 
				
			||||||
 | 
					        'sql',
 | 
				
			||||||
 | 
					        'commented_code',
 | 
				
			||||||
 | 
					        'sql_with_substitutions',
 | 
				
			||||||
 | 
					        'sql_output',
 | 
				
			||||||
 | 
					        'end',
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    transitions = [
 | 
				
			||||||
 | 
					        {'trigger': 'webide', 'source': '*', 'dest': 'stripped_code'},  # TODO: delet this
 | 
				
			||||||
 | 
					        {'trigger': 'webide', 'source': 'start', 'dest': 'stripped_code'},
 | 
				
			||||||
 | 
					        {'trigger': 'login', 'source': 'stripped_code', 'dest': 'sql'},
 | 
				
			||||||
 | 
					        {'trigger': 'logger', 'source': 'sql', 'dest': 'commented_code'},
 | 
				
			||||||
 | 
					        {'trigger': 'webide', 'source': 'commented_code', 'dest': 'sql_with_substitutions'},
 | 
				
			||||||
 | 
					        {'trigger': 'logger', 'source': 'sql_with_substitutions', 'dest': 'sql_output'},
 | 
				
			||||||
 | 
					        {'trigger': 'logger', 'source': 'sql_output', 'dest': 'end'},
 | 
				
			||||||
 | 
					        {'trigger': 'reset', 'source': 'end', 'dest': 'start'},
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        super().__init__('start')
 | 
				
			||||||
							
								
								
									
										3
									
								
								solvable/supervisor/components/event_handlers.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								solvable/supervisor/components/event_handlers.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[program:event_handler_main]
 | 
				
			||||||
 | 
					directory=%(ENV_TFW_APP_DIR)s
 | 
				
			||||||
 | 
					command=env python event_handler_main.py
 | 
				
			||||||
							
								
								
									
										4
									
								
								solvable/supervisor/components/login.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								solvable/supervisor/components/login.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					[program:login]
 | 
				
			||||||
 | 
					directory=%(ENV_TFW_LOGIN_APP_DIR)s
 | 
				
			||||||
 | 
					command=env python server.py
 | 
				
			||||||
 | 
					autostart=false
 | 
				
			||||||
		Reference in New Issue
	
	Block a user