\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[a4paper, margin=0.75in]{geometry}

% set up hyperlink coloring
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,
    urlcolor=cyan
}

\setlength{\parindent}{0pt} % no indentation

% checkbox list: https://tex.stackexchange.com/questions/247681/how-to-create-checkbox-todo-list
\usepackage{enumitem,amssymb}
\newlist{boxlist}{itemize}{2}
\setlist[boxlist]{label=$\square$}

% code support: listings and fancy verbatim
\usepackage{listings}
\lstset{basicstyle=\ttfamily\footnotesize}
\usepackage{fancyvrb}

\renewcommand{\familydefault}{\sfdefault} % default to sans serif

\usepackage{xcolor}
\newcommand{\code}[1]{\colorbox{lightgray}{\texttt{#1}}}
\newcommand{\sh}[1]{\code{\$ #1}}

\usepackage{graphicx}

%%%%%%%%%%%%%%%%
\begin{document}

\title{Advanced 5\\Git Hooks}
\author{EECS 201 Fall 2020}
\date{}
\maketitle

\section*{Submission Instructions}
This assignment will be submitted as a repository on the \href{https://gitlab.umich.edu}{UMich GitLab server}.
Create a Project on it with the name/path \code{eecs201-adv5} and add \code{brng} as a Reporter.
The repository should have the following directory structure, starting from the repository's root:
\begin{lstlisting}
/
|-- commit-msg
|-- pre-commit
|-- report.txt
\end{lstlisting}

\section*{Git Hooks}

One feature of most version control systems is \textbf{hooks}. A hook is an
automated script or tool that runs at various points in time. For example,
you can automatically run test cases every time anyone commits code.

\medskip
A slightly easier one to wire up, however, is a hook that will automatically
check the spelling of your commit messages for you, letting you know if you
made any mistakes. While spelling rarely counts for a class projects, it
adds a nice bit of professionalism to any future work you'll share with
others.

\medskip
I recommend creating a temporary Git repository to
play with while you test things and try to get things working.

\medskip
Git stores all of its information and configuration in a folder named
\code{.git} in the root of each project. Navigate to \code{.git/hooks} and
rename \code{commit-msg.sample} to \code{commit-msg}. This activates the
commit message hook, which runs after you write and save your commit message.
Now go back to your repository, make a change, and commit it. Hmm, doesn't
look like anything changed. Make another change, but this time make this your
commit message (\textbf{exactly this, capitalization matters}):
\begin{lstlisting}
This is a test.

Signed-off-by: Me!
Signed-off-by: Me!
\end{lstlisting}
After trying to commit, type \code{git status}. What happened? Go back and
look at the commit hook. Do you understand what it does? Try running
\code{git commit -{}-no-verify} with the same commit message. Go edit the
commit hook and delete the line \code{exit 1}. Try making a new commit with
the same commit message, what happens now? What is \code{\$1} in this
script?  (not sure? try adding lines like \code{echo~\$1} or
\code{echo~\$(file~\$1)} or \code{echo~\$(cat~\$1)} to the hook and making
commits, what happens?)

\newpage
\section{Automating Professionalism (5)}
\code{aspell} is a simple command-line utility that checks spelling. Install
it and play with it a little.

\medskip
\textbf{Write a commit message hook that checks the spelling of a commit message.}
Your hook \textbf{should not} prevent the commit from going through (that'd be
annoying...). Your hook should print out ``Spelling errors detected!'' and then
print out a \code{sort}ed list of offending words, with one word per line.

\medskip
\textbf{Example output:}
\begin{lstlisting}
Spelling errors detected!
alkdj
dakfjll
dklak
ldkafjlk
notarealword
\end{lstlisting}

\subsection*{Some tips}
\begin{itemize}
  \item Remember to look only at the \textbf{commit message} itself. Commit message files
        have ``commented out'' stuff with lines beginning with \code{\#} to communicate
        with the user what's going on in a commit, but they aren't in the commit message itself.
  \item This can be a little intimidating to get started. \textit{Try some things.}
        Make a bunch of garbage commits, modify the hook a little, see what happens.
  \item Remember that a shell script is exactly like working in a terminal. The only magic
        is that you've typed all the commands in advance instead of one at a time.
        So try some things in your terminal! Mess around until you get some
        commands that do what you want, then copy them to your script.
  \item There is \textbf{zero} need to be efficient. This hook is called
        rarely and operates on hundreds of bytes of text. Read the file 6 times.
        Write 7 temporary files. \textit{Who cares.} The goal is not to be pretty,
        the goal is to work.
  \item Speaking of temporary files, the \code{/tmp} directory can be a
        great place to throw those. There's even a command called \code{mktemp}
        to create temporary files or directories here.
\end{itemize}

\paragraph{Further exploration and some gotchas:}
\begin{itemize}
  \item Take a look at some of the other hooks, are any of them useful?
  \item For a list of all available hooks, type \code{man githooks}.
  \item Hooks have to be marked as executable to run (\code{chmod +x}). The
        sample hooks already had the executable bit set, which is why renaming the
        existing sample worked above.
  \item Hooks can call other scripts. Because invocation of hooks is
        controlled by the name of the script, if you want multiple scripts to run
        for a single hook, you'll need to have one script named correctly that
        calls your other hooks.
  \item Git hooks need not necessarily be shell scripts; they can be any sort of
        executable. You could possibly implement your hooks as, for example,
        Python scripts (not in this assignment though).
\end{itemize}


\newpage
\section{Automating security (5)}
When you are developing a web application, sometimes you need to access the services of some API
to access things like weather information from one source or a user's Google calendar from another.

\medskip
Such services tend to require the use of an \textit{API key} that is used to authenticate the client
requesting services and can be used to do things like rate limiting and tracking API use.

\medskip
If someone else (say, another competing application) gets a hold of your application's API key,
they could mooch off of whatever quotas that API key has.

\medskip
Another security issue is when people unwittingly put private SSH keys into a repository.
Recall that when you generated an SSH key it created a private and public key pair
(e.g. public: \code{id\_rsa.pub}, private: \code{id\_rsa}.)
The public key, being ``public'' is provided to various servers to authenticate
your computer with. Your private key is what verifies that you are you: if it gets out of
your hands, others can access things that have saved your public key for authorization.
(This is simplifying it greatly: just know that your private key is private!).

\medskip
Such things shouldn't necessarily be put onto a public Git repository being hosted somewhere
(unless you actually intended for the entire internet to be able to use your key).

\medskip
In this exercise you'll be writing a Git \textbf{pre-commit hook} that \textbf{stops} the commit from
happening when an API key is directly in the staged code files or if a private SSH key file is staged.
If your hook fails the commit, it should print out ``Keys detected!'' and a \code{sort}ed list of what files are the culprits,
one file on each line. \textbf{Every} offending file should have its name printed out; do \textbf{not}
exit early once a key is detected.

\medskip
\textbf{Example output:}
\begin{lstlisting}
Keys detected!
example_key_assigns
example_rsa_private_key
\end{lstlisting}


\medskip
Here are some things to identify each component with (these are simplified for this exercise).

\medskip
\textbf{API keys}:
\begin{itemize}
  \item They are a string literal enclosed by double quotes (\code{"}) or single quotes (\code{'})
  \item They are a string composed of alphanumeric characters of both cases (A-Z, a-z, 0-9)
  \item They are being assigned via `\code{=}' to some variable whose
        name ends in ``\code{key}'' or ``\code{Key}''.
        There can be an arbitrary amount of whitespace around the `\code{=}'
\end{itemize}

\textbf{SSH private keys}:
\begin{itemize}
  \item The file's first line is ``\code{-{}-{}-{}-{}-{}BEGIN OPENSSH PRIVATE KEY-{}-{}-{}-{}-{}}''
  \item The file's last line is ``\code{-{}-{}-{}-{}-{}END OPENSSH PRIVATE KEY-{}-{}-{}-{}-{}}''
\end{itemize}

Helpful hints:
\begin{itemize}
  \item The \code{https://eecs.umich.edu/courses/eecs201/files/assignments/adv5.tar.gz} archive
        has an example private key and API key assignments.
  \item You can get a list of staged files via \code{git diff~-{}-{}name-only~-{}-{}cached}.
  \item \code{head} and \code{tail} can get the first and last lines of a file.
\end{itemize}


\section{Conclusion}
\begin{enumerate}
  \item Copy your hook scripts to your submission repo and commit them.
  \item Create a file called \code{report.txt}.
  \item On the first line provide an integer time in minutes of how long it took
        for you to complete this assignment.
  \item On the second line and beyond, write down what you learned while doing this assignment.
        If you already knew how to do all of this, put down ``N/A''.
  \item Add and commit this \code{report.txt} file. Push your repo.
\end{enumerate}


\end{document}
