2024年5月19日日曜日

Stable diffusion WebUI で ERROR: python3-venv is not installed, aborting...

Stable diffusion WebUI で ERROR: python3-venv is not installed, aborting...

概要

最新版を clone したらタイトルのエラーが発生したので対応しました

環境

  • macOS 14.4.1
  • sd-webui 1.6.0
  • Python 3.10.11

対応方法

デフォルトだと python3.10 というコマンドを探すのでこれがないとエラーになります
Homebrew でインストールしてもいいのですがメインの Python はすでに 3.12 になっているので 3.10 にすると困ります
brew link で切り替えるのも手ですが毎回切り替えるのも面倒なので pyenv を使います

  • cd stable-diffusion-webui
  • pyenv local 3.10.11

これで python3.10 コマンドが stable-diffusion-webui 配下で使えるようになります

動作確認

あとは ./webui.sh を実行すれば OK です

最後に

執筆時点の sd-webui では Python 3.10 が推奨っぽいです
最新版にした場合はサポートしている Python のバージョンを確認して pyenv で切り替えると良いかなと思います

参考サイト

2024年5月18日土曜日

Bark 用の学習済み音声モデル(npz)を使ってTTSさせる方法

Bark 用の学習済み音声モデル(npz)を使ってTTSさせる方法

概要

Bark は transformers に対応しているので学習した音声モデルを使うことができます
今回は transformers を使って Python スクリプトで tts してみます

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.12.2
  • bark 0.1.5
  • scipy 1.13.0
  • transformers 4.40.2

サンプルコード

from scipy.io import wavfile
from transformers import AutoProcessor, BarkModel

# モデルのダウンロード
processor = AutoProcessor.from_pretrained("suno/bark-small")
model = BarkModel.from_pretrained("suno/bark-small")

# 学習済み音声モデルの指定
# voice_preset = "v2/ja_speaker_6"
voice_preset = "/Users/user01/one-click-installers-tts-6.0/tts-generation-webui/voices/Alice.npz"

# TTS設定
inputs = processor("こんにちわ、今日はいい天気ですね", voice_preset=voice_preset)

# モデルから音声の作成
audio_array = model.generate(**inputs, semantic_max_new_tokens=100)
audio_array = audio_array.cpu().numpy().squeeze()

# 音声の保存
sample_rate = model.generation_config.sample_rate
wavfile.write("/Users/user01/Downloads/audio.wav", sample_rate, audio_array)

最後に

tts-generator-webui でも同じように学習済み音声モデルを使って TTS できますがどちらがいいのが気になりました
transformers を使い慣れている人は直接 Python を触れる方が良いのかもしれません

参考サイト

2024年5月17日金曜日

Bark で AI 音声作成超入門

Bark で AI 音声作成超入門

概要

Bark は事前に学習された音声モデルを使って与えた文章を読み上げることができる transformers で扱えるツールです
今回はデフォルトの音声モデルを使ってとりあえず文章を読ませてみました
最終的には音声データが作成できます

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.12.2
  • bark 0.1.5

インストール

  • pipenv install bark

サンプルコード

import os

from bark import SAMPLE_RATE, generate_audio, preload_models
from IPython.display import Audio
from scipy.io.wavfile import write as write_wav

# AppleSillicon上で動作させるための設定
os.environ["SUNO_ENABLE_MPS"] = "True"

# 事前学習済みの音声モデルのダウンロード(全部10GBほどあるので注意
preload_models()

# 音声モデルに喋らせる文章の準備
text_prompt = """
     Hello, my name is Suno. And, uh — and I like pizza. [laughs] 
     But I also have other interests such as playing tic tac toe.
"""
audio_array = generate_audio(text_prompt)

# 音声モデルから実際に音声を作成する
write_wav("bark_generation.wav", SAMPLE_RATE, audio_array)

# 音声の再生
Audio(audio_array, rate=SAMPLE_RATE)

モデルは ~/.cache/suno/bark_v0/fine_2.pt などにダウンロードされます

動作確認

サンプルコードを実行すると自動で音声が再生されます
サンプルコードは英語ですが日本語でも普通に再生されました

最後に

bark で TTS をとりあえず試してみました
これを応用して自分の声の音声モデルを作成すれば自分のクローンが作れます
また歌を歌ってもらうこともできるようです

初回にダウンロードするモデルのデータがかなり大きいのでディスクの容量に注意してください
M2 Mac の場合 GPU 対応していないので少し時間がかかります
低スペックのマシンだと音声を生成するのにかなり時間がかかるかもしれません
喋らせる文章が長ければ長いほど実行にも時間がかかります

成功した場合の音声ファイルは 1MB 弱ですが失敗すると100MBほどになりビープ音みたいな感じになることもあったので失敗する場合は再度実行してみてください

参考サイト

2024年5月16日木曜日

AudioCraft を M2 mac mini 上で動かしてみた

AudioCraft を M2 mac mini 上で動かしてみた

概要

AudioCraft は音を生成することができる MusicGen や AudioGen を簡単に扱うことができるツールです
今回は M2 mac 上にインストールして AudioGen を使ってみました

環境

  • macOS 14.4.1
  • Python 3.9.17
  • AudioCraft 1.3.0 (795f8dc)

Python3.9 インストール

  • pyenv install 3.9.17

プロジェクトクローン

  • git clone https://github.com/facebookresearch/audiocraft
  • cd audiocraft
  • pyenv local 3.9.17

プロジェクトセットアップ

pytorch はバージョン 2.1.0 である必要があります

  • pip install "torch==2.1.0"
  • pip install -r requirements.txt

MusicGen 用のデモアプリの起動

MusicGen にはデモアプリが付属しているので今回はそれを使います

  • python -m demos.musicgen_app --share

http://127.0.0.1:7860 で起動します

動作確認

Input Text に作成したい音楽のテキストを入力してみます
今回は「happy rock」と入力しました
あとは「Submit」をクリックするだけです

初回は各種モデルをダウンロードするので時間がかかります
モデルのサイズは全部で 5GB ほどあるのでディスク容量に注意しましょう

音楽が完成すると右側でダウンロードや直接再生ができます
デフォルトでは10秒間分の音楽のみ生成してくれます

最後に

AudioCraft の MusicGen を試してみました
sd-webui の音楽版という感じでテキストから音楽を作成することができます
今回は10秒でしたがもっと長い音楽も生成することができます

AudioGen 用のデモもあるのですが AudioGen は WebUI ではないようです

参考サイト

2024年5月15日水曜日

tts-generator-webui で bark 用の音声モデルを使ってテキストの読み上げをやってみる

tts-generator-webui で bark 用の音声モデルを使ってテキストの読み上げをやってみる

概要

前回 Bark 用のモデルを生成してみました
今回はそれを使ってテキストの読み上げを行います

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • tts-generator-webui 6.0

方法

tts-generator-webui を起動します
最初に「Generation (Bark)」タブに移動します

次に「Audio Voice」で学習させた Bark 用の音声モデルファイルを指定します (npz)
次に「Prompt」に読み上げさせる文章を指定します
あとは画面下部にある「Generate」をクリックするだけです

初回生成時は Bark 関連のモデルがダウンロードされるので時間がかかります
5GB ほどあるのでディスクの容量に注意しましょう

ちょっとポイント

読み上げる文章が短い場合には Max length パラメータを調整しましょう
最大で18秒かけて文章を読み上げてくれますが文字が少ないのに length が長いとうまく読み上げてくれないことがあるので文字数に応じて length を調整するようにしてください

自然に読み上げてみてそれにかかった秒数を指定するのが良いかなと思います

動作確認

Generate 後に音声が完了するとそのまま再生することができるので再生して確認しましょう

最後に

Bark 用の音声モデルを使ってテキストの読み上げを行ってみました
最大で18秒分しか生成できないので長文を読ませる場合には何度か生成する必要があります
日本語にも対応していました (音声モデルも日本語の音源から生成しています)

Bark で使用したモデルファイル (npz) は RVC で生成したモデルファイル (pth) では使えないので注意しましょう

どちらも音声モデルから新しい音声を生成する手法ですが

  • Bark はテキストから音声を生成するのに対して
  • RVC は音声から声の部分だけを挿げ替えて音声を生成する

ので使用するモデルも変わってきます

また StableDiffusion のように生成ごとに結果が変わるのでうまく読み上げてくれるまでガチャする必要があります

2024年5月14日火曜日

tts-generator-webui で bark 用の音声モデルを作成する

tts-generator-webui で bark 用の音声モデルを作成する

概要

Bark 用の音声モデルを生成するのに有名なサンプルで https://github.com/serp-ai/bark-with-voice-clone がありますがこれだといろいろとハマるところがあります
tts-generator-webui には bark の Generate と Voice Clone が WebUI として実装されているので簡単に生成することができます
今回は Bark 用の音声モデル npz ファイルを生成する方法を紹介します

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • tts-generator-webui 6.0

準備

事前に1分程度の音声ファイルを準備しましょう
ファイルは BGM などのないシンプルな音声ファイルが望ましいです

モデル生成

tts-generator-webui を起動します
次に「Bark Voice Clone」タブを選択します
「Input Audio」に準備した音声ファイルを指定します

M2 mac の場合 GPU は使えないので「Use GPU」のチェックは外しましょう

そして「Generate Voice」をクリックします
しばらくすると npz ファイルが作成されます

またモデルの生成が完了したら「Use as histroy」をクリックしておきましょう
そのまま Generate の画面に移動しますが念の為モデルが保存されているか確認するためです

Tips

音源ファイルが長すぎるとうまくいかないことがあるので可能な限り短い音源を準備しましょう
自分は 2 分程度であればうまくモデルを生成することができました

最後に

tts-generator-webui で Bark 用の音声モデルを生成してみました
次回はこの音声モデルを使ってテキストを読み上げてみたいと思います

2024年5月13日月曜日

tts-generator-webui を M2 mac mini 上で動かす方法

tts-generator-webui を M2 mac mini 上で動かす方法

概要

tts-generator-webui を M2 mac mini 上で動かしてみました
voice-generator-webui よりもこちらのほうが良いかなと思います

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • tts-generator-webui 6.0

ダウンロード

https://github.com/rsxdalv/one-click-installers-tts/archive/refs/tags/v6.0.zip これをダウンロードします

ダウンロードしたら解答しましょう

  • unzip one-click-installers-tts-6.0.zip

インストール/起動

必要なものをすべてインストールしてくれるスクリプトがあるのでそれを実行します

  • cd one-click-installers-tts-6.0
  • chmod +x start_macos.sh
  • ./start_macos.sh

途中 GPU を選択する部分があるので Apple M Series を選択しましょう

A) NVIDIA
B) AMD
C) Apple M Series
D) None (I want to run in CPU mode)

Input> C

conda や Python などを自動で installer_files 配下にダウンロード、インストールしてくれます
Python のバージョンは 3.10.14 でした (installer_files/env/bin/python

必要なライブラリがインストールされ localhost:3000 で起動すれば OK です

動作確認

以下のような感じで起動すれば OK です
各音声モデルジェネレータごとにタブで分かれているのでわかりやすいです

React 版は localhost:7860/ で動作しているようです

最後に

tts-generator-webui を M2 mac 上で動作させてみました
次回はこれを使って音声モデルから適当な文章を喋らせてみようと思います

参考サイト

2024年5月12日日曜日

RVC WebUI を使って音楽の BGM と声を分離する方法

RVC WebUI を使って音楽の BGM と声を分離する方法

概要

前回 RVC WebUI で音声を他の音声で推論する処理をやってみました
今回は音源に歌を準備し歌の BGM とボーカルパートを分割する方法を紹介します

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.9.18
  • RVC WebUI (updated1006v2)

準備

BGM と声を分割したい音源を準備しましょう
適当な歌で OK です
できれば一人で歌っている歌がいいかなと思います

方法

RVC WebUI を立ち上げ「Vocals/Accompaniment Separation & Reverberation Removal」を選択します

まず「Enter the path of the audio folder to be processed」に音源を配置したディレクトリを指定します
ファイルへのフルパスではなくディレクトリなので注意してください
このディレクトリ配下にファイルはすべて分割されます

次に「Model」を選択します
いろいろありますが今回は「HP3_all_vocals」を選択しました
分割の精度が悪い場合は HP2 など他のモデルで試してみてください

最後に「Convert」で分割を開始します

Success になれば完了です
分割したファイルは Retrieval-based-Voice-Conversion-WebUI-updated1006v2/opt 配下に flac 形式で保存されます
instrument_ で始まるファイルが 声のみで vocal_ から始まるファイルが BGM のみになります

最後に

RVC WebUI で音楽の BGM と声を分割してみました
おそろしく簡単にできすぎてびっくりします

参考サイト

2024年5月11日土曜日

RVC WebUI を使って音声の変換をする

RVC WebUI を使って音声の変換をする

概要

前回 安定バージョンの RVC WebUI を動かし音声データからモデルを生成するところまでやりました
今回は作成した音声モデルを使って音声の変換をしてみたいと思います

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.9.18
  • RVC WebUI (updated1006v2)

準備

音声を変換する音源を準備しましょう
何でも OK ですができれば単純な文章読み上げがいいかもしれません
自分は適当な歌を mp3 ファイルとして用意しました

声の変換

RVC WebUI を起動してアクセスします

「Model Inference」タブを選択します
そして「Inferencing voice」に前回作成した音声モデルファイル (pth) を設定します
更に音声を変換したいファイルを「Enter the path of the audio file to be processed (default is the correct format example)」にフルパスで指定します

動作確認

成功すると以下のようなログが流れて RVC WebUI 上で音声を再生できるようになります
ダウンロードも可能で audio.wav というファイル名で保存されます

2024-05-10 09:06:14 | INFO | infer.modules.vc.pipeline | Loading rmvpe model,assets/rmvpe/rmvpe.pt
2024-05-10 09:06:52 | INFO | httpx | HTTP Request: POST http://localhost:7865/api/predict "HTTP/1.1 200 OK"
2024-05-10 09:06:52 | INFO | httpx | HTTP Request: POST http://localhost:7865/reset "HTTP/1.1 200 OK"

聞いてみると学習させた音声モデルで変換されていることが確認できると思います

トラブルシューティング

ValueError: mode must be 'r', 'w', or None, got: rb 

音声を変換するファイルを指定した際にエラーになりました
av ライブラリのバージョンを下げるとうまく動作するようです

  • . ./.venv/bin/activate
  • pip install --force-reinstall -v "av==11.0.0"
  • deactivate
  • ./run.sh

参考

最後に

RVC WebUI で音声変換できるところまでやってみました
基本の流れは今回紹介した方法なのであとはモデルを生成するときのチューニングや学習させる音声データのクリーニング、分割をしてモデルの精度をあげましょう
できれば学習させる際の音声データは歌などではなく会話が良いかなと思います
そして変換/推論する際にもパラメータがいくつかあるのでこれもチューニングしましょう
推論する際は歌などでも全然 OK ですができれば推論もアカペラなど BGM がない音源を準備できると良いかなと思います

参考サイト

https://toranoana-lab.hatenablog.com/entry/2023/12/22/120000

2024年5月10日金曜日

RVC を使って自分の音声を使ってモデルを生成する方法 (リベンジ編)

RVC を使って自分の音声を使ってモデルを生成する方法 (リベンジ編)

概要

前回 最新のコミットから起動してみましたが今回はリリースの安定版を動かしてみました

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.9.18
  • RVC WebUI (updated1006v2)

事前準備

  • brew install aria2 ffmpeg

プロジェクトのダウンロード

https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/releases/tag/updated1006v2 から Retrieval-based-Voice-Conversion-WebUI-updated1006v2.tar.gz をダウンロードします

プロジェクトのセットアップ

  • tar zvxf Retrieval-based-Voice-Conversion-WebUI-updated1006v2.tar.gz
  • cd Retrieval-based-Voice-Conversion-WebUI-updated1006v2
  • pyenv local 3.9.18
  • python -m venv .venv
  • . ./.venv/bin/activate
  • pip install -r requirements.txt
  • deactivate

RVC WebUI 起動

  • ./run.sh

初回はモデルのダウンロードがあります
起動すると http://localhost:7865/ で起動します

音声の学習

前回同様です
ディレクトリがないエラーが出た場合は手動で作成します

動作確認

前回はモデル生成時にセグメンテーションエラーになり RVC WebUI が落ちる挙動があったのですがそれがなく正常に終了します

モデルは ./assets/weights/mi-test.pth に作成されます

最後に

最新のコミットではなくリリースにある安定版を使うほうが今のところは良さそうです
次回は作成できた pth モデルを使って別の音声情報と音声を交換してみたいと思います

参考サイト

2024年5月9日木曜日

RVC を使って自分の音声を使ってモデルを生成する方法

RVC を使って自分の音声を使ってモデルを生成する方法

概要

Retrieval-based-Voice-Conversion-WebUI というツールを見つけたので使ってみました
自分の音声から音声モデルを使って喋らせることができるようです

環境

  • macOS 14.4.1 (M2Pro Mac mini)
  • Python 3.8
  • RVC WebUI (fb16ba3)

起動

自動で Python3.8 がインストールされます
試しに Python 3.10 以上で試したのですがライブラリのインストールでエラーになったので3.8を使います http://localhost:7865/ で起動します

モデルのダウンロード

なぜか hubert_base.pt やらいろいろ足りていないのでモデルをダウンロードします

https://github.com/RVC-Project/RVC-Models-Downloader/releases から rvcmd_darwin_arm64.tar.gz をダウンロードします
展開し Retrieval-based-Voice-Conversion-WebUI のルートに配置します

  • tar zvxf rvcmd_darwin_arm64.tar.gz
  • mv rvcmd Retrieval-based-Voice-Conversion-WebUI
  • cd Retrieval-based-Voice-Conversion-WebUI
  • ./rvcmd assets/all

警告が出る場合は一度 Finder からクリックで起動して Open を選択することでターミナルからも実行できるようになります
実行すると必要なモデルを必要なパスに自動でダウンロードしてくれます

<

assets/hubert/hubert_base.pt がない場合は https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/hubert_base.pt こちらからダウンロードして配置してください

フォルダの作成

なぜか足りなかったので作成します

  • cd Retrieval-based-Voice-Conversion-WebUI
  • mkdir logs/mi-test/2a_f
  • mkdir logs/mi-test/2b-f0nsf

音声の準備

何でも OK です

音声の学習

パラメータはいろいろとチューニングできますが今回はデフォルトのままでいきます
まずは Train タブを選択します

UI 上にステップが記載されているのでそのステップ通りに進めます
ステップ1では名前とパラメータを設定します (基本はそのままで OK)
準備した音声ファイルを「Enter the path of the training folder」に入力し「Process data」を実行します

ステップ2の部分はそのままで OK です
あとはステップ3の「One-click training」を実行すれば OK です

これでモデルが生成できます

Segmentation fault 対策

  • cd Retrieval-based-Voice-Conversion-WebUI
  • . ./.venv/bin/active
  • pip install faiss-cpu==1.7.3

最後に

とりあえずモデルは生成できたので次回はこのモデルを使って話をさせてみます

参考サイト

2024年5月8日水曜日

Cygwin 上に pyenv をインストールする方法

Cygwin 上に pyenv をインストールする方法

概要

pyenv はインストールできました
が Python のビルドは失敗しました
メモとして残しておきます

環境

  • Windows10 22H2
  • Cygwin 3.5.3
  • pyenv 2.4.0

pyenv インストール手順

  • apt-cyg install bash curl make automake gcc-core gcc-g++ zlib zlib-devel libffi-devel
  • wget -O pyenv_install.sh https://pyenv.run
  • vim pyenv_install.sh
  • curl に -k オプションを追加
  • vim ~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

一度クローズして pyenv コマンドが使えることを確認

Python ビルド (失敗)

  • pyenv install --list
  • pyenv install 3.11.9
Downloading Python-3.11.9.tar.xz...
-> https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tar.xz
Installing Python-3.11.9...

BUILD FAILED (CYGWIN_NT-10.0-19045 3.5.3-1.x86_64 using python-build 20180424)

Inspect or clean up the working tree at /tmp/python-build.20240507170209.2270
Results logged to /tmp/python-build.20240507170209.2270.log

Last 10 log lines:
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 148, in _get_module_details
  File "<frozen runpy>", line 112, in _get_module_details
  File "/tmp/python-build.20240507170209.2270/Python-3.11.9/Lib/ensurepip/__init__.py", line 4, in <module>
    import subprocess
  File "/tmp/python-build.20240507170209.2270/Python-3.11.9/Lib/subprocess.py", line 104, in <module>
    from _posixsubprocess import fork_exec as _fork_exec
ModuleNotFoundError: No module named '_posixsubprocess'
make: *** [Makefile:1865: install] Error 1

最後に

ビルドする方法はあるのだろうか
大人しく pyenv-win を使うのがいいと思います

2024年5月7日火曜日

RQ でジョブがエラーになった際の挙動を確認する

RQ でジョブがエラーになった際の挙動を確認する

概要

ジョブ内で raise した際の挙動を確認してみました

環境

  • macOS 11.7.10
  • Python 3.11.6
  • rq 1.16.1

サンプルコード

エンキューする側のコードは以下です

from datetime import timedelta

from redis import Redis
from rq import Queue
from rq_scheduler import Scheduler

from lib.util import Message

queue = Queue("default", connection=Redis(host="192.168.1.2"))
scheduler = Scheduler(queue=queue, connection=queue.connection)


scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello")

ジョブは単純に raise するようにしています

import time


class Message:
    def say(self, **kwargs):
        print("Start say")
        print(kwargs)
        time.sleep(10)
        raise ValueError()
        # print("End say")

起動

  • pipenv run rq worker
  • pipenv run rqscheduler
  • pipenv run app.py

動作確認

failed のジョブを確認

redis 内のキーの情報を確認すると failed したジョブの情報が格納されています

1) "rq:job:2c380d9c-c65b-41b8-8d92-3b85135782c0"
2) "rq:results:2c380d9c-c65b-41b8-8d92-3b85135782c0"
3) "rq:failed:default"
4) "rq:scheduler_instance:e276ed31a4434691b91c426e979a9e4d"
5) "rq:worker:86f028648da249c38de683f8ce10f865"
6) "rq:queues"

失敗したジョブは zset としてジョブIDが格納されています

127.0.0.1:6379> zrange rq:failed:default 0 -1
1) "2c380d9c-c65b-41b8-8d92-3b85135782c0"

結果には何も格納されていませんでした

ワーカーは自動でリトライすることはなさそう

オプションを付与していない限りリトライはしないようです

なおワーカー、スケジューラを再起動しても特にリトライはしませんでした

失敗したジョブの情報を確認するスクリプト

FailedJobRegistry として管理されています
以下のスクリプトを実行すると失敗したジョブの情報を一覧で表示してくれます

from redis import Redis
from rq import Queue
from rq.job import Job
from rq.registry import FailedJobRegistry

redis = Redis()
queue = Queue(connection=redis)
registry = FailedJobRegistry(queue=queue)

# Show all failed job IDs and the exceptions they caused during runtime
for job_id in registry.get_job_ids():
    job = Job.fetch(job_id, connection=redis)
    print(job_id, job.exc_info)

最後に

rq では基本はリトライせず失敗したジョブは別途管理されるようです

参考サイト

2024年5月2日木曜日

Mac で gcloud コマンドのタブ補完を有効にする方法

Mac で gcloud コマンドのタブ補完を有効にする方法

概要

zsh の場合はを紹介します

環境

  • macOS 11.7.10
  • google-cloud-sdk 468.0.0
  • Python 3.12.2

補完を有効にする方法

  • vim ~/.zshrc
source "$(brew --prefix)/share/google-cloud-sdk/path.zsh.inc"
source "$(brew --prefix)/share/google-cloud-sdk/completion.zsh.inc"

参考

brew info google-cloud-sdk を実行するとちゃんと表示されていました
bash などの方法も記載されています

brew info google-cloud-sdk
==> google-cloud-sdk: 470.0.0 (auto_updates)
https://cloud.google.com/sdk/
/usr/local/Caskroom/google-cloud-sdk/468.0.0 (129B)
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/g/google-cloud-sdk.rb
==> Name
Google Cloud SDK
==> Description
Set of tools to manage resources and applications hosted on Google Cloud
==> Artifacts
google-cloud-sdk/install.sh (Installer)
google-cloud-sdk/bin/git-credential-gcloud.sh -> git-credential-gcloud (Binary)
google-cloud-sdk/completion.zsh.inc -> /usr/local/share/zsh/site-functions/_google_cloud_sdk (Binary)
google-cloud-sdk/bin/gsutil (Binary)
google-cloud-sdk/bin/anthoscli (Binary)
google-cloud-sdk/bin/bq (Binary)
google-cloud-sdk/completion.bash.inc -> /usr/local/etc/bash_completion.d/google-cloud-sdk (Binary)
google-cloud-sdk/bin/docker-credential-gcloud (Binary)
google-cloud-sdk/bin/gcloud (Binary)
==> Caveats
To add gcloud components to your PATH, add this to your profile:

  for bash users
    source "$(brew --prefix)/share/google-cloud-sdk/path.bash.inc"

  for zsh users
    source "$(brew --prefix)/share/google-cloud-sdk/path.zsh.inc"
    source "$(brew --prefix)/share/google-cloud-sdk/completion.zsh.inc"

  for fish users
    source "$(brew --prefix)/share/google-cloud-sdk/path.fish.inc"

==> Analytics
install: 11,433 (30 days), 32,208 (90 days), 107,295 (365 days)

最後に

これでサブコマンドなどの補完が行えます

2024年5月1日水曜日

docker kics 超入門

docker kics 超入門

概要

kicsはIaC用のセキュリティチェックツールです
Dockerfile や k8s の YAML ファイルにセキュリティ的な脆弱性や記載がないかをチェックしてくれます

今回はとりあえず動かしてみました
docker で動かします

環境

  • macOS 11.7.10
  • docker 24.0.2
  • kics 1.7.13

コマンド

  • docker run -t -v $(pwd):/path checkmarx/kics:latest scan -p /path -o "/path/"

結果確認

ターミナルにも結果が表示されますが results.json というファイルでも保存されています

  • cat results.json
{
        "kics_version": "v1.7.13",
        "files_scanned": 2,
        "lines_scanned": 10,
        "files_parsed": 2,
        "lines_parsed": 10,
        "lines_ignored": 0,
        "files_failed_to_scan": 0,
        "queries_total": 291,
        "queries_failed_to_execute": 0,
        "queries_failed_to_compute_similarity_id": 0,
        "scan_id": "console",
        "severity_counters": {
                "HIGH": 0,
                "INFO": 0,
                "LOW": 0,
                "MEDIUM": 0,
                "TRACE": 0
        },
        "total_counter": 0,
        "total_bom_resources": 0,
        "start": "2024-04-17T01:07:50.40506235Z",
        "end": "2024-04-17T01:09:50.037978163Z",
        "paths": [
                "/path"
        ],
        "queries": []
}

再帰的に実行するには

オプションではないようです
-p オプションで複数のディレクトリを指定すれば複数のディレクトリに対してスキャンしてくれるようです

  • docker run -t -v $(pwd):/path checkmarx/kics:latest scan -p /path -p /path/archive -o "/path/"

脆弱性がある場合には

例えば Dockerfile に脆弱性がある場合は以下のようなエラーが表示されます

Missing User Instruction, Severity: HIGH, Results: 1
Description: A user should be specified in the dockerfile, otherwise the image will run as root
Platform: Dockerfile
CWE: 250
Learn more about this vulnerability: https://docs.kics.io/latest/queries/dockerfile-queries/fd54f200-402c-4333-a5a4-36ef6709af2f

        [1]: ../../path/Dockerfile:1

                001: FROM ruby:3.1.2
                002: 
                003: ADD . /home



Results Summary:
HIGH: 1
MEDIUM: 5
LOW: 4
INFO: 0
TOTAL: 10

Generating Reports: Done

最後に

IaC のコードのセキュリティチェックができる kics を試してみました
使うこと自体は簡単にできそうです

Query という機能を使って簡単に脆弱性ルールを追加することもできます

参考サイト

2024年4月30日火曜日

Traefik 超入門

Traefik 超入門

概要

Traefik は Host ヘッダベースのリバースプロキシです
ルーティングのルールを細かく設定できたりパスベースのルーティングも実現できます
設定ファイルも YAML で記載できる他正規表現などのルールも作成できます
今回は docker 上で簡単に動かしてみました

環境

  • macOS 11.7.10
  • docker 24.0.2
  • traefik 3.0

まずは traefik を起動する

リバースプロキシのみ起動します
このあとでアプリをぶら下げて Host ヘッダベースでバランシングできているか確認します

  • vim docker-compose.yml
version: '3'

services:
  reverse-proxy:
    image: traefik:v3.0
    command: --api.insecure=true --providers.docker
    ports:
      # The HTTP port
      - "80:80"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
  • docker-compose up -d

で localhost:8080 にアクセスすると traefik のダッシュボードを確認できます

この段階で localhost にアクセスしてもアプリがないので 404 が返ってきます

アプリをぶら下げる

traefik の下にアプリをぶら下げる設定を追加します

  • vim docker-compose.yml
version: '3'

services:
  reverse-proxy:
    image: traefik:v3.0
    command: --api.insecure=true --providers.docker
    ports:
      # The HTTP port
      - "80:80"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
  whoami:
    # A container that exposes an API to show its IP address
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

コンテナにラベルを振ることで Host ヘッダの値に応じてバランシングしてくれます
一度 down させて再度起動します
ちなみに traefik/whoami はただのデバッグ用のアプリになります

  • docker-compose down
  • docker-compose up -d
  • docker-compose ps
NAME                         IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
python-try-reverse-proxy-1   traefik:v3.0        "/entrypoint.sh --ap…"   reverse-proxy       25 seconds ago      Up 23 seconds       0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp
python-try-whoami-1          traefik/whoami      "/whoami"                whoami              25 seconds ago      Up 23 seconds       80/tcp

これで今度は Host ヘッダを付与してアプリにアクセスしてみます
するとちゃんと whoami アプリにアクセスできていることが確認できます

  • curl -H "Host: whoami.docker.localhost" localhost
Hostname: 716c5a018b13
IP: 127.0.0.1
IP: 172.19.0.2
RemoteAddr: 172.19.0.3:57016
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/8.4.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.19.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: c8479f4b7c06
X-Real-Ip: 172.19.0.1

もう一台追加してバランシングされるか確認する

一台だと味気ないのでもう一台追加してちゃんと Host を変えたときに正しいアプリにバランシングされることを確認してみます
whoami アプリをもう一つ追加します

  • vim docker-compose.yml
version: '3'

services:
  reverse-proxy:
    image: traefik:v3.0
    command: --api.insecure=true --providers.docker
    ports:
      # The HTTP port
      - "80:80"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
  whoami:
    # A container that exposes an API to show its IP address
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
  whoami2:
    # A container that exposes an API to show its IP address
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami2.rule=Host(`whoami2.docker.localhost`)"

ラベルも whoami2 にして追加します
これで再作成してみます

  • docker-compose down
  • docker-compose up -d
  • docker-compose ps
NAME                         IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
python-try-reverse-proxy-1   traefik:v3.0        "/entrypoint.sh --ap…"   reverse-proxy       55 seconds ago      Up 54 seconds       0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp
python-try-whoami-1          traefik/whoami      "/whoami"                whoami              55 seconds ago      Up 54 seconds       80/tcp
python-try-whoami2-1         traefik/whoami      "/whoami"                whoami2             55 seconds ago      Up 54 seconds       80/tcp

そして再度 Host ヘッダを変更してアクセスすると別の whoami アプリにバランシングされていることが確認できます

  • curl -H "Host: whoami.docker.localhost" localhost
Hostname: 77c5ff6e72f4
IP: 127.0.0.1
IP: 172.21.0.4
RemoteAddr: 172.21.0.3:36418
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/8.4.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.21.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 60057b9154e0
X-Real-Ip: 172.21.0.1
  • curl -H "Host: whoami2.docker.localhost" localhost
Hostname: e6cef80986c8
IP: 127.0.0.1
IP: 172.21.0.2
RemoteAddr: 172.21.0.3:47060
GET / HTTP/1.1
Host: whoami2.docker.localhost
User-Agent: curl/8.4.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.21.0.1
X-Forwarded-Host: whoami2.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 60057b9154e0
X-Real-Ip: 172.21.0.1

最後に

Traefik を使って Host ベースのアプリバランシングをしてみました
nginx などのリバースプロキシでも Host ベースのバランシングはできますがラベルにルール付やデフォルトで管理用のダッシュボードなどは用意されていません
また定義を YAML で書けるのも便利です
違いについてはこのあたりが非常にまとまっているので興味があれば見てみてください

また今回は紹介しませんが k8s との連携も簡単にできるのも特徴です

参考サイト

2024年4月29日月曜日

Outlook のマクロでメッセージの一覧を取得する方法

Outlook のマクロでメッセージの一覧を取得する方法

概要

メッセージの件数が長いと Outlook が固まるので注意しましょう

環境

  • Windows 10
  • Outlook 2302 build 16.0

サンプルコード

Option Explicit
Public Sub Outlook_mail_list()
    ' 変数定義
    Dim InboxFolder, i, n, k As Long
    Dim outlookObj As Outlook.Application
    Dim myNameSpace, objmailItem As Object
 
    ' 変数初期化
    Set outlookObj = CreateObject("Outlook.Application")
    Set myNameSpace = outlookObj.GetNamespace("MAPI")
    Set InboxFolder = myNameSpace.GetDefaultFolder(6)
    n = 2
 
    ' 現在のメールの数を取得、数が多い場合はループの数は固定したほうが良い
    Debug.Print InboxFolder.Items.Count
    ' For i = 1 To InboxFolder.Items.Count
    For i = 1 To 100
        Set objmailItem = InboxFolder.Items(i)
 
        ' メールの内容を表示、参照可能なプロパティはこちらを参照 https://learn.microsoft.com/ja-jp/office/vba/api/outlook.mailitem.senderemailaddress
        Debug.Print i
        Debug.Print "SenderEmailAddress: " + objmailItem.SenderEmailAddress
        Debug.Print "To" + objmailItem.To
        ' Stop
        n = n + 1
    Next
 
    ' 変数の削除
    Set outlookObj = Nothing
    Set myNameSpace = Nothing
    Set InboxFolder = Nothing
End Sub

最後に

マクロでメッセージの一覧を取得して見ました
エクセルのマクロでも動作するはずです

参考サイト

2024年4月28日日曜日

Apps Script で doGet を実装して http リクエストを受け取れるようにする

Apps Script で doGet を実装して http リクエストを受け取れるようにする

概要

Google Apps Script にはウェブアプリとしてデプロイできる機能がありこれを使うことで Apps Script の特定の関数を curl からコールできるようになります
今回はその方法を紹介します

環境

  • Google Apps Script (2024/04/22 時点)

doGet の実装

function doGet(e) {
  var params = JSON.stringify(e);
  return ContentService.createTextOutput(params).setMimeType(ContentService.MimeType.JSON);
}

アプリのデプロイ

curl で実行する場合には全公開する必要があります

ウェブアプリの URL が発行されるのでメモしておきます

動作確認

リダイレクトがあるので curl の場合は -L を付与します

  • curl -L "https://script.google.com/macros/s/xxxxxx/exec"
{"contextPath":"","parameter":{},"parameters":{},"contentLength":-1,"queryString":""}

クエリストリングも送れます

  • curl -L "https://script.google.com/macros/s/xxxxxx/exec?name=hawksnowlog"
{"contentLength":-1,"parameters":{"name":["hawksnowlog"]},"queryString":"name=hawksnowlog","parameter":{"name":"hawksnowlog"},"contextPath":""}

最後に

AppsScript で定義した関数を外部からコールできるようにしてみました
ショートカットにしておけばアクセスするだけで特定のデータを抽出したりできます

自分しかアクセスできないウェブアプリの場合はブラウザでしかアクセスできないので注意しましょう

参考サイト

2024年4月26日金曜日

RQ のジョブのタイムアウトについて調査した

RQ のジョブのタイムアウトについて調査した

概要

RQ のジョブにはタイムアウトが設定されておりデフォルトでは 180 秒のようです
このタイムアウトは単純にワーカーが実行しているジョブが 180 秒経過しても終了しない場合には強制的にジョブを終了させる設定になります

環境

  • macOS 11.7.10
  • Python 3.11.6
  • rq 1.16.1

挙動を確認するためのスクリプト

ジョブは 190 秒待つようにします
初回はエンキュー時にタイムアウトなしでエンキューして本当にタイムアウトが発生するか確認します

  • vim lib/utils.py
import time


class Message:
    def say(self, **kwargs):
        print("Start say")
        print(kwargs)
        time.sleep(190)
        print("End say")
  • vim app.py
from datetime import timedelta

from redis import Redis
from rq import Queue
from rq_scheduler import Scheduler

from lib.util import Message

queue = Queue("default", connection=Redis(host="192.168.1.2"))
scheduler = Scheduler(queue=queue, connection=queue.connection)


scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello")
# scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello", timeout=3000)

実行

  • pipenv run rq worker
  • pipenv run rqscheduler
  • pipenv run app.py

ログ

実際に実行するとジョブの終了時に表示されるメッセージが表示されずに 180 経過してジョブが矯正終了していることがわかります
なお JobTimeoutException で終了したジョブはリトライなどはされませんでした

08:39:14 default: say(msg='hello') (c97f39f8-c197-43ac-828f-245d78ef78f0)
Start say
{'msg': 'hello'}
08:42:14 [Job c97f39f8-c197-43ac-828f-245d78ef78f0]: exception raised while executing (say)
Traceback (most recent call last):
  File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/worker.py", line 1431, in perform_job
    rv = job.perform()
         ^^^^^^^^^^^^^
  File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/job.py", line 1280, in perform
    self._result = self._execute()
                   ^^^^^^^^^^^^^^^
  File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/job.py", line 1317, in _execute
    result = self.func(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/data/repo/python-try/lib/util.py", line 8, in say
    time.sleep(190)
  File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/timeouts.py", line 63, in handle_death_penalty
    raise self._exception('Task exceeded maximum timeout value ({0} seconds)'.format(self._timeout))
rq.timeouts.JobTimeoutException: Task exceeded maximum timeout value (180 seconds)

timeout=3000 にして再度試す

コメントにしていた部分を変更して再度エンキューしてみます
今度はジョブのタイムアウトを 3000 秒にしてエンキューします

すると先ほどタイムアウトしたジョブがタイムアウトせずにちゃんと最後まで実行されることが確認できました

08:52:14 default: say(msg='hello') (91aab157-25a5-44b9-898b-4da6dcb3baff)
Start say
{'msg': 'hello'}
End say
08:55:24 default: Job OK (91aab157-25a5-44b9-898b-4da6dcb3baff)
08:55:24 Result is kept for 500 seconds

最後に

ジョブの実行時間が長くなりそうな場合にはエンキュー時に timeout を設定してあげましょう

参考サイト

2024年4月25日木曜日

RQ のシグナルハンドリングについて調べてみる

RQ のシグナルハンドリングについて調べてみる

概要

RQ でプロセスハンドリングの挙動を確認してみました

環境

  • macOS 11.7.10
  • Python 3.11.6
  • rq 1.16.1

サンプルコード

  • vim app.py
from datetime import timedelta

from redis import Redis
from rq import Queue
from rq_scheduler import Scheduler

from lib.util import Message

queue = Queue("default", connection=Redis(host="192.168.1.2"))
scheduler = Scheduler(queue=queue, connection=queue.connection)


scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello")
  • vim lib/util.py
import time


class Message:
    def say(self, **kwargs):
        print("Start say")
        time.sleep(30)
        print(kwargs)
  • pipenv run rq worker
  • pipenv run rqscheduler
  • pipenv run python app.py

10秒以内にワーカーを Ctrl+c で停止した場合

ワーカーがジョブを掴んでからワーカーのプロセスを停止しようとするとちゃんと最後まで処理が終了してからワーカーが停止しました

11:21:53 default: say(msg='hello') (4d5a4db9-e8c9-4ee3-b64c-1dd266e66068)
Start say
11:21:55 Worker 98f9aac6f73445f685d4f5588abd514f [PID 32100]: warm shut down requested
{'msg': 'hello'}
11:22:03 default: Job OK (4d5a4db9-e8c9-4ee3-b64c-1dd266e66068)
11:22:03 Result is kept for 500 seconds
11:22:03 Worker rq:worker:98f9aac6f73445f685d4f5588abd514f: stopping on request
11:22:03 Unsubscribing from channel rq:pubsub:98f9aac6f73445f685d4f5588abd514f

kill -9 した場合

ワーカーがジョブを実行中に kill -9 を送信してみました
その場合ワーカーは Warm shut down せずにすぐに終了してしまいます

12:05:54 default: say(msg='hello') (b4eac96d-9591-482c-9753-e3a9c150d83b)
Start say
zsh: killed     pipenv run rq worker

redis 外部からアクセスできない場合

Protection mode が有効になっているので一旦無効にしましょう

  • CONFIG SET protected-mode no

docker の場合

docker stop はデフォルトでは SIGTERM -> SIGKILL の順番で信号を送ります
SIGKILL までの時間は time というオプションで変更可能でデフォルトで10秒になります

ワーカーを docker 上で動かし docker stop した際のワーカーの挙動を確認します

  • vim Dockerfile
FROM python:3.11.9-bullseye

COPY . /home
WORKDIR /home

RUN pip install pipenv
RUN pipenv install

CMD ["pipenv", "run", "rq", "worker", "--url", "redis://192.168.1.2:6379"]
  • docker build -t worker .
  • docker create --name worker worker
  • docker start worker
  • docker logs -f worker

でワーカーを起動します
スケジューラとエンキューは python から行います

  • pipenv run rqscheduler
  • pipenv run python app.py

これでワーカーがジョブを実行中にワーカーコンテナを停止します

  • docker stop worker
03:28:54 default: say(msg='hello') (76dbdc1b-5af2-4fa1-b4d2-49793454b235)
03:28:57 Worker 15c934ce3084457da63ade0e89ea14b6 [PID 1]: warm shut down requested

SIGTERM を受取り Warm shut down がスタートしますが10秒後に docker が強制的に SIGKILL を送信するためワーカーはジョブの完了を待たずに終了してしました

また強制終了したジョブは FailedJobRegistry に移動するようです

StartedJobRegistry cleanup: Moving job to FailedJobRegistry (due to AbandonedJobError)

time=60 にしてみる

SITTERM -> SIGKILL の送信にかかる時間を 60 秒に伸ばしてみます

  • docker stop --time=60 worker

すると今度はちゃんとワーカーがジョブの終了を待ってから停止していることが確認できました

03:32:54 default: say(msg='hello') (8e04f278-c5b1-4c4a-9069-3105960129f4)
03:33:14 Worker faa70ceee374410ba9416f55d74f4927 [PID 1]: warm shut down requested
Start say
{'msg': 'hello'}
03:33:25 default: Job OK (8e04f278-c5b1-4c4a-9069-3105960129f4)
03:33:25 Result is kept for 500 seconds
03:33:25 Worker rq:worker:faa70ceee374410ba9416f55d74f4927: stopping on request
03:33:25 Unsubscribing from channel rq:pubsub:faa70ceee374410ba9416f55d74f4927

最後に

RQ のシグナルハンドリングについて調べてみました
基本は RQ 側で実装されているので気にすることはないですが docker などと組み合わせる場合には SIGKILL の送信タイミングについて考慮する必要がありそうです

2024年4月24日水曜日

WSL2 で OneDrive をマウントする方法

WSL2 で OneDrive をマウントする方法

概要

特に設定は不要でした

環境

  • Windows10 22H2
  • WSL2 (Ubuntu22.04)

OneDrive アプリのインストールと設定

Windows 上に OneDrive アプリをインストールしましょう
あとはログインすれば OK です

WSL2 側での設定は特に不要

WSL2 は Windows の領域をデフォルトで参照できます
/mnt/c から参照できます
OneDrive のディレクトリをデフォルトのままにしているのであれば /mnt/c/Users/username/OneDrive でアクセスできます

最後に

OneDrive WSL2 ではすでにマウントされているので設定は不要です

参考サイト

2024年4月23日火曜日

WSL2 の Ubuntu に ssh する方法

WSL2 の Ubuntu に ssh する方法

概要

最近の WSL2 であれば特に何も考えずにデフォルトの設定のままできるようです

環境

  • Windows10 22H2
  • WSL2 (Ubuntu22.04)

openssh-server のインストール

  • sudo apt -y update
  • sudo apt -y install openssh-server

自動起動をONにする

  • sudo systemctl status ssh

動作確認

  • ssh devops@localhost

これが一番のポイントかもしれませんが localhost にアクセスします
WSL2 は localhost にバインドするので vEthernet (WSL) で払い出される IP ではなく localhost にアクセスします

パスワード WSL 初回起動時に設定したパスワードを使用します

最後に

デフォルトの WSL2 のターミナルは Windows コンソールのターミナルなのでキーバインドなどが微妙です
使い慣れたターミナルを使いたい場合には ssh を使いましょう

また ssh にするには当然 WSL を起動しておく必要があるので注意しましょう
Windows コンソールが不要な場合は「wsl」コマンドを実行するだけでも起動させることができます

2024年4月22日月曜日

Python Slack SDK でスレッドとして返信する方法

Python Slack SDK でスレッドとして返信する方法

概要

chat_postMessage で thread_ts を指定します

環境

  • macOS 11.7.10
  • Python 3.11.6
  • slack-sdk 3.27.1

サンプルコード

from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token="xoxb-xxxxxx")
channel_id = "C0123456789"

try:
    # 会話情報の取得、最新100件
    result = client.conversations_history(channel=channel_id)
    conversation_history = result["messages"]
    # とりあえず最新のメッセージのスレッドに返信する
    ts = result["messages"][0]["ts"]
    # thread_tsを指定することでスレッド返信になる
    response = client.chat_postMessage(
        channel="#private",
        text="Hello world!",
        thread_ts=ts,
        # アイコンやユーザ名をカスタムする場合は以下を設定する
        username="hawksnowlog",
        icon_url="https://pbs.twimg.com/profile_images/712848447569661952/ayfI9-77_400x400.jpg",
    )
except SlackApiError as e:
    print(e)

最後に

as_user オプションは廃止されているので使えません
代わりに username と icon_url を使いますが APP というタグは必ず付与されてしまうようで完全にユーザになり変わって投稿することはできないようです

参考サイト

2024年4月19日金曜日

Ubuntu にインストールされているパッケージの脆弱性チェックをしてみる (OpenScap編)

Ubuntu にインストールサれているパッケージの脆弱性チェックをしてみる (OpenScap編)

概要

Ubuntu 上にインストールされているパッケージの脆弱性をチェックするのに OpenScap というツールを使ってみました
インストールから実際に脆弱性をチェックする方法まで紹介します

環境

  • Ubuntu 22.04
  • oscap 1.2.17

インストール

  • sudo apt -y install libopenscap8

jammy では 1.3 はインストールされないようです

脆弱性定義のダウンロード

OVAL (Open Vulnerability and Assessment Language) 形式の脆弱性定義ファイルをダウンロードします

OpenScap は OVAL 形式のファイルをサポートしているのでこの定義ファイルを元にマシン上にあるパッケージのバージョンと比較して脆弱性があるかどうかチェックします

  • wget https://security-metadata.canonical.com/oval/com.ubuntu.$(lsb_release -cs).usn.oval.xml.bz2
  • bunzip2 com.ubuntu.$(lsb_release -cs).usn.oval.xml.bz2

スキャン実行

結果は html に保存されます

  • oscap oval eval --report report.html com.ubuntu.$(lsb_release -cs).usn.oval.xml
Definition oval:com.ubuntu.jammy:def:52051000000: false
Definition oval:com.ubuntu.jammy:def:51821000000: false
Definition oval:com.ubuntu.jammy:def:51811000000: false
Definition oval:com.ubuntu.jammy:def:1021000000: false
Definition oval:com.ubuntu.jammy:def:1011000000: false
Definition oval:com.ubuntu.jammy:def:1001000000: false
Definition oval:com.ubuntu.jammy:def:100: true
Evaluation done.

上記のようなログが流れ最後に done となれば完了です

html ファイルの確認

方法は何でも OK です

  • mv report.html /var/www/html
  • curl localhost/report.html

以下のような感じで表示されます
オレンジっぽくなっている部分が脆弱性未対応のパッケージを使っている部分になります

対象の使用しているパッケージは一番右の欄を見るか CVE のリンク先に詳細な情報があるのでそこを見るしかありません

最後に

OpenScap と公開されている脆弱性情報ファイルを使ってローカルマシン上のパッケージの脆弱性チェックをしてみました

基本は apt upgrade で対応することになりますが Ubuntu Pro でのみ公開されているパッチもあるのでその場合は手動でパッチを当てるか対象のパッケージを削除するかしかないかなと思います

参考サイト

2024年4月18日木曜日

Windows の WSL2 でてっとり早くインターネットに接続する方法

Windows の WSL2 でてっとり早くインターネットに接続する方法

概要

WSL2 はデフォルトだと NAT 接続になります
またネットワークアダプタは WSL2 専用のネットワークアダプタになるため例えば複数のネットワークアダプタがあり通常作業は別のネットワークアダプタから通信する場合には全くインターネットに接続できなくなります

ネット上の記事だと DNS の接続を変更したりプロキシの設定を変更したりすれば何とかなる記事が多くありますがそもそもネットワークが別で普段使っているネットワークに疎通できないのであれば普段使っている DNS やプロキシへもそもそもアクセスできないので意味がありません

今回はそんなときに簡単に WSL2 からインターネットにアクセスすることができる設定を紹介します

環境

  • WSL2 (Ubuntu 22.04)
  • Windows10 22H2

解決方法: ネットワークアダプタの共有設定を使う

Windows のネットワークアダプタには他のネットワークアダプタからの通信を共有する機能があります
これを使用することで普段使っているネットワークアダプタに対して WSL2 で作成されたネットワークアダプタからの通信を許可することでインターネットに接続できるようにします

まずはネットワークアダプタの設定から行います
普段使っているネットワークアダプタのプロパティを開き「共有」を選択します
するとネットワークを共有するアダプタを選択する画面になるので WSL2 が作成した「vEthernet (WSL)」を選択します

ちなみに自分の通常のネットワークは Wi-Fi アダプタになるので Wi-Fi アダプタに対して共有を設定を行っています

vEthernet (WSL) は以下のような表示です

WSL 側の設定

ネットワークを共有すると vEthernet (WSL) の IP アドレス帯が変わります
なのでこの IP を WSL (Ubuntu) に設定してあげます

  • sudo ip addr add 192.168.137.10/24 dev eth0
  • sudo ip route delete default
  • sudo ip route add default via 192.168.137.1

既存のネットワークに 192.168.137.10 という IP を付与しデフォルトゲートウェイを 192.168.137.1 にしているだけです
おそらくネットワーク共有すると同じ IP 帯になるはずなのでそのままコピペして Ubuntu で実行すれば OK です

DNS の設定

WSL2 の場合デフォルトだと vEthernet (WSL) の共有前のアドレスが DNS に設定されています
これはもう使わないので外部の DNS を使います

  • vim /etc/resolv.conf
nameserver 8.8.8.8

動作確認

これで apt update などもできるようになります

この構成の問題点

今回共有したネットワークは本当に普段使っているネットワークで自宅のマシンやスマホ、Chromecast などが存在しているネットワークになります
自宅のホームルータを抜けてインターネットに接続する経路になります

もしその経路ではなく VPN などを張っていて職場やプライベートな環境に WSL2 から通信したい場合にはこの方法ではできません
なぜなら共有しているネットワークアダプタが VPN 用のネットワークではなくただの自宅ネットワークだからです

もし WSL2 から VPN の経路も使いたい場合には VPN 用のネットワークアダプタにも vEthernet (WSL) からのアクセスを許可してあげれば OK です
ただその場合には外部に出るネットワークと VPN に行くネットワークの2つになるので適切に経路を設定してあげないとうまく動作しないので注意しましょう

Windows のネットワーク共有は1つのアダプタに対してのみから行えないようなのでどちらか一方のネットワークを使うしかないようです

最後に

WSL2 でプロキシなどの設定をせずにインターネットに接続する方法を紹介しました

インターネット以外のネットワークにも接続したい場合には更に工夫が必要なので注意しましょう
WSL2 にはブリッジ接続もあるようなのですそれを試すのもありかもしれません
また今回は無線だったのでネットワーク共有を使いましたが有線ネットワークだと今回の共有設定などはしなくても動くかもしれません

参考サイト

2024年4月17日水曜日

個人でUbuntu Proに申し込む方法

個人でUbuntu Proに申し込む方法

概要

Ubuntu Pro は Ubuntu の商用ライセンスです
ESM (Extended Security Maintenance) パッケージの提供などをしておりよりセキュアな Ubuntu を使うことができます
今回は個人で Ubuntu Pro を登録し Ubuntu に ESM パッケージをインストールしてみました

環境

  • Ubuntu 22.04

登録

まず https://ubuntu.com/pro/subscribe にアクセスします
個人であれば5台までは無料で使えるようです

Ubuntu One のアカウントが必要なのでなければ作成しましょう
すでにあればログインします

トークンの確認

Ubuntu Pro に登録するとサブスクリプションの画面で以下のようなトークン情報が表示されます
コマンドでも登録できるので確認しましょう

Ubuntu を登録する

先ほどのコマンドを Ubuntu 上で実行してみましょう

  • sudo pro attach xxxx
Enabling default service esm-apps
Updating Ubuntu Pro: ESM Apps package lists
Ubuntu Pro: ESM Apps enabled
Enabling default service esm-infra
Updating Ubuntu Pro: ESM Infra package lists
Ubuntu Pro: ESM Infra enabled
Enabling default service livepatch
Installing canonical-livepatch snap
Canonical Livepatch enabled
This machine is now attached to 'Ubuntu Pro - free personal subscription'

SERVICE          ENTITLED  STATUS       DESCRIPTION
anbox-cloud      yes       disabled     Scalable Android in the cloud
esm-apps         yes       enabled      Expanded Security Maintenance for Applications
esm-infra        yes       enabled      Expanded Security Maintenance for Infrastructure
fips-preview     yes       disabled     Preview of FIPS crypto packages undergoing certification with NIST
fips-updates     yes       disabled     FIPS compliant crypto packages with stable security updates
livepatch        yes       enabled      Canonical Livepatch service
realtime-kernel* yes       disabled     Ubuntu kernel with PREEMPT_RT patches integrated
usg              yes       disabled     Security compliance and audit tools

 * Service has variants

NOTICES
Operation in progress: pro attach

For a list of all Ubuntu Pro services and variants, run 'pro status --all'
Enable services with: pro enable <service>

     Account: xxxxx@mail.com
Subscription: Ubuntu Pro - free personal subscription

登録が成功するとサブスクリプション画面の「Active machines」が増えていることが確認できると思います

動作確認

ESM バージョンのパッケージがインストールできるか確認してみます
今回は graphviz に ESM パッケージがあるのでこれがインストールされるか確認します (参考)

インストール前は以下のような状態です

dpkg -l | grep 'graphviz'
ii  libgraphviz-dev:amd64                  2.42.2-6                                amd64        graphviz libs and headers against which to build applications

まずは apt update します
update すると esm のリポジトリが追加されていることが確認できます

  • sudo apt -y update
Hit:1 https://aquasecurity.github.io/trivy-repo/deb jammy InRelease
Hit:2 https://download.docker.com/linux/ubuntu jammy InRelease
Hit:3 https://esm.ubuntu.com/apps/ubuntu jammy-apps-security InRelease
Hit:4 https://esm.ubuntu.com/apps/ubuntu jammy-apps-updates InRelease
Hit:5 https://esm.ubuntu.com/infra/ubuntu jammy-infra-security InRelease
Hit:6 https://esm.ubuntu.com/infra/ubuntu jammy-infra-updates InRelease
Hit:7 https://ppa.launchpadcontent.net/ansible/ansible/ubuntu jammy InRelease
Hit:8 https://ppa.launchpadcontent.net/git-core/ppa/ubuntu jammy InRelease
Hit:9 http://jp.archive.ubuntu.com/ubuntu jammy InRelease
Get:10 http://jp.archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Hit:11 http://jp.archive.ubuntu.com/ubuntu jammy-backports InRelease
Get:12 http://jp.archive.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:13 http://jp.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [1,558 kB]
Get:14 http://jp.archive.ubuntu.com/ubuntu jammy-updates/restricted amd64 Packages [1,699 kB]
Get:15 http://jp.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [1,060 kB]
Fetched 4,547 kB in 7s (635 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
12 packages can be upgraded. Run 'apt list --upgradable' to see them.

ではパッケージを更新してみます
更新が始まるので終了するまで待ちます

  • sudo apt -y upgrade

そして再度 graphviz のパッケージを確認すると ESM バージョンのパッケージに更新されていることが確認できます
これにより CVE 対応されたパッケージが使えるようになります

dpkg -l | grep 'graphviz'
ii  libgraphviz-dev:amd64                  2.42.2-6ubuntu0.1~esm1                  amd64        graphviz libs and headers against which to build applications

最後に

個人で Ubuntu Pro に申し込み ESM バージョンのパッケージをインストールしてみました
CVE 対応などの脆弱性緊急対応版のパッケージは結構 ESM として公開されることが多い印象です
5台までなら無料で使えるので登録しておいて損はないかなと思います

参考サイト