20210613のGoに関する記事は5件です。

Markdownのフォーマットからtreeコマンド結果を出力できるCLI

どんなCLI? 掲題通りです。このCLIを使った様子を以下に載せます。 12:24:56 > gentree -ts << EOS - root - parent_a - parent_b - child_a - 1 - 2 - a - 1 - child_b - 1 - a - parent_c - child_a - parent_d EOS root ├── parent_a ├── parent_b │ ├── child_a │ │ ├── 1 │ │ └── 2 │ │ └── a │ │ └── 1 │ └── child_b │ └── 1 │ └── a ├── parent_c │ └── child_a └── parent_d このように、Markdown形式の入力をgentreeコマンドに渡すことで、treeコマンド結果が出力されます。 gentreeのコードはこちらにあります。また、インストール方法・詳しい使い方についてはリンク先のREADME.mdに記載しています。 treeコマンドで出力される結果が欲しいけど、ディレクトリ・ファイルが存在せず、手作業で木構造を作らないといけない、といった場合に役に立つかと思います。 ちなみに、一時的にディレクトリ・ファイルを作成するといったことはしていません。 あと、個人的にディレクトリ階層を表現する以外にも使えるのではないかなと思っています。 最後に、gentreeはCLIとして提供していますが、Packageとしても提供しています。 是非使ってみてください?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[自動化] サブドメインの監視・報告システムを作ってみた。

Webアプリを監視し、新しいサブドメインが見つかると報告してくれるシステムを作ってみました。 ほぼHaklukeさんのyoutube動画の内容です。こっち見た方がいいかも 5 Minutes to Build a Basic Monitoring and Alerting System for New Subdomains 利用するツール オープンソースのツール3種類を使います。 - Anew (Tomnomnomさん) - Haktrails (Haklukeさん) - Notify (ProjectDiscovery) 環境設定 環境設定をしていきます。 VPSの設定 ここではDigitalOceanを使っていきます。 OSにはUbuntuを設定しました。 各種ツールのインストール 各種ツールを利用するためにGolangをインストールします。 sudo apt update && sudo apt install golang SSHで回線が切れたときのためにTmuxをインストールします。 apt install tmux オープンソースの各種ツールをインストールします。 GO111MODULE=on go get -v github.com/projectdiscovery/notify/cmd/notify go get -u github.com/hakluke/haktrails go get -u github.com/tomnomnom/anew GOBINに$PATHをとおす。 毎回~/go/bin/haktrailsと打つのはめんどくさいのでGOBINに$PATHを通します。 まず~/.bashrcにexport PATH="$PATH:~/go/bin/"を追加します。 そしてターミナルを再起動後、source ~/.bashrcと打ちます。 Configファイルを設定する。 SecurityTrails API keyを取得します。 haktrails-config.ymlファイルの<yourkey>を取得したkeyに書き換えます。 ~/.config/haktools/haktrails-config.yml securitytrails: key: <yourkey> notify.confにアラートをとばしたいdiscord_webhook_urlを入力します。 ~/.config/notify/notify.conf discord: true discord_webhook_url: https://a.b.c discord_username: test サブドメインの収集 サブドメインを収集するコマンドは以下のようになります。 Tomnomnomさんのanewツールを使用しています。 echo <ターゲットのURL> | haktrails subdomains | tee subdomains.txt 監視ツールの作成 常時ターゲットURLの監視を行うスクリプトを作ります。 monitor.sh while : do echo securitytrails.com | haktrails subdomains | tee subdomains.txt sleep 3600 done 実行権限を付与した後、実行可能となります。 chmod +x ./monitor.sh Run ./monitor.sh 新しいサブドメインだけ収集するようできるようにする。 新しいサブドメイン情報だけを取得したい。 そういった場合はteeをTomnomnomさんのanewツールに書き換えます。 monitor.sh while : do echo securitytrails.com | haktrails subdomains | anew subdomains.txt sleep 3600 done アラートを送る 実行結果をDiscordにとばすためにnotifyツールを使います。 ./monitor.sh | notify
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Tips: Hugoで静的サイト構築

各種静的サイト構築を試す遊びに興じてしまいそれぞれをメモしている。 3000文字Tips - 知ると便利なTipsをみんなへ届けよう にあやかりHugoで静的サイト構築までを書きます。 環境: Microsoft Windows 10 Home 公式 Install githubのHugoで https://github.com/spf13/hugo/releases よりwindowsの64bitバージョンを選び、 C:\hugo_0.83.1_Windows-64bit に置いた。 Hugoのbinフォルダを作りexeを配置。パスを通す。 C:\hugo_0.83.1_Windows-64bit\bin\hugo.exe set path=%path%;C:\hugo_0.83.1_Windows-64bit\bin; hugo help などが使えることを確認。 Hugoの初期フォルダを作る。ここでは blog-hugo。 cd C:\git\blog-hugo hugo new site <サイト名> でサイトが作れる。 C:\git\blog-hugo>hugo new site InitialSites Congratulations! Your new Hugo site is created in C:\git\blog-hugo\InitialSites. Just a few more steps and you're ready to go: 1. Download a theme into the same-named folder. Choose a theme from https://themes.gohugo.io/ or create your own with the "hugo new theme <THEMENAME>" command. 2. Perhaps you want to add some content. You can add single files with "hugo new <SECTIONNAME>\<FILENAME>.<FORMAT>". 3. Start the built-in live server via "hugo server". Visit https://gohugo.io/ for quickstart guide and full documentation. Theme テーマをインストール。今回は github-style にした。 cd InitialSites mkdir themes cd themes git clone https://github.com/MeiK2333/github-style C:\git\blog-hugo\InitialSites>hugo new readme.md C:\git\blog-hugo\InitialSites\content\readme.md created 起動 cd .. InitialSitesに戻り、以下で起動してみる。 hugo server -t github-style -D -w https://localhost:1313/ サイトプレビュー停止には中断コマンドの Ctrl+C config.toml の設定 config.toml baseURL = "https://e99h2121.github.io/blog-hugo/" publishDir = "docs" languageCode = "ja-ja" title = "e99h2121's New Hugo Site" theme = "github-style" googleAnalytics = "UA-1234567890" pygmentsCodeFences = true pygmentsUseClasses = true [params] author = "yamada_n" description = "" github = "e99h2121" twitter = "e99h2121" url = "https://e99h2121.github.io/" rss = true lastmod = true location = "Japan" [[params.links]] title = "Link" href = "https://e99h2121.github.io/" [frontmatter] lastmod = ["lastmod", ":fileModTime", ":default"] 記事を書く hugo -t github-style で公開ファイルを生成。 cd C:\git\blog-hugo-src\InitialSites 例: hugo new post/newpost202106091417.md C:\git\blog-hugo-src\InitialSites>hugo new post/newpost202106091417.md C:\git\blog-hugo-src\InitialSites\content\post\newpost202106091417.md created hugo server -t github-style -D -w で動作確認。 hugo -t github-style で生成。 config.toml publishDir = "docs" と、config.toml に設定することで、docs 以下を GitHubPages化しているリポジトリにコピーすればまずは手動公開できる。 https://github.com/<ユーザー名>/<リポジトリ名>/tree/main/docs 参考 静的サイトは群雄割拠ですね。色々比較軸があります。 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ログの一部をマスクする

ログの一部をマスクしたい。 例えば ログの一部にパスワードが書かれているとき などに 別の文字に置き換えておきたい(マスクしたい)ときがあります。 変更前 [LOG] ID : hiro [LOG] PASS: password [LOG] exec: hoge.exe --id hiro --pass password ↓ マスクする 変更後 [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** そんなときは io.Writer をラップしたものを作るのがお手軽です。 また io.Writer 準拠で作っておくと 汎用性がある・テストしやすい のでオススメです。 io.Writer は interface です。 なので以下の 指定されたメソッドを実装してあげる 必要があります。 type Writer interface { Write(p []byte) (n int, err error) } https://golang.org/pkg/io/#Writer ということでサクッと作ります。 実装 今回は マスクしたい文字列 を貯めておく実装にしてみました。 mask.go package main import ( "io" "strings" ) // MaskWriter : マスク用のWriter type MaskWriter struct { writer io.Writer // マスクした後に書き込む先 keywords []string // マスク対象の文字列 maskString string // 置き替える文字 } // NewMaskWriter : マスク用のWriterを作成する func NewMaskWriter(w io.Writer) MaskWriter { m := MaskWriter{ writer: w, keywords: []string{}, maskString: "********", } return m } // AddMaskWord: マスク対象の文字列を追加する func (m *MaskWriter) AddMaskWord(word string) { m.keywords = append(m.keywords, word) } // Write : 出力処理 func (m *MaskWriter) Write(p []byte) (n int, err error) { // 置換用のリストを作成する replaceList := []string{} for _, word := range m.keywords { // list = append(list, マスク対象の文字列, 置き換える文字) replaceList = append(replaceList, word, m.maskString) } replacer := strings.NewReplacer(replaceList...) // 文字を置換して書き込む return m.writer.Write([]byte(replacer.Replace(string(p)))) } 上の実装だと、 マスクしたくない場所に同じ文字列があったときにもマスクされてしまうので そういうケースがある場合はもう少し工夫が必要です。 念のためにテストも。 bytes.Buffer を使えばオンメモリでテストできます。 mask_test.go package main import ( "bytes" "testing" ) func TestMaskWriter(t *testing.T) { tests := []struct { name string input string mask []string output string wantErr bool }{ { name: `mask (1 word)`, input: `hogefugapiyo`, mask: []string{`fuga`}, output: `hoge********piyo`, wantErr: false, }, { name: `mask (2 words)`, input: `hogefugapiyo`, mask: []string{`fuga`, `piyo`}, output: `hoge****************`, wantErr: false, }, { name: `mask (multiline)`, input: "hoge\nfugapiyo", mask: []string{`fuga`}, output: "hoge\n********piyo", wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := &bytes.Buffer{} ml := NewMaskWriter(got) for _, w := range tt.mask { ml.AddMaskWord(w) } _, err := ml.Write([]byte(tt.input)) if (err != nil) != tt.wantErr { t.Errorf("MaskWriter.Write() error = %v, wantErr %v", err, tt.wantErr) return } if got.String() != tt.output { t.Errorf("MaskWriter.Write() = %v, want %v", got.String(), tt.output) } }) } } あとは先ほど作ったものを使うだけ。 main.go package main import ( "log" "os" ) func main() { id := `hiro` pass := `password` // ログファイル logFile, err := os.Create(`output.log`) if err != nil { log.Fatal(err) } defer logFile.Close() // マスク用Writerに変更 maskLogFile := NewMaskWriter(logFile) maskLogFile.AddMaskWord(pass) // ログ出力先設定 log.SetOutput(&maskLogFile) // フォーマット設定 log.SetPrefix(`[LOG] `) log.SetFlags(0) // 出力 log.Printf(`ID : %s`, id) log.Printf(`PASS: %s`, pass) log.Printf(`exec: hoge.exe --id %s --pass %s`, id, pass) } output.log [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** できました。 出力をわける 標準出力されるログは マスクしない で ログファイルだけマスクする 場合は、 io.MultiWriter() を使って まとめたWriter を使えばシンプルなコードにできます。 main.go package main import ( "io" "log" "os" ) func main() { id := `hiro` pass := `password` // ログファイル logFile, err := os.Create(`output.log`) if err != nil { log.Fatal(err) } defer logFile.Close() // マスク用Writerに変更 maskLogFile := NewMaskWriter(logFile) maskLogFile.AddMaskWord(pass) // 両方に出力する mw := io.MultiWriter(os.Stdout, &maskLogFile) // ログ出力先設定 log.SetOutput(mw) // フォーマット設定 log.SetPrefix(`[LOG] `) log.SetFlags(0) // 出力 log.Printf(`ID : %s`, id) log.Printf(`PASS: %s`, pass) log.Printf(`exec: hoge.exe --id %s --pass %s`, id, pass) } 標準出力 [LOG] ID : hiro [LOG] PASS: password [LOG] exec: hoge.exe --id hiro --pass password output.log [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** ね、簡単でしょう?(ボブ・ロス)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go ログの一部をマスクする

Go言語でログの一部をマスクしたい。 例えば ログの一部にパスワードが書かれているとき などに 別の文字に置き換えておきたい(マスクしたい)ときがあります。 変更前 [LOG] ID : hiro [LOG] PASS: password [LOG] exec: hoge.exe --id hiro --pass password ↓ マスクする 変更後 [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** そんなときは io.Writer をラップしたものを作るのがお手軽です。 また io.Writer 準拠で作っておくと 汎用性がある・テストしやすい のでオススメです。 io.Writer は interface です。 なので以下の 指定されたメソッドを実装してあげる 必要があります。 type Writer interface { Write(p []byte) (n int, err error) } https://golang.org/pkg/io/#Writer ということでサクッと作ります。 実装 今回は マスクしたい文字列 を貯めておく実装にしてみました。 mask.go package main import ( "io" "strings" ) // MaskWriter : マスク用のWriter type MaskWriter struct { writer io.Writer // マスクした後に書き込む先 keywords []string // マスク対象の文字列 maskString string // 置き替える文字 } // NewMaskWriter : マスク用のWriterを作成する func NewMaskWriter(w io.Writer) MaskWriter { m := MaskWriter{ writer: w, keywords: []string{}, maskString: "********", } return m } // AddMaskWord: マスク対象の文字列を追加する func (m *MaskWriter) AddMaskWord(word string) { m.keywords = append(m.keywords, word) } // Write : 出力処理 func (m *MaskWriter) Write(p []byte) (n int, err error) { // 置換用のリストを作成する replaceList := []string{} for _, word := range m.keywords { // list = append(list, マスク対象の文字列, 置き換える文字) replaceList = append(replaceList, word, m.maskString) } replacer := strings.NewReplacer(replaceList...) // 文字を置換して書き込む return m.writer.Write([]byte(replacer.Replace(string(p)))) } 上の実装だと、 マスクしたくない場所に同じ文字列があったときにもマスクされてしまうので そういうケースがある場合はもう少し工夫が必要です。 念のためにテストも。 bytes.Buffer を使えばオンメモリでテストできます。 mask_test.go package main import ( "bytes" "testing" ) func TestMaskWriter(t *testing.T) { tests := []struct { name string input string mask []string output string wantErr bool }{ { name: `mask (1 word)`, input: `hogefugapiyo`, mask: []string{`fuga`}, output: `hoge********piyo`, wantErr: false, }, { name: `mask (2 words)`, input: `hogefugapiyo`, mask: []string{`fuga`, `piyo`}, output: `hoge****************`, wantErr: false, }, { name: `mask (multiline)`, input: "hoge\nfugapiyo", mask: []string{`fuga`}, output: "hoge\n********piyo", wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := &bytes.Buffer{} ml := NewMaskWriter(got) for _, w := range tt.mask { ml.AddMaskWord(w) } _, err := ml.Write([]byte(tt.input)) if (err != nil) != tt.wantErr { t.Errorf("MaskWriter.Write() error = %v, wantErr %v", err, tt.wantErr) return } if got.String() != tt.output { t.Errorf("MaskWriter.Write() = %v, want %v", got.String(), tt.output) } }) } } あとは先ほど作ったものを使うだけ。 main.go package main import ( "log" "os" ) func main() { id := `hiro` pass := `password` // ログファイル logFile, err := os.Create(`output.log`) if err != nil { log.Fatal(err) } defer logFile.Close() // マスク用Writerに変更 maskLogFile := NewMaskWriter(logFile) maskLogFile.AddMaskWord(pass) // ログ出力先設定 log.SetOutput(&maskLogFile) // フォーマット設定 log.SetPrefix(`[LOG] `) log.SetFlags(0) // 出力 log.Printf(`ID : %s`, id) log.Printf(`PASS: %s`, pass) log.Printf(`exec: hoge.exe --id %s --pass %s`, id, pass) } output.log [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** できました。 出力をわける 標準出力されるログは マスクしない で ログファイルだけマスクする 場合は、 io.MultiWriter() を使って まとめたWriter を使えばシンプルなコードにできます。 main.go package main import ( "io" "log" "os" ) func main() { id := `hiro` pass := `password` // ログファイル logFile, err := os.Create(`output.log`) if err != nil { log.Fatal(err) } defer logFile.Close() // マスク用Writerに変更 maskLogFile := NewMaskWriter(logFile) maskLogFile.AddMaskWord(pass) // 両方に出力する mw := io.MultiWriter(os.Stdout, &maskLogFile) // ログ出力先設定 log.SetOutput(mw) // フォーマット設定 log.SetPrefix(`[LOG] `) log.SetFlags(0) // 出力 log.Printf(`ID : %s`, id) log.Printf(`PASS: %s`, pass) log.Printf(`exec: hoge.exe --id %s --pass %s`, id, pass) } 標準出力 [LOG] ID : hiro [LOG] PASS: password [LOG] exec: hoge.exe --id hiro --pass password output.log [LOG] ID : hiro [LOG] PASS: ******** [LOG] exec: hoge.exe --id hiro --pass ******** ね、簡単でしょう?(ボブ・ロス)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む