Use lstinline to display inline code instead of texttt
This commit is contained in:
parent
fab9861d0d
commit
ce8cad2ac4
@ -16,7 +16,7 @@ content using TFW.
|
|||||||
The purpose of this chapter is to further detail the built-in components
|
The purpose of this chapter is to further detail the built-in components
|
||||||
provided by the framework.
|
provided by the framework.
|
||||||
As previously mentioned, these components are implemented as event handlers
|
As previously mentioned, these components are implemented as event handlers
|
||||||
running in the \texttt{solvable} Docker container and frontend
|
running in the \code{solvable} Docker container and frontend
|
||||||
components written in Angular.
|
components written in Angular.
|
||||||
For instance the built-in code editor requires a frontend component and an event
|
For instance the built-in code editor requires a frontend component and an event
|
||||||
handler to function properly, while the frontend component responsible for
|
handler to function properly, while the frontend component responsible for
|
||||||
@ -36,14 +36,14 @@ For example, to inject a command into the terminal one would use a message like
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Notice the \texttt{\textbackslash{}n} at the end of the command.
|
Notice the \code{\n} at the end of the command.
|
||||||
By including a newline character, we are also capable of executing commands in the
|
By including a newline character, we are also capable of executing commands in the
|
||||||
user's terminal.
|
user's terminal.
|
||||||
Were this newline omitted, the command would only be written to the terminal
|
Were this newline omitted, the command would only be written to the terminal
|
||||||
(but not automatically executed) for users to inspect and potentially execute themselves.
|
(but not automatically executed) for users to inspect and potentially execute themselves.
|
||||||
|
|
||||||
Some components emit or broadcast messages on specific events, for instance the
|
Some components emit or broadcast messages on specific events, for instance the
|
||||||
\texttt{FSMManagingEventHandler} broadcasts the following message on state transitions:
|
\code{FSMManagingEventHandler} broadcasts the following message on state transitions:
|
||||||
\begin{lstlisting}[captionpos=b,caption={An FSM Update message}]
|
\begin{lstlisting}[captionpos=b,caption={An FSM Update message}]
|
||||||
{
|
{
|
||||||
"key": "fsm_update",
|
"key": "fsm_update",
|
||||||
@ -97,7 +97,7 @@ The timing of pauses and messages is based on the \emph{WPM} --- or Words Per Mi
|
|||||||
set by developers according to their specific use cases.
|
set by developers according to their specific use cases.
|
||||||
This creates an experience similar to chatting with someone in real time, as the time
|
This creates an experience similar to chatting with someone in real time, as the time
|
||||||
it takes for each message to be displayed is depending on the lenght of the previous message.
|
it takes for each message to be displayed is depending on the lenght of the previous message.
|
||||||
This illusion is made possible through appropriate \texttt{setTimeout()} calls in
|
This illusion is made possible through appropriate \code{setTimeout()} calls in
|
||||||
TypeScript and some elementary math to calculate the proper delays in milliseconds based on
|
TypeScript and some elementary math to calculate the proper delays in milliseconds based on
|
||||||
message lengths:
|
message lengths:
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ message lengths:
|
|||||||
|
|
||||||
This is the code editor integrated into the frontend of the framework.
|
This is the code editor integrated into the frontend of the framework.
|
||||||
It allows users to select, display and edit files.
|
It allows users to select, display and edit files.
|
||||||
Developers can configure which directory on the file system of the \texttt{solvable}
|
Developers can configure which directory on the file system of the \code{solvable}
|
||||||
container should the editor list files from.
|
container should the editor list files from.
|
||||||
The editor features the ``Deploy'' button referred to earlier in this paper, which is
|
The editor features the ``Deploy'' button referred to earlier in this paper, which is
|
||||||
capable of restarting processes that might execute a file visible in the editor.
|
capable of restarting processes that might execute a file visible in the editor.
|
||||||
@ -136,11 +136,11 @@ to display, that file is automatially displayed on a new tab in the IDE.
|
|||||||
|
|
||||||
This allows for really interesting demo opportunities.
|
This allows for really interesting demo opportunities.
|
||||||
Lets say I create a file using the terminal on the frontend by executing the
|
Lets say I create a file using the terminal on the frontend by executing the
|
||||||
command \texttt{touch file.txt}. A new tab on the editor automatically
|
command \code{touch file.txt}. A new tab on the editor automatically
|
||||||
appears. If I select it I can confirm that I have successfully created an
|
appears. If I select it I can confirm that I have successfully created an
|
||||||
empty file.
|
empty file.
|
||||||
After this let's run a \texttt{while} cycle in the command line which
|
After this let's run a \code{while} cycle in the command line which
|
||||||
peroadically appends some text to \texttt{file.txt}:
|
peroadically appends some text to \code{file.txt}:
|
||||||
\begin{lstlisting}[captionpos=b,caption={Bash While Cycle Writing to a File Periodically},
|
\begin{lstlisting}[captionpos=b,caption={Bash While Cycle Writing to a File Periodically},
|
||||||
language=bash]
|
language=bash]
|
||||||
while true
|
while true
|
||||||
@ -183,9 +183,9 @@ terminal emulator to do so.
|
|||||||
|
|
||||||
This component has a tiny server process which is managed by a TFW event handler.
|
This component has a tiny server process which is managed by a TFW event handler.
|
||||||
This small server is responsible for spawning bash sessions and
|
This small server is responsible for spawning bash sessions and
|
||||||
unix pseudoterminals (or \texttt{pty}s) in the \texttt{solvable} Docker
|
unix pseudoterminals (or \code{pty}s) in the \code{solvable} Docker
|
||||||
container.
|
container.
|
||||||
It is also responsible for connecting the master end of the \texttt{pty} to the
|
It is also responsible for connecting the master end of the \code{pty} to the
|
||||||
emulator running in your browser and the slave end to the bash session it has
|
emulator running in your browser and the slave end to the bash session it has
|
||||||
spawned.
|
spawned.
|
||||||
This way users are able to work in the shell displayed on the frontend just like
|
This way users are able to work in the shell displayed on the frontend just like
|
||||||
@ -212,21 +212,21 @@ monitoring solution such as Sysdig%
|
|||||||
\footnote{\href{https://sysdig.comq}{https://sysdig.com}}.
|
\footnote{\href{https://sysdig.comq}{https://sysdig.com}}.
|
||||||
I deemed most simiar systems a huge overkill to implement this functionality, and their
|
I deemed most simiar systems a huge overkill to implement this functionality, and their
|
||||||
memory footprints are not something we could afford here.
|
memory footprints are not something we could afford here.
|
||||||
Another way would be to use \texttt{pam\_tty\_audit.so} in the PAM%
|
Another way would be to use \code{pam_tty_audit.so} in the PAM%
|
||||||
\footnote{Linux Pluggable Authentication Modules:
|
\footnote{Linux Pluggable Authentication Modules:
|
||||||
\href{http://man7.org/linux/man-pages/man3/pam.3.html}
|
\href{http://man7.org/linux/man-pages/man3/pam.3.html}
|
||||||
{http://man7.org/linux/man-pages/man3/pam.3.html}}
|
{http://man7.org/linux/man-pages/man3/pam.3.html}}
|
||||||
configurations responsible for logins, as this allows for various TTY auditing functions,
|
configurations responsible for logins, as this allows for various TTY auditing functions,
|
||||||
but I have found an ever simpler approach to the problem in the end.
|
but I have found an ever simpler approach to the problem in the end.
|
||||||
By using the inotify system built into TFW, I can set up the user's environment in
|
By using the inotify system built into TFW, I can set up the user's environment in
|
||||||
such a way, that I can enforce and determine the location of the bash \texttt{HISTFILE}%
|
such a way, that I can enforce and determine the location of the bash \code{HISTFILE}%
|
||||||
\footnote{This environment variable contains the path to the file bash writes command
|
\footnote{This environment variable contains the path to the file bash writes command
|
||||||
history to}
|
history to}
|
||||||
of the user.
|
of the user.
|
||||||
This way I can monitor changes made to this file and read the commands executed
|
This way I can monitor changes made to this file and read the commands executed
|
||||||
by the user from it.
|
by the user from it.
|
||||||
It is important to keep in mind that the user is able to ``sabotage'' this method%
|
It is important to keep in mind that the user is able to ``sabotage'' this method%
|
||||||
\footnote{By unsetting the \texttt{HISTFILE} envvar for example},
|
\footnote{By unsetting the \code{HISTFILE} envvar for example},
|
||||||
but that should not be an issue as this is not a feature that is intended to be
|
but that should not be an issue as this is not a feature that is intended to be
|
||||||
used in competitive environments (and if the users of a tutorial intentionally
|
used in competitive environments (and if the users of a tutorial intentionally
|
||||||
break the system under themselves, well, good for them).
|
break the system under themselves, well, good for them).
|
||||||
@ -248,7 +248,7 @@ experience similar to working in an IDE on your laptop.
|
|||||||
\section{Process Management}\label{processmanagement}
|
\section{Process Management}\label{processmanagement}
|
||||||
|
|
||||||
The framework includes an event handler capable of managing processes running inside
|
The framework includes an event handler capable of managing processes running inside
|
||||||
the \texttt{solvable} Docker container.
|
the \code{solvable} Docker container.
|
||||||
It's capabilities include starting, stopping and restarting processes.
|
It's capabilities include starting, stopping and restarting processes.
|
||||||
It is also capable of emitting the standard out or standard error logs of processes
|
It is also capable of emitting the standard out or standard error logs of processes
|
||||||
(by broadcasting TFW messages).
|
(by broadcasting TFW messages).
|
||||||
@ -273,17 +273,17 @@ a complex system could come with.
|
|||||||
|
|
||||||
I'll briefly explain such a bug, which I've found to be immersely exciting.
|
I'll briefly explain such a bug, which I've found to be immersely exciting.
|
||||||
During the initial development of this feature all processes inside the
|
During the initial development of this feature all processes inside the
|
||||||
\texttt{solvable} Docker container were writing their logs to files
|
\code{solvable} Docker container were writing their logs to files
|
||||||
in the FHS%
|
in the FHS%
|
||||||
\footnote{The File Hierarchy Standard is a standard maintained by the Linux foundation,
|
\footnote{The File Hierarchy Standard is a standard maintained by the Linux foundation,
|
||||||
defining a common directory structure for compliant systems. See
|
defining a common directory structure for compliant systems. See
|
||||||
\href{https://wiki.linuxfoundation.org/lsb/fhs}{https://wiki.linuxfoundation.org/lsb/fhs}}
|
\href{https://wiki.linuxfoundation.org/lsb/fhs}{https://wiki.linuxfoundation.org/lsb/fhs}}
|
||||||
location \texttt{/tmp/}.
|
location \code{/tmp/}.
|
||||||
All logs coming from the container itself were also logged to this location.
|
All logs coming from the container itself were also logged to this location.
|
||||||
This had caused an infinite recursion: when a process would write to \texttt{/tmp/}
|
This had caused an infinite recursion: when a process would write to \code{/tmp/}
|
||||||
inotify would invoke a process that would also log to that location causing the kernel to
|
inotify would invoke a process that would also log to that location causing the kernel to
|
||||||
emit more inotify events, which in turn would cause more and more new proesses to spawn
|
emit more inotify events, which in turn would cause more and more new proesses to spawn
|
||||||
and write to \texttt{/tmp/}, causing the whole procedure to repeat again and again.
|
and write to \code{/tmp/}, causing the whole procedure to repeat again and again.
|
||||||
This continued until my machine would start to run out of memory and stat swapping
|
This continued until my machine would start to run out of memory and stat swapping
|
||||||
pages to disk%
|
pages to disk%
|
||||||
\footnote{When a modern operating system runs out of physical RAM, it is going to swap
|
\footnote{When a modern operating system runs out of physical RAM, it is going to swap
|
||||||
@ -296,7 +296,7 @@ fascinating phenomenon, but those were \emph{very} fun hours.
|
|||||||
|
|
||||||
\section{FSM Management}
|
\section{FSM Management}
|
||||||
|
|
||||||
I have already mentioned the event handler called \texttt{FSMManagingEventHandler},
|
I have already mentioned the event handler called \code{FSMManagingEventHandler},
|
||||||
which is responsible for managing the framework FSM.
|
which is responsible for managing the framework FSM.
|
||||||
For completeness I chose to include it on this chapter as well.
|
For completeness I chose to include it on this chapter as well.
|
||||||
The API it exposes through TFW messages allows client code to attempt stepping the
|
The API it exposes through TFW messages allows client code to attempt stepping the
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
It is important to understand that the Tutorial Framework is currently implemented as
|
It is important to understand that the Tutorial Framework is currently implemented as
|
||||||
two Docker images:
|
two Docker images:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item the \texttt{solvable} image is responsible for running the framework and the client
|
\item the \code{solvable} image is responsible for running the framework and the client
|
||||||
code depending on it
|
code depending on it
|
||||||
\item the \texttt{controller} image is responsible for solution checking (to figure out
|
\item the \code{controller} image is responsible for solution checking (to figure out
|
||||||
whether the user completed the tutorial or not)
|
whether the user completed the tutorial or not)
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
During most of this capter I am going to be discussing the \texttt{solvable} Docker image,
|
During most of this capter I am going to be discussing the \code{solvable} Docker image,
|
||||||
with the exception of section~\ref{solutioncheck}, where I will dive into how the
|
with the exception of Section~\ref{solutioncheck}, where I will dive into how the
|
||||||
\texttt{controller} image is implemented.
|
\code{controller} image is implemented.
|
||||||
|
|
||||||
The most important feature of the framework is it's messaging system.
|
The most important feature of the framework is it's messaging system.
|
||||||
Basically what we need is a system where processes running inside a Docker container
|
Basically what we need is a system where processes running inside a Docker container
|
||||||
@ -51,7 +51,7 @@ of your website (and as such requiring to go over the whole TCP handshake and th
|
|||||||
HTTP request-response on each update).
|
HTTP request-response on each update).
|
||||||
This has been superseded by WebSockets around 2011, which provide a full-duplex
|
This has been superseded by WebSockets around 2011, which provide a full-duplex
|
||||||
communication channel over TCP between your browser and the server.
|
communication channel over TCP between your browser and the server.
|
||||||
This is done by initiation a protocol handshake using the \texttt{Connection: Upgrade}
|
This is done by initiation a protocol handshake using the \code{Connection: Upgrade}
|
||||||
HTTP header, which establishes a premanent socket connection between the browser
|
HTTP header, which establishes a premanent socket connection between the browser
|
||||||
and the server.
|
and the server.
|
||||||
This allows for communication with lower overhead and latency facilitating efficient
|
This allows for communication with lower overhead and latency facilitating efficient
|
||||||
@ -85,7 +85,7 @@ A few examples of top contenders and reasons for not using them in the end:
|
|||||||
\item The handling of raw TCP sockets would involve lot's of boilerplate logic that
|
\item The handling of raw TCP sockets would involve lot's of boilerplate logic that
|
||||||
already have quality implementations in messaging libraries: i.e.\ making sure that
|
already have quality implementations in messaging libraries: i.e.\ making sure that
|
||||||
all bytes are sent or received both require checking the return values of the
|
all bytes are sent or received both require checking the return values of the
|
||||||
libc \texttt{send()} and \texttt{recv()} system calls, while ZMQ takes care of this
|
libc \code{send()} and \code{recv()} system calls, while ZMQ takes care of this
|
||||||
extra logic involved and even provides higher level messaging patterns such as
|
extra logic involved and even provides higher level messaging patterns such as
|
||||||
subscribe-publish, which would need to be implemented on top of raw sockets again.
|
subscribe-publish, which would need to be implemented on top of raw sockets again.
|
||||||
\item Using something like gRPC\footnote{\href{https://grpc.io}{https://grpc.io}}
|
\item Using something like gRPC\footnote{\href{https://grpc.io}{https://grpc.io}}
|
||||||
@ -113,10 +113,10 @@ Architecturally TFW consists of four main components:
|
|||||||
\item \textbf{TFW (proxy) server}: responsible for message routing/proxying
|
\item \textbf{TFW (proxy) server}: responsible for message routing/proxying
|
||||||
between the frontend and event handlers
|
between the frontend and event handlers
|
||||||
\item \textbf{TFW FSM}: a finite state machine responsible for tracking user progress,
|
\item \textbf{TFW FSM}: a finite state machine responsible for tracking user progress,
|
||||||
that is implemented as an event handler called \texttt{FSMManagingEventHandler}
|
that is implemented as an event handler called \code{FSMManagingEventHandler}
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
Note that it is important to keep in mind that as I've mentioned previously,
|
Note that it is important to keep in mind that as I've mentioned previously,
|
||||||
the TFW Server and event handlers reside in the \texttt{solvable} Docker container.
|
the TFW Server and event handlers reside in the \code{solvable} Docker container.
|
||||||
They all run in separate processes and only communicate using ZeroMQ sockets.
|
They all run in separate processes and only communicate using ZeroMQ sockets.
|
||||||
|
|
||||||
In the following sections I am going to explain each of the main components in
|
In the following sections I am going to explain each of the main components in
|
||||||
@ -147,17 +147,17 @@ Let's inspect further what a valid TFW message might look like:
|
|||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
All valid messages \emph{must} include a \texttt{key} field as this is used by the
|
All valid messages \emph{must} include a \code{key} field as this is used by the
|
||||||
framework for addressing: event handlers and frontend components subscribe to one
|
framework for addressing: event handlers and frontend components subscribe to one
|
||||||
or more \texttt{key}s and only receive messages with \texttt{key}s they have
|
or more \code{key}s and only receive messages with \code{key}s they have
|
||||||
subscribed to.
|
subscribed to.
|
||||||
It is possible to send a message with an empty key, however these messages will not
|
It is possible to send a message with an empty key, however these messages will not
|
||||||
be forwarded by the TFW server (but will reach it, so in case the target of a message
|
be forwarded by the TFW server (but will reach it, so in case the target of a message
|
||||||
is the TFW server exclusively, an empty \texttt{key} can may used).
|
is the TFW server exclusively, an empty \code{key} can may used).
|
||||||
|
|
||||||
The rest of the fields are optional, but most messages will carry something
|
The rest of the fields are optional, but most messages will carry something
|
||||||
in their \texttt{data} field.
|
in their \code{data} field.
|
||||||
The purpose \texttt{trigger} and \texttt{signature} fields will be detailed
|
The purpose \code{trigger} and \code{signature} fields will be detailed
|
||||||
at a later point in this paper.
|
at a later point in this paper.
|
||||||
|
|
||||||
\subsection{Networking Details}
|
\subsection{Networking Details}
|
||||||
@ -171,8 +171,8 @@ the frontend via WebSockets.
|
|||||||
The TFW server is also capable of ``reflecting'' messages back to the side they were
|
The TFW server is also capable of ``reflecting'' messages back to the side they were
|
||||||
received on (to faciliate event handler to event handler for instance), or broadcast
|
received on (to faciliate event handler to event handler for instance), or broadcast
|
||||||
messages to all components.
|
messages to all components.
|
||||||
This is possible by embedding a whole TFW message in the \texttt{data} field of
|
This is possible by embedding a whole TFW message in the \code{data} field of
|
||||||
an outer wrapper message with a special \texttt{key} that signals to the TFW server that
|
an outer wrapper message with a special \code{key} that signals to the TFW server that
|
||||||
this message requires special attention.
|
this message requires special attention.
|
||||||
An example of this would be:
|
An example of this would be:
|
||||||
\begin{lstlisting}[captionpos=b,caption={Broadcasting and mirroring TFW messages}]
|
\begin{lstlisting}[captionpos=b,caption={Broadcasting and mirroring TFW messages}]
|
||||||
@ -187,12 +187,12 @@ An example of this would be:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Any invalid messages (not valid JSON or no \texttt{key} field present) are ignored
|
Any invalid messages (not valid JSON or no \code{key} field present) are ignored
|
||||||
by the TFW server.
|
by the TFW server.
|
||||||
|
|
||||||
\subsection{Event Handlers}
|
\subsection{Event Handlers}
|
||||||
|
|
||||||
Event handlers are processes running in the \texttt{solvable} Docker container
|
Event handlers are processes running in the \code{solvable} Docker container
|
||||||
that subscribe to specific message types using ZeroMQ sockets.
|
that subscribe to specific message types using ZeroMQ sockets.
|
||||||
As discussed earlier, using ZeroMQ allows developers to implement event handlers
|
As discussed earlier, using ZeroMQ allows developers to implement event handlers
|
||||||
in a wide variety of programming languages.
|
in a wide variety of programming languages.
|
||||||
@ -253,7 +253,7 @@ This code editor is essentially a Monaco editor%
|
|||||||
{https://microsoft.github.io/monaco-editor/}}
|
{https://microsoft.github.io/monaco-editor/}}
|
||||||
instance integrated into Angular and upgraded with the capability to
|
instance integrated into Angular and upgraded with the capability to
|
||||||
exchanges messages with an event handler to save, read and edit files
|
exchanges messages with an event handler to save, read and edit files
|
||||||
that reside in the writeable file system of the \texttt{solvable}
|
that reside in the writeable file system of the \code{solvable}
|
||||||
Docker container.
|
Docker container.
|
||||||
|
|
||||||
All of the built-ins come with full API documentation explaining what they do
|
All of the built-ins come with full API documentation explaining what they do
|
||||||
@ -337,7 +337,7 @@ state transitions, or onentering and exiting a state.
|
|||||||
It is \emph{very} important to be aware of these callbacks, as much of the
|
It is \emph{very} important to be aware of these callbacks, as much of the
|
||||||
actual tutorial logic is often going to be implemented in these.
|
actual tutorial logic is often going to be implemented in these.
|
||||||
|
|
||||||
Architecturally a built-in event handler called \texttt{FSMManagingEventHandler}
|
Architecturally a built-in event handler called \code{FSMManagingEventHandler}
|
||||||
is capable of managing the FSM defined by clients.
|
is capable of managing the FSM defined by clients.
|
||||||
The responsibilities of said event handler include:
|
The responsibilities of said event handler include:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
@ -347,16 +347,16 @@ The responsibilities of said event handler include:
|
|||||||
such as successful transitions
|
such as successful transitions
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
The \texttt{trigger} field of a message can be used to step the framework FSM
|
The \code{trigger} field of a message can be used to step the framework FSM
|
||||||
if all preconditions are met.
|
if all preconditions are met.
|
||||||
The way this works is if the TFW server encounters a message with a
|
The way this works is if the TFW server encounters a message with a
|
||||||
\texttt{trigger} defined, it notifies the event handler managing
|
\code{trigger} defined, it notifies the event handler managing
|
||||||
the state machine.
|
the state machine.
|
||||||
|
|
||||||
Since messages can come from unauthenticated sources, it is possible to
|
Since messages can come from unauthenticated sources, it is possible to
|
||||||
enforce the authentication of privileged messages, such as messages containing a \texttt{trigger}.
|
enforce the authentication of privileged messages, such as messages containing a \code{trigger}.
|
||||||
The framework allows trusted code to access a cryptographic key on the file system, which
|
The framework allows trusted code to access a cryptographic key on the file system, which
|
||||||
can be used to digitally sign messages (this is what the \texttt{signature} message
|
can be used to digitally sign messages (this is what the \code{signature} message
|
||||||
field is designed for).
|
field is designed for).
|
||||||
In this case the TFW server will only forward privileged messages that
|
In this case the TFW server will only forward privileged messages that
|
||||||
have a valid signature.
|
have a valid signature.
|
||||||
@ -364,9 +364,9 @@ have a valid signature.
|
|||||||
\subsection{Solution checking}\label{solutioncheck}
|
\subsection{Solution checking}\label{solutioncheck}
|
||||||
|
|
||||||
Traditionally most challenges on the Avatao platform implement a Docker image called
|
Traditionally most challenges on the Avatao platform implement a Docker image called
|
||||||
\texttt{controller}, which is responsible for detecting the successful
|
\code{controller}, which is responsible for detecting the successful
|
||||||
solution of a challenge.
|
solution of a challenge.
|
||||||
When using the Tutorial Framework a pre-implemented \texttt{controller}
|
When using the Tutorial Framework a pre-implemented \code{controller}
|
||||||
image is available, which listens to messages emitted by the
|
image is available, which listens to messages emitted by the
|
||||||
framework FSM, and detects if the final state defined by developers is reached.
|
framework FSM, and detects if the final state defined by developers is reached.
|
||||||
This means that if content creators implement a proper FSM, the solution checking
|
This means that if content creators implement a proper FSM, the solution checking
|
||||||
|
@ -105,7 +105,7 @@ After I got this working I was looking into writing hacky bash scripts to automa
|
|||||||
required to complete the challenge in order to make it easier for me to record the solution,
|
required to complete the challenge in order to make it easier for me to record the solution,
|
||||||
as I have often found myself recording over and over again for a demo without any mistakes.
|
as I have often found myself recording over and over again for a demo without any mistakes.
|
||||||
During the time I was playing around with this idea, researching possible solutions have led me
|
During the time I was playing around with this idea, researching possible solutions have led me
|
||||||
to a hidden gem of a project on GitHub called \texttt{demo-magic}%
|
to a hidden gem of a project on GitHub called \code{demo-magic}%
|
||||||
\footnote{\href{https://github.com/paxtonhare/demo-magic}{https://github.com/paxtonhare/demo-magic}},
|
\footnote{\href{https://github.com/paxtonhare/demo-magic}{https://github.com/paxtonhare/demo-magic}},
|
||||||
which is esentially a bash script that simulates someone typing into a terminal and executing
|
which is esentially a bash script that simulates someone typing into a terminal and executing
|
||||||
commands.
|
commands.
|
||||||
@ -118,7 +118,7 @@ Soon after recording demo videos was not even necessary anymore, as I have start
|
|||||||
the solution script with the challenge code itself, making it toggleable using build-time
|
the solution script with the challenge code itself, making it toggleable using build-time
|
||||||
variables.
|
variables.
|
||||||
Should the solution script be enabled, the challenge would automatically start%
|
Should the solution script be enabled, the challenge would automatically start%
|
||||||
\footnote{I did this by injecting the solution script into the user's \texttt{.bashrc} file}
|
\footnote{I did this by injecting the solution script into the user's \code{.bashrc} file}
|
||||||
completing itself in the terminal integrated into it's frontend, often even explaining the
|
completing itself in the terminal integrated into it's frontend, often even explaining the
|
||||||
commands executed during the solution process.
|
commands executed during the solution process.
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
In this section I am going to dive into further detail on how client code is supposed
|
In this section I am going to dive into further detail on how client code is supposed
|
||||||
to use the framework, some of the design decisions behind this and how everything is
|
to use the framework, some of the design decisions behind this and how everything is
|
||||||
is integrated into the \texttt{solvable} Docker image.
|
is integrated into the \code{solvable} Docker image.
|
||||||
|
|
||||||
To use the framework one has to do several things to get started.
|
To use the framework one has to do several things to get started.
|
||||||
The main points include:
|
The main points include:
|
||||||
@ -25,7 +25,7 @@ framework.
|
|||||||
This repository is a really simple client codebase that is suitable for
|
This repository is a really simple client codebase that is suitable for
|
||||||
developing TFW itself as well (a good place to host tests for the framework).
|
developing TFW itself as well (a good place to host tests for the framework).
|
||||||
|
|
||||||
It also provides an ``industry standard'' \texttt{hack} directory
|
It also provides an ``industry standard'' \code{hack} directory
|
||||||
containing bash scripts that make the development of tutorials and TFW itself very convenient.
|
containing bash scripts that make the development of tutorials and TFW itself very convenient.
|
||||||
These scripts span from bootstrapping a complete development environment in one command,
|
These scripts span from bootstrapping a complete development environment in one command,
|
||||||
to building and running challenges based on the framework.
|
to building and running challenges based on the framework.
|
||||||
@ -54,7 +54,7 @@ understanding of how the framework interacts with client code.
|
|||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
\subsection{Avatao Configuration File}
|
\subsection{Avatao Configuration File}
|
||||||
The \texttt{config.yml} file is an Avatao challenge configuration file,
|
The \code{config.yml} file is an Avatao challenge configuration file,
|
||||||
which is used describe what kind of Docker containers implement a challenge,
|
which is used describe what kind of Docker containers implement a challenge,
|
||||||
what ports do they expose talking what protocols, define the name of the
|
what ports do they expose talking what protocols, define the name of the
|
||||||
excercise, it's difficulity, and so on.
|
excercise, it's difficulity, and so on.
|
||||||
@ -63,12 +63,12 @@ The Tutorial Framework does not use this file, this is only required to run
|
|||||||
the exercise in production, so it is mostly out of scope for this thesis.
|
the exercise in production, so it is mostly out of scope for this thesis.
|
||||||
|
|
||||||
\subsection{Controller Image}
|
\subsection{Controller Image}
|
||||||
It was previously mentioned that the \texttt{controller} Docker image is responsible
|
It was previously mentioned that the \code{controller} Docker image is responsible
|
||||||
for the solution checking of challenges (whether the user has completed the exercise or not).
|
for the solution checking of challenges (whether the user has completed the exercise or not).
|
||||||
Currently this image is maintained in the test-tutorial-framework repository.
|
Currently this image is maintained in the test-tutorial-framework repository.
|
||||||
It is a really simple Python server which functions as a TFW event handler as well.
|
It is a really simple Python server which functions as a TFW event handler as well.
|
||||||
It subscribes to the FSM update messages
|
It subscribes to the FSM update messages
|
||||||
broadcasted by the \texttt{FSMManagingEventHandler}, we've previously discussed,
|
broadcasted by the \code{FSMManagingEventHandler}, we've previously discussed,
|
||||||
this way it is capable of keeping track of the state of the tutorial,
|
this way it is capable of keeping track of the state of the tutorial,
|
||||||
which allows it to detect if the final state of the FSM is reached.
|
which allows it to detect if the final state of the FSM is reached.
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ Currently the Tutorial Framework is maintained in three git repositories:
|
|||||||
\item[test-tutorial-framework] An example tutorial built using baseimage and frontend
|
\item[test-tutorial-framework] An example tutorial built using baseimage and frontend
|
||||||
\end{description}
|
\end{description}
|
||||||
Every tutorial based on the framework must use the TFW baseimage as the parent of
|
Every tutorial based on the framework must use the TFW baseimage as the parent of
|
||||||
it's own \texttt{solvable} image, using the \texttt{FROM}%
|
it's own \code{solvable} image, using the \code{FROM}%
|
||||||
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#from}
|
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#from}
|
||||||
{https://docs.docker.com/engine/reference/builder/\#from}}
|
{https://docs.docker.com/engine/reference/builder/\#from}}
|
||||||
Dockerfile command.
|
Dockerfile command.
|
||||||
@ -88,7 +88,7 @@ Being an example project of the framework this is the case with
|
|||||||
test-tutorial-framework as well.
|
test-tutorial-framework as well.
|
||||||
|
|
||||||
\section{Details of the Solvable Image}
|
\section{Details of the Solvable Image}
|
||||||
Let us dive into greater detail on how the \texttt{solvable} Docker image of the
|
Let us dive into greater detail on how the \code{solvable} Docker image of the
|
||||||
test-tutorial-framework operates.
|
test-tutorial-framework operates.
|
||||||
The directory structure is as follows:
|
The directory structure is as follows:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
@ -102,9 +102,9 @@ solvable/
|
|||||||
I am going to discuss these one by one.
|
I am going to discuss these one by one.
|
||||||
|
|
||||||
\subsection{Dockerfile}
|
\subsection{Dockerfile}
|
||||||
Since this is a Docker image it must define a \texttt{Dockerfile}.
|
Since this is a Docker image it must define a \code{Dockerfile}.
|
||||||
This image always uses the baseimage of the framework as a parent image.
|
This image always uses the baseimage of the framework as a parent image.
|
||||||
Besides this developers can use this as a regular \texttt{Dockerfile} to work with as
|
Besides this developers can use this as a regular \code{Dockerfile} to work with as
|
||||||
they see fit to implement their tutorial.
|
they see fit to implement their tutorial.
|
||||||
|
|
||||||
\subsection{Frontend}
|
\subsection{Frontend}
|
||||||
@ -124,7 +124,7 @@ very hard and impractial to do in practice.
|
|||||||
Supervisor is a process control system designed to be able to work with
|
Supervisor is a process control system designed to be able to work with
|
||||||
processes on UNIX-like operating systems.
|
processes on UNIX-like operating systems.
|
||||||
When a tutorial built on TFW is started, the framework starts supervisor with
|
When a tutorial built on TFW is started, the framework starts supervisor with
|
||||||
PID\footnote{Process ID, on UNIX-like systems the \texttt{init} program is the first
|
PID\footnote{Process ID, on UNIX-like systems the \code{init} program is the first
|
||||||
process started} 1, which in turn starts all the programs defined
|
process started} 1, which in turn starts all the programs defined
|
||||||
in this directory using supervisor configuration files.
|
in this directory using supervisor configuration files.
|
||||||
For example, a developer would use a file similar to this to run a webserver
|
For example, a developer would use a file similar to this to run a webserver
|
||||||
@ -141,7 +141,7 @@ can be managed by the framewok using API messages.
|
|||||||
|
|
||||||
\subsection{Nginx}
|
\subsection{Nginx}
|
||||||
For simplicity, exercises based on the framework only expose a single port from the
|
For simplicity, exercises based on the framework only expose a single port from the
|
||||||
\texttt{solvable} container.
|
\code{solvable} container.
|
||||||
This port is required to serve the frontend of the framework.
|
This port is required to serve the frontend of the framework.
|
||||||
If this is the case, how do we run additional web applications to showcase vulnerabilies
|
If this is the case, how do we run additional web applications to showcase vulnerabilies
|
||||||
on during the tutorial?
|
on during the tutorial?
|
||||||
@ -167,7 +167,7 @@ What this means is that they are going to be serverd from a ``subdirectory'' of
|
|||||||
for example ``/register'' will be served under ``/yoururl/register''.
|
for example ``/register'' will be served under ``/yoururl/register''.
|
||||||
This means that all links in the final HTML must refer to the proxied urls, e.g.\
|
This means that all links in the final HTML must refer to the proxied urls, e.g.\
|
||||||
``/yoururl/register'' and server side redirects must point to the correct hrefs as well.
|
``/yoururl/register'' and server side redirects must point to the correct hrefs as well.
|
||||||
Idiomatically this is usually implemented by supplying a \texttt{BASEURL}
|
Idiomatically this is usually implemented by supplying a \code{BASEURL}
|
||||||
to the application through an environment variable, so that it is able to set
|
to the application through an environment variable, so that it is able to set
|
||||||
itself up correctly.
|
itself up correctly.
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ itself up correctly.
|
|||||||
Behind the curtains, the Tutorial Framework uses some Dockerfile trickery to
|
Behind the curtains, the Tutorial Framework uses some Dockerfile trickery to
|
||||||
faciliate the copying of supervisor and nginx configuration files to their correct
|
faciliate the copying of supervisor and nginx configuration files to their correct
|
||||||
locations.
|
locations.
|
||||||
Normally when one uses the \texttt{COPY}%
|
Normally when one uses the \code{COPY}%
|
||||||
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#copy}
|
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#copy}
|
||||||
{https://docs.docker.com/engine/reference/builder/\#copy}}
|
{https://docs.docker.com/engine/reference/builder/\#copy}}
|
||||||
command to create a layer%
|
command to create a layer%
|
||||||
@ -188,23 +188,23 @@ these configuration files that will be written by content developers do not even
|
|||||||
exist.
|
exist.
|
||||||
How could we copy files into an image layer that will be created in the future?
|
How could we copy files into an image layer that will be created in the future?
|
||||||
|
|
||||||
It is possible to use a command called \texttt{ONBUILD}%
|
It is possible to use a command called \code{ONBUILD}%
|
||||||
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#onbuild}
|
\footnote{\href{https://docs.docker.com/engine/reference/builder/\#onbuild}
|
||||||
{https://docs.docker.com/engine/reference/builder/\#onbuild}}
|
{https://docs.docker.com/engine/reference/builder/\#onbuild}}
|
||||||
in the Dockerfile of a baseimage to delay another command
|
in the Dockerfile of a baseimage to delay another command
|
||||||
to the point in time when other images will use the baseimage
|
to the point in time when other images will use the baseimage
|
||||||
as a parent with the \texttt{FROM} command. This makes it possible to execute
|
as a parent with the \code{FROM} command. This makes it possible to execute
|
||||||
commands in the build context of the descendant image.
|
commands in the build context of the descendant image.
|
||||||
This is great, because the config files we need \emph{will} exist in the build
|
This is great, because the config files we need \emph{will} exist in the build
|
||||||
context of the \texttt{solvable} image of test-tutorial-framework.
|
context of the \code{solvable} image of test-tutorial-framework.
|
||||||
In practice this looks something like this in the baseimage \texttt{Dockerfile}:
|
In practice this looks something like this in the baseimage \code{Dockerfile}:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
ONBUILD COPY ${BUILD_CONTEXT}/nginx/ ${TFW_NGINX_COMPONENTS}
|
ONBUILD COPY ${BUILD_CONTEXT}/nginx/ ${TFW_NGINX_COMPONENTS}
|
||||||
ONBUILD COPY ${BUILD_CONTEXT}/supervisor/ ${TFW_SUPERVISORD_COMPONENTS}
|
ONBUILD COPY ${BUILD_CONTEXT}/supervisor/ ${TFW_SUPERVISORD_COMPONENTS}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
\subsection{Source Directory}
|
\subsection{Source Directory}
|
||||||
The \texttt{src} directory usually holds tutorial-specific code, such as
|
The \code{src} directory usually holds tutorial-specific code, such as
|
||||||
the implementations of event handlers, the framework FSM, additional web applications
|
the implementations of event handlers, the framework FSM, additional web applications
|
||||||
served by the exercise and generally anything that won't fit in the other,
|
served by the exercise and generally anything that won't fit in the other,
|
||||||
framework-specific directories.
|
framework-specific directories.
|
||||||
@ -227,11 +227,11 @@ It is possible to use this format to define a state machine like so:
|
|||||||
caption={A Finite State Machine implemented in YAML},
|
caption={A Finite State Machine implemented in YAML},
|
||||||
captionpos=b
|
captionpos=b
|
||||||
]{listings/test_fsm.yml}
|
]{listings/test_fsm.yml}
|
||||||
This state machine has 2 states, state 0 and 1.
|
This state machine has two states, state \code{0} and \code{1}.
|
||||||
It defines a single transition between them.
|
It defines a single transition between them, \code{step_1}.
|
||||||
On entering state 1 the FSM will write a message to the frontend messaging component
|
On entering state \code{1} the FSM will write a message to the frontend messaging component
|
||||||
by invoking TFW library code in Python.
|
by invoking TFW library code using Python.
|
||||||
The transition can only occour if the file \texttt{allow\_step\_1} exists.
|
The transition can only occour if the file \code{allow_step_1} exists.
|
||||||
|
|
||||||
YAML based state machine implementations also allow the usage of the Jinja2%
|
YAML based state machine implementations also allow the usage of the Jinja2%
|
||||||
\footnote{\href{http://jinja.pocoo.org/docs/2.10/}{http://jinja.pocoo.org/docs/2.10/}}
|
\footnote{\href{http://jinja.pocoo.org/docs/2.10/}{http://jinja.pocoo.org/docs/2.10/}}
|
||||||
@ -258,11 +258,11 @@ Python as well, it is going to be easier to interface with library code.
|
|||||||
\section{Configuring Components}
|
\section{Configuring Components}
|
||||||
|
|
||||||
The configuration of built-ins is generally done in two different ways.
|
The configuration of built-ins is generally done in two different ways.
|
||||||
For the frontend (Angular) side, developers can edit a \texttt{config.ts} file,
|
For the frontend (Angular) side, developers can edit a \code{config.ts} file,
|
||||||
which is full of key-value pairs of configurable frontend functionality.
|
which is full of key-value pairs of configurable frontend functionality.
|
||||||
These pairs are generally pretty self-documenting:
|
These pairs are generally pretty self-documenting:
|
||||||
\lstinputlisting[
|
\lstinputlisting[
|
||||||
caption={Example of the frontend \texttt{config.ts} file (stripped down to save space)},
|
caption={Example of the frontend \code{config.ts} file (stripped down to save space)},
|
||||||
captionpos=b
|
captionpos=b
|
||||||
]{listings/config.ts}
|
]{listings/config.ts}
|
||||||
Configuring built-in event handlers is possible by editing the Python file they are
|
Configuring built-in event handlers is possible by editing the Python file they are
|
||||||
@ -283,7 +283,7 @@ This script is distributed as a bash one-liner command, like so:
|
|||||||
\begin{lstlisting}[language=bash]
|
\begin{lstlisting}[language=bash]
|
||||||
bash -c "$(curl -fsSL https://git.io/vxBfj)"
|
bash -c "$(curl -fsSL https://git.io/vxBfj)"
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
This command downloads a script using \texttt{curl}, then executes the downloaded
|
This command downloads a script using \code{curl}, then executes the downloaded
|
||||||
script in bash.
|
script in bash.
|
||||||
In the open source community it is quite common to distribute installers this way%
|
In the open source community it is quite common to distribute installers this way%
|
||||||
\footnote{A good example of this is oh-my-zsh
|
\footnote{A good example of this is oh-my-zsh
|
||||||
@ -318,9 +318,9 @@ The bootstrap script clones the three TFW repositories and does several steps
|
|||||||
to create a working environment:
|
to create a working environment:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item It builds the newest version of the TFW baseimage locally
|
\item It builds the newest version of the TFW baseimage locally
|
||||||
\item It pins the version tag in \texttt{solvable/Dockerfile},
|
\item It pins the version tag in \code{solvable/Dockerfile},
|
||||||
so that this newly-built version will be used by the tutorial
|
so that this newly-built version will be used by the tutorial
|
||||||
\item It places the latest frontend in \texttt{solvable/frontend} with
|
\item It places the latest frontend in \code{solvable/frontend} with
|
||||||
depencendies installed
|
depencendies installed
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
It is important to note that this script \emph{does not} install anything system-wide,
|
It is important to note that this script \emph{does not} install anything system-wide,
|
||||||
|
@ -15,10 +15,6 @@
|
|||||||
}
|
}
|
||||||
\RequirePackage[bottom,hang,flushmargin]{footmisc}
|
\RequirePackage[bottom,hang,flushmargin]{footmisc}
|
||||||
|
|
||||||
\definecolor{andigray}{RGB}{237,237,237}
|
|
||||||
\sethlcolor{andigray}
|
|
||||||
\newcommand{\code}[1]{\hl{\mbox{#1}}}
|
|
||||||
|
|
||||||
\newtheorem*{note}{Note}
|
\newtheorem*{note}{Note}
|
||||||
|
|
||||||
\newcommand{\pic}[3][width=\textwidth]
|
\newcommand{\pic}[3][width=\textwidth]
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
aboveskip=15pt,
|
aboveskip=15pt,
|
||||||
belowskip=15pt,
|
belowskip=15pt,
|
||||||
}
|
}
|
||||||
|
\newcommand{\code}{\lstinline}
|
||||||
|
|
||||||
\setmainfont{Constantia}
|
\setmainfont{Constantia}
|
||||||
\setmonofont{DejaVu Sans Mono}
|
\setmonofont{DejaVu Sans Mono}
|
||||||
|
Loading…
Reference in New Issue
Block a user