sanadamaru's blog

学びメモや考えごとなど

Codecovセキュリティアップデートの対応~ Android編

前回のCodecovのセキュリティアップデートの対応~iOS編 - sanadamaru's blog

に引き続き今回はCodecovセキュリティアップデートで対応したことのAndroid編を書いていこうと思います。

対応内容

CircleCIのEnvironment Variablesに登録している以下のシークレット情報を更新しました。

  • PLAY_ACCOUNT_JSON_BASE64の変更(Google Playのサービスアカウント)

  • Android keystoreとアップロード鍵の変更

  • Google Play Consoleに登録している各アプリのアップロード鍵のリセット申請

PLAY_ACCOUNT_JSON_BASE64の変更

私のプロジェクトではGoogle Playにapkのアップロードを自動化するためにGradle Play Publisherプラグインを使用しています。 github.com

このプラグインを使用するためにはPlay Developer API にアクセスできるサービスアカウントが必要なため、 Gradle Play PublisherのリポジトリのREADMEのサービスアカウントの作成手順を参考に再作成しました。 多くのプロジェクトでは、サービスアカウント作成時にダウンロードできるJSON認証情報はプロジェクト内に配置すると思いますが、私のプロジェクトではCircleCIに登録しているためJSON認証情報をbase64エンコードして登録し直しました。

通常であれば上記の手順のみで済むのですが、実際にはデベロッパーアカウントの所有者権限が退職者のアカウントに紐づいていてデベロッパーアカウントを最作成しアプリを移行する必要があったり結構大変でした。(サービスアカウントの最作成はデベロッパーアカウントの所有者しか出来ないため)

Android keystoreとアップロード鍵の変更

次にkeystoreとアップロード鍵についてです。これに関してもCIで管理していたため変更が必要になりました。 私のプロジェクトのようにkeystoreをCIで管理しているプロジェクトもさほど多くないと思うので変更が必要になった方は結構少ないのではないかと思います。

まずはAndroidの公式ドキュメントを参考にkeystoreとアップロード鍵を再生成しました。 developer.android.com

上記手順で生成したファイルをサービスアカウントのJSONと同じようにbase64エンコードしてRELEASE_KEYSTORE_BASE64として再登録。

その他にkeystoreとアップロード鍵の生成時に設定した[key store password, key alias, key password]をそれぞれ

  • RELEASE_KEYSTORE_KEY_ALIAS
  • RELEASE_KEYSTORE_KEY_PASSWORD
  • RELEASE_KEYSTORE_PASSWORD

として登録し直しました。

登録したEnvironment Variablesはapp/build.gradleで

android {
        signingConfigs {
        release {
            if (System.getenv("RELEASE_KEYSTORE_BASE64") != null) {
                storeFile decodeFileFromBase64Env('RELEASE_KEYSTORE_BASE64', "tmp_ks_", ".jks")
                storePassword System.getenv('RELEASE_KEYSTORE_PASSWORD')
                keyAlias System.getenv('RELEASE_KEYSTORE_KEY_ALIAS')
                keyPassword System.getenv('RELEASE_KEYSTORE_KEY_PASSWORD')
            }
        }
    }
}

static decodeFileFromBase64Env(String name, String fileName, String ext) {
    String base64String = System.getenv(name)
    if (base64String == null) return null
    File tempFile = File.createTempFile(fileName, ext, File.createTempDir())
    FileOutputStream fos = null
    try {
        fos = new FileOutputStream(tempFile)
        fos.write(base64String.decodeBase64())
        fos.flush()
    } finally {
        if (fos != null) {
            fos.close()
        }
    }
    return tempFile
}

のような形でkeystoreとアップロード鍵を読み込んで署名しています。

Google Play Consoleに登録している各アプリのアップロード鍵のリセット申請

keystoreとアップロード鍵の変更に伴い、Google Play Consoleに登録しているアプリのアップロード鍵のリセット申請が必要になります。

先程の手順で生成したアップロード鍵のファイルを以下のコマンドで PEM 形式にエクスポートします

$ keytool -export -rfc -keystore upload-keystore.jks -alias upload -file upload_certificate.pem

※ upload-keystore.jks, upload, upload_certificate.pemは適宜置き換えてください。

Google Play Consoleで対象アプリを開いたら【設定】→【アプリの完全性】を開き、【鍵のアップグレードをリクエスト】をクリック。

事由を聞かれるので、【現在の鍵が不正使用されている】を選択し【次へ】を押下

サポートに問い合わせてほしい旨のメッセージが表示されるので、【サポートにお問合せ】を押下。

問い合わせ画面が表示されるので、各種アプリ情報を入力して【お客様のアプリは Google Play アプリ署名に登録されていますか?】で【はい、Google Play でアップロード鍵を管理しています】を選択

それ以降の選択はこのように選択。 f:id:sndyut:20210608061314p:plain

【フィードバックまたは問題の内容をご記入ください *】の項目に詳細内容を記入。

最後にpemファイルを添付して【送信】を実行。

数日経つとGoogle Play デベロッパー サポートからメールが届きます。

メールにいつから使用可能になるか記載されていたのでその日時以降にapkをアップロードできるかを試しました。

結果、問題なくアップロードできたためこれにて対応完了となりました。

最後に

Codecovセキュリティアップデート対応のAndroidの対応内容についてご紹介しました。

Androidの署名やCIの設定等は前任者が設定しており今回の対応をするまでは正直そこまで理解できていなかったので良い学びになりました。

もし似たような設定をされていたり、keystoreをCIで管理したいという方がいれば参考になると嬉しく思います。

Play Consoleの所有者権限に関してはちょっとした罠だなと思ったのでそこについては忘備録的にいつか書きたいと思います。