【macOS】リポジトリアクセス時の403エラー対策!AWS CodeCommitのキーチェインパスワードを自動的に削除してみる

どうも!大阪オフィスの西村祐二です。

最近、AWS CodeCommitをよく使っています。AWSのサービスと簡単に連携できたり、プライベートなリポジトリを作れたりと便利です。

macOSでAWS CodeCommitを使っていると、今までリポジトリへアクセスできていたのに、急に403が返ってきてアクセスできなくなることがあります。

そのための対策には、いろいろと方法があります。その一つにAWS CodeCommitのキーチェーンパスワードを削除する方法があるのですが、Gitのデフォルト設定だと、削除してもリポジトリにアクセスするたびに作成されてしまうので、都度、削除する必要があります。それは、さすがに面倒なので自動的に削除するようにしてみたいと思います。

そもそも、なんで403のエラーが返ってくるのか

macOSでリリースされているデフォルトバージョンのGitは、キーチェーンアクセスを使用して、生成された認証情報(キーチェーンパスワード)を保存します。セキュリティ上の理由により、AWS CodeCommit リポジトリにアクセスするために生成されるパスワードは一時パスワードであるため、15分経過すると、キーチェーンに保存されている認証情報(キーチェーンパスワード)は無効になり、403が返ってきます。

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/troubleshooting-ch.html#troubleshooting-macoshttps

対策

403エラーとならないようにする対策がいくつかあります。詳細は下記リンクのドキュメントを参照ください。

今回は一番シンプルなキーチェーンパスワードを削除する方法を自動的に行ってみたいと思います。

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/troubleshooting-ch.html#troubleshooting-macoshttps

Swith Roleで複数のAWSアカウント間を切替えることが多いとかなければ、HTTPSではなくSSHを使用してAWS CodeCommitに接続するのがいいんじゃないかなと個人的には思います。

環境

  • Mac
    • macOS High Sierra 10.13.4

作業方針

macOSでcronのような定期実行を行えるlaunchdをつかってAWS CodeCommitのキーチェーンパスワードを削除するコマンドを定期実行し、自動的に削除します。

※はじめ、macのcrontabで定期実行しようとしていたのですが、crontabの実行ユーザがrootで実行されるようで、ユーザ管理のキーチェーン情報に設定変更できなかったので、launchdを使ってみました。

https://superuser.com/questions/1050993/cant-use-usr-bin-security-to-retrieve-password-from-keychain-via-cron

キーチェーンアクセスの操作はsecurityコマンドからできる

キーチェーンアクセスの操作はsecurityコマンドからある程度実行できるので、このコマンドを使ってAWS CodeCommitのキーチェーンパスワードを削除できます。

キーチェーンパスワードをコマンドから削除

securityコマンドを使って削除することができます。

下記コマンドで上記の認証情報を削除することができます。注意点として、一回のコマンド実行で古いものから一つが削除されます。複数まとめて削除はできないようです。

$ security delete-internet-password -l git-codecommit.ap-northeast-1.amazonaws.com

作業概要

前置きが長くなってしまいました。さっそくやっていきましょう。やることは下記2つです。

  • launchdの設定ファイルを作成

  • 作成した設定ファイルを読み込む

以上です。

launchdの設定ファイルを作成

crontabのような設定ファイルを作成します。

作成するファイルは下記ディレクトリ配下になります。

$ cd /Users/<ユーザ名>/Library/LaunchAgents

そこに作成する設定ファイルcom.keychain.codecommit.del.plistは下記になります。

今回は直接コマンドを記載しています。スクリプトを作成してそれを指定することも可能です。また、指定リージョンはap-northeast-1となっていますので、別リージョンのリポジトリを使用している際は別途変更してください。

5分に一回、AWS CodeCommitのキーチェーンパスワードを削除するコマンドが実行されます。

$ vi com.keychain.codecommit.del.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <!-- label -->
  <key>Label</key>
  <string>com.keychain.codecommit.del</string>

  <!-- script -->
  <key>ProgramArguments</key>
  <array>
    <string>security</string>
    <string>delete-internet-password</string>
    <string>-l</string>
    <string>git-codecommit.ap-northeast-1.amazonaws.com</string>
  </array>

  <!-- launchctl loadしたタイミングで実行するか -->
  <key>RunAtLoad</key>
  <true/>

  <!-- インターバル指定(例:5分毎) -->
  <key>StartInterval</key>
  <integer>300</integer>


  <!-- ログの指定 -->
  <key>StandardErrorPath</key>
  <string>/tmp/err.log</string>
  <key>StandardOutPath</key>
  <string>/tmp/launch.log</string>
  <!-- ログを出さない場合は/dev/null -->
  <!--
  <key>StandardErrorPath</key>
  <string>/dev/null</string>
  <key>StandardOutPath</key>
  <string>/dev/null</string>
  -->
</dict>
</plist>

設定ファイルを読み込む

下記コマンドで作成した設定ファイルを読み込むことができます。これで完了です。

$ launchctl load ~/Library/LaunchAgents/com.keychain.codecommit.del.plist

動作確認

設定ファイルを読み込んだ際にコマンドが実行されるので、ログを確認してみます。

作成した設定ファイルはtmp配下にログを出力するように設定しています。

$ less /tmp/launch.log
keychain: "/Users/<user>/Library/Keychains/login.keychain-db"
version: 512
class: "inet"
attributes:
    0x00000007 <blob>="git-codecommit.ap-northeast-1.amazonaws.com"
    0x00000008 <blob>=<NULL>
    "acct"<blob>="XXXXXXXXXXXXXXXXX"
    "atyp"<blob>="dflt"
    "cdat"<timedate>=0x0000000000000  "2018050000000Z\000"
    "crtr"<uint32>="aapl"
    "cusi"<sint32>=<NULL>
    "desc"<blob>=<NULL>
    "icmt"<blob>=<NULL>
    "invi"<sint32>=<NULL>
    "mdat"<timedate>=0x0000000000  "201800000000Z\000"
    "nega"<sint32>=<NULL>
    "path"<blob>="v1/repos/test"
    "port"<uint32>=0x00000000
    "prot"<blob>=<NULL>
    "ptcl"<uint32>="htps"
    "scrp"<sint32>=<NULL>
    "sdmn"<blob>=<NULL>
    "srvr"<blob>="git-codecommit.ap-northeast-1.amazonaws.com"
    "type"<uint32>=<NULL>
$ less /tmp/err.log
password has been deleted.
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.

ファイル更新をしたいとき

launchdの設定ファイルを更新したいときは下記コマンドで設定を削除した後に、再ロードする必要がありますのでご注意ください。

ファイル更新
$ vi ~/Library/LaunchAgents/com.keychain.codecommit.del.plist

設定削除
$ launchctl unload ~/Library/LaunchAgents/com.keychain.codecommit.del.plist

再読み込み
$ launchctl load ~/Library/LaunchAgents/com.keychain.codecommit.del.plist

さいごに

いかがだったでしょうか。

macOSでAWS CodeCommitを使っているときの、リポジトリアクセス時403エラー対策として、 launchdを使って、AWS CodeCommitのキーチェインパスワードを定期的に削除する仕組みを作ってみました。

誰かの参考になれば幸いです。