Created
September 27, 2018 21:48
-
-
Save StevenACoffman/f0c084b428977430d2baacd0263c3563 to your computer and use it in GitHub Desktop.
Rotate Github Personal Access Keys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
TOKEN_UUID=$(uuidgen) | |
if [ -z ${GITHUB_USERID+x} ]; then | |
echo "GITHUB_USERID is unset, exitting"; | |
exit 1 | |
else | |
echo "GITHUB_USERID is set to '$GITHUB_USERID'" | |
fi | |
if [ -z ${GITHUB_AUTH_TOKEN_ID+x} ]; then | |
echo "GITHUB_AUTH_TOKEN_ID is unset, so cannot proceed."; | |
else | |
echo "GITHUB_AUTH_TOKEN_ID is already set, so rotating personal access token" | |
GITHUB_URL="https://api.github.com/authorizations" | |
# store the whole response with the status at the and | |
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" \ | |
--user "${GITHUB_USERID}" \ | |
--data '{"scopes":["repo"],"note":"Rotate-Creds-Demo'"${TOKEN_UUID}"'"}' \ | |
$GITHUB_URL) | |
# extract the body | |
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g') | |
# extract the status | |
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') | |
# print the body | |
echo "$HTTP_BODY" | |
# example using the status | |
if [ $HTTP_STATUS -eq 401 ]; then | |
echo "Recieved 401, so trying again with Multifactor Auth OTP" | |
echo -n "Enter Multi-Factor Auth code for $GITHUB_USERID: " | |
read -s GITHUB_OTP | |
echo "" | |
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" \ | |
-H "X-GitHub-OTP: ${GITHUB_OTP}" \ | |
--user "${GITHUB_USERID}" \ | |
--data '{"scopes":["repo"],"note":"Rotate-Creds-Demo'"${TOKEN_UUID}"'"}' \ | |
$GITHUB_URL) | |
# extract the body | |
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g') | |
# extract the status | |
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') | |
fi | |
if [ ! $HTTP_STATUS -eq 201 ]; then | |
echo "Error [HTTP status: $HTTP_STATUS]" | |
echo "RESPONSE:" | |
echo "$HTTP_BODY" | |
exit 1 | |
fi | |
#Note: Do not overwrite existing variables yet | |
GITHUB_NEW_AUTH_TOKEN=$(echo "$HTTP_BODY" | jq -r .token) | |
GITHUB_NEW_AUTH_TOKEN_ID=$(echo "$HTTP_BODY" | jq -r .id) | |
GITHUB_NEW_AUTH_TOKEN_NOTE=$(echo "$HTTP_BODY" | jq -r .note) | |
echo "RESPONSE:" | |
echo "$HTTP_BODY" | |
echo 'export GITHUB_AUTH_TOKEN="'"$GITHUB_NEW_AUTH_TOKEN"'"' > secret_token.sh | |
echo 'export GITHUB_AUTH_TOKEN_ID="'"$GITHUB_NEW_AUTH_TOKEN_ID"'"' >> secret_token.sh | |
echo 'export GITHUB_AUTH_TOKEN_NOTE="'"$GITHUB_NEW_AUTH_TOKEN_NOTE"'"' >> secret_token.sh | |
chmod u+x secret_token.sh | |
echo "Wrote new GITHUB_AUTH_TOKEN to secret_token.sh" | |
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" \ | |
--user "${GITHUB_USERID}" \ | |
-X DELETE "${GITHUB_URL}/${GITHUB_AUTH_TOKEN_ID}") | |
# extract the body | |
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g') | |
# extract the status | |
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') | |
# example using the status | |
if [ $HTTP_STATUS -eq 401 ]; then | |
echo "Recieved 401, so trying again with Multifactor Auth OTP" | |
echo -n "Enter Multi-Factor Auth code for $GITHUB_USERID: " | |
read -s GITHUB_OTP | |
echo "" | |
HTTP_RESPONSE=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" \ | |
-H "X-GitHub-OTP: ${GITHUB_OTP}" \ | |
--user "${GITHUB_USERID}" \ | |
-X DELETE "${GITHUB_URL}/${GITHUB_AUTH_TOKEN_ID}") | |
# extract the body | |
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g') | |
# extract the status | |
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') | |
fi | |
if [ ! $HTTP_STATUS -eq 204 ]; then | |
echo "Error [HTTP status: $HTTP_STATUS]" | |
echo "RESPONSE:" | |
echo "$HTTP_BODY" | |
exit 1 | |
fi | |
echo "Successfully deleted old github personal access tokens" | |
git ignore secret_token.sh | |
echo "Git ignored secret_token.sh" | |
fi |
Have you seen this?
Seems like a good use case for secrets manager.
@karlw00t I've used both secrets manager and parameter store, and I've seen that code. My use case was handling the tricky interaction with the github api, which that code doesn't address AFAICT.
@StevenACoffman Were you ever able to solve this? I am in a very similar situation where I need to be able to use a service account to generate GitHub access tokens for rotation. I am planning to use AWS Secrets Manager and a rotation Lambda to perform the rotation. Having trouble with the GitHub side of things.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Left it ugly but working for now. Just a proof of concept. I'll redo it in golang as an aws lambda using parameter store when we do it for real. I've got neat tricks for the MFA bits.