Spaceship::Slack2fa
This is a gem to get the 6-digit code for AppStore Connect’s 2 factor auth from posts to a specific Slack channel.
It can be used to automate deployment with actions like fastlane deliver
.
Installation
Add the following line to your Gemfile.
ruby
gem "spaceship-slack2fa", git: "https://github.com/manicmaniac/spaceship-slack2fa.git"
Then run bundle install
.
Prerequisites
You have to create Slack app to read Slack messages beforehand. Please create an app from https://api.slack.com/apps that meets the following requirements.
- Bot token scope with
channels.history
andchat.write
permission - The bot token is enabled on the relevant channel.
Usage
For example, if you have a Fastfile like the following:
ruby
lane :release do
deliver
end
Just wrap the deliver
action in a block that is passed to Spaceship::Slack2fa.enable
.
Note that you may need to set SPACESHIP_2FA_SMS_DEFAULT_PHONE_NUMBER
environment variable to tell Fastlane which phone number is preferred.
```ruby require “spaceship/slack2fa”
lane :release do Spaceship::Slack2fa.enable( slack_api_token: “xoxb-000000000-000000000-XXXXXXXXXXXXXXXXXXXXXXXX”, channel_id: “CXXXXXXXXXX”, user_id: “UXXXXXXXXXX”, referrer: “My App”, ) do deliver end end ```
I use deliver
as an example, but any action that internally references Spaceship::Client
can be used.
You can pass options to Spaceship::Slack2fa.enable
as arguments.
slack_api_token
: Required. A bot token for your Slack app.channel_id
: Required. The ID of the channel where the message will be posted.user_id
: Required. The ID of the user posting the message.referrer
: Required. Amrkdwn
text to identify which service consumes 6-digit code, typically the name of your app.allow_any_users
: Optional. Iftrue
,spaceship-slack2fa
recognizes only messages from the bot user specified inslack_api_token
, otherwise it treats all messages with 6-digits numbers as 2FA code. The default isfalse
.retry_count
: Optional. The number of retries to try if a message is not found. The default is3
.retry_interval
: Optional. The interval between retries in seconds. The default is20
.
See What is the simplest way to find a slack team ID and a channel ID? to know how to get channel ID and user ID. ## How it works
The fastlane spaceship
invokes the Spaceship::Client.ask_for_2fa_code
method to receive 2FA codes from standard input.
This gem temporarily rewrites the above method to use the Slack API’s conversations.history
to retrieve the message and return it.
The method rewriting only takes effect in the block passed to Spaceship::Slack2fa.enable
.
Known bugs
Security
Basically, sending 2FA code to external service out of your device has security risk. Use API key provided by App Store Connect instead, if possible.
Concurrency
This program does not consider concurrency at all. When you run multiple processes of this program and those watches the same Slack channel, some processes may retrieve wrong 2FA code.
Testing
Run the following command to run test
sh
bundle exec rake spec
You can use bin/login-to-appstore-connect
to do end-to-end testing.
This script does nothing but login to AppStore Connect.
:warning: Note that your account will be locked out if you request Apple to send 2FA code many times without establishing a session.
sh
bin/login-to-appstore-connect \
--user 'developer@example.com' \
--password 'PASSWORD' \
--phone_number '+81 80-XXXX-XXXX' \
--slack_api_token 'xoxb-XXXXXXXX' \
--slack_channel_id CXXXXXXXX \
--slack_user_id UXXXXXXXX
Or you can pass some of the options though environment variables.
```sh export FASTLANE_USER=developer@example.com export FASTLANE_PASSWORD=PASSWORD export SPACESHIP_2FA_SMS_DEFAULT_PHONE_NUMBER=’+81 80-XXXX-XXXX’
bin/login-to-appstore-connect -t ‘xoxb-XXXXXXXX’ -c CXXXXXXXX -s UXXXXXXXX ```
After the script successfully establish login session, you can see ~/.fastlane/spaceship/*/cookie
, which serializes a cookie of AppStore Connect.
Release
This library is not intended to be published on rubygems.org. So the release flow is simple as described below.
1. Create a pull request to bump version
sh
export VERSION='x.x.x'
git checkout -b "release/$VERSION"
ruby -pi -e 'sub(/[0-9.]+/, ENV["VERSION"]) if /VERSION/' lib/spaceship/slack2fa/version.rb
bundle install
git commit -am "Bump version to $VERSION"
gh pr create -fa@me
gh pr merge -dm --auto
2. Publish release
After the pull request is merged, run the following commands.
sh
export VERSION='x.x.x'
git tag -am "$VERSION" "$VERSION"
git push origin "$VERSION"
gh release create -t "$VERSION" --generate-notes "$VERSION"