Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redeam nuggits #19

Merged
merged 2 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions create_challenge.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ if [ -e challenge ]; then
rm -rf challenge2
mv challenge challenge2
fi
. ./src/redeem.nuggit >/dev/null 2>&1

LOCAL_CODE_EXECUTION_HASH="$(success "LocalCodeExecution" | git hash-object --stdin)"

# initial setup

Expand All @@ -18,6 +21,7 @@ cd challenge
reproducibility_setup

cp "$DOCDIR/01_init/"* .
cp "$DOCDIR/01_init/.gitignore" .
git add .
commit -m "Initial Commit"

Expand All @@ -27,7 +31,7 @@ cp "$DOCDIR/04_branch/branch.md" .
git add branch.md
commit -m "WIP: add description on branches

Flag: ShowMeMore"
nuggit: ShowMeMore"
# For reference in commit.md later
BRANCH_COMMIT="$(git rev-parse --short @)"

Expand Down Expand Up @@ -61,8 +65,8 @@ cp "$DOCDIR/08_tags/tags.md" .
git add tags.md
commit -m 'Add description on tags

Flag: LogCat'
git tag -a the-first-tag -m "Flag: AnnotateMeIfYouCan"
nuggit: LogCat'
git tag -a the-first-tag -m "nuggit: AnnotateMeIfYouCan"

git switch main -c history
cp "$DOCDIR/06_log/log.md" .
Expand All @@ -74,9 +78,9 @@ git switch main
# uncommitted changes/status
# Needs to be second to last (only before hooks), so that the uncommitted changes are available initially
cat "$DOCDIR/02_status_diff/status.md" >> README.md
UNSTAGED_FLAG='Flag: WorkInProgress'
UNSTAGED_FLAG='nuggit: WorkInProgress'
STAGING_DIFF_DESCRIPTION='For seeing what would be committed next you can run `git diff --staged`. A synonym for "--staged" that you might see in some places is "--cached".'
STAGING_FLAG='Flag: CommitmentIssues'
STAGING_FLAG='nuggit: CommitmentIssues'
COMMIT_DESCRIPTION='To commit all changes in the staging area you can run `git commit` and an editor will open where you can type a commit message. Further information can be found in "commit.md"'
{
echo "$UNSTAGED_FLAG"
Expand All @@ -99,6 +103,8 @@ sed "/$UNSTAGED_FLAG/{N;N;d;}" README.md > tmp
sed "/$STAGING_DIFF_DESCRIPTION/{N;N;d;}" tmp > README.md
rm tmp

"$DOCDIR/store_nuggits.sh"
cp "$DOCDIR/redeem.nuggit" .
# hooks (should be installed last, since they are self-mutating and would be called e.g. by `git commit`)
rm .git/hooks/*

Expand All @@ -107,5 +113,6 @@ for file in $(ls "$DOCDIR/hooks"); do
chmod +x ".git/hooks/$file.orig"
done
while read -r hook; do
cp "$DOCDIR/hook_preamble.sh" ".git/hooks/$hook"
replace_placeholders "$DOCDIR/hook_preamble.sh" > ".git/hooks/$hook"
chmod +x ".git/hooks/$hook"
done < "$DOCDIR/all-git-hooks"
1 change: 1 addition & 0 deletions lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ reproducibility_setup() {
replace_placeholders() {
sed -e "s/INTERACTIVE_REBASE_BASE_COMMIT/$INTERACTIVE_REBASE_BASE_COMMIT/" \
-e "s/BRANCH_COMMIT/$BRANCH_COMMIT/" \
-e "s/LOCAL_CODE_EXECUTION_HASH/$LOCAL_CODE_EXECUTION_HASH/" \
-e "s/INTERACTIVE_REBASE_EXAMPLE_PICKS/$INTERACTIVE_REBASE_EXAMPLE_PICKS/" \
-e "s/INTERACTIVE_REBASE_COMMIT/$INTERACTIVE_REBASE_COMMIT/" "$1"
}
1 change: 1 addition & 0 deletions src/01_init/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/redeem.nuggit
7 changes: 5 additions & 2 deletions src/01_init/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
# Nuggits

This is an explanation/game on how to use the version control system `git`. It is not intended that you use other tools like `grep` to find the flags, but instead find them with the builtin git commands.
This is an explanation/game on how to use the version control system `git`. It is not intended that you use other tools like `grep` to find the "nuggits" (little strings of text to show you that you make progress learning git ;) - otherwise known as flags in CTF challenges), but instead find them with the builtin git commands. For instructions on how to redeem them, see the FAQ below.

For many day-to-day tasks the graphical user interfaces for it might well work, but it will definitely get to its limits on this challenge, since it will get into the nitty-gritty details (if you want) so it is recommended to use the command line instead.

By default in most Projects there exists a README file, so with opening this file you already made the first step (I promise: even if you know git you probably get to know a thing or two about `git` that you didn't hear about. And if you did: please get in touch so that I can learn more from you and maybe even add some more ideas!)

## Game FAQ

Q: How to I redeem a nuggit (flag)?
A: Just run `./redeem_nuggit <name of the nuggit>` - it will show you if you are correct or not.

Q: Why you get this folder in this way instead of the usual `git clone <url>`?
A: That is a good question and you will figure out the answer the more you get into the quests (many of which are impossible in a fresh clone).

Q: Can I use my favourite git GUI tool?
A: Well... For a few of the flags, yes, but some are well hidden in the stranger parts of git, so this project assumes running git from the command line from the beginning.
A: Well... For a few of the nuggits, yes, but some are well hidden in the stranger parts of git, so this project assumes running git from the command line from the beginning.

NOTE: This challenge uses git hooks. Because of the way you download this repository they are enabled and COULD run arbitrary code. I promise you they are just here for the benefit of the people learning git and don't do anything malicious. If you are paranoid, you should never download repositories like this!

Expand Down
7 changes: 6 additions & 1 deletion src/hook_preamble.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#!/usr/bin/env bash
# Flag: LocalCodeExecution
# nuggit: LocalCodeExecution
# Congrats on finding this! This flag is gonna destroy itself when any of the hooks are executed ;)
set -e
shopt -s extglob
ROOT="$(git rev-parse --show-toplevel)"

this_file="$0"

hash="LOCAL_CODE_EXECUTION_HASH"
# Make sure to delete the flag, so it can't be redeemed after this got triggered once
rm ".git/objects/${hash:0:2}/${hash:2}"

(
cd "$ROOT/.git/hooks" || exit
# delete all of the "LocalCodeExecution" hook stubs
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/post-checkout
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ IS_SWITCH="$3"

# switched to my-new-branch
if [ "$(git rev-parse --abbrev-ref HEAD)" = "my-new-branch" ] && [ "$IS_SWITCH" = 1 ]; then
echo "Flag: MyFirstBranch"
echo "nuggit: MyFirstBranch"
exit
fi

# switched to branches-explained
if [ "$NEXT_REF" = "$(git rev-parse branches-explained)" ] && [ "$IS_SWITCH" = 1 ]; then
echo "Flag: Switcheridoo"
echo "nuggit: Switcheridoo"
exit
fi
5 changes: 4 additions & 1 deletion src/hooks/prepare-commit-msg
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ COMMIT_SOURCE=$2
SHA1=$3

# add a flag to the commit message
git interpret-trailers --in-place --trailer "Flag: CommitMirInsAbendteuerland" "$COMMIT_MSG_FILE"
git interpret-trailers --in-place \
--trailer "This is the challenge nuggit speaking. Please don't mind me. I am injecting myself in a few places (like this one), so if you ever see anything starting with nuggit in this repo, I injected it and it usually wouldn't be there in a normal git repo." \
--trailer "nuggit: CommitMirInsAbendteuerland" \
"$COMMIT_MSG_FILE"
if test -z "$COMMIT_SOURCE"
then
/usr/bin/env perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
Expand Down
10 changes: 10 additions & 0 deletions src/nuggits
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
LocalCodeExecution
WorkInProgress
CommitmentIssues
CommitMirInsAbendteuerland
LocalCodeExecution
Switcheridoo
ShowMeMore
MyFirstBranch
LogCat
AnnotateMeIfYouCan
28 changes: 28 additions & 0 deletions src/redeem.nuggit
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

nuggit="$1"

success() {
echo "Success! What a nice nuggit for your collection! 🏅 $1 looks really good!"
}


if [ -z "$nuggit" ]; then
echo "no nuggit passed in..." >&2
echo "Useage: \`$0 TestNuggit\`" >&2
else
if [ "$nuggit" = TestNuggit ]; then
echo "This is a test. You passed it! 👍"
exit
fi

git cat-file -p "$(echo "'$nuggit' already redeemed" | git hash-object --stdin)" 2>/dev/null && exit
git cat-file -p "$(echo "You tried '$nuggit' before. It still isn't a valid answer... 🙄" | git hash-object --stdin)" 2>/dev/null && exit 1

git cat-file -p "$(success "$nuggit" | git hash-object --stdin)" 2>/dev/null || {
echo "Unfortunately that is not a valid nuggit :/ Try again!" >&2
echo "You tried '$nuggit' before. It still isn't a valid answer... 🙄" | git hash-object --stdin -w >/dev/null 2>&1
exit 1
}
echo "'$nuggit' already redeemed" | git hash-object --stdin -w >/dev/null 2>&1
fi
8 changes: 8 additions & 0 deletions src/store_nuggits.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

. "$DOCDIR/redeem.nuggit" >/dev/null 2>&1

while read -r nuggit; do
printf "%s \t" "$nuggit"
success "$nuggit" | git hash-object --stdin -w
done < "$DOCDIR/nuggits"
59 changes: 48 additions & 11 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,96 @@ set -e

echo "Building..."
./create_challenge.sh >/dev/null 2>&1
cd challenge

it 'LocalCodeExecution should be nonexistent/unredeamable after the trap got triggered' '
git commit -am "Just a test to trigger hooks"
expect "! ./redeem.nuggit LocalCodeExecution 2>&1" to contain "Unfortunately that is not a valid nuggit"
'

echo "Building once more..."
cd ..
./create_challenge.sh >/dev/null 2>&1
echo "Running tests..."

cd challenge

redeem_nuggit() {
expect "./redeem.nuggit '$1'" to contain Success
}

it 'LocalCodeExecution flag in hooks' '
expect "cat .git/hooks/*" to contain "Flag: LocalCodeExecution"
expect "cat .git/hooks/*" to contain "nuggit: LocalCodeExecution"
redeem_nuggit LocalCodeExecution
'

it 'WorkInProgress in diff' '
expect "git diff" to contain "Flag: WorkInProgress"
expect "git diff" to contain "nuggit: WorkInProgress"
redeem_nuggit WorkInProgress
'

it 'CommitmentIssues in diff --staged' '
expect "git diff --staged" to contain "Flag: CommitmentIssues"
expect "git diff --staged" to contain "nuggit: CommitmentIssues"
redeem_nuggit CommitmentIssues
'

it 'CommitMirInsAbendteuerland in new commit message' '
git commit -m "My first commit" --quiet
expect "git show" to contain "Flag: CommitMirInsAbendteuerland"
expect "git show" to contain "nuggit: CommitMirInsAbendteuerland"
redeem_nuggit CommitMirInsAbendteuerland
'

it 'LocalCodeExecution flag should be deleted after execution of any hook (in this case the commit)' '
expect "cat .git/hooks/*" not to contain "Flag: LocalCodeExecution"
expect "cat .git/hooks/*" not to contain "nuggit: LocalCodeExecution"
'

it 'restore should not show Switcheridoo flag' '
expect "git restore README.md 2>&1" not to contain "Flag: Switcheridoo"
expect "git restore README.md 2>&1" not to contain "nuggit: Switcheridoo"
'

it 'ShowMeMore in branch commit' <<EOF
expect 'eval "\$(get_sh_codeblock commit.md)"' to contain "Flag: ShowMeMore"
expect 'eval "\$(get_sh_codeblock commit.md)"' to contain "nuggit: ShowMeMore"
redeem_nuggit ShowMeMore
EOF

it 'Switcheridoo when switching to "branches-explained"' '
expect "git switch branches-explained 2>&1" to contain "Flag: Switcheridoo"
expect "git switch branches-explained 2>&1" to contain "nuggit: Switcheridoo"
redeem_nuggit Switcheridoo
'

it 'MyFirstBranch when creating' '
expect "git switch -c my-new-branch 2>&1" to contain "Flag: MyFirstBranch"
expect "git switch -c my-new-branch 2>&1" to contain "nuggit: MyFirstBranch"
redeem_nuggit MyFirstBranch
git switch history -q
'

it 'LogCat for log' <<EOF
expect 'eval "\$(get_sh_codeblock log.md)"' to contain "Flag: LogCat"
expect 'eval "\$(get_sh_codeblock log.md)"' to contain "nuggit: LogCat"
redeem_nuggit LogCat
EOF

it 'AnnotateMeIfYouCan in annotated tag' '
expect "git show the-first-tag" to contain "Flag: AnnotateMeIfYouCan"
expect "git show the-first-tag" to contain "nuggit: AnnotateMeIfYouCan"
redeem_nuggit AnnotateMeIfYouCan
git switch --detach -q the-first-tag
'

xit 'TODO: find title for combine_history testcase' <<EOF
expect 'eval "\$(get_sh_codeblock combine_history.md)"' to contain "FIXME TODO"
EOF

it 'An invalid nuggit should show an error' '
expect "! ./redeem.nuggit NotANuggit 2>&1" to contain "Unfortunately that is not a valid nuggit"
expect "! ./redeem.nuggit NotANuggit 2>&1" to contain "It still isn'\''t a valid answer..."
'

check_redeem() {
while read -r nuggit; do
expect "./redeem.nuggit '$nuggit'" to contain "already redeemed"
expect "./redeem.nuggit '$nuggit'" not to contain Success
done < "$DOCDIR/nuggits"
}

it 'All nuggits should be redeemed at the end of the test' check_redeem

echo success!