はじめに
この記事は**and factory Advent Calendar 2020の18日目の記事**です。
昨日は @ichi-nakashimaさんの【React Hooks】Component から stateを伴ったロジックを切り出す技術たちでした。
RedisにはPub/Sub機能がある
Redisと言えばKVS(Key-Value Store)として使われるのが一般的と思いますが、Pub/Sub機能も備わっているので、こいつを使ってGoとやり取りをしてみたいと思います。
RedisのPub/Sub機能とは
それぞれPublish(発行)、Subscrib(購読)という意味で、RedisではあるChannelを作成して、
そのChannelに対してメッセージを**Publish(発行)したりSubscrib(購読)**したりする(=メッセージの発信・受信みたいな)ことができる機能を指します。
今回は堅牢なRedisを立ててそいつに対してGoからPublishを行ってみます。
Redisサーバーを立てる
一応自分で試した環境はVagrant+VM上のCentOS7にRedisをインストールしました。
以下はインストール時の一連(EPELのリポジトリ追加→Redisインストール)のログ
まずはEPELのリポジトリの追加
(※EPELについては CentOSなどで使う、EPELってなんだ? - Qiita などを参照してください。)
[vagrant@localhost ~]$ sudo yum install epel-release
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: ftp.tsukuba.wide.ad.jp
* extras: ftp.tsukuba.wide.ad.jp
* updates: download.nus.edu.sg
Resolving Dependencies
--> Running transaction check
---> Package epel-release.noarch 0:7-11 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
===================================================================================================================================================================
Package Arch Version Repository Size
===================================================================================================================================================================
Installing:
epel-release noarch 7-11 extras 15 k
Transaction Summary
===================================================================================================================================================================
Install 1 Package
Total download size: 15 k
Installed size: 24 k
Is this ok [y/d/N]: y
Downloading packages:
epel-release-7-11.noarch.rpm | 15 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : epel-release-7-11.noarch 1/1
Verifying : epel-release-7-11.noarch 1/1
Installed:
epel-release.noarch 0:7-11
Complete!
次にRedisのインストール
[vagrant@localhost ~]$ sudo yum install redis -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink | 6.4 kB 00:00:00
* base: ftp.tsukuba.wide.ad.jp
* epel: download.nus.edu.sg
* extras: ftp.tsukuba.wide.ad.jp
* updates: download.nus.edu.sg
epel | 4.7 kB 00:00:00
(1/3): epel/x86_64/group_gz | 95 kB 00:00:01
(2/3): epel/x86_64/updateinfo | 1.0 MB 00:00:02
(3/3): epel/x86_64/primary_db | 6.8 MB 00:00:01
Resolving Dependencies
--> Running transaction check
---> Package redis.x86_64 0:3.2.12-2.el7 will be installed
--> Processing Dependency: libjemalloc.so.1()(64bit) for package: redis-3.2.12-2.el7.x86_64
--> Running transaction check
---> Package jemalloc.x86_64 0:3.6.0-1.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
===================================================================================================================================================================
Package Arch Version Repository Size
===================================================================================================================================================================
Installing:
redis x86_64 3.2.12-2.el7 epel 544 k
Installing for dependencies:
jemalloc x86_64 3.6.0-1.el7 epel 105 k
Transaction Summary
===================================================================================================================================================================
Install 1 Package (+1 Dependent package)
Total download size: 648 k
Installed size: 1.7 M
Downloading packages:
warning: /var/cache/yum/x86_64/7/epel/packages/jemalloc-3.6.0-1.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY0 B/s | 0 B --:--:-- ETA
Public key for jemalloc-3.6.0-1.el7.x86_64.rpm is not installed
(1/2): jemalloc-3.6.0-1.el7.x86_64.rpm | 105 kB 00:00:02
(2/2): redis-3.2.12-2.el7.x86_64.rpm | 544 kB 00:00:02
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 293 kB/s | 648 kB 00:00:02
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Importing GPG key 0x352C64E5:
Userid : "Fedora EPEL (7) <epel@fedoraproject.org>"
Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5
Package : epel-release-7-11.noarch (@extras)
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : jemalloc-3.6.0-1.el7.x86_64 1/2
Installing : redis-3.2.12-2.el7.x86_64 2/2
Verifying : redis-3.2.12-2.el7.x86_64 1/2
Verifying : jemalloc-3.6.0-1.el7.x86_64 2/2
Installed:
redis.x86_64 0:3.2.12-2.el7
Dependency Installed:
jemalloc.x86_64 0:3.6.0-1.el7
Complete!
Redisのインストールが完了したので立ち上げる
[vagrant@localhost ~]$ sudo systemctl start redis.service
Redisの自動起動を有効にする
[vagrant@localhost ~]$ sudo systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.
最後にRedisの状態を確認する
[vagrant@localhost ~]$ sudo systemctl status redis.service
● redis.service - Redis persistent key-value database
Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/redis.service.d
└─limit.conf
Active: active (running) since Mon 2020-07-13 09:43:21 UTC; 31s ago
Main PID: 22002 (redis-server)
CGroup: /system.slice/redis.service
└─22002 /usr/bin/redis-server 127.0.0.1:6379
Jul 13 09:43:21 localhost.localdomain systemd[1]: Starting Redis persistent key-value database...
Jul 13 09:43:21 localhost.localdomain systemd[1]: Started Redis persistent key-value database.
念のためredis-cli
コマンドでping
を行い、PONG
と返ってくるか確認する。
※このping
コマンドは疎通確認によく使用されるコマンドです。
[vagrant@localhost ~]$ redis-cli ping
PONG
あとは/etc/redis.conf
を編集してIPアドレスなどを設定すればRedisのインストールは完了
[vagrant@localhost ~]$ sudo vi /etc/redis.conf
Redisを堅牢にする(パスワードの設定)
[vagrant@localhost ~]$ echo "secretkey" | sha256sum
92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a -
[vagrant@localhost ~]$ sudo vi /etc/redis.conf
SECURITY
の項目があるので、その下にrequirepass
を追加し、パスワードを記述する。
################################## SECURITY ###################################
# Require clients to issue AUTH <PASSWORD> before processing any other
# commands. This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
requirepass 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a
(※ここではsha256sum
を使って生成したハッシュ値をパスワードとして設定していますが、ある程度の長さがあればいいと思います。)
/etc/redis.conf
編集後にRedisを再起動し、redis-cli
から先ずはパスワードなしの状態でコマンドを実行する。
[vagrant@localhost ~]$ sudo systemctl restart redis.service
[vagrant@localhost ~]$ redis-cli
127.0.0.1:6379> set key 10
(error) NOAUTH Authentication required.
上記のように認証エラーがでることを確認。
次にauth
コマンドを書き、先ほど設定したパスワードを入れて実行する。
127.0.0.1:6379> auth 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a
OK
OKが出れば認証された状態なので、コマンドを実行すれば以下のようにふつうに動くようになる。
127.0.0.1:6379> set key 10
OK
127.0.0.1:6379> get key
"10"
127.0.0.1:6379> quit
Goのサンプルコード
サンプルコードはパスワードを設定したRedisにパブリッシュする処理を書いています。(※パスワード設定は必須ではないです。念のため)
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
// RedisPublish : コマンドをRedisへパブリッシュする
func RedisPublish(message string) (int, error) {
conn, redisAuthPass, err := ConnectionRedis()
if err != nil {
fmt.Println(err)
return 0, err
}
defer conn.Close()
// パス認証
if redisAuthPass != "" {
_, err = conn.Do("AUTH", redisAuthPass)
if err != nil {
fmt.Println(err)
return 0, err
}
}
// パブリッシュ
res, err := redis.Int(conn.Do("PUBLISH", "test_channel", message))
if err != nil {
fmt.Println(err)
return 0, err
}
return res, err
}
// ConnectionRedis : Redisと接続し接続情報とAuthパスを返す
func ConnectionRedis() (redis.Conn, string, error) {
// RedisのAUTHパス
AuthPass := "92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a"
// RedisのIPアドレス
RedisIPAddress := "192.168.33.100"
// Redisのポート番号
RedisPort := "6379"
// 接続
conn, err := redis.Dial("tcp", RedisIPAddress+":"+RedisPort)
if err != nil {
fmt.Println(err)
return nil, "", err
}
return conn, AuthPass, err
}
実際にはAUTHパスとかは環境によって変わると思うので、ソースに書かずに.env
とかに記述して読み込むのがいいと思います。
参考:【Go】.envファイルをGolangでも使用するためのライブラリ「godotenv」 - Qiita
Redisをさらに堅牢にする
個人的にはRedisに接続する際のAuthパスだけでもいいと思うんですが念には念を入れて強化する場合は以下のことが出来ます。
ポート番号の変更
Redisのデフォルトポート番号は6379
番ですが、これを変更することで多少なりともセキュリティが向上します。
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
# port 6379
port 6597
変更後はRedisの再起動すること。
重要なコマンドの変更
例えばCONFIG
やSHUTDOWN
、FLUSHDB
コマンドなど、実行されるとマズいコマンドをほかの文字列に置き換えることが出来ます。
代わりのコマンド名を以下のredis.conf
に追記して再起動をすることで適用されます。
# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG ""
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to slaves may cause problems.
rename-command CONFIG configconfig
rename-command FLUSHDB SF_FLUSHDB
rename-command SHUTDOWN RENAME_SD
以下コマンドがかわっているか確認の様子
[vagrant@localhost ~]$ sudo systemctl restart redis.service
[vagrant@localhost ~]$ redis-cli
127.0.0.1:6379> auth 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a // 上で設定したパス
OK
127.0.0.1:6379> config get requirepass
(error) ERR unknown command 'config' // configというコマンドは無い(上で変更したため)
127.0.0.1:6379> configconfig get requirepass
1) "requirepass"
2) "92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a"
127.0.0.1:6379> exit
Redisデータディレクトリの権限変更
RedisユーザーとRedisグループのみがアクセスできるように770
に変更する。
[vagrant@localhost ~]$ ls -l /var/lib | grep redis
drwxr-x---. 2 redis redis 22 Jul 13 13:31 redis
[vagrant@localhost ~]$ sudo chmod 770 /var/lib/redis
[vagrant@localhost ~]$ ls -l /var/lib | grep redis
drwxrwx---. 2 redis redis 22 Jul 13 13:31 redis
おわり
- なんか走り書きしたら雑なまとめになってしまった感がある・・・
- ちなみにSubscribは今度時間あれば書くかもしれません・・・(予定は未定です)
- あとまだRedisは構成ファイルの権限変更したりなどで強固にできますがここでは割愛します(DigitalOceanさんの参考記事をどうぞ)