OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleAppSscriptからNotionAPIを利用してみた

本記事は、[サムザップ Advent Calendar 2021]
(https://qiita.com/advent-calendar/2021/sumzap) の12/24の記事です。

#はじめに
初めまして、サムザップの白濱です。
最近話題のNotionで、今年の5月にパブリックベータとして Notion APIが公開されました。
今回は、こちらを使用して、Google Apps ScriptからNotionAPIを実施してみた話をしたいと思います。

#Notion APIについて
2021 5月にパブリックベータとして公開されました。
https://developers.notion.com/

API Reference
https://developers.notion.com/reference/intro

今回は、Google Apps Scriptから利用しました。

#使用したAPIの各種処理について

Notoinデータベースの取得・追加・更新でそれぞれAPIが用意されていて、こちらを使用しました。
<b>・データベースの取得処理</b>
　　https://api.notion.com/v1/databases/"+databaseId (※)+"/query
　　databaseIdを指定して情報を取得するAPI  
　　※ databaseIdは、対象のテーブルのURLのv=以下のIDを指定
　　![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/33746b94-631f-1cbe-47c1-e0c74c3e2eef.jpeg)

　　<b>!一度に取得できるレコード数は、MAX100件</b>
　　<b>!100件以降は、ページIDを指定して、取得する</b>

　　上記URLに対して、dataとoptionsを指定して、POSTで送信する。
　　1ページ目のdata指定
　　　var data = {'page_size': 100};
　　2ページ目以降のdata指定
　　　var data = {'page_size': 100,'start_cursor': next_cursor};
　　next_cursorは、前ページのプロパティ（next_cursor）から設定。

　　var options = {"method": "POST","headers": headers,"payload": JSON.stringify(data),"muteHttpExceptions" : true,};

<b>・データベースの追加処理</b>
　　https://api.notion.com/v1/pages
　　指定して情報を取得するAPI

　　上記URLに対して、dataとoptionsを指定して、POSTで送信する。

　　var data = {
　　　"parent": { "database_id": databaseId },
　　　"properties":{
　　　"title": [ {"text": { content: 【更新内容】, link: null } } ]
　　　}
　　};

　　var options = {"method": "POST","muteHttpExceptions" : true,"payload": JSON.stringify(data),"headers": headers};


<b>・データベースの更新処理</b>
　　https://api.notion.com/v1/pages/+pageId (※)
　　指定して情報を取得するAPI

　　※ pageIdは、データベースの取得処理で、取得したレコード情報で取得できる。
　　　（propertyName=ID）

　　上記URLに対して、dataとoptionsを指定して、PATCHで送信する。
　　（POSTでない点が注意）

　　dataは、
　　var data = {
　　　"properties":{"Name": { "name" : [ {"text": { content: 【更新内容】, link: null } } ]}}
　　};
　　propertiesでNotionのカラム名を指定する。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/39622282-154d-f2fe-d3ed-aebf9ed3182d.jpeg)

　　var options = {"method": "PATCH","muteHttpExceptions" : true,"payload": JSON.stringify(data),"headers": headers};

<b>・その他注意事項</b>
　　操作したいDBに対して、APIのIntegrationを追加しないと操作ができないので注意。
　　![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/e5920e95-48d7-785a-2966-8bd777c5d3a9.jpeg)


　　Integrationの設定はこちらを参考に。
　　https://developers.notion.com/docs/getting-started

#具体的な使用例について
　業務では、GoogleAppSscriptとNotionAPIの連携で以下のような用途に使用しました。
<b>・WrikeとNotionの連携</b>
　　　WrikeAPIからWrikeデータを取得して、NotionレコードとWrikeタスクを連携。
　　![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/5370e998-682f-ae55-cf00-562bc2430ae0.jpeg)


<b>・Notionレコードの自動追加</b>
　　　1ヶ月分のデータ入力用のレコードを月次処理で自動追加。
　　![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/22e22e7c-a014-83ee-7951-e25d1870dad4.jpeg)
　　　
#まとめ
　Notionは、とても魅力的なツールで、生産性の向上にとても役に立っています。
　APIを使用することで、その魅力や可能性がさらに高まったことを実感しています。
　皆さんもぜひ活用してみてください！
脆弱性診断の勉強をはじめて半年の間で参考にしたサイトの紹介

この記事は シーエー・アドバンス Advent Calendar 2021 23日目の記事です。

前回の記事は@ken_2さんの[シンプルなGraphQLサーバでCRUDする（Express.js, Objection.js, MySQL, Docker）](https://qiita.com/ken_2/items/43995ee9708b9ee6e97f)でした。
明日の記事は@sk888さんです。

# はじめに
シーエー・アドバンス（CAAD）技術統括本部セキュリティチームの @azama_yasuhiroです。
社内（グループ会社含む）サービスの脆弱性診断に関わる業務を行っています。
前職はアパレルの販売員でIT業界は未経験の僕が昨年12月に現在の部署に異動し、
半年間は開発の研修をして、そこから脆弱性診断士として成長すべく、
脆弱性診断の勉強をはじめてこの半年間の間にスキルの幅を広げるために使用したサイトを紹介させていただきます。

## 参考にしたサイト
 - [PortSwigger](https://portswigger.net/kb/issues)
このサイトはBurpの自動診断で出てくる可能性のある脆弱性を全て表記してくれていてBurpを使用して診断をする上で必ず確認するサイトです。
※英語表記のため必要であれば日本語訳をした方が良いです。

 - [知っていますか？脆弱性](https://www.ipa.go.jp/security/vuln/vuln_contents/index.html)
こちらはIPA（情報処理推進機構）のサイトです。
代表的な脆弱性はほとんど記載されており、HTML版だと画像も使って説明してくれていてかなりわかりやすくなっております。

 - [OWASPトップ10](https://owasp.org/www-project-top-ten/)
こちらはWebアプリケーションのセキュリティリスクをランキング形式で記載しており、
一番最近では今年の2021年にランキングが更新されております。
その時その時の最も重大なセキュリティリスクが確認できるため更新のタイミングは確実に確認した方が良いサイトです。
※その前は2017年度で3~4年に1回程で更新される傾向にあります

 - [WPScan 入門](https://www.wivern.com/security20150526.html)
こちらはWordPressを使用しているWebアプリケーションに対して行う脆弱性スキャン（WPScan）の方法が記載されております。
細かいオプションなどのコマンドも記載されているので、WPScanを行う前に要チェックすると良いかと思います。

 - [徳丸浩の日記](https://blog.tokumaru.org/)
こちらは「体系的に学ぶ 安全なWebアプリケーションの作り方」の著者、徳丸さんのブログです。
一番新しい記事で2020年12月19日となっており、現在は更新が止まっておりますが、
様々な脆弱性の事例などを元に記事を記載されているので、
過去の記事でも幅を広げるために見る価値は十分にあります。

 - [JVN iPediaにようこそ](https://jvndb.jvn.jp/)
こちらは脆弱性対策情報のデータベースです。
製品やパッケージなどの様々な発見された脆弱性の情報及びその対策を記載してくれていて、
脆弱性名などで検索もできるため、非常に便利です。
実際の診断時にはjQueryなどのライブラリでどのバージョンにどういう脆弱性があったか調べたりするのに活用しております。

 - [XSS Attack Tips / 今日から始めるXSS](https://www.hack.vet/entry/20161126/1480135655)
こちらはXSSを発火させるための様々なコードを記載しております。
実際に診断時はXSSの発火を確認するために様々なコードを入力するため参考になります。
※わかりやすく記載されておりますが、悪用厳禁でお願いします。

 - [静的サイト、動的サイトの違いについて調べてみた(html、css、javascript編)](https://zenn.dev/jiin/articles/0db95dd92c06de)
こちらは静的サイト・動的サイト・性的ファイル・動的ファイルの違いなどを分かりやすく解説してくれております。
診断時は静的サイトや動的サイトで見る観点なども変わってくるため、
理解を深めるのに役に立ちました。

 - [OSI参照モデルとは？TCP/IPとの違いを図解で解説](https://www.itmanage.co.jp/column/osi-reference-model/)
こちらは脆弱性に関するサイトではないのですが、OSI参照モデルというネットワーク通信のモデルを階層ごとにかなり詳しく書いていて勉強になりますのでおすすめです。

## おわりに
まだまだ自身が勉強中の身で初めて記事を書くため、拙い文章ではありますが、
僕のようにこれから脆弱性診断の勉強をはじめてスキルの幅を広げていきたいという方の少しでも力になれれば幸いです。
読んでいただきありがとうございます。
Content-Typeとはなにか

## 概要
今回は先日学習したHTTPヘッダーで使用するContent-typeについて備忘録として書き残しておきます。

## 前提知識

#### HTTPヘッダーとは
レスポンスやリクエストに追加でデータを渡せる応答フィールドのことです。
またHTTPヘッダーは下記種類があります。
>・__リクエストヘッダー__は、読み込むリソースについての情報や、そのリソースをリクエストしているクライアントに関する詳細な情報を持ちます。
・__レスポンスヘッダー__は、レスポンスに関する追加情報、例えば場所や提供しているサーバーに関する情報を保持します。
・__表現ヘッダー__ (en-US)は、リソースの本体に関する情報、例えば MIME タイプや適用されるエンコード／圧縮方式などについての情報を持ちます。
・__ペイロードヘッダー__ (en-US)は、転送されるデータの表現から独立した情報、例えばコンテンツの長さや転送に使われるエンコード方式などを持ちます。

下記記事から参照
[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers)

## Content-typeとは
表現ヘッダーに含まれるもので、受け渡されるコンテンツの形式（メディアタイプと呼ばれるもの）を指定するものです。
例えば__HTML形式__だったり、__JSON形式__だったり他にもたくさんあります。
一例としてよく使われるのは`application/json`です。
これを指定することによりコンテンツの形式がJSON形式であることを意味します。
他にも知りたい場合は下記を参照してください。

[https://www.iana.org/assignments/media-types/media-types.xhtml](https://www.iana.org/assignments/media-types/media-types.xhtml)


## 参考文献
[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers)
[HTTPヘッダーのContent-Typeを自在に扱う
](https://tech.stmn.co.jp/entry/2021/03/15/183722)
stylelint-orderはobject styleだと動かない

## この記事の概要

[Stylelint](https://stylelint.io/)や、そのプラグインである[stylelint-order](https://github.com/hudochenkov/stylelint-order)をCSS in JSで使う際、object styleで書くと並び変えが上手くいきません。

ちなみに、object styleとは以下のような記載の仕方を指します。

```javascript
const style = css({
  backgroundColor: '#55c500',
  color: '#fff',
  fontSize: 20,
  padding: '16px 24px',
})
```

名前の通りですが、文字列としてスタイルを記述するのではなくオブジェクトとして記述するやり方ですね。

## 伝えたいこと

1番伝えたいのはCSS in JSでstylelint-orderが動かないこと自体ではありません。

「object styleであることが大事だから、orderは諦めよう」とか「orderの方が大事だからstring styleにしよう」とか話し合うきっかけになれば幸いで、そのために記事にまとめようと思いました。

## 背景

以前私が関わっているプロジェクトにてｍCSS in JSの方針を議論してこんな着地をしたことがあります。

- 使うライブラリ
    - Emotion
        - 他で実績があるのと、私がある程度詳しいため
- 書き方
    - object style
        - せっかくJavaScriptの世界で書いているのだから、1つの長い文字列よりもデータとして取り回しがしやすいはずのオブジェクトを使おう
- プロパティ順
    - アルファベット順
        - プロパティ順に特にこだわりはないものの、無秩序なのも……という感情だけ

さて、pre-commit時にstylelint-orderが走るようにセッティングしてしばらく運用していましたが、ある日気付きました。

「**プロパティ、全く並び変られてないぞ？**」

タイトルの通りですがstylelint-orderはobject styleでは動かないのですが、私は手でスタイルを書く時点でアルファベット順に書く癖があったのでstylelintが動いていないのに気付いていませんでした。

しかし誰かが新しいスタイルを書いた際、既存のコードの後ろにスタイルを追加していたので以下のような感じになっており、そのままでPull Requestが出ていたので気付いたのです。

```javascript
const style = css({
  width: '100%',
  margin: 16,
})
```

## 公式の見解

2019年と随分古いですが、Issueが立っていました。

https://github.com/hudochenkov/stylelint-order/issues/99

ここに書いてある通りですが、最後のカンマが状態で順番を入れ替えるとエラーになってしまうためだそうです。

```
{
  a: 0,
  c: 2,
  b: 1
}
```

`
{
  a: 0,
  b: 1
  c: 2,
}
`

JavaScriptの文法を修正するのは、このプラグインの範囲外なので対応するつもりはないとのことでした。

## まとめ

- stylelint-orderはobject styleだと動かない
- チームの方針が……
    - object styleでスタイルを書くことが優先なら、CSSのプロパティ順を自動で並び変えるのは諦める（or stylelint-orderではない手段を考える）
    - プロパティ順にルールを持たせることが優先なら、object styleではなくstring styleで書く
AWS ATHENAでは、テーブル名に数字から始めるとエラーとなる


AWS ATHENAで、テーブルを作ろうとしたら、エラーで作成できませんでした。エラーメッセージが意味不明で少しハマったのですが、数字から始まるテーブルは作成できないようです。修正して解決しました。

（参考）ドキュメントに書いてある通りのCREATE文を組んだつもりでした。（CloudFrontからのログからテーブル作成）
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/cloudfront-logs.html

（参考）ハイフンも駄目なようです。
https://qiita.com/snaka/items/500a34be2c16af7701b5

```
line 1:8: mismatched input 'EXTERNAL'. Expecting: 'OR', 'SCHEMA', 'TABLE', 'VIEW'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83911/3fdcb598-567d-594c-5b41-5e3a10a7f7da.png)

以下のCREATE文はエラーになります。

```
CREATE EXTERNAL TABLE IF NOT EXISTS default.123news_cloudfront_logs (
  `date` DATE,
  time STRING,
  location STRING,
  bytes BIGINT,
  request_ip STRING,
  method STRING,
  host STRING,
  uri STRING,
  status INT,
  referrer STRING,
  user_agent STRING,
  query_string STRING,
  cookie STRING,
  result_type STRING,
  request_id STRING,
  host_header STRING,
  request_protocol STRING,
  request_bytes BIGINT,
  time_taken FLOAT,
  xforwarded_for STRING,
  ssl_protocol STRING,
  ssl_cipher STRING,
  response_result_type STRING,
  http_version STRING,
  fle_status STRING,
  fle_encrypted_fields INT,
  c_port INT,
  time_to_first_byte FLOAT,
  x_edge_detailed_result_type STRING,
  sc_content_type STRING,
  sc_content_len BIGINT,
  sc_range_start BIGINT,
  sc_range_end BIGINT
)
PARTITIONED BY(
         date string)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t'
LOCATION 's3://123news-logs/cf-prod'
TBLPROPERTIES ( 'skip.header.line.count'='2' )
```
ElixirでPNGを画像をRGBA形式の行列に変換したい


[Elixir]: https://elixir-lang.org/docs.html
[Nerves]: https://hexdocs.pm/nerves/getting-started.html
[pixels]: https://hexdocs.pm/pixels/Pixels.html
[Inky pHAT]: https://shop.pimoroni.com/products/inky-phat?variant=12549254217811

以前、[Inky pHAT]というEペーパーディスプレイにPNG画像を表示させたいときのことです。
[Elixir]でPNG画像をピクセルに変換する方法が中々見つからず、手こずってました。
Eペーパーディスプレイ上ではピクセルごとに色を指定する必要があるのです。

後学のためにElixirでPNGをピクセルに変換する方法をメモを残します。

[「JupyterNotebook + NumPyでサクッと画像加工するノリ」をElixirでやってみた（lennaさんのバージョンアップもあるよ）](https://qiita.com/piacerex/items/533d26c81bada4741422) by @piacerex が参考になりました。

[![](https://user-images.githubusercontent.com/7563926/146623097-445833c7-a37a-44f1-a893-3a83a6337328.jpg)](https://github.com/mnishiguchi/nerves_inky_phat_weather_example)

[「nerves_inky_phat_weather_example」サンプルNervesファームウエア](https://github.com/mnishiguchi/nerves_inky_phat_weather_example)（拙作）

https://qiita.com/advent-calendar/2021/nervesjp

## やりたいこと

- プログラミング言語：[Elixir]
- PNGアイコン画像をRGBA形式の行列に変換して自由に加工したい。

![](https://raw.githubusercontent.com/pimoroni/inky/fc17026df35447c1147e9bfa38988e89e75c80e6/examples/phat/resources/icon-sun.png)

本アイコン画像は[Eペーパーディスプレイのメーカーのリポジトリー](https://github.com/pimoroni/inky)から直接ダウンロードできます。

## IExでデモ

#### IExを起動

```
iex
```

#### 依存関係をインストール

- 環境変数`CROSSCOMPILE`に何らかの値をセットしておかないと[pixels]がうまくコンパイルされませんでした。（MacOS）

```elixir
Mix.install([{:pixels, "~> 0.2.1"}, {:req, "~> 0.2.1"}, {:nx, "~> 0.1.0"}], system_env: [{"CROSSCOMPILE", "1"}])
```

#### PNG画像をダウンロード

- ここでは例としてPimoroniのお天気アイコンを使用。
- [Livebookコアチームオススメ](https://github.com/livebook-dev/nerves_livebook/pull/148)のHTTPクライアント[req](https://hex.pm/packages/req)を用いてPNG画像をダウンロードします。


```elixir
weather_icon = "https://raw.githubusercontent.com/pimoroni/inky/fc17026df35447c1147e9bfa38988e89e75c80e6/examples/phat/resources/icon-sun.png"
%{body: png, status: 200} = Req.get!(weather_icon)
```

#### PNG画像をピクセルに変換

- [pixels]を用いてPNGをRGBA形式の行列に変換します。
- [pixels]により処理された画像は、「RGBA」の4バイトで1ピクセルを構成しています。

```elixir
{:ok, %{data: data, height: height, width: width}} = Pixels.read(png)
```

https://qiita.com/piacerex/items/533d26c81bada4741422

#### 後は好きなようにデータを加工する

```elixir
data
|> :binary.bin_to_list
|> Enum.chunk_every(4)
|> Enum.map(fn
  [_, _, _, 0] -> 0
  _ -> 1
end)
|> Enum.chunk_every(width)
|> Nx.tensor
|> Nx.to_heatmap
```

![](https://user-images.githubusercontent.com/7563926/149340069-abd39290-5f94-41f7-8a3d-e5ef28744ea9.png)

https://qiita.com/kikuyuta/items/70152a04c8baa5b3b19c

:tada::tada::tada:

# <u><b>Elixirコミュニティに初めて接する方は下記がオススメです</b></u>

**Elixirコミュニティ の歩き方 －国内オンライン編－**<br>
https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/f891b7ad-d2c4-3303-915b-f831069e28a4.png)](https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian)
Spinnerで同一項目が選択されたことを検知したい same position tapped of spinner

#やりたいこと
AndroidのSpinnerには、同一項目が選択されたタイミングを知る術がなく必須の項目なのに仕方なく未選択という項目を入れることになってしまう場合等があるかと思います。

#解決策
最も手っ取り早く簡単に解決する方法がカスタムのSpinnerクラスを作成することです

```kotlin:CustomPtogramSpinner.kt
class CustomProgramSpinner @JvmOverloads constructor(context: Context?,
                                                     attrs: AttributeSet? = null,
                                                     defStyleAttr: Int = 0)
    : AppCompatSpinner(context, attrs, defStyleAttr) {

    override fun setSelection(position: Int, animate: Boolean) {
        val sameSelected = position == selectedItemPosition
        super.setSelection(position, animate)
        // 同じ要素が選択されてもonItemSelectedが呼ばれる様に調整
        if (sameSelected) {
            onItemSelectedListener?.onItemSelected(this, selectedView, position, selectedItemId)
        }
    }

    override fun setSelection(position: Int) {
        val sameSelected = position == selectedItemPosition
        super.setSelection(position)
        // 同じ要素が選択されてもonItemSelectedが呼ばれる様に調整
        if (sameSelected) {
            onItemSelectedListener?.onItemSelected(this, selectedView, position, selectedItemId)
        }
    }
}
```
本来、AndroidのSpinnerは同一項目が選択された場合は`onNothingSelected`のみが呼ばれてしまい、同一項目を選択したタイミングのみに走るものが存在しません。
なので何か項目が選択されたタイミングで、直前に選択されていたものと選択されたもののpositionを見て手動で`onItemSelected`を呼ぶことにより、同一項目が選択された場合でも同じ挙動をさせることができます。

#最後に
以上が、同一項目選択時を簡単に検知する方法です。
もし他にもっといいやり方があった場合、コメントでぜひ教えてください
neosでlogix その28

# 概要

niosでlogixやってみる。
CharacterControllerコンポーネントを使ってみた。
多分、物理エンジン。


# 写真

![2021-12-21 10.35.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e23edd4e-4abd-86ac-38cf-cdb25b641861.jpeg)

# 手順

- devtooltipを装着。
- 新規->3d->box
- インスペクターを開き、コンポーネントを追加
- Physics->CharacterController
- logixtooltipを装着。
- インターフェースを取り出す
- ノードブラウザを表示
- Actions>Write Refをスポーン
- つなぐ


以上。
Gradleでコンパイル警告を100件より多く表示する

### 背景

コンパイル警告があまりに多いプロジェクトだと、最初の100件までしか警告内容が出力されない。そもそもコンパイル警告が多い状態で放置していること自体が問題だが、途中で省略させずにすべてを確認したいこともある。

```
$ ./gradlew clean build
Starting a Gradle Daemon (subsequent builds will be faster)
...
ノート:一部の入力ファイルは推奨されないAPIを追加使用またはオーバーライドしています。
ノート:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。
ノート:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
警告100個
```

### 対応方法

`-Xmaxwarns` の値としてすごく大きな値を指定してやることで回避することができる。

```gradle
    compileJava {
        sourceCompatibility = 17
        targetCompatibility = 17
        options.deprecation = true
        options.compilerArgs << "-Xmaxwarns" << "1000"
    }
```

### 確認環境

* OpenJDK 17.0.1
* Gradle 7.3.1
master にマージ済みのローカルブランチを全部消す



```bash
for i in $(git branch | grep -v '\*') ; do git branch -d $i ; done
```

1. `git branch` でブランチ一覧を取得
1. `grep -v '\*'` で現在のブランチ(master)を除外
1. for で一つのブランチずつ、 `git branch -d ブランチ名` していく

マージしていないものは、以下のようなエラーで失敗するので問題ない。

```
error: The branch 'foobar' is not fully merged.
If you are sure you want to delete it, run 'git branch -D foobar'.
```
AtCoder Beginner Contest 008をやった(Java)

AtCoder Beginner Contest 008をやった。

##[A](https://atcoder.jp/contests/abc008/tasks/abc008_1)
差分を出してあげて、ひと工夫すれば終わります。

```Java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();
        System.out.println((num2 - num1) + 1);

    }
}
```

##[B](https://atcoder.jp/contests/abc008/tasks/abc008_2)
重複文字は**key : Value**でカウントを重ねればおのずと結果に導かれます。


```Java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();
        
        String[] strIndex = new String[Integer.parseInt(scan.nextLine())];
        for(int i = 0; i < strIndex.length; i++){
            strIndex[i] = scan.nextLine();
        }
        
        Map<String, Integer> map = new HashMap<String, Integer>();
        
        for(String str : strIndex){
            int v;
            if(map.containsKey(str)){
                v = map.get(str) + 1;    
            } else {
                v = 1;
            }
            map.put(str, v);
        }
        
        int max = 0;
        String S = "";
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            if(max < entry.getValue()){
                S = entry.getKey();
                max = entry.getValue();
            }
        }        
        System.out.println(S);
    }
}


```

いつかC問題もJavaで解きたいな(n回目)。
デザイナーが爆速コーディングするためCSS周りをどうするか問題

フリーランスのWebデザイナーはWeb制作を一気通貫に行うためにデザインのみならず、コーディングもすべきだと私は思います。小規模なWebサイトであれば問題ないですが、ちょっと大きめの案件になると、単純にHTMLとCSSでコーディングすればいいでは済ませなくなります。

この記事では、私が爆速コーディングするためにどうしているかを共有します。

#結論
結論からいいますと、次の３点をこなしていくと爆速になります。

1.FLOCSSとBEM記法の組み合わせ
2.いかに自分が使いやすいmixinを作れるかを考える
3.エディターの使いこなし

#FLOCSSとBEM記法の組み合わせ
今更感やベタ感を否めませんが、フロントエンドエンジニアのみならず、デザイナーにとっても最強だと感じています。

FLOCSSについて：https://github.com/hiloki/flocss
BEM記法について：https://zenn.dev/knts0/articles/quick-understanding-bem

これらは考え方であり、個々のプロジェクトは絶対にそのルールに100%守らなければならないわけではありません。１ページものであればわざわざprojectフォルダを作る必要はないし、html要素がシンプルな構造であればいちいち入れ子にしたりする必要もないかもしれません。

FLOCSSとBEMが解決してくれるのは以下だと考えています：

##FLOCSS
- HTMLの要素を階層化して考えることができる。
- partialsは程よい粒度で作成するので、CSSファイルの構造が複雑になりにくい。

##BEM
- BlockやElement単位でHTML要素を見ることができるため、マークアップが楽。
- SCSSとの組み合わせで、アンパサンドでどんどん子要素に繋がって書けます。

#いかに自分が使いやすいmixinを作れるかを考える
ここは結構重要です。主流なCSSフレームワークを使ってもいいですが、デザイナーがコーディングする場合、ビジュアルとの兼ね合いで自身で細かいところの調整とかしたいことが出ると、フレームワークのカスタマイズより、自分が作ったmixinをカスタマイズしたほうがよほど早いです。

一例ではありますが、例えば「縦横」や「前景色と後景色」、「flexboxの中央配置」などよく使われてるものや、テキスト二行表示、Webフォントなど、コーディング時よく使ってるものを作れば非常に楽となります。

ここで重要なのは、ある程度変数も入れてpartialsをテンプレート化することです。目標は、新規コーディング時、partialsの中の変数をいじるだけでコーディングをスタートできることです。例えばmainColorやpadding、breakpointあたりです。

ひとつ難しいのはmixinの名前です。主流のcssフレームワークや大きめのプロジェクトでは結構わかりやすさ重視で名前が長くなりがちです、個人の場合は、ある程度名前をシンプルにしてもいいのではないかと思います。例えばwh(width,height)とかcolorSet(color,background-color)とかです。この辺りの判断はメンテナンス性やチームメンバーとの相談が必要だと思います。

#エディターの使いこなし
これも結構コーディングのスピードを左右します。特にemmetは必須です。

emmetについて：https://b-risk.jp/blog/2021/06/emmet/

私はvscodeを使っていて、emmetはデフォルトで使えるので非常に楽です。デザイナーのコーディングは基本的にvscodeを使えば間違えなしかなと思っています。gitあたりのハイライトもデフォルトで使えるし、使いたい機能のプラグインもわりと見つけやすいです。

エディターによってショートカットが違うのでこの辺り慣れが必要ですが、そこまで学習時間は必要ではありません。要するに、「これをしたいけどなんかショートカットはないか？プラグインはないか？」を考えることが大事です。

私がHTML/CSSコーディング時はprettierとauto rename tagのプラグインがあれば事足りるかなという印象です。

#最後に
フリーランスだからなのか、最近は「デザインしかできません！」では済ませなくなりつつあると感じています。最後に私が普段コーディングで作っているテンプレートを公開しますので、よろしければご参考になっていただければ幸いです。

https://github.com/bje0696/frontend_template
LaravelでCarbon\CarbonとIlluminate\Support\CarbonとCarbon\CarbonImmutableで迷ったらCarbonImmutable

## Laravelの日時ライブラリ

Laravelを使い始めて日時ライブラリがたくさんあり、迷ったので備忘録として。

### 注意

Laravel8系での話になります。Laravel5系とかだと`Illuminate\Support\Carbon`はまたちょっと違うので参考程度にしてください。

## Carbon\\Carbon

https://carbon.nesbot.com/docs/

おなじみの日時ライブラリ。組み込みのDateTimeクラスを継承している。
**mutable**なので、インスタンスを直接変更するため注意が必要。

```php
$time = Carbon::create(2021, 12, 25); // 2021-12-25 00:00:00
$time->addDay(); // 2021-12-26 00:00:00
$time->addDay(); // 2021-12-27 00:00:00 (直感的には2021-12-26であってほしい)
```

`Carbon::now()->copy()->addDay()`のようにインスタンスをコピーしてから使わないとコードのあちこちで変更があった時に追うのが辛くなる。

テストで時間を固定させたい時は `Carbon::setTestNow()`

PHPに触り始めた人だとサラッと流しがちなのでバグの温床になりやすい。（１時間ハマった）

## Illuminate\\Support\\Carbon

https://laravel.com/api/8.x/Illuminate/Support/Carbon.html

`Carbon\Carbon`と`Carbon\CarbonImmutable`を拡張した日時ライブラリ。実装を見ると分かる通り、Laravel8だともう`setTestNow()` しか実装がない。 (テストで日時を固定できるメソッド)


## Carbon\\CarbonImmutable

https://carbon.nesbot.com/docs/

Carbonの **immutable**版。組み込みの`DateTimeImmutable`クラスを継承している。
こちらは新しいインスタンスが返されるため、`copy()`する必要がない。
インスタンスが作られた一番最初の状態を持つので、コードを順に追う必要がなくなる。

```php
$time = CarbonImmutable::create(2021, 12, 25); // 2021-12-25 00:00:00
$time->addDay(); // 2021-12-26 00:00:00
$time->addDay(); // 2021-12-26 00:00:00 (宣言時のものを基準にする)
```

テストで時間を固定したい時は `CarbonImmutable::setTestNow()`

### 注意

~~`CarbonImmutable::setTestNow()`だと上手く時間が設定出来ない可能性があるので、テスト時のみ`Carbon::setTestNow()`推奨~~

- CarbonImmutable::setTestNow()だとCarbonImmutable::now()などの時間固定ができる。
- Carbon::setTestNow()だとCarbon::now()などの時間固定が出来る。

## DateTime

https://www.php.net/manual/ja/class.datetime.php

Carbonの元になっているPHP組み込みの日時ライブラリ。
何か特別な理由がない限りはLaravelではCarbonを使った方が楽に感じる。

## DateTimeImmutable

https://www.php.net/manual/ja/class.datetimeimmutable.php

CarbonImmutableの元になっているPHP組み込みの日時ライブラリ。
何か特別な理由がない限りはLaravelではCarbonImmutableを使った方が楽に感じる。

## まとめ(CarbonImmutableを使おう)

出来ることならば**CarbonImmutable**を採用したい。（プロジェクトで統一することが一番大切）
また、DateTimeを使うことで柔軟なインターフェース設計にできることを@mpywさんに教えていただきました。
ありがとうございます:bow:

その他追記があれば随時更新していきます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://t.co/iNHK3FiuHW">https://t.co/iNHK3FiuHW</a><br><br>interface と class で必ずしも一致させる必要がない点も注意してください！自分はモジュラモノリスプロジェクトで以下のようにしました<br><br>interface<br>引数: DateTimeInterface, 返り値: DateTimeImmutable<br><br>class<br>引数: DateTimeInterface, 返り値: CarbonImmutable</p>&mdash; 素人 (@mpyw) <a href="https://twitter.com/mpyw/status/1473236915805880321?ref_src=twsrc%5Etfw">December 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">一点追記です<br><br>class のコンストラクタ引数に関しては、interface での束縛対象にならないと思うので、CarbonImmutable 直接指定もありだとは思います<br><br>この場合、インスタンス生成は「使ってもらう側」が全て巻き取り、「使う側」には全く意識させない設計が必要となりますが</p>&mdash; 素人 (@mpyw) <a href="https://twitter.com/mpyw/status/1473325928529154051?ref_src=twsrc%5Etfw">December 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
mongoDBとは

## 勉強前イメージ

あまり良く知らない。。。。

## 調査

### mongoDB とは

もんごでーびーと呼び、オープンソースのNoSQLデータベースになります。
NoSQLデータベースの中のドキュメント指向型データベースというものになり、JSON形式のドキュメントでデータを管理します。
これよって複雑なデータを扱うことができます。

リレーショナルデータベースではデータ型を事前に来て目置かないといけないのですが、
mongoDBではドキュメント構造を柔軟に変更できます。

### mongoDBの特徴

- 高速

mongoDBはインメモリで動作するので高速なデータ処理が可能になります。
ドキュメント指向形データベースということも有り、RDBと同じような感じで運用ができます。

- 外部システムとの連携

JSONに似たような形式でデータを保存しているため、外部システムとの連携も簡単にできます。

- 拡張性・冗長性に優れている

レプリカセットやシャーディングなど拡張したり常朝したりするための機能があります。
そのためクラスタを組んで耐障害性を高めることが出来ます。

- SQLが使用できない

mysqlなどで使用されるSQLはmongoDBでは使用できず、javascriptを使ってクエリを定義します。
大部分はマッピングできますが、一部grop by などが使用できないので注意する必要があります。

### ユースケース

以下の際にmongoDBが向いています。

- webサイトの操作ログを蓄積
- 負荷の低い読み取りで、更新が大量にあるシステム

## 勉強後イメージ

ドキュメント指向型データベース初めて知ったかも・・・
あと大体sql使えるでしょって思ってたけど、そうでもないのいっぱいあるのね。。。

## 参考

- [MongoDBとは](https://products.sint.co.jp/topsic/blog/mongodb)
- [MongoDBとは](https://www.designet.co.jp/faq/term/?id=TW9uZ29EQg)
未経験初心者がWEB家計簿を作ってみた【Rails  / Docker / Heroku / CircleCI】

## 初めに
こんにちは。
当記事は独学・未経験者がポートフォリオを兼ねてWEBアプリを作った、ご紹介させて頂きたいと思います。

昨今、未経験者が作成したポートフォリオ作成記事も多く存在するので、何番煎じかにはなってしまいますが、
この記事も同じ初学者の方の参考になればうれしく思います


## 概要
共同口座専用の家計簿アプリ「キョウドウコウザ」
　http://www.kyodokoza.com/

シンプルかつ見やすさにこだわった「共同口座（共用口座・共同財布）向けの家計簿アプリ」です。

<img width="300" alt="img1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766860/30d4af70-f86b-5ea7-0b3e-6b0677e1f334.png">     <img width="300" alt="img2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766860/de40bb4b-571b-5f0b-444f-19b7d457984d.png">
<br>
<img width="300" alt="img3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766860/23969709-1cce-1c16-4e59-ac41c88d467e.png">   <img width="300" alt="img4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766860/43e8db2f-539b-7fd8-e1de-1eed58a89a1f.png">


<br>
家計簿アプリは世の中に多々ありますが、私個人に合うものがなかったため自作しました。また、同様の悩みを抱える方にお使いいただければと思っております。<br>
<br>


## 工夫した点
### ユーザー目線
- スマホで利用することが多くなることを想定し、レスポンシブ化
- 夫婦二人で使うことにこだわりたかったので、ユーザーの交流などはできない仕様に。また、登録作業をできうる限りセキュリティに配慮しつつ、シンプルにした<br>（2人が会員登録→片方が他方の認証コードとアドレスを入力）
- 入力のモチベーションアップのため、入力履歴の可視化
- 入力作業の効率化のため、支出のテンプレート機能を導入。また、テンプレート化しても毎月の額が変動する（電気代や携帯料金等）ことを想定し、テンプレートとして登録された支出の額を修正し、選択した上で支出に反映。
### 開発者目線
- CircleCIでCI/CDパイプラインの構築
- dockerのコンテナをDB/Rails/webpack-dev-serverの３コンテナ構造とし、ホットリロードで開発効率化
<br>
<br>


## アプリ作成の経緯
### 現状
夫婦で、共同口座形式で家計を運用してます。<br>  
月初に夫婦それぞれの口座から、共同口座に定額入金<br>  
→普段は個人口座/個人財布から出金<br>
→月末にレシートや領収書を元に共同口座から清算<br>

### 課題
- 清算作業が月末に偏るため、ヌケモレ発生する。
- 月末以外は、夫婦合わせて現状どれくらい支出があるかわからない<br>

#### その後いくつかの家計簿アプリやエクセルを使いましたが、そこでも課題を感じました。
<br>

- 写真の画像解析で自動入力→ 解析制度が悪い。
- 料金がかかる
- 作業が属人化する(夫婦2人のコスト意識向上につながらない)

### 目標
- 随時支出の記録を行い、月末以外でも支出の合計を把握しやすいようにする
- 夫婦2人で手軽に入力作業ができるようにする
- 今後複雑な解析をしたいと考えた時のために、データをエクセルと統合できるようにする
<br>
<br>


## 実装機能

### 基本機能
- ゲストログイン機能
- 会員登録、家族登録、ログイン
- メールを用いたパスワードリセット機能
### 記録機能
- ユーザ・家族情報の編集、削除
- カテゴリ登録、編集、削除
- 目標額の設定、編集
- 支出の登録、編集、削除
- 収入の登録、編集、削除
- 毎月支出されることが多い項目（固定費）の登録、編集、削除
### 集計・見える化機能 等
- 支出・収入の一覧、ソート機能（カテゴリ毎、ユーザー毎）
- 月毎の支出の集計（カテゴリ毎、ユーザー毎、対目標額）
- 月毎の比較（支出、収入）
- 残高表示
- エクセル出力機能(単月出力・範囲指定による複数月出力)
- メールでの毎週のレポート機能
- 入力履歴の可視化
- SNSシェアボタン
<br>
<br>

## 使用技術
### フロントエンド
- HTML/CSS
- Javascript
- Bootstrap 5.1.0
- chart.js

### バックエンド
- Ruby 2.7.4
- Ruby on Rails 6.1.4
- RSpec

### インフラ・開発環境
- Docker/Docker-compode
- CircleCI(CI/CD)
- Heroku
- SendGrid(mailer)

### 主要gem
- chartkick(グラフの描画)
- caxlsx(excel出力)
- rspec(テスト)
- whenever(バッチ処理 / 定期メール配信等)
<br>
<br>

## ER図
![ER.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766860/dc8f9278-b9b9-b19c-d032-43b189d2a775.png)

## 参考情報：私のこれまでの学習履歴
29歳・大学院卒です。
そんな私ですが「Webエンジニア」という職種を目指すきっかけがあり、2021年3月よりプログラミング学習を開始しました。
おおよそ以下のようなスケジュールで学習を進めていました。
離職しながらの学習だったのですが、家庭の事情で１日平均５時間程度のみ作業にあてていました。
期間は、ざっくり7か月です。

- 2021/3：　HTML/CSS(Progate)
- 2021/4：　Javascript(Progate)
- 2021/5：　基本情報技術者試験
- 2021/6~7：　Ruby/rails(railsチュートリアル)
- 2021/8：　React基礎(Progate等)、Docker
- 2021/9：　本アプリ作成

## さいごに
結婚されてる方やカップルの方は、
ぜひキョウドウコウザを使っていただけると幸いです。
そして、本記事のコメントや私のツイッターあてにコメントいただけると嬉しいです。
忌憚なき意見を頂戴いただけると幸いです。

ツイッター↓
https://twitter.com/SHOMATSUDA3
「RecursionError: maximum recursion depth exceeded while calling a Python object」とエラーが出てしまったらこれをみよう


# 目的
djangoのアプリを作成しようとして、modelの登録やsettings.pyの初期設定などどのdjangoのプロジェクトでも最初に行うようなことを行おうとして、ローカルサーバーで確認をしていこうと思った矢先、**「RecursionError: maximum recursion depth exceeded while calling a Python object」**と表示されてしまった。

# 状況

```
.test_api
├── db.sqlite3
├── manage.py
├── test_app
│   ├── __init__.py
│   ├── __pycache__
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   ├── urls.py②
│   └── views.py
└── test_api
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py①
    └── wsgi.py
```
# 結論
①urls.pyのpathのinclude先を間違えていた。

# 実施環境
### ハードウェア環境
| 項目 | 情報 |
|:-:|:-:|
| OS  |macOS Catalina(10.15.7)   |
|ハードウェア   |  MacBook Air (11-inch, Early 2015) |
|プロセッサ   | 1.6 GHz デュアルコアIntel Core i5|
|メモリ   |  4 GB 1600 MHz DDR3 |
|グラフィックス   |  intel HD Graphics 6000 1536 MB |
### ソフトウェア環境
| 項目 | 情報 |
|:-:|:-:|
| homebrew  | 3.3.8 |
| mysql | Ver 8.0.27 for macos10.15 on x86_64 |
| python  | 3.8.12 |
| django  | 3.1.2 |
| anaconda  | 4.10.1 |
| pip  | 21.2.4 |



# 経緯
djangoのアプリを作成しようとして、modelの登録やsettings.pyの初期設定などどのdjangoのプロジェクトでも最初に行うようなことを行おうとして、ローカルサーバーで確認をしていこうと思った矢先、**「RecursionError: maximum recursion depth exceeded while calling a Python object」**と表示されてしまった。

# 原因究明
「RecursionError: maximum recursion depth exceeded while calling a Python object」
ちゃんとエラー文を読んでみると、「Pythonオブジェクトの呼び出し中に最大再帰深度を超えました」→再帰しすぎです。
ということだった。

「再帰関数なんてどこにも使ってない気がするんだけどな、、」と追記したファイルを漁っていく。

# 解決
①urls.pyを見てみると、下記のようなコードになっていた。

①urls.py

```urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test_api/', include('test_api.urls')),
]
```

これではtest_apiのurls.pyがtest_apiのurls.pyを呼ぶことになっていて、やはりエラー通り永遠に再帰してしまうことになってしまう。
ここを

```urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    # 修正前 path('test_api/', include('test_api.urls')),
    path('test_app/', include('test_app.urls')),
]
```
このように変更すれば、解決。

こんなバカなことするなと思う人が大半かと思うが、意外と間違えてこのように実装して焦る人もいるのではないかと思う。気をつけよう。
ソフトウェアエンジニアのメンタルについて考えてみた

# １．背景
ソフトウェアエンジニアは、メンタルを病む方が多いですね。
メンタルを病む方の姿は、見たくないものです。

なぜメンタルを病むのかについて考えてみました。

なお、本記事は気付きがあったら随時更新していきます！

# ２．考えたこと
## ２．１．評価制度のせい？
## ２．１．１．MBO
こちらの２つの記事を見つけました。

[1-1]安達裕哉，「頑張れば頑張るほど、成果が出なくなる「落とし穴」の話。」
https://blog.tinect.jp/?p=66582

[1-2]名無き仙人，「不安だから、頑張る貴方へ【今に感謝する】なぜ目標が高い人は幸せになれないのか？」
https://tensei.nanaki.biz/syme.html

この２つを読んで、ソフトウェアエンジニアに目標管理制度（MBO）は向いていないのでは？と感じました。
　-　ソフトウェアエンジニアの特徴
　　- 業務では、QCD達成が求められる。
　　- 個人では、常に新しい技術を身に着け続けていくことが求められる。
　-　目標管理制度（MBO）の特徴
　　- 一定期間内に目標達成を求められる。

ソフトウェアエンジニアは、新人時代に既存の技術を勉強すると思います。これが身に付いても次々登場する常に新しい技術を身に付けることが求められると感じます。10年前、5年前の技術は、役に立たないことが多いですね。つまり、常に頑張ってる心理状態です。

もし仮に、なんらかのタイミングで現状に満足・感謝したとしても、目標管理制度（MBO）で頑張ることを強く意識させられるため、頑張らなければならない状況に引きずり戻さている気がします。

常に頑張ってる状態なので、心が休まる暇がないのかもしれません。

## ２．１．２．MBOとリスクマネジメントシステム
リスクマネジメントシステムにおけるリスクは、次のような感じだと認識しています。
　-　今は発生していないけど、発生すればプロジェクトの目標に影響を与える事象
この事象は、次の２つに分かれると認識しています。
　-　好機：プラスに影響を与える事象
　-　脅威：マイナスに影響を与える事象
計画に対して、上振れも下振れも管理する必要があると認識しています。
ここで次の疑問がわいてきます。
　-　上振れは、ほんとうに良いことなの？
　-　下振れは、ほんとうに悪いことなの？
そもそも計画がおかしいだけかもしれません。

## ２．２．食えない人参
　-　https://millreef.co.jp/blog/aba/post-7435/

## ２．３．逃げ道・逃げ方を教えてもらえない？
[2-1]ITmedia，「なぜできない？」は「どうしたらできる？」に変えてみる
https://www.itmedia.co.jp/bizid/articles/0901/28/news114.html

できる方法を考えることは、大事なことだと思います。一方、「出来ない理由ではなく、出来る方法を考えなさい」としか教えられていない人は、「どうにも出来ない壁」に出会った時に、自らできる方法を考えるしかないため、もはや助けを求められる人はいない気がします。

「どうにも出来ない壁」は、ソフトウェアや、技術に関することはではない気がします。

例えば、人間関係などでしょうか。

教える側の「出来ない理由ではなく、出来る方法を考えなさい」は、業務に関することだけを指しているのかもしれません。ただし、教えられる側は、業務だけと捉えていない可能性は高いと思います。

だとすると
　-　「出来ない理由ではなく、出来る方法を考えなさい」を教えるならば、同時に逃げ方を教える必要がある
のではないでしょうか。

ただし、「出来ない理由ではなく、出来る方法を考えなさい」で育った人が、逃げ方を教えられるかは・・・。

# ３．対策
自分の手の届く範囲の人が、メンタルを病まないようにするための対策案を募集中！
新たな気付き・工夫を教えて頂きたいです！
Online Linux Terminal - Wazatermを支える技術



<iframe width="560" height="315" src="https://www.youtube.com/embed/CU82KSZ4Ev4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

私はサイドプロジェクトで [Wazaterm](https://www.wazaterm.com ) というWebサービスを開発しています。 WazatermはブラウザからLinuxを操作する端末(Terminal)Webアプリケーションです。 SSHでVPSなどのサーバに接続してリモート上で開発している人をターゲットとしています。

今年は[Wazatermアドベントカレンダーで使い方等を説明しているので詳しくはそちら](https://qiita.com/advent-calendar/2021/wazaterm )を見ていただければと思いますが、特長として下記があります。

* ブラウザから操作するのでOS/Device非依存
* CPUとメモリを自由に選べる
* SSHが使える
* ルート権限がある
* WebhookによるSuspend, Resumeの自動化できる
* バックアップを取れる
* 250以上のテーマから選べる
* ブラウザを利用するので日本語入力ができる


この記事では、Wazatermの解説よりもどのようなアーキテクチャになっているか説明したいと思います。

## サービスの全体像

![Untitled-2021-12-22-0702.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13663/1783b9af-b249-246a-68e5-2ad8bed4c597.png)


## コスト面で有利なスポットインスタンスの利用
AWSのEC2スポットインスタンスを利用しています。最近ではスポットインスタンの価格帯も安定しています。そして、キャパシティが足りなくてTerminateされるということも滅多にありません。Amazonのブラックフライデーでも少なくても私が使っているインスタンスは落ちることはありませんでした。Wazaterm にスポットインスタンスを利用したのはやはり価格面です。最大80％以上のコストのメリットがあります。また利用していないときに停止することができるのも環境に優しいので良い点だと思います。

## コンテナとしてLXDを採用
EC2インスタンスとユーザが使うLinuxの権限を分けるためにコンテナを利用しました。データを保存する必要があるのでDockerでは実現することはできないので、いくつかコンテナやVMを検証しましたが直感的にわかりやすく、ドキュメントもある程度しっかりして、Linuxでは広く使われているLXD/LXCを採用しました。

## ホストOSにはDebianを採用
AWSのスポットインスタンスでは明確にhibernateをサポートすると言っていませんが、検証してみるとhibernateが成功するタイプのインスタンスがあることがわかりました。ホストOSがUbuntuのときに失敗するケースがあり、Debianの方が成功したのでDebianを採用しました。他のディストリビューションは検証していません。

## PackerでAMIを作成
ホストのイメージも毎回手動で入れるのは面倒なのでPackerを利用しています。冪等性ですね。

## Heroku上にRails
サーバは慣れているRailsを採用しました。メインの業務でも開発して5年になるので呼吸をするように開発できます。RailsからAWS Ruby APIを叩いています。シンプルな構成をHeroku上に構築しています。

* Postgres — main DB
* Redis — background job(Sidekiq) + cache
* Sendgrid — email
* Papertrail — log

## ttydを使いUbuntuコンテナにアクセスする
ブラウザからterminalを使うJSモジュールは数多くあります。VS Codeのターミナルで使われるxterm.jsとサーバプロセスの組み合わせのモジュールもたくさんあります。私は[ttyd](https://github.com/tsl0922/ttyd)を採用しました。ttydをforkしてビルドしたものを使っていたのですが、esbuildを試したくなり、ttydのソースをコピーしてきてRails側でPrecomileしています。JSはtypescriptです。（適材適所でレイアウトで切ってJQueryも利用しています）

## 課金回り
Stripeを採用しています。やはりAPIドキュメントが素晴らしいです。3時間ぐらいで課金回りを実装できたのは驚きました。Paypalのこととか思い出すと遠い目になりますね。

## まとめ
個人のプロジェクトでSasS(Paas寄り?)を作るのは面白いです。インフラからフロントまで全て作れるので、全ての技術スタックを検証して実装、またそれを考えるのは楽しいですね。サイドプロジェクトで実験したものを本業へと知見を生かせているのでとても良いサイクルです。”プログラマたるもの自分のツールは自分で作る”を実行できています。できればマネタイズもできれば良いのですが、まぁそれは数年かけてということにしておきます。

PS 来年はGraviton2（Graviton3も)を検証して導入していきたい。
Flutter 標準で使えるアイコンのギャラリー

アイコンを探すのにいつも苦労するのでリンクを貼っておく。

## Material Icons

いわゆる `Icons.xxx` で使えるもの。

### 公式

https://api.flutter.dev/flutter/material/Icons-class.html

全部のアイコンが探せる。リストなので一覧性がイマイチ。


### サードパーティー

https://materialui.co/icons

7Spanというデザインチームが運営しているサイト。グリッド表示で一覧性、検索性が良く個人的にはこちらの方が好み。
もしかしたらFlutterで入ってないアイコンもあるかもしれないが今の所はそういったアイコンには出会ってない。

## Cupertino Icons 

https://web.archive.org/web/20210728212734/https://flutter.github.io/cupertino_icons/

いわゆる `CupertinoIcons.xxx` で使えるもの。公式が404になってしまっているので、しばし過去のアーカイブから参照する。
SQLアンチパターン厳選したまとめ



## SQLアンチパターンまとめ

SQLのアンチパターンをまとめました。
15項目ぐらいありますが、実際に必要なのは6個だけなのでこれらを抑えれば不適切なデータベースを作ることはなくなると思います。


https://techblog.short-tips.info/sql/3003id_required.md

https://techblog.short-tips.info/sql/3004hate_reference_key.md

https://techblog.short-tips.info/sql/3005Entity_attribute_value.md

https://techblog.short-tips.info/sql/3006polymorphic.md

https://techblog.short-tips.info/sql/3007_multi_column.md

https://techblog.short-tips.info/sql/3201fear_of_the_unkown.md
DBとGoogleスプレッドシートの簡単連携

# はじめに
最近DB使ってますか？
クラウド全盛の時代なので話題に上がることがめっきり減ってしまいましたが、基本に戻ってDBを使った連携をご紹介します。
DBは自分のPCに入っていたMySQLを使用。（ちなみにMySQLのMyって作った人の娘の名前だったんですね。。。「俺の」じゃなかったのか）
とりあえずテストデータ作成サイトなる便利なサイトがあったのでダミーの従業員データを作成して突っ込んでおきました。
こんな感じでDBにダミーの従業員データが入っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/68f2acbd-6f4d-913d-93a3-9fcf453c4cae.png)
連携先はGoogleスプレッドシート。APIを使用する接続先はCDataコネクタが得意としているところです。
あらかじめ次のようなシートを用意しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/5368bd0d-a82c-681a-2a3a-d9051d34fce8.png)
DBのデータをGoogleスプレッドシートに入れるときに少し加工したいので、今回はASTERIA Warpという製品を使用します。
ASTERIA Warpは簡単にいうと連携ツールなのですが、CDataコネクタが組み込まれたことによってある時期から接続先が一気に増えた経緯があります。最近流行ってきた？ノーコードツールでもあるので、誰でも簡単に扱えることを知っていただけるよう、早速取りかかってまいります！

#事前準備
- MySQL8 + JDBCドライバー
- ASTERIA Warp + Googleスプレッドシートアダプター
- OAuth認証情報の取得とコネクションの作成　[こちらを参照](https://support.asteria.com/hc/ja/articles/235577248-Google-%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC-Google-%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC%E3%82%92%E4%BD%BF%E3%81%86%E3%81%9F%E3%82%81%E3%81%AE%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E4%BD%9C%E6%88%90%E6%96%B9%E6%B3%95)

#フローの構成
フローの全体図は次のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/4ea5196f-59e5-864d-37af-260233eeabb2.png)

#RDBGetコンポーネント
 ![rdb_get.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/8ea760b8-49e9-b8a7-26b6-6d57cd9beb95.png)
DBからデータを取得します。
アイコンをダブルクリックするとSQLビルダーが起動するので、テーブルをドラッグ&ドロップして取得するデータにチェックボタンを付けるだけでSQL文が自動的に作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/e94da731-3a22-156d-ea20-9128049eb604.png)

#GoogleSheetsPutコンポーネント

![CDataGoogleSheetsPut.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/08d30124-b38b-e20f-6ba2-0c34151557e1.png)
Googleスプレッドシートにデータを書き込みます。
ダブルクリックすると「テーブルとフィールドの設定」ダイアログが開くのでテーブルを選択後、書き込むフィールドのチェックボックスにチェックを付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/4314b2ac-6435-3144-70ab-7d81c04f930d.png)

#Mappingコンポーネント
![mapping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/1fdf7d47-ce96-0c19-22a7-a42b8da66aac.png)
データのマッピングや加工を行います。
入力側のフィールドと出力側のフィールドを線で結ぶこと以外に、関数を置いてデータの加工を行うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/8e2f0926-58b0-9595-2dcc-ad861f786b4b.png)
上記の例ではSplit関数とIf関数を使用してデータの加工を行っています。

#実行結果
マッピングしたデータが登録されて、姓名の分割と性別の表記の変換も正しく行われていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151881/24e2461f-3963-d0b8-1569-ca8754a533a9.png)

#さいごに
CDataコネクタを使用するとどんな接続先でもSQLで処理することができるようになります。さらにASTERIA Warpを使用することでSQL文の組み立てやデータの加工が簡単に操作できるようになります。CDataの機能はASTERIA Warpのマルチセレクトオプションとして提供されているので気になる方は使ってみてください。
点字メーカープログラムの動画レビュー Part 4 - Rubyプログラミング問題にチャレンジ！ －改訂版・チェリー本発売記念－

## この記事は何？
Qiita Advent Calendar 2021「Rubyプログラミング問題にチャレンジ！ －改訂版・チェリー本発売記念－」で投稿してもらったコードを出題者である僕、伊藤淳一が動画でコードレビューしてみました。この記事はその第4回です。

https://qiita.com/advent-calendar/2021/ruby-challenge

第1回〜第3回のレビュー動画はこちらです。

https://qiita.com/jnchito/items/26e8bd7c635e3d32e620

https://qiita.com/jnchito/items/d5f71c9ad90f2890647e

https://qiita.com/jnchito/items/60c0342971d93b174b6b

### アドベントカレンダー参加者のみなさんへ

ネタバレになってしまうので、自分の投稿が完了するまでこちらの記事（動画）は見ないようにお願いします〜 :pray: 

### レビュー対象の記事はこちら！

今回レビューさせてもらったのは以下の16日目から19日目、21日目の記事です。投稿してくれたみなさん、どうもありがとうございました！

@libru1 さん

https://qiita.com/libru1/items/2dc59a3ebc3af2261496

@adebadayo さん

https://qiita.com/adebadayo/items/5aeaa24dc001970437ec

@sa_tech0518 さん

https://qiita.com/sa_tech0518/items/b30f4e8f780c12fa5849

@kazkura さん

https://qiita.com/kazkura/items/8b0132d4be98b7a02bea

@akmhmgc さん

https://qiita.com/akmhmgc/items/8164d45cb7ab90818ec3

## 動画でコードレビューしています

今回のコードレビューは動画で実施してみました。だいたい1投稿あたり5分〜10分ぐらいでさーっとコメントしています。
（あまりしっかりレビューできなくてすいません🙇🏻‍♂️）

動画はこちらです 👇

https://youtu.be/q2UkMw4syLU

「それは好みの問題や！」みたいなコメントもあるかもしれませんが、何か参考になれば幸いです。

## まとめ

こんな調子でまたこの後の投稿についでもレビューしていきたいと思います。みなさん、どうぞよろしくお願いします〜！

### 告知：銀座Rails#41で僕の解答例を公開します！

2022年1月25日（火）に開催される銀座Rails#41にて、僕の解答例を公開します。アドベントカレンダーに参加してくださった方はもちろん、そうじゃない方もぜひこのイベントに参加してもらえると嬉しいです😄

https://ginza-rails.connpass.com/event/234304/

### PR：改訂版・チェリー本が発売されました！🍒

「プロを目指す人のためのRuby入門 改訂2版（通称チェリー本）」が2021年12月2日に発売されました。この点字メーカープログラムを作る際にも役立つ知識が満載です。第1版を持っている方も持っていない方も、一度書店で手に取ってもらえると嬉しいです〜🍒

https://gihyo.jp/book/2021/978-4-297-12437-3

改訂版の見どころについては以下のブログにまとめていますので、こちらもあわせてどうぞ 💁‍♂️

https://blog.jnito.com/entry/2021/12/02/072804
BigQueryのQUALIFY句をWHEREもGROUP BYもHAVINGもない時に使う方法

今年にBigQueryにQUALIFY句が追加されました。
これを使うことで、今までならサブクエリを使って行う必要のあったRANKなどの分析関数の結果に基づいた絞り込みができるようになります。

しかし、QUALIFYには以下の3つのどれかと併用する必要があるという制約があります。

- WHERE
- GROUP BY
- HAVING

これらのいずれもない時には以下のエラーが発生します。

```sql
select start_station_name, bikeid, duration_minutes,
rank() over(partition by start_station_name order by duration_minutes desc) as rank
from `bigquery-public-data.austin_bikeshare.bikeshare_trips`
qualify rank <= 3
```

```
Error: googleapi: Error 400: QUALIFY clause must be used in conjunction with WHERE or GROUP BY or HAVING clause at [XX:XX], invalidQuery
```

# 答え
ダミーのWHERE句を追加する。
確実にTRUEになるWHERE句を追加し、syntax的にはWHERE句が存在するように見せかけることで、この制約を回避できます。

```sql
select start_station_name, bikeid, duration_minutes,
rank() over(partition by start_station_name order by duration_minutes desc) as rank
from `bigquery-public-data.austin_bikeshare.bikeshare_trips`
where 1 = 1 # 追加
qualify rank <= 3
```

参考：

https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#qualify_clause
Perlアプリケーション + AWS Lambda + API GatewayでWebhookを受ける

こちらは[Perl Advent Calendar 2021](https://qiita.com/advent-calendar/2021/perl)の21日目の記事になります。
昨日は　nanto_viさんによる

https://nanto.asablo.jp/blog/2021/12/20/9449537

でした。

---

さて、今年も軽い気持ちでPerl Advent Calendarに投稿してみようと思ったのですが、
今年は年末進行の深遠なる理由によりネタの仕込みが間に合わなかったため、
昨年の[PerlでGitHub webhookを受けるbotを作ってみた話](https://qiita.com/teckl/items/c3bff1419e06f2972949)をAWS Lambda + API Gatewayで動作するように手直ししてみましたので、今更のネタですが、軽い紹介とさせてください。。:bow:

# なぜ今頃これを試したのか？
某所で例のGitHub Webhookを受けるbotを運用しているのですが、
これまではわざわざ専用のホストを用意するまでもないような、ちょっとしたアプリケーション群をコンテナで上げていたのですが、今回事情によりそのホストを縮退することになりました。

わざわざサーバを立てるほどのものでもないし、費用面だけでなくサーバの管理コストも極力省力化したいという事になり、AWS Lambdaでサーバレスで省エネ化出来たら良さそうということで、締め切りに追われて試してみました。

# やったこと
https://shogo82148.github.io/blog/2018/11/30/perl-in-lambda/

https://shogo82148.github.io/blog/2018/12/16/run-cgi-in-aws-lambda/

を拝見しまして、 https://github.com/shogo82148/p5-aws-lambda の [psgiのサンプル](https://github.com/shogo82148/p5-aws-lambda/tree/main/examples/psgi)をまるっと流用させていただきました。

https://github.com/teckl/Lambda-GitHub-Webhook-Bot

元々たいしたことをしていないアプリケーションということもありますが、
diffにして見るとわずか数行程度の変更で、
AWS Lambdaのサーバレス化が組み込めてしまいました:relaxed:

# ハマった事
そもそもこれまでなかなか機会がなく、AWS Lambda + API Gatewayを触るのが初めてだった事もあって概念や用語などを把握するのに苦労しました。。

特にAPI Gatewayの方は最初参考にした記事が `REST API` のものだったため、「URL パスパラメータ」や「マッピングテンプレート」「ステージ変数」あたりの概念がなかなか理解できず、任意のパス(`/*/payload`)にルーティングさせる方法が分からずハマりました。。
（その後API タイプを `HTTP API` で作り直してみたら何事もなく動作してくれましたがｗ）

# やってみての感想
実際に触ってみて思ったのは、（3年遅れの反応ですが）Lambdaで動かす事によって過去のPerlアプリケーション・CGIなども十分にサーバレス化できそうになったのは改めてすごい事だなぁと…

特に、

https://shogo82148.github.io/blog/2021/06/13/aws-lambada-efs-and-perl/

https://d.nekoruri.jp/entry/2020/06/17/serverless-minibbs

こういった例を見ると、いにしえのCGI技術がこれからもサーバレスで生き続ける事が出来るというのは胸が熱くなりますねぇ…

…という事で内容は薄かったですが、とてもいい勉強になったのでこれから他にもPerlをLambdaに乗っけて遊んでみようと考えています。

明日は、papixさんによる

https://papix.hatenablog.com/entry/2021/12/22/234935

です！お楽しみに！
世の中の現象は「運動」で説明できる

#結論
日本の中学学校の理科の1分野、2分野は以下の3個に分類され、以下の構造になっている。

| 階層 | 内容|
|:--------|:---------:|
| 3階部分 | 生物、自然 |
| 2階部分 | 物質、電気 |
| 1階部分 | 運動 |

##運動
 力・速さ・加速度・エネルギー・直線運動・円運動・振動運動・圧力の基礎を学ぶ。

##物質、電気
それを応用して、物質と電気で身の回りの現象を説明する。熱・状態変化・光・電磁波・抵抗・イオン・親水性など。

##生物、自然
さらに応用して生物と自然というシステムを説明する。

---
私の感想だが、知識を構造的にとらえず、バラバラに単元を分けて3年間かけて教えられるため、理科の構造を理解している中学生は少ないと感じている。
【SQL】SQL入門

## はじめに
　本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## SQL入門

### SQLとは

SQLとは、データーベースに対する命令を記述するための言語です。
データの分析等をすることができます。

### SQL文　初歩
以下の通り記述することで、データベースからデータを取得することができます。
SQL文は終わりに`;`をつける必要があります。忘れないように注意しましょう。

```
# 指定したテーブルの指定したカラムのデータを取得する
　SELECT カラム名   # 複数指定する場合には「,」で区切る
　FROM　テーブル名;

# 指定したテーブルの全てのカラムから条件に合致したものを取得する
　　SELECT *
　　FROM　テーブル名
　　WHERE 条件式;   #　条件式には、「カラム名="太郎"」等を入れる。条件式を記述する際にはデータ型に注意。

# 指定した文字列を含むデータを取得
 SELECT *
　　FROM　テーブル名
　　WHERE カラム名　LIKE 文字列;  # 文字列には、ワイルドカード「%」を使用する。

# 指定した条件に合致しないものを取得する
　　SELECT *
　　FROM　テーブル名
　　WHERE NOT 条件式;   # NOTを記述する位置に注意。

# 指定したカラムがNULLであるデータを取得
 SELECT *
　　FROM　テーブル名
　　WHERE カラム名 IS NULL;　　　# NULLの場合には「=」は使えない。


# 指定したカラムがNULLではないデータを取得
　　SELECT *
　　FROM　テーブル名
　　WHERE カラム名 IS NOT NULL;   # NOTの記述位置に注意。

# 条件1と条件2の両方を満たすデータを取得
　　SELECT *
　　FROM　テーブル名
　　WHERE 条件式1
　　AND 条件式2;   

# 条件1と条件2のどちらかを満たすデータを取得
　　SELECT *
　　FROM　テーブル名
　　WHERE 条件式1
　　OR 条件式2;   

# 条件を満たすデータを降順で取得
　　SELECT *
　　FROM　テーブル名
　　WHERE 条件式
　　ORDER BY カラム名　DESC;   # ASCを指定すると昇順。

# 指定した数だけデータを取得
　　SELECT *
　　FROM テーブル名
　　WHERE 条件式
　　LIMIT 数;

```



## おわりに
上記以外に備忘録として記載する必要のあるものについては、随時追記する予定です。
本番環境でやらかしちゃったかもしれない話 2021-12-22

# 本番環境でやらかしちゃったかもしれない話

[本番環境でやらかしちゃった人 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yarakashi-production) 22日目。

log4jの脆弱性CVE-2021-44228を狙った攻撃が多発していますね。
ご存知の方も多いと思いますが、私のサーバにもこの日(12/10)から多くの攻撃者が訪れています。

[FortiGuard Labs Weekly Threat Briefs](https://www.fortiguard.com/resources/threat-brief)では、毎週どんな攻撃が流行っていたのか、週ごとにまとめて紹介しています。[12/17掲載記事](https://www.fortiguard.com/resources/threat-brief/2021/12/17/fortiguard-threat-intelligence-brief-december-17-2021)

```Log4j.Error.Log.Remote.Code.Execution``` が初登場で 検出数で1位を獲得しました。ThinkPHPやPHPUnitなど、昨年春からTOP5に鎮座していた競合からトップを奪取しました。すごいことです。

今回は、なんとlog4jさんのノック攻撃に返信してしまい、さらなる攻撃（第二波、第三波...）を受けるという失態を犯してしまいました。
皆さんも、サイバー問題を調査する際には、十分に注意してください。

## TL;DR

* 実際に受け取った攻撃コードから攻撃を調査するために、log4jへの攻撃が成功したと仮定し、攻撃コードを実行する。
* 攻撃者が用意したサイトにアクセスすると、攻撃用のJavaシリアライズコードが降ってくる。
* 被害サーバが特定されたことで、さらなる攻撃にさらされることになります。

## Log4j Vulnerability Summary はじめに。

* [Apache Log4j 脆弱性ガイダンス｜CISA](https://www.cisa.gov/uscert/apache-log4j-vulnerability-guidance)
    * おそらく最も権威があり、包括的な情報（各ベンダーの対策や影響状況）が記載されています。
* [JC3コラム - あなたのサーバーやウェブサイトは大丈夫! | トピックス｜脅威情報｜日本サイバー犯罪対策センター(JC3)](https://www.jc3.or.jp/threats/topics/article-418.html)
    * [JC3](https://www.jc3.or.jp/about/) という組織が一般向けに解説しています（ケー察も加わっています）。対応が甘い経営者に説明する際に紹介するにはわかりやすいページです。
* [Log4jの深刻な脆弱性CVE-2021-44228のまとめ - piyolog](https://piyolog.hatenadiary.jp/entry/2021/12/13/045541)
    * みんな大好きpiyokangoは、日本語で程よくまとまったまとめがあります。最初に把握するのに良いですね。
* [脆弱性を緩和するAWS WAF「Log4j Log4JRCE」、DevelopersIOサイトで3日分の検知結果を紹介｜DevelopersIO](https://dev.classmethod.jp/articles/log4jrce-devio-3day/)
    * クラスメソッドのAWS WAFは、実際にLog4jを標的とした攻撃を検出しました。

## Log4j exploitはUser-Agentとpathを利用する。

Log4jの攻撃コードは単純で、log4jがログとして食べれば [HTTPリクエストのどこでも](https://blogs.jpcert.or.jp/ja/2021/12/log4j-cve-2021-44228.html) 成功します.

そのため、一般公開されているWebサーバを運用している場合、アクセスログに大量に記録され、誰でも簡単に入手・閲覧することが可能です。

## 試してみたくなるようなコード実行

この攻撃の詳細については、Juniperのブログなどもそうであるように、多くのブログで紹介されています。

* [Apache Log4j 脆弱性 CVE-2021-44228 Raises widespread Concerns｜ジュニパーネットワークス公式ブログ](https://blogs.juniper.net/en-us/security/apache-log4j-vulnerability-cve-2021-44228-raises-widespread-concerns)

サーバーに配信された攻撃コードだけでなく、攻撃者がどのような攻撃を仕掛けてくるかを確認するのもよいでしょう。
調べる最も簡単な方法は、 ```ldap://example.com:389/...``` で始まるURLを追加することである。最も簡単な確認方法は、実際に ```ldap://example.com:389/...``` などで始まる URL を ```curl``` コマンドでリクエストしてみることです。

しかし、ここには大きな罠があります。

## 攻撃者が待ち受ける場所

攻撃者がサーバーに仕掛けたものには、主に2つのパターンがあるようです。

1. LDAPには、シリアライズされたJavaオブジェクトを保存するためのスキーマが定義されています。http://www.zytrax.com/books/ldap/ape/java.html
1. 被害にあったサーバーをノックして反応があれば、第2波、第3波の実攻撃を仕掛けるための罠を仕掛けている。

2番目の攻撃を仕掛けるときは、LDAPではなくDNSをターゲットにしようとするはずです。

LDAPの場合、インターネットへの通信がWebサーバーから発信される可能性は極めて低いので、ファイアウォールでブロックされることが多いのですが、DNSの場合、Webサーバーから発信される可能性は低いので、ファイアウォールでブロックされることはありません。しかし、DNSの場合、DNSの問い合わせはファイアウォール内のDNSキャッシュサーバーを経由してインターネット側へ発信されることになる。

攻撃者が用意した権威あるサーバにDNSクエリが届けば、被害サーバは応答したことになり、ターゲットにLog4jの脆弱性があることを知られることになります。

## では、攻撃コード(exploit)を実行する場合...

攻撃者のサーバーへの対応としてエクスプロイトコードを試す場合、TorなどでPCを匿名化してガードするのは当然ですが、本番サーバーに届いたコードを解析せずにそのまま実行しないようにしましょう。

どんな情報がついているのかわからないままコードを実行すると、報復ではないにしろ、とんでもない攻撃を招いてしまうかもしれません。
demo.localdev.meとは何者か

NGINX Ingress Controllerのインストールガイドに出てくるあいつ

https://github.com/kubernetes/ingress-nginx/

ローカル環境のkubernetesクラスタでNGINX Ingress Controllerを使う際、大体最初は公式ドキュメントに従ってセットアップし、通信が通るかの動作確認すると思いますが、その際の方法がこちら

https://kubernetes.github.io/ingress-nginx/deploy/#local-testing

単純なレスポンスを返すだけのpodとそれに対応するserviceを作成、最後にhostを`demo.localdev.me`にしたingressを設定
で、最後にingress controllerのserviceをport-forwardしてlocalhostからこのserviceへアクセス可能にします

ここまで設定すると

> At this point, if you access http://demo.localdev.me:8080/, you should see an HTML page telling you "It works!".

とある通り、確かにcurlなどで`http://demo.localdev.me:8080/`にアクセスすると`It works!`と返ってきます

完全にこのテストの本筋から脱線してるのですが
このdemo.localdev.meはどっから出てきてなんで普通にlocalhostに名前解決できているのか？
ということがわからずに気になってしまいました

普通こういうのって/etc/hostsに登録するじゃないですか

# なんのことはない

`.me` ってれっきとした国別のドメインなんですね、`.jp`みたいなやつ

https://ja.wikipedia.org/wiki/.me

それで誰かが`localdev.me`を取得してるみたいです

digしてみると

```
$ dig +trace demo.localdev.me
---省略---
demo.localdev.me.	300	IN	A	127.0.0.1
localdev.me.		172800	IN	NS	ns-1276.awsdns-31.org.
localdev.me.		172800	IN	NS	ns-1699.awsdns-20.co.uk.
localdev.me.		172800	IN	NS	ns-276.awsdns-34.com.
localdev.me.		172800	IN	NS	ns-734.awsdns-27.net.
;; Received 201 bytes from 205.251.194.222#53(ns-734.awsdns-27.net) in 111 ms
```

このような感じなので、`demo.localdev.me`を`127.0.0.1`のAレコードでパブリックDNSに登録してるみたいです
route53っぽいですね
NGINX Ingress Controllerの人がやってるんだろうか

# お得情報なのでは？

`demo`の部分は何でも127.0.0.1に解決できるみたいです
`hoge.localdev.me`など
なんなら`localdev.me`も同じ

このへんよく知らないですけど、ワイルドカードな形でDNSレコードが登録できるんですかね

これ勝手に使えば/etc/hostsを触らなくて済みますね、地味に便利かも