やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

GitHubアップローダの未解決課題2

何ができて、何ができていないのか。

前回まで

http://ytyaru.hatenablog.com/entry/2017/12/09/000000

概要

課題

  • 実装
    • 抽象化
      • CUI
      • Database系
      • Web系
  • テスト

解決済み

Web系の抽象化

  • GitHubAPIの認証用requestsライブラリ引数生成を抽象化した
    • 認証なし, Basic, TwoFactor, OAuth
    • DBからTokenを取得する
    • APIでTokenを生成してDBに登録する
  • APIごとに認証方法を使い分ける
    • RequestParameter.py
  • 認証クラス配列を生成する
    • AuthenticationsCreator.py
      • DBとユーザ名から以下の認証クラス配列を生成する
      • OAuth, TwoFactor/Basicの優先順に作成できるものがあれば作る
  • HTTPメソッド文字列からリクエストメソッドを識別して実行する
  • AuthenticationsCreator.py
    • Basic認証またはTwoFactor認証を返すメソッドを作成した
      • ./cui/register/command/配下の各クラスで同じ処理を書いているのを解消した

ssh-keygenとsshコマンド

  • SshKeyGen.py
    • SSH通信確認ができない
      • ssh-keygen -lコマンドで行うのみ。真偽値で取得したい
        • ssh-keygenコマンド操作用クラスを作った
          • 失敗すると例外発生するようにした
            • 固定テキストによる判定なので危うい
    • SSH鍵生成時に、任意の値を指定したい
      • 暗号化方式、暗号化強度などを指定できるようにした

アカウント登録

  • GitHubAPIを叩く認証部分を重複なくスマートに実装したい
    • ./cui/register/command/Inserter.pyUpdater.pyに重複コード多数あるので解消したい
    • /cui/register/github/api/v3/web/serviceのと重複する
  • アカウント管理で2FA関連を一部実装
    • 2FA有効アカウント作成
    • 有効OTP生成するPythonライブラリで認証確認できた
    • DB保存一部実装
      • Secretを保存する
      • リカバリコードやその有効期限の保存は未実装

テスト

単体、結合テスト

対象ソースコード 単体テスト記事 単体テストGitHub
./web/service/github/api/v3/authentication http://ytyaru.hatenablog.com/entry/2017/11/29/000000 GitHub.API.Authentication.Abstract.201704141006
.cui/register/SshConfigurator.py http://ytyaru.hatenablog.com/entry/2017/12/10/000000 Github.Uploader.SshConfigurator.unittest.201704221606
.cui/register/SshKeyGen.py http://ytyaru.hatenablog.com/entry/2017/12/11/000000 Github.Uploader.SshKeyGen.unittest.201704221809|Github.Uploader.SshKeyGen.unittest.201704221809
`./web/sqlite/Json2Sqlite.py http://ytyaru.hatenablog.com/entry/2017/12/13/000000 Github.Uploader.Json2Sqlite.unittest.201704230804
./web/log/Log.py http://ytyaru.hatenablog.com/entry/2017/12/20/000000 GitHub.Uploader.Log.unittest.201704251509
./web/http/Response.py http://ytyaru.hatenablog.com/entry/2017/12/29/000000 GitHub.Uploader.ContentType.201705040739
./web/service/github/api/v3/AuthenticationsCreator.py http://ytyaru.hatenablog.com/entry/2017/12/31/000000 Github.Uploader.AuthenticationsCreator.unittest.201705041033
./web/service/github/api/v3/RequestParameter.py GoogleAppsScriptでHelloWorldしてみた - やってみる Github.Uploader.RequestParameter.unittest.201705041425
./web/service/github/api/v3/Response.py GASでFusionTablesAPIを叩いてみた - やってみる Github.Uploader.GithubV3Response.unittest.201705041626

機能テスト

未解決

Web系の抽象化

  • APIごとに必要なHttpHeadersのAccept指定を抽象化する
    • たとえばLicenseAPIはすべてapplication/vnd.github.drax-preview+jsonが必要である
  • GETの引数であるparamsを抽象化する
  • POSTの引数であるdataを抽象化する

paramsやdataはAPIごとに異なる。Pythonの名前付き引数にしたい。それをどのように抽象化すればいいのか。 辞書引数**kwargsならできそうだが、名前や初期値を指定して何を渡せばいいかわかるようにしたい。 引数のバリデートが必要だから抽象化は難しいか。

理想はAPIごとのdataやparamsの代入やバリデート処理を一切書かない上、以下のようにAPIを呼び出せること。

  • GitHubUploader.py
    • Client(AuthenticationCreator(db, username).Create())
      • client.repo.create(name='', desc='', url='', ..., sort='', direct='', per_page=100)
  • GitHubUserRegister.py
    • Client([BasicAuthentication(username, password)])
      • client.auth.create(scopes)
      • client.sshkeys.create()
    • client.SetAuthentications([OAuthAuthentication(token), BasicAuthentication(username, password)])
      • client.users.get(username)
      • client.repo.gets()

動作確認していない

  • アカウント登録 update
    • ユーザ名の更新について動作未確認
    • メールアドレスの更新について動作未確認

未実装

  • アカウント管理で2FA関連が一部未実装

セキュリティ

  • ふだん使うTokenに権限がたくさん付与されてしまう
    • 通信傍受などでTokenが漏洩したときに危険(SSH鍵が変更されてしまうかも?)
      • admin:public_keyの権限は初回限りにする
        • SSH鍵設定したらすぐに権限を削除する
        • SSH鍵の更新に必要
          • 更新は削除後に生成することで実現するGitHubAPIの仕様
          • 削除するのにadmin:public_keyの権限が必要である

枠組み

  • 抽象化したい(各classの密結合を疎結合にしたい)
    • CUI
    • Database系

細かいこと

  • SSHのconfigを編集したい(定義順などきれいに整形したい)
  • AccessTokenのScopeGrantの文言を統一したい
    • dqn.sakusakutto.jp/2012/03/database_refactoring.html

改修しないと問題になる可能性がある

  • ツールでAccessTokenを自動作成したが、サイトで削除してしまった。その後、ツールでアップロードしようとしたが、Tokenが存在しないためAPI実行時にエラーが出た
    • SSH鍵についても同様のことが生じうる
      • GitHubアカウントについても同様のことが生じうる

他にもユーザ操作次第で不具合が生じそうなワークフローがないか考えてみたほうがいいか。

  • GitHubUserRegister.pyでinsertサブコマンドのテスト時、途中でエラーになるとAccessTokenが作成されたままになってしまう。途中で異常終了したときはTokenやSSH鍵などAPIで生成したものを削除するようにしたい。残すとセキュリティホールになりうるが、手動で削除するのも面倒。

改修せずとも問題にはならない

  • ./cui/register/command/Inserter.py
    • __CreateRecordAccount()
      • AccountsテーブルのCreatedAtUpdatedAtの値が1970-01-01T00:00:00Z固定になっている。UsersAPIで日時を取得して設定したい
  • ユーザ作成日時取得のついでにプロフィール情報も取得したい
  • 指定ユーザの全リポジトリを再取得したい
  • AccessTokenの権限設定を任意にしたい

作業中に不満だったこと