\input{../../src/parts/template.tex}

\begin{titlepage}
  \newcommand{\HRule}{\rule{\linewidth}{0.5mm}} % Defines a new command for the horizontal lines, change thickness here

  \center % Center everything on the page

  \textsc{\LARGE QubesOS articles}\\[1.5cm] % Name of your university/college
  %\textsc{\Large Nvidia driver debugging}\\[0.5cm] % Major heading such as course name
  %\large Yukikoo\\[0.5cm] % Minor heading such as course title

  \HRule \\[0.4cm]
  { \huge \bfseries New QubesOS package}\\[0.4cm] % Title of your document
  \HRule \\[1.5cm]
 % If you don't want a supervisor, uncomment the two lines below and remove the section above
  \Large \emph{Author:}\\
  Neowutran \\[3cm] % Your name

    \begin{multicols}{2}
  \includegraphics[width=80mm]{shinra.png}\\[1cm] % Include a department/university logo - this will require the graphicx package
      \columnbreak
  \includegraphics[width=80mm]{neowutranlogo.png}\\[1cm] % Include a department/university logo - this will require the graphicx package
    \end{multicols}
  \vfill % Fill the rest of the page with whitespace

\end{titlepage}

 \tableofcontents                                                                
    \pagebreak 


\section{Building a new QubesOS package}

\subsection{References}
\begin{itemize}
	\item \href{https://www.youtube.com/watch?v=WYDfzg9T0MU}{QubesOS minisubmit video (QubesOS - 3mdeb), by Frédéric Pierret}
	\item \href{https://github.com/QubesOS-contrib/qubes-skeleton}{qubes-skeleton}
\end{itemize}

\subsection{Goal}
The goal will be to create simple Qube software that do the following:

\begin{itemize}
	\item Provide a binary named "qvm-druide-antidote"
	\item The binary will create a new disposableVM, and send file to it
	\item The disposableVM will open the software "Antidote" from "Druide" '(it is a proprietary spellchecker) on the file it received
	\item The user fix the spelling issue and close "Antidote"
	\item The corrected file is sent back to the original VM
\end{itemize}

We will only explain the "packaging" and "building" part.
My repository: \href{https://github.com/neowutran/qubes-app-linux-druide-antidote}{qubes-app-linux-druide-antidote}


\subsection{The software}
To be run on the "client" vm:
\begin{minted}{bash}
#!/bin/bash
FILE=${1?file required}
TMPFILE=$(mktemp --tmpdir druide-antidote-XXXXXXXX)
BACKUP=$(mktemp --tmpdir druide-antidote-backup-XXXXXXXX)
cp "$FILE" "$BACKUP"
echo "Backup file is: $BACKUP" >&2

cat "$FILE"
exec >&-
cat > "$TMPFILE"
[ -s "$TMPFILE" ] && mv "$TMPFILE" "$FILE"
\end{minted}
To be run on the "server" vm:
\begin{minted}{bash}
#!/bin/bash

FILE=$(mktemp --tmpdir druide-antidote-XXXXXXXX)

cat > "$FILE"
/opt/Druide/Antidote10/Application/Bin/Antidote10 -f "$FILE" 2> /dev/null > /dev/null
cat "$FILE"

rm -f "$FILE"
\end{minted}
\subsection{Packaging}
I want it to be: \begin{itemize}
	\item compatible with the following templates:\begin{itemize}
		\item Fedora
		\item Debian
		\item Archlinux
\end{itemize}
\item easily reusable for other software that use this kind of client-server RPC 
\end{itemize}
For the easily reusable part, lots of packaging variables come from the README.md. Read the file "vars.sh" and "archlinux/PKGBUILD" to understand better.
PKGBUILD:
\begin{minted}{bash}
pkgname=(qubes-$(./vars.sh name)-vm)
pkgver=$(cat version)
pkgrel=$(cat rel)
arch=(x86_64)
pkgdesc=$(./vars.sh description)
url=$(git remote get-url origin)
license=(GPL3)
depends=()
makedepends=(pandoc git)

build() {
 ln -s "$srcdir"/../ "$srcdir/src"
}
check(){
 src/tests/all
}
package() {
 cd src
 make install-vm DESTDIR="$pkgdir/"
}
\end{minted}
vars.sh:
\begin{minted}{bash}
#!/bin/bash

name(){
 head -n 1 README.md | cut -d ' ' -f 2 | cut -d '(' -f 1 | cut -c5- | tr [:upper:] [:lower:]
}

description(){
 awk '/DESCRIPTION/,!//' ./README.md | tail -n +3 | awk '1;/=======/{exit}' | head -n -3
}

variable=${1:?Variable name is required. name, description or camelname}
case "$variable" in
 "name"):
  name
  ;;
 "description"):
  description
  ;;
 "camelname"):
  name | sed 's/^\([A-Za-z0-9]\)\([A-Za-z0-9]\+\)-\([A-Za-z0-9]\)\([A-Za-z0-9]\+\)$/\U\1\L\2\U\3\L\4/g'
  ;;
 "summary"):
  description | head -n 1
  ;;
 *):
  echo "This variable doesn't exist" >&2
  exit 1
 ;;
esac
\end{minted}
For the building flow, it start from the template packaging (./debian/, ./archlinux/, ./rpm/), then the build script of the template will call the Makefile
\subsection{Building}
I learned everything in this section from the minisubmit video I referenced before.

We need to build this package using the standard qubes builder.
So the most important things are in the next file named "app-builder.conf".
\begin{itemize}
	\item How to build a QubesOs package that doesn't come from the official repository
	\item How to build only that package and not everything related to QubesOS
\end{itemize}
app-builder.conf : 
\begin{minted}{make}
# vim: ft=make ts=4 sw=4

GIT_BASEURL ?= https://github.com
GIT_PREFIX ?= QubesOS/qubes-
NO_SIGN ?= 1
#BRANCH ?= release4.0

BACKEND_VMM=xen

DIST_DOM0 ?= fc32
DISTS_VM ?= fc33+minimal buster+minimal bullseye+minimal

COMPONENTS ?= \
app-linux-druide-antidote \
builder \
builder-debian \
builder-rpm

INSECURE_SKIP_CHECKING = app-linux-druide-antidote
GIT_URL_app_linux_druide_antidote = https://github.com/neowutran/qubes-app-linux-druide-antidote
BRANCH_app_linux_druide_antidote = master

BUILDER_PLUGINS = builder-rpm builder-debian
BUILDER_PLUGINS += mgmt-salt

DISTS_VM += archlinux+minimal
COMPONENTS += builder-archlinux
BUILDER_PLUGINS += builder-archlinux
\end{minted}

app-builder.sh

\begin{minted}{bash}
#!/bin/bash
BASE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
directory=$BASE/qubes-builder
sudo rm -Rf "$directory"
sudo dnf install wget make git qubes-gpg-split
git clone "https://github.com/QubesOS/qubes-builder.git"

key1=$(curl -s https://keys.qubes-os.org/keys/qubes-master-signing-key.asc | sha512sum | cut -d " " -f 1)
key2=$(sha512sum /usr/share/qubes/qubes-master-key.asc | cut -d " " -f 1)

if [ "$key1" != "$key2" ]; then
echo "CRITICAL SECURITY FAILURE: qubes master signing key is not the same on different source (local and official qubes os website)" >&2
exit 1
fi

gpg --import /usr/share/qubes/qubes-master-key.asc
echo "Check the key, if it is good for you, set the trust to 5 and exit"
echo "fpr" | gpg --edit-key 0x427F11FD0FAA4B080123F01CDDFA1A3E36879494

wget https://keys.qubes-os.org/keys/qubes-developers-keys.asc
gpg --import qubes-developers-keys.asc
rm qubes-developers-keys.asc

commit_data=$(cd "$directory" && git tag -v $(git describe) 2>&1 | grep "gpg: ")
echo "$commit_data"
echo "$commit_data"  | tail -n 1 | grep "Good signature from "
success=$?

if (( $success == 1 )); then 
echo "CRITICAL SECURITY FAILURE: last commit from qubes-builder is not signed with an approved gpg key" >&2
exit 1
fi

echo "Does this seems good to you ?"
read trash

cp ./app-builder.conf $directory/builder.conf

cd "$directory"
make get-sources 

make install-deps
make qubes-vm
\end{minted}

\batchmode
\end{document}

