OmniAICreator/Qiita-1.07M huggingface dataset:
ECDSAを含むSSH鍵を複数管理する（SourceTree使用）

## はじめに
今までGithubに使用するSSHキーはRSAしか使用したことがありませんでした。

つい最近ECDSAで生成する機会があったので、記載しておこうと思います。

下記のような方には少し参考になると思います。

`・SourceTreeを使っている`
`・イマイチ鍵について分かっていない`
`・RSA以外に使用してみたい`
`・ターミナル操作が苦手`

## そもそもECDSAとはなんぞや

SSHの公開鍵暗号には「RSA」「DSA」「ECDSA」「EdDSA」という種類があります。

その中の`ECDSA`は楕円曲線DSAとも呼ばれビットコインやイーサリアムの文脈では特にトランザクションの署名に使われます。

なかなか難しい内容なので詳しく知りたい方は下記をチラ見してくださいｗ
https://zoom-blc.com/what-is-ecdsa


## SourceTreeでSSHキーを登録する

※既に登録済みの方はスルーで大丈夫です

- 環境設定→アカウント→追加
![スクリーンショット 2022-06-27 16.30.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/76faa4f9-4381-b773-7f37-a8431fd9510d.png)

GitHubのユーザー名、パスワードを入れる
※ハスワードについてはGitHubのSettings→Developer settings→Personal access tokensで追加
![スクリーンショット 2022-06-27 16.37.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/284866a4-8cb1-34ac-33ca-fd50a7a96e19.png)

Noteは自由な名前でOK、repoにチェック

![スクリーンショット 2022-06-27 16.37.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/244b4b80-019a-2522-b078-99ad86e57d1e.png)

ユーザー名とパスワードを入れたらキー生成ボタンを押します

![スクリーンショット 2022-06-27 16.40.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/fd81d215-2b2f-243f-6ea0-1e6fd43bd15a.png)

そうしたら、キーが生成されているか確認してみましょう。

Finderでホームディレクトリに移動します。
`※ホームディレクトリがない！`って人は[こちら](https://gahaha.xyz/catconfigmac/howtodisplayhomedirinfinder.html)で確認しましょう

ホームまで来たら隠しファイルを表示するため `Command ＋　shift ＋　.`を打ち、`.ssh`ファイルを確認します。
![スクリーンショット 2022-06-27 16.50.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/ec73af0e-44b7-bcaa-b20e-709c1c6dc8cb.png)

中には公開鍵・秘密鍵のペアがちゃんと登録されています！
![スクリーンショット 2022-06-27 16.52.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/7442223c-6e93-a9f3-9d43-778375ce9c6d.png)

configファイルを確認すると、SourceTreeで登録した内容が記載されています。
![スクリーンショット 2022-06-27 16.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/b499afef-b235-d0b1-5753-ae551471fc30.png)

あとは公開鍵（.pubのほう）の内容をGitHubに登録して完了です↓
![スクリーンショット 2022-06-27 16.58.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/7f010c3c-6a73-53b4-9625-554ba434de67.png)


## ECDSAキーを登録する

さて本題ですが、まずkeyをコマンドで生成します。

`ssh-keygen -t ecdsa -b 256`

色々質問されますが、全てEnterを打ちます。

そうすると先程の`.sshファイル`に鍵が生成されていることが確認できます。

![スクリーンショット 2022-06-27 17.07.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/1ca8e011-cc44-55c4-0ab4-dc9c5a5eb0cf.png)

そしてconfigファイルを開き、下記情報を追記します。

```:   
Host Hoge　　            //自由に変更できる　　　　ここでconfigファイル内の情報が識別される
    HostName github.com
    User git
    Port 22
 IdentityFile ~/.ssh/id_ecdsa　    　//ディレクトリのパス
```

次に先程と同じようにGitHubに公開鍵を登録します。

## ECDSA鍵を使用してリポジトリをクローンしたい時

ECDSAで生成した鍵を使用したい場合は、`github.com`の部分を上でいう`Hoge`の名前に変更する。
![スクリーンショット 2022-06-27 17.19.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/44317758-1e67-0b30-d51c-de7c5fcc6cf5.png)

↓↓↓↓↓↓

![スクリーンショット 2022-06-27 17.30.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112697/6e19f1c0-5bd7-36b8-1bb5-5315d4ac301c.png)

## 終わりに

SSH鍵に関しては最初手こずったので、初心に戻って書いてみました。

間違っている箇所があるかもですがご指摘いただければと思います。

少しでも役に立てばLGTMお願いします♪
MacのAlfredでクエリ検索できるカスタムサーチを作る

次の韻検索ツールを例にカスタムサーチを作ります。

https://kujirahand.com/web-tools/Words.php

ここのサイトは、単語を検索欄に入れることで母音が同じつまり韻を踏んでる単語をリストアップしてくれます。

完成形としては、Alfredに「wd \<単語\>」のように入力して使います：

![スクリーンショット 2022-06-27 21.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/25651f96-5136-9cee-0266-d0d1884dc379.png)

# 検索した際のURLを特定する

このツールで単語を検索欄に入力すると次のようなURLが生成されます：

```
https://kujirahand.com/web-tools/Words.php?m=boin-search&key=<単語>&opt=comp&len=%3F
```

# Alfredに設定する

Alfredのpreferencesページを開きます（Alfredで「preferences」と検索すれば表示できます）。

Custom Searchesに進んで、「+」のマークを押します：

![スクリーンショット 2022-06-27 21.14.20 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/76cb6f07-1f2e-967c-81ca-44693e230cad.png)

次のように設定します：

![スクリーンショット 2022-06-27 21.17.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/0bdff14f-7829-2eb1-dbb0-4e8624f6ddf3.png)

「Search URL」の部分には、最初に特定したURLより次を指定します：


```
https://kujirahand.com/web-tools/Words.php?m=boin-search&key={query}&opt=comp&len=%3F
```

検索した単語が入る部分に`{query}`と書きました。

「Keyword」には "wd" と指定しました。これにより、"wd" の次に半角スペースを開けて、それに続けて検索したい単語を入力します：

![スクリーンショット 2022-06-27 21.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/c79b0fbb-1e3a-173e-243b-87e61f4ee2e6.png)

Alfredカスタムサーチの設定にある「Title」については、上の画像にあるように表示されます。
権限セットの考慮事項

Link：
https://help.salesforce.com/s/articleView?id=sf.perm_sets_considerations.htm&type=5

・Apex クラスのアクセス
権限セットについて、最上位の Apex クラスのどのメソッドが実行可能であるかを指定できます。Apex クラスのアクセス設定は、次のメソッドにのみ適用されます。
Web サービスメソッドなどの Apex クラスメソッド
Visualforce ページに適用されるカスタム Visualforce コントローラまたはコントローラ拡張で使用されるメソッド
トリガは、権限設定に関係なく、トリガイベント (insert または update) で必ず起動されます。
・割り当てられたアプリケーション
割り当てられたアプリケーション設定では、Lightning Platform アプリケーションメニューで選択できるアプリケーションを指定します。プロファイルとは異なり、権限セットではデフォルトのアプリケーションを割り当てることはできません。アプリケーションを表示するかどうかのみを指定できます。
・コミュニティ
権限セットをコミュニティのメンバーシップに割り当てると、その権限セットに割り当てられたユーザにコミュニティへのアクセス権が付与されます。コミュニティへのメンバーシップを付与するために使用されている権限セットに権限を追加すると、コミュニティメンバーにもコミュニティメンバーシップに関連しない権限へのアクセス権が付与されます。新しい権限を追加する前に、権限セットがコミュニティのメンバーシップリストで使用されているかどうかを確認することをお勧めします。
・制限
必ず、特定のエディションに関する Salesforce のエディション別の機能制限を参照してください。
・新しい権限セットとコピーした権限セット
新しい権限セットには、開始時に選択されたユーザライセンスと有効な権限はありません。コピーした権限セットには、コピー元の権限セットと同じユーザライセンスと権限があります。コピーした権限セットのユーザライセンスは変更できません。新しい権限セットに元の権限セットと同じユーザライセンスを設定する場合のみ、権限セットをコピーしてください。
・オブジェクト権限
プロファイルまたは権限セットには、主従関係のあるエンティティ (取引先など) を含めることができます。子エンティティに親が持つべき権限があると、権限の連動関係が壊れます。Salesforce は、プロファイルまたは権限セットの最初の保存アクションで壊れた権限の連動関係の親エンティティを更新します。
子エンティティに次の権限がある場合	　　　親エンティティで次の権限が有効
「すべて変更」または「すべて表示」        　　　「すべて表示」
「すべて変更」または「参照」	　　　　　　「参照」
・権限セットグループ 
組織に多数の権限セットがある場合、権限セットグループを使用するとパフォーマンスが改善することがあります。
・権限セットライセンス
API バージョン 38.0 以降、権限セットを作成して権限セットライセンスに関連付けることができます。特定の権限セットライセンスを使用して権限セットを作成すると、その権限セットに割り当てられているユーザは、権限セットライセンスに関連付けられているすべての機能を利用できるようになります。
・プロファイル
API バージョン 25.0 以降、明示的に割り当てられているかどうかに関係なく、すべてのプロファイルは自動的に権限セットに関連付けられます。この権限セットには、プロファイルのユーザ権限、オブジェクト権限、項目権限と、設定エンティティアクセス権設定が含まれます。これらのプロファイルによって所有される権限セットは、照会できますが、変更はできません。また、ユーザインターフェースには表示されません。
・ユーザライセンスの制限
一部のユーザライセンスでは、ユーザがアクセスできるカスタムアプリケーション数またはカスタムタブ数が制限されます。この場合、ユーザに割り当てられたプロファイルと権限セットを使用して、許可された数のみを割り当てることができます。たとえば、ある Light アプリケーションにアクセスできる App Subscription ユーザライセンスを持つユーザは、そのアプリケーションのカスタムタブにのみアクセスできます。
基本情報（メモリの種類）

メモリはコンピュターの動作に必要なデータを記憶する装置です。
メモリを分類すると**RAM**と**ROM**に分かれます。

```
半導体メモリ - RAM - DRAM
                  SRAM
          
          - ROM - マスクROM
                - PROM    - EPROM 
                          - EEPROM
                          - フラッシュメモリ 

RAMは電源を切ると中身が消えてしまう、読み書き可（揮発性）
ROMは電源を切っても中身が消えない、読み出し専用（不揮発性）  
```

RAMは（Random Access Memory）の略です。
ROMは(Read Only Memory)の略です。

## RAMの種類
ランダムに読み書きできるメモリです。
主記憶装置に使われるDRAMとキャッシュメモリに使われるSRAMの2種類に分かれます。

```
DRAM (Dynamic RAM)
安価で容量が大きく、主記憶装置に用いられるメモリです。
読み書きはSRAMに比べて低速。記憶内容を保つためには、定期的に内容を再書き込みする
リフレッシュ動作が欠かせない。メモリといったらDRAMのことを指すことが多い。

使用する回路　　リフレッシュ動作　　速度　　集積度　　価格　　主な用途
コンデンサ   必要　　　　　　　　　　　　　　　　　　低速　　高い　　　　　　安価　　主記憶装置

SRAM(Static RAM)
DRAMに比べて非常に高速だが、価格が高い。小容量のキャッシュメモリとして用いられるメモリ。
記憶内容を保持するのに、リフレッシュ動作は必要ない。

使用する回路　　      リフレッシュ動作　　 速度　　集積度　　価格　　主な用途
フリップフロップ回路   不要　　　　　　　　　　　　　　　　　　高速　　　低い　　　　　　高価　　キャッシュメモリ
```
## ROMの種類
リードオンリーなメモリですね。
基本的には読み出しだけですが、専用の機器を使うと記憶内容の消去と書き込みができる
PROMという種類も存在します。

```
マスクROM
読み出し専用のメモリ。製造時にデータを書き込み、以降は内容を書き換えることができない。
通常ROMといえば、マスクROMです。

PROM（Programmable ROM）
プログラマブルなROM。ユーザーので手で書き換えることができるROMです。下記の種類があります。

EPROM(Erasable PROM)
紫外線でデータを消去して書き換えることができる。

EEPROM(Electrically EPROM)
電気的にデータを消去して書き換えることができる。

フラッシュメモリ
EEPROMの１種。全消去ではなく、ブロック単位でデータを消去して書き換えることができる。
```
## まとめ
パソコン組み立てましょう。
Anacondaを使ってyolov5で画像を学習させて物体検知する

※yolov5の導入方法についてはこちらを参照
「AIと電子工作系ブログ　2022年1月時点のyolov5の導入方法」
https://soiyasoiya58.hatenablog.com/entry/2022/02/14/204400

1. labelimgをインストールする
※labelimgのインストールはこちらを参照
https://laid-back-scientist.com/labelimg

2. data/predefined_classes.txtにラベル名を入力する
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/fec9843c-56cc-bcd7-81ee-d643afa199f5.jpeg)


3. exeを実行してlabelimgを起動する
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/f5ecb131-e5f3-1ce8-22c2-a5b7d6159f03.png)

4. 画像を読み込み、「YOLO」を指定して、位置の指定とラベル名の設定を行い保存する。
画像名.txtファイルが生成される。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/5039e9e2-8359-908e-93be-dcbd091e2304.jpeg)

5. 画像ファイルとtxtファイルを配置する
![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/827a1e76-cbf3-f32d-8aef-4b8095cab31e.jpeg)

6. Anacondaを起動する
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/6dc6e7fb-dacb-5a72-827e-c280a7829b6e.jpeg)

7. Environmentsをクリック⇒yolov5⇒Open Terminalをクリックする
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/a1126882-9144-7dc8-a79c-7280bd5cf261.jpeg)

8. 仮想メモリを設定しておく。
SystemPropertiesPerformance.exe を実行して[パフォーマンス オプション] ダイアログ ボックスを表示する。 [詳細設定] タブを選択して「仮想メモリ」 ボックス内の変更ボタンをクリックする。
「すべてのドライブのページング ファイルのサイズを自動的に管理する」チェックボックスをOFFにする。
「カスタム サイズ」を選択、[初期サイズ (MB)] と [最大サイズ (MB)] を設定する。
![a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/1b6a45a5-7653-eb6f-6c07-a03770ee3e60.jpeg)


9. Terminalから画像を学習させるコマンドを実行する。
cd yolov5-6.0
python train.py --img 640 --batch 16 --epochs 200 --data ./kaiko_Dataset/kaiko.yaml --weight yolov5s.pt


10. 学習が完了する。
![val_batch0_pred.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/6e61f96a-191a-4dd7-2e97-ea79c0c53917.jpeg)
![results.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/11c4e547-e682-f0c5-af1c-d371348a28d2.png)


11. 学習結果（best.pt）を元に物体検知を行う
python detect.py --source ./kaiko_Dataset/test --weights runs/train/exp16/weights/best.pt


12. 結果が表示される
![20220615_065432.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/207bac3a-288c-7917-22a2-f3074f26f3b2.jpeg)

13. 学習対象の画像を増やしてみる。
![val_batch0_pred.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/1c6f00a6-9cd1-bb86-246d-95a8ff2f7024.jpeg)
![results.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/a8a71583-42e8-c0b2-4058-9822fceccad7.png)


14.　再び物体検知を行う。
![k1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/c9860388-9cb5-c923-bd19-2c49ec191b1d.jpeg)

![k2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/bce67ada-ecf2-654f-d8f9-83a4c179c505.jpeg)

![k3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/0f96e6fa-4e51-d99c-684c-3d9bcd46efc8.jpeg)

![k4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258265/87a1fc85-d0be-0b44-4fe5-5f8041b86396.jpeg)
【Laravel】中間テーブルの定義でPivotを使った場合のBefore/After



## 環境
Laravel v9.5.1 (PHP v8.1.3)

>usersテーブル
    id - integer
    name - string

>rolesテーブル
    id - integer
    name - string

>role_userテーブル
    user_id - integer
    role_id - integer

## Pivotを使わない場合

```Models/RoleUser.php
class RoleUser extends Model
{
  ...
  public function user(): BelongsTo
  {
	return $this->belongsTo(User::class);
  }

  public function role(): BelongsTo
  {
	return $this->belongsTo(Role::class);
  }
}
```

```Models/User.php
class User extends Model
{
  ...
  public function roleUsers(): HasMany
  {
	return $this->hasMany(RoleUser::class);
  }
}
```

```Models/Role.php
class Role extends Model
{
  ...
  public function roleUsers(): HasMany
  {
	return $this->hasMany(RoleUser::class);
  }
}
```

userからroleを取得するとき、めちゃくちゃめんどくさいし分かりづらい！

```php
User::first()->roleUsers()->first()->role()->first()
```

## Pivotを使う場合
```Models/RoleUser.php
use Illuminate\Database\Eloquent\Relations\Pivot;

class RoleUser extends Pivot
{
  ...
  public function user(): BelongsTo
  {
	return $this->belongsTo(User::class);
  }

  public function role(): BelongsTo
  {
	return $this->belongsTo(Role::class);
  }
}
```

```Models/User.php
class User extends Model
{
  ...
  public function roles(): BelongsToMany
  {
	return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
  }
}
```

```Models/Role.php
class Role extends Model
{
  ...
  public function users(): BelongsToMany
  {
	return $this->belongsToMany(User::class, 'role_user', 'user_id', 'role_id');
  }
}
```

userからroleを取得するとき下記のようにしたら取得できるので、シンプルで分かりやすい！

```php
User::first()->roles()
```

## 参考

https://readouble.com/laravel/9.x/ja/eloquent-relationships.html
ロードバランサー・リバースプロキシざっくり概要[メリットデメリット]

# ロードバランサーとは
大量のアクセスに対するサーバーへの負荷を分散させるための仕組みです。
また複数サーバーへアクセスを分散させる際、ダウンしているサーバーを検知してそのサーバー以外に分散させます。そのため、システムダウンを防いでくれます。


アクセス集中によるシステムダウンやサーバーが故障して停止するといったアクシデントはwebサイトを運営するうえで起こりえるものなので、ロードバランサーのような機能が必要になってくるのです。
（補足: ロードバランサーはLBと略されたり、負荷分散装置と呼んだりします。）

## ロードバランサーのメリット

### システムダウンを防ぐ

先ほど大体書きましたが、サーバーへのアクセスを分散させることによりサーバーへの負荷が軽減します。アクセスが一極集中すると高負荷になりシステムダウンを招く恐れがありますが、アクセスを分散させれば回避できます。

![ロードバランサーアクセス分散.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/388f4676-5319-35c3-07b9-c02930a3dbf4.png)


複数サーバーの内、システムダウンしているサーバーを避けて振り分けてくれるため、ユーザーはシステムダウンしているサーバーを利用できないようにしてくれます。
その間にサーバーのメンテナンスを行うこともできるのでシステムの可用性は高まります。

### 処理速度の低下を抑えることができる

サーバーへの負荷を分散させることにより、CPU・リソースなどが効率的に使用可能になる。分散させない時より処理が高速になり、webページの表示速度が向上します。

### 拡張性に優れている

今後サービスが拡大してアクセス数が増大すると、現状のままでは処理能力不足が懸念されるかもしれません。
しかし、ロードバランサーでは必要分のリソースに合わせて拡張することができます。


## ロードバランサーのデメリット

### 導入費用が高額

ロードバランサーの導入には必要な機器を用意する必要があるので、高額な費用がかかってしまいます。
その費用を払えるかどうかを検討してから導入するべきです。

ただ、上記はハードウェアタイプのお話で今だとクラウドタイプのロードバランサーがあり、機器を揃えなくても利用できるため、こちらのほうが安価で導入することができます（AWSなどで利用できる）。

### サービスの選定が難しい

ロードバランサー製品を提供している会社はいくつもあり、取り扱うサービスに適した製品かどうかを選択するのが難しいです（[こちら](https://www.itreview.jp/categories/loadbalancer#tutorial) でどのようなサービスがあるか確認できます）。

# リバースプロキシとは
## その前にプロキシとは

プロキシサーバーは内部ネットワーク（社内ネットワークなど）とインターネットの間に立って代理人としての役割を果たしています。

図のように一連の通信の流れの中で中継役をしています。
クライアントのwebサイトへのリクエストをプロキシサーバーが受け取り、クライアントの代わりにプロキシサーバーがwebサーバーへリクエストします。
プロキシサーバーは、webサーバーからのレスポンスを受け取りクライアントに返します。

![プロキシ仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/8b2a0a53-fabb-6d79-ed7b-e3be98961ad5.png)



## プロキシサーバーのメリット

### プロキシサーバー上にログが記録される
サイトへのアクセスなどがログとして記録に残されます。サイバー攻撃による被害発生時でもログ解析を行い対応方法を考える材料になります。

### 匿名性が確保できる
個人のIPアドレスではなくプロキシサーバーのIPアドレスが送信されます。
アクセスした端末を隠すことでインターネット上の様々な脅威から守ることができます。

### ウイルスチェックができる
個人が使用しているPC端末ではなく、プロキシサーバーでウイルスチェックを行うことができます。社内ネットワークへのウイルスの侵入を防ぐ役割にもなり、安全性の向上につながっています。

## リバースプロキシ

リバースプロキシは外部からのwebサイトなどのアクセスを代理で受けてPrivateな領域に配置しているwebサーバーへリクエストを行う役割を果たしています。

図のように一連の通信の流れの中で中継役をしています。
クライアント(PC)のwebサイトへのリクエストをインターネット経由でリバースプロキシサーバーに送信されます。
リバースプロキシサーバーはwebサーバーへリクエストを行います。
webサーバーはリバースプロキシサーバーにレスポンスを行い、リバースプロキシサーバーはクライアント(PC)にレスポンスします。

![リバースプロキシ仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/bae49b0a-7d5b-b2a3-ef60-9030c486495e.png)

### リバースプロキシのメリット

#### 負荷の分散
リバースプロキシを1台用意することで、クライアントに対して単一サーバーとしてふるまえます。クライアント側から見ればリバースプロキシ1台ですが、リバースプロキシの裏にはwebサーバーが複数配置されており、大量アクセスを各サーバーに振り分け処理することが可能（ロードバランサーと似たようなもの）です。

#### SSL証明書の管理が最小限
リバースプロキシ1台が複数のwebサーバへアクセスする場合でも、SSL暗号化はクライアント⇔リバースプロキシ間で済みます。
クライアント⇔リバースプロキシ間はhttpsによる通信、リバースプロキシ⇔webサーバー間はhttpによる通信が可能になります。


#### 異なるアプリケーションの統合
リバースプロキシ1台で役割が異なるwebサーバーを複数用意可能で、1つのIPに異なるアプリケーションを統合させることができます。

例:
example1.com → 動的ページ応答
example2.com → 静的ページ応答



### プロキシ・リバースプロキシのデメリット

#### サイバー攻撃を受ける可能性がある
プロキシおよびリバースプロキシは、DMZ(非武装ネットワーク)に設置されるのが一般的であるため、セキュリティ上の考慮が必要になります。
DMZは内部のネットワークに接続を許可しないが、外部と接続する領域にサーバーが配置され、外部ネットワークと接続を行います。
つまり、外部から直接アクセスが可能であり、サイバー攻撃の対象となります。
定期的に設定の確認をして、意図しない動作や設定でないか確認、またパッチにより最新の状態を保つなど対応していく必要があります。
チームビルディングやってみた〜新メンバー加入編〜

## またもや自己紹介
2022年6月に、チームにさらに新メンバーが参加することになりました。毎回、同じ自己紹介のワークを行なってきたのですが、最初から所属しているメンバーはそろそろ飽きてきたので、ちょうど良い機会だと思い、「9-Tiles」という新しい自己紹介のワークを取り入れてみることにしました。また2、3週間後に「WorkingAgreement」というチームのルールを決めるチームビルディングも行ったので、そちらもご紹介します。

ちなみにこれまでの話は…
自己紹介の際におすすめのチームビルディングはこちら（[前々回](https://qiita.com/javano/items/4e6db46ee35304e9943a)）
なぜチームビルディングをするべきなのか「心理的安全性」の話はこちら（[前回](https://qiita.com/javano/items/23904ab89c695dc25c40)）

## やってみた自己紹介ワーク 9-Tiles
 今回はじめてやってみた自己紹介ワーク「9-Tiles」、自分の名前を中心に書き、その周辺に自分のことについてみんなに知らせたいことを8つ書いていきます。ちょっとゲーム性を持たせるためにそのうちの1つには嘘を混ぜることにしました。各メンバー書き終わったら1つずつ順番に説明していき、聞いていた人たちは内容などについて質問をしていきます。一通り質問が終わった後にどれが嘘だったかを投票して、正解を明かします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/83d411e0-81ef-8eb1-ec6f-24f354e4ad06.png)
やってみると、なかなか8つ出すことが出来ずに、書く時間の延長を求めるメンバーが多かったです。仕事関係で3つ、性格について1つ、休日の過ごし方について2つなど、大雑把にカテゴリ分けなどを決めておくと書きやすくなるかもしれません。
また、嘘を1つ混ぜるというのが思いのほかに難しく、うまくさりげない嘘をまぜれた人もいれば、発言している途中からこれは怪しいぞと見抜かれているメンバーもいました。

## 働き方や価値観を共有してチームのものとする WorkingAgreement
自己紹介も済み、チームのリズムがうまく周り始めたかなというタイミングで、WorkingAgreement（ワーキングアグリーメント） というワークに取り組みました。簡単にいうとチームで一緒に働く際のルールや価値観を決めるワークです。一緒に仕事していくにあたって、メンバーがストレスを抱えず、働きやすい環境を整えるために作成します。例えば、「Aについてはチームみんなで合意している」「Bについては〜派と〜派の考えのメンバーがいる」など、予め知っておくことで、知らず知らずに強要してしまっていることや、誰かのストレスになっていることなどを防ぐことができます。今回私のチームで行ったやり方としては、「技術的なこと」「仕事中の過ごし方」「視点や価値観」「アグリーメントというよりは状態」「プロダクトへの取り組み方」という5つのカテゴリわけて各メンバーに案を出してもらい、1つ1つ出した理由などを話してもらいました。その上で、合意できるかどうか、できるもの全てにサムズアップスタンプをおいてもらい、全員が合意したもののみをワーキングアグリーメントに加えました。（今回は5人）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/36da05c7-26f5-1894-e78a-0deb842584f2.png)
やってみると、これは全員が合意できそうだなと思うことでも、意外に揃わないことも多かったです。その際は、揃わなかったですねで終わらせずに、なぜ合意できないのかという理由を聞いてみることで、さらに議論が深まるきっかけにすることができました。
ここで決めたアグリーメントは、今回きりで固定するものではなく、1ヶ月間隔くらいで更新していくと、チームの状況によって最適な状態にアップデートできるのでオススメです。
　
## まとめ
最近行ったチームビルディング2つをご紹介しました。今回新メンバーが入るにあたり、チームに参加してもらう初日の一番最初に自己紹介系のチームビルディング＋全員でランチを実施したことで、初対面の固さがとても早く解け、新メンバーが早い段階からチームに馴染んでくれたと実感しています。忙しい業務の中、時間を確保するのは大変ですが、その価値はあったと思いますので、ぜひチーム結成や、新メンバー加入の際はお試しください。

## 参考・引用
- [ワーキングアグリーメント](https://fintan.jp/page/274/)
- [自己紹介で使える"9-Tiles"](https://scrapbox.io/yohhatu/%E8%87%AA%E5%B7%B1%E7%B4%B9%E4%BB%8B%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%229-Tiles%22)
Git 基本操作

## クローン
```sh:commond
$ git clone {GitリポジトリのURL}
```

## ローカルブランチ作成
```sh:commond
$ git branch {ローカルブランチ名称}
$ git branch
```
## リモートブランチ作成
```sh:commond
$ git checkout {プッシュするローカルブランチ名称}
$ git branch
$ git push -u {リモートリポジトリ名称} {リモートブランチ名称}
# ex) git push -u origin develop
```
## コミット
```sh:commond
$ git add {コミットするファイル名称}
# ex) git add .
$ git commit -m "{コメント}"
```
## プッシュ
```sh:commond
$ git push {リモートリポジトリ名称} {リモートブランチ名称}
# ex) git push origin develop
```
【PHP基礎⑲】配列-3.連想配列

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksBasic.html)
要素数5の整数型の配列を宣言し、すべての配列に対して順に入力された整数値を代入し、すべての要素の値を表示するプログラムを作成しなさい。


# コード
```php
$a = [1,2,3,4,5];
foreach($a as $key => $m){
    $a[$key] = intval(fgets(STDIN));
}
foreach($a as $i){
    echo $i, PHP_EOL;
}
```

↓
「6
　3
　5
　7
　-2」　　　と入力


# 結果
```
6
3
5
7
-2
```

☆連想配列
・配列では、0番目、1番目…と番号（キー）が振られて、そのキーを指定することで要素を指定し取り出せた。
一方、連想配列では番号の代わりに名前をつけて要素を管理することができる。

＄a = ['りんご' => '赤色', 'バナナ' => '黄色', 'みかん' => 'オレンジ色'];
→＄a['りんご']とすれば、'赤色'を取り出せる。

・「=>」は「→」のような意味で、りんごは赤色のラベルのような感じ。
=>を使うことでキーと値をペアにして要素を作ることができる。

・連想配列でforeach文を使う場合は、
foreach(＄配列変数 as ＄キー取得変数 => ＄値取得変数){
　　　実行する処理;
}

となる。
Git サブモジュールをクローン

## サブモジュールと一緒にクローン
Gitリポジトリをクローンする時に、そのGitリポジトリのサブモジュールも一緒にクローンするために使用するコマンド。
```sh:commond
$ git clone --recursive {GitリポジトリのURL}
```

## サブモジュールをクローン
Gitリポジトリをクローンし、その後サブモジュールをクローンするために使用するコマンド。
```sh:commond
$ git submodule update –init
```
上記が権限問題等でクローン出来ない場合、下記で解消される可能性がある
```sh:commond
$ git pull --recurse-submodules
$ git submodule foreach --recursive git reset --hard
```
動画学習だけでは伸び悩んでないですか？〜エンジニア勉強法再考〜

## 概要

特にエンジニア（もしくはそれを目指す人）に向けて、勉強方法の選択肢を整理した記事です。

それぞれの手段の良し悪しを理解して、バランス良く勉強できると良いですよね。

## 読んでほしい人

- 「そもそもどうやって勉強すれば良いかわからない」という人
- 「動画で勉強しているけど、なかなか身につかない」など、学習意欲があるのに、上手く結果が出せていない人

※「しっかり勉強して、結果も出せてる」という人には不要な記事です！

## 勉強法再考〜インプット編〜

### 動画で学ぶ

有料無料問わず、最近は色んな動画教材が世に出ていますよね。

プログラミングスクールの教材も、動画であることが多いそうです。

#### 良い点

- とにかくわかりやすい。図表のみならず、実際の開発画面などを見ながら学べるため、イメージも湧きやすい。
- 視聴しているだけでドンドン情報が入って来るため、比較的ラクに学べる。（悪い点でもあります。）

#### 悪い点

- ドンドン情報が入って来るため、理解できていなくても勉強している気になる。（良い点の裏返し。）
- 表面的な理解で終わってしまうコンテンツも多いため、見極めが重要になる。

### 書籍で学ぶ

所謂「名著」と呼ばれる書籍も、多くが電子で読めるようになり、保管や持ち運びに関してのデメリットは殆ど無いと言って良いでしょう。

#### 良い点

- 「考えながら読み進める」ことで、内容の理解だけでなく思考力を向上させることにも繋げやすい。
- 「〇〇を学ぶならこの本」みたいなオススメ解が、ある程度確立されている。
    - 得てして、そういった本に表面的なものが少ない。

#### 悪い点

- そもそも読解力が必要なため、動画よりハードルは高い。
    - とはいえ、その読解力を磨くために書籍を読むべきだとは思いますが...。
- パット見のわかりやすさは動画に劣る。

### 人に教えてもらう

[以前に記事を書きました](https://qiita.com/kjm_nuco/items/99a0acf5e1fbd054603f)が、身近に教えてもらえる人がいるかどうか、は成長速度に結構ダイレクトに関わってくると思います。

相手の都合はしっかり確認し、敬意と謝意を持って向き合いましょう。

#### 良い点

- わからないところ・知りたいところをピンポイントに質問できる。
- 自分で勉強するだけでは気づかなかった周辺知識を教えてもらえることもある。

#### 悪い点

- 当然だがいつでもできるわけではない。相手の都合依存。
- 何なら得られる知識・スキルも相手依存なので、鵜呑みにし続けて良いかは要判断。

## 勉強法再考〜アウトプット編〜

インプットだけじゃなくアウトプットも大事、とはよく言われますし、実際その通りです。

アウトプットを増やすと、勉強が進むだけでなく、自信にも繋がります。

### 学んだことを文章（記事）にする

このQiitaに記事を書いても良いです。ただのメモ、ではなく、「他人が読んでもある程度理解できる文章」にするのはかなり勉強になります。

「人に説明できる」ということは、「知識が脳内で整理されている」ということなので。

#### 良い点

- 知識の網羅性を担保しやすくなる。
 - 書きながら、自分の理解が足りない点に気づきやすいので。
- 自分の学びをナレッジ化でき、いつでも振り返れるようになる。

#### 悪い点

- 書くのが苦手な人にはとにかく辛い。
- 誰かにレビューをもらわないと、誤りや中途半端な理解がそのままになりがち。

### 人に説明する

共に切磋琢磨する仲間がいるならば、学んだことを教え合う時間を作るのはとても有効な勉強法になります。

#### 良い点

- その場でレビューがもらえる。
- モチベーションを高く保たざるをえなくなる。
 - 嘘を教えるわけにいかないですし、相手の時間も取っているわけなので。

#### 悪い点

- 相手に嘘を教えてしまう可能性がある。
 - ので、しっかりインプットしましょう。
- これも当然、いつでもできるわけではない。

### 何か作ってみる

一般的にアウトプットというと、このことを指しているケースが多い気がします。

何かを作り上げる経験はとても大事で、自信に直結するのでおすすめです。

#### 良い点

- 欠けている知識やスキルに気づきやすい。
    - というか、それを補わないとモノが動かない。
- 自分で考える力が身につく。
    - デバッグなんかやっていると、仮説検証をスピーディに回す力が身についていくのを感じます。

#### 悪い点

- 時間はかかる。
    - まとまった時間を確保できる人向けかもしれません。

## まとめ

切り分けてみると色んな手段がありますが、「これが最強の勉強法」みたいなものはありません。

「インプット・アウトプットのバランスが大事」なのはもちろん、インプット・アウトプットそれぞれの手段についても、やはり良い点悪い点があるということを理解して勉強していきましょう。

## おわりに

弊社では、経験の有無を問わず、社員やインターン生の採用を行っています。

興味のある方は[こちら](https://www.recruit.nuco.co.jp/)をご覧ください。
AWS CognitoとUnityによるパスワードなしメール認証を試してみた。

# 概要
CognitoとUnityによるパスワードなしメール認証について情報が少なく、ハマったので方法をシェアします。

# 準備
以下の記事を参考にAWSの設定を行ってください。
https://dev.classmethod.jp/articles/cognito-lambda-passwordless/#toc-10

# Unityでのポイント
ポイントは以下の２点です。

1. SignUpAsyncでユーザープールにユーザーを作成した後に、StartWithCustomAuthAsyncを叩いてCustomAuthを開始する必要がある。
1. さらにメールで受け取ったコードを入力としてRespondToCustomAuthAsyncを叩いて、メールを確認済みとする必要がある。

# 実際のコード
```csharp:SignUp.cs
    var userPool = new CognitoUserPool(UserPoolId, AppClientID, _provider);
    var user = new CognitoUser(email, AppClientID, userPool, _provider);
    var authRequest = new InitiateCustomAuthRequest
    {
        AuthParameters = new Dictionary<string, string>(StringComparer.Ordinal)
        {
            {
                "USERNAME",
                "username"
            }
        },
        ClientMetadata = new Dictionary<string, string>(StringComparer.Ordinal)
    };

    var result = user.StartWithCustomAuthAsync(authRequest).ConfigureAwait(false).GetAwaiter()
        .GetResult();

    _sessionID = result.SessionID;
    _userName = result.ChallengeParameters["USERNAME"];
```

```csharp:Confirm.cs
   var userPool = new CognitoUserPool(UserPoolId, AppClientID, _provider);
    var user = new CognitoUser(email, AppClientID, userPool, _provider);
    var authRequest = new RespondToCustomChallengeRequest
    {
        ChallengeParameters = new Dictionary<string, string>(StringComparer.Ordinal)
        {
            {
                "ANSWER",
                confirmationCode
            },
            {
                "USERNAME",
                _userName
            }
        },
        SessionID = _sessionID
    };
    var result = user.RespondToCustomAuthAsync(authRequest).ConfigureAwait(false).GetAwaiter().GetResult();
  

```
【PHP基礎⑱】配列-2.配列の初期化

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksBasic.html)
要素数10の整数型の配列を宣言し、整数値を入力させ、すべての配列の要素を入力値として、すべての要素の値を表示するプログラムを作成しなさい。


# コード
```php
$a = [1,2,3,4,5,6,7,8,9,10];
$m = intval(fgets(STDIN));
$k = [];
foreach($a as $i){
    $k[] = $m;
}
foreach($k as $r){
    echo $r, PHP_EOL;
}
```

↓「5」と入力


# 結果
```
5
5
5
5
5
5
5
5
5
5
```

☆配列の初期化
＄k = [];

☆配列に新しい要素を追加する
＄k[] = ＄m;
→キーを指定しない場合は、自動で整数のキーが付与される。
現在ある最大のキーに1を加えたものが与えられるが、キーが1つもない時は0から付与される。
cscの作法 その217

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
自己署名証明書を作れ。

# サンプルコード

```
using System;
using System.IO;
using System.Security.Cryptography;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Security;
using System.Collections.Generic;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;

static class X509CreateTest {
	static void Main(string[] args) {
		DateTime notBefore = DateTime.Now;
		DateTime notAfter = DateTime.Now.AddYears(1);
		RSA privateKey = new RSACryptoServiceProvider(2048);
		string issuerDN = "CN=127.0.0.1";
		string serialString = "123456789";
		var x509gen = new X509V3CertificateGenerator();
		var serial = new BigInteger(serialString);
		var keyPair = DotNetUtilities.GetKeyPair(privateKey);
		x509gen.SetSerialNumber(serial);
		x509gen.SetIssuerDN(new X509Name(issuerDN));
		x509gen.SetSubjectDN(new X509Name(issuerDN));
		x509gen.SetNotBefore(notBefore);
		x509gen.SetNotAfter(notAfter);
		x509gen.SetPublicKey(keyPair.Public);
		var signerFactory = new Asn1SignatureFactory(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, keyPair.Private);
		var cert = x509gen.Generate(signerFactory);
		using (var sw = new StreamWriter("test0.crt"))
		{
			var writer = new PemWriter(sw);
			writer.WriteObject(cert);
		}
		Console.WriteLine("OK");
	}
}
```



以上。
cscの作法 その216

# 概要
cscの作法、調べてみた。
証明書署名要求から、証明書作ってみた。

# サンプルコード

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;

public class test0 {
	public static void Main(string[] args) {
			var attributes = new Dictionary<DerObjectIdentifier, string>() {
				{ X509Name.CN, "oreoreca" },
			};
			var attributeOrder = new [] {
				X509Name.CN,
			};
			var random = new SecureRandom();
			var csrStreamReader = new StreamReader("localCA.csr");
			var csrReader = new PemReader(csrStreamReader);
			var csrPemObj = csrReader.ReadPemObject();
			var csr = new Pkcs10CertificationRequest(csrPemObj.Content);
			if (!csr.Verify()) 
				throw new Exception();
			var keyStreamReader = new StreamReader("localCA.key");
			var keyReader = new PemReader(keyStreamReader);
			var keyObj = keyReader.ReadObject() as AsymmetricCipherKeyPair;
			var privateKey = keyObj.Private;
			if (privateKey == null) 
				throw new Exception("Failed to read private key.");
			var issure = new X509Name(attributeOrder, attributes);
			var certGen = new X509V3CertificateGenerator();
			certGen.SetSerialNumber(new Org.BouncyCastle.Math.BigInteger(256, random));
			certGen.SetIssuerDN(issure);
			certGen.SetSubjectDN(csr.GetCertificationRequestInfo().Subject);
			var today = DateTime.UtcNow.Date;
			certGen.SetNotBefore(today);
			certGen.SetNotAfter(today.AddYears(1));
			certGen.SetPublicKey(csr.GetPublicKey());
			certGen.AddExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(true));
			certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(csr.GetPublicKey()));
			var factory = new Asn1SignatureFactory("SHA256withRSA", privateKey, random);
			var cert = certGen.Generate(factory);
			using (var sw = new StreamWriter("localCA2.crt"))
			{
				var writer = new PemWriter(sw);
				writer.WriteObject(cert);
			}
			Console.WriteLine("OK2");
	}
}





```

以上。
zappaでFlaskアプリをデプロイできなくなった

 # 急にデプロイできなくなった

`zappa deploy`済みのアプリに対して`zappa update`できていたはずが、急に update できなくなった。

CloudWatchのログをみるとcryptographyがちゃんと入っていないことが原因のようだが、ちゃんと入っているはず（と思ってた）

```
[ERROR] ModuleNotFoundError: No module named 'cryptography'
Traceback (most recent call last):
  File "/var/task/handler.py", line 655, in lambda_handler
    return LambdaHandler.lambda_handler(event, context)
  File "/var/task/handler.py", line 249, in lambda_handler
    handler = global_handler or cls()
  File "/var/task/handler.py", line 146, in __init__
    self.app_module = importlib.import_module(self.settings.APP_MODULE)
```

仮想環境を作り直して update したり、 `zappa undeploy` してから `zappa deploy` しても改善せず。

# 原因はキャッシュ

情報を探していたらそれっぽいのを見つけた。
[Add a command to clear the wheel cache](https://github.com/zappa/Zappa/issues/1009)

zappaでdeployするとwheelファイルがキャッシュされ、次のdeploy時にキャッシュ済みのwheelファイルを使用しようとするのだが、
このwheelファイルちゃんと作成できていないことがある。

私の場合は通信タイムアウトが原因だった。特にデプロイ中にPyPIにアクセスしたりすると発生しやすいっぽい。

```bash
Downloading and installing dependencies..
 - cryptography==37.0.3: Downloading
  0%|          | 13.3k/4.04M [00:04<22:30, 2.98kB/s]
HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.
Packaging project as zip.
  0%|          | 0.00/27.9M [00:00<?, ?B/s]
```

一度こうなるとまともなwheelファイルじゃないのに「キャッシュあるやんけ！使ったろ！」とzipにパッケージングしてしまう。

結果、Lambda上で`ModuleNotFoundError`になってしまうのでした。

実際にファイルを確認したが、本来4MBあるはずのwheelファイルが13KBしかなく明らかにおかしかった。

![スクリーンショット 2022-06-27 18.54.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611565/b8920c35-0e10-1752-e283-21297329e0fd.png)
※Mac環境です

# 対策

キャッシュを削除してからデプロイすればいい。
私はキャッシュが保持されているフォルダを削除するプログラムを作って、デプロイのフローに組み込んだ。

```python
import shutil
import tempfile


def delete_cached_wheels():
    # zappaがwheelのキャッシュを作成する場所
    # Macでの例: '/var/folders/vj/dcgw_0kj26ncm1lp7cshdqt40000gp/T/cached_wheels'
    # Windowsでの例: 'C:¥Users¥ユーザー名¥AppData¥Local¥Temp¥cached_wheels'
    temp_dir = tempfile.gettempdir()
    cached_wheels_path = os.path.join(temp_dir, 'cached_wheels')

    if os.path.isdir(cached_wheels_path):
        shutil.rmtree(cached_wheels_path)

```

急にデプロイできなったのでヒヤヒヤしました。
別の人の助けになれば。
cscの作法 その215

# 概要
cscの作法、調べてみた。
証明書署名要求を作ってみた。

# サンプルコード

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;

public class test0 {
	public static void Main(string[] args) {
		var keyGen = new RsaKeyPairGenerator();
		var keyGenParam = new KeyGenerationParameters(new SecureRandom(), 2048);
		keyGen.Init(keyGenParam);
		var keyPair = keyGen.GenerateKeyPair();
		var attributes = new Dictionary<DerObjectIdentifier, string>() {
			{ X509Name.CN, "oreoreca" },
		};
		var attributeOrder = new [] {
			X509Name.CN,
		};
		var subject = new X509Name(attributeOrder, attributes);
		var extGen = new X509ExtensionsGenerator();
		extGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keyPair.Public));
		extGen.AddExtension(X509Extensions.KeyUsage, false, new KeyUsage(KeyUsage.DigitalSignature));
		var extensions = extGen.Generate();
		var extAttr = new AttributeX509(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(extensions));
		var csr = new Pkcs10CertificationRequest("SHA256withRSA", subject, keyPair.Public, new DerSet(extAttr), keyPair.Private);
		using (var sw = new StreamWriter("ca.csr"))
		{
			var writer = new PemWriter(sw);
			writer.WriteObject(csr);
		}
	}
}



```


以上。
Slackに貼り付けたURLの一部が絵文字に変換されてしまう

:::note warn
アプリの挙動が変わってこの記事で書かれている「解決したかったこと」は発生しなくなりました。
:::

# 解決したかったこと
SharePointのURLなどSlack上で絵文字に変換可能な文字を含んだURLを張り付けるとURLの一部が絵文字になってしまい、URLとして機能しなくなってしまう。

例えば次のようなURLを
```
https://hoge.sharepoint.com/:x:/r/sites/FOO-BAR/_layouts/99/Doc.aspx
```

Slackにペーストすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/10966711-8a49-70e0-4627-c07557279aab.png)

こんな表示になってしまう。

[Slackで自動絵文字変換をオフにする方法](https://ja.gouma.org/automatic/How-to-Turn-Off-Automatic-Emoji-Conversion-in-Slack/)
これを試してみたけど効果なし。

# 解決策１

バッククォートでくくることでコードブロック扱いにする方法。

```
`https://hoge.sharepoint.com/:x:/r/sites/FOO-BAR/_layouts/99/Doc.aspx`
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/fa7d18ef-1dbb-8cf9-e134-384dbd15ccd8.png)

でもこれだと文が冗長になるしこういったリンク表記にできない…。

```
[ほげほげ](https://hoge.sharepoint.com/:x:/r/sites/FOO-BAR/_layouts/99/Doc.aspx)
```

# 解決策２

マークアップで書式設定するのをやめて、Slackの組み込み書式設定に切り替えれば上記のようなURLも貼り付け可能になる。

https://slack.com/intl/ja-jp/help/articles/360039953113-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E6%9B%B8%E5%BC%8F%E8%A8%AD%E5%AE%9A%E3%82%92%E8%A1%8C%E3%81%86

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/b96b8fd2-e572-bf01-7a5e-d2e2d4e355e3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/16b7bea5-0b9d-ed00-b69c-8c3f2604ed46.png)

でもワイはマークアップが使いたいんや…。

# 解決策３
```
https://hoge.sharepoint.com/:x :/r/sites/FOO-BAR/_layouts/99/Doc.aspx
```

このように絵文字に変換される文字の間に半角スペースを追加した状態でペースト（`:x :`）。
そのあとスペースを削除すると絵文字の変換候補が出てくるので、ここでEscを押すと絵文字への変換をキャンセルできます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/2e07176d-b2c5-c5ea-e21e-d1bf52a5f459.png)

解決策１でできなかったリンク表記もこの状態からスタートすれば可能になります。

```
[ほげほげ](https://hoge.sharepoint.com/:x :/r/sites/FOO-BAR/_layouts/99/Doc.aspx)
```

めんどくさいけどとりあえずヨシ！
リモート追跡ブランチから不要なブランチを削除する [git fetch --prune]

## やりたいこと
例えば、`develop`ブランチにマージ済みのブランチ`feature/add-feature`がGitHub上にあるとする。

マージ済みなので、ブランチ`feature/add-feature`をリモートから削除した。

ただ、リモート追跡ブランチには残っている。もう不要なので消したい。
```bash:bash
git branch -a
* develop
  main
  remotes/origin/develop
  remotes/origin/main
  remotes/origin/feature/add-feature  // こいつ
```

## git fetch --pruneを使う

Gitコマンド`git fetch --prune`はリモートに存在しなくなったブランチを
リモート追跡ブランチから削除してくれる。

無事削除された。
超初級UNIXコマンド

## はじめに
サーバー知識全般苦手なため、アレルギー反応が起きないように克服に向けた第一歩ということで、まずは、簡単な（簡単すぎる？）UNIXコマンドをメモがわりにまとめて見ました。（石の上にも三年...塵も積もればなんちゃら....）

## 環境
VirtualBoxにCentOS7を入れたLinux環境を用意

## コマンド操作
### Ctrl + c
直前のコマンドを実行せずにキャンセルし、新しいプロンプトに移動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185869/c6b42c74-035b-fca0-468b-8272e9a2b1f4.png)
### Ctrl + u
直前で打ったコマンドを消すことができる
### Clear / Ctrl + l
画面全体をクリアする
### pwd
present working directoryの略？
今いる場所を表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185869/b1d7ca71-54f2-e01a-04e8-aec25237ee97.png)
### cd
change directoryの略
`cd /`でrootディレクトリ、`cd ~`でhomeディレクトリに戻る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185869/c20efc42-f3c6-9d70-5591-3439ebcaa426.png)


## おまけ
代表的なディレクトリ構成と役割
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185869/dff15c34-7d2f-9155-8ca3-ecf9841c5f7b.png)
etc　・・・　各種設定ファイルを格納する場所
home　・・・　ユーザーが好きに使える場所,ユーザーごとにサブディレクトリを作ることができる。
var　・・・　アプリケーションが管理するデータを格納する場所(Web,DB,LOG)
bin/sbin　・・・　コマンド用の実行ファイル(sbinは管理者用)
tmp　・・・　一時ファイル
【Rails】コメント機能Ajax実装③ 削除編

[【Rails】コメント機能をAjax実装① 準備編](https://qiita.com/coneco12_/items/2d6e44ce5c1b374ca7df)
[【Rails】コメント機能Ajax実装② 投稿編](https://qiita.com/coneco12_/items/61174a80a611b7e0049e)

投稿したコメントをAjaxで削除します！
今回の目標の完成形はこちらです↓
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/3b0f5780-2bfb-a10e-c8b9-131db2512858.gif)

#### Commentコントローラーにdestroyアクションを追加
```ruby:comments_controller.rb
class CommentsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_comment, only: [:edit, :update, :destroy]
  before_action :set_post, only: [:create, :edit, :update]

  def create
    @comment = current_user.comments.new(comment_params)
    @comment.post_id = @post.id
    if @comment.save
      render "create", notice: "コメントを投稿しました"
    else
      redirect_to @comment.post
    end
  end

  # -------ここから追加-------
  def destroy
    if @comment.destroy
    render "destroy", notice: "コメントを削除しました"
    else
      redirect_to @comment.post
    end
  end
  # -------ここまで-------

  private
 #~~省略~~
end
```
### ビューファイルを修正

今回扱うファイルは、show.html.erbにボタンを追加し、
新規でdestroy.js.erbを作成します。

```
.views
├── comments
│   ├──_comments.html.erb
│   ├──_form.html.erb
│   ├──create.js.erb
│   └──destroy.js.erb(←今回 追加するファイル)
│ 
└── posts
    └──show.html.erb
```

#### Viewファイルに削除ボタンを追加

```erb:views/comments/_comments.html.erb
<% post.comments.each do |comment| %>
  <div id="comment_<%= comment.id %>" class="comment pb-3 d-flex gap-3">
    <div class="profile_icon">
      <%= image_tag comment.user.profile_icon.url, class: 'rounded-circle' %>
    </div>
    <div class="p-3 border flex-grow-1 rounded">
      <div class="d-flex gap-3 pb-3">
        <div class="fw-bold"><%= comment.user.name %></div>
        <div><%= comment.created_at %></div>
      </div>
      <div>
        <p class="pb-3"><%= comment.body %></p>
        <!------ここから追加------->
          <% if  user_signed_in?　&& comment.user_id == current_user.id %>
            <div>
              <%= link_to "削除", post_comment_path(comment.post, comment), method: :DELETE, remote: true, class: "btn btn-sm btn-outline-danger" %>
            </div>
          <% end %>
 　　　　　　　　　　　　<!------ここまで------->
      </div>
    </div>
  </div>
<% end %>
```
link_to に remote: trueを入れ非同期に切り替えます！
また、削除ボタンは投稿したユーザーのみに表示させたいので、`<% if  user_signed_in?　&& comment.user_id == current_user.id %>`を追加します。


#### JavaScriptファイルを作ります
```erb:views/comments/destroy.js.erb
$('#comment_<%= @comment.id %>').remove();
```

以上で、削除機能が実装できました。
次回の記事で更新機能を追加します！

関連記事
----
[【Rails】コメント機能をAjax実装① 準備編](https://qiita.com/coneco12_/items/2d6e44ce5c1b374ca7df)
[【Rails】コメント機能Ajax実装② 投稿編](https://qiita.com/coneco12_/items/61174a80a611b7e0049e)
[【Rails】コメント機能Ajax実装④ 更新編](https://qiita.com/coneco12_/items/5afa9c0788ec65c3bcbe)
【Laravel】Class "Database\Factories\(モデル名)" not found

2,3回同じエラーで5分ほど無駄にしてるのでいい加減忘れないために備忘録として。


## 環境
Laravel v9.5.1 (PHP v8.1.3)

## 状況

テストを実行した際に下記のエラー

```
Class "Database\Factories\Post" not found
```


## 解決法

```protected $model = Post::class;```を追記したときの```use App\Models\Post;```の定義忘れが原因。
```use App\Models\Post;```を追記する。

```php
namespace Database\Factories;

use App\Models\User;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
  protected $model = Post::class;

  public function definition(): array
  {
    return [
      'user_id' => User::factory(),
	  'title' => 'タイトル',
      'content' => '内容',
    ];
  }
}
```
GoogleCloudRunからGCSにファイルをアップロードする

# VS Codeの設定

もしもCloudRunが初めてで、VSCodeを使っているのなら、このあたりを試してみてデプロイ出来るようにしておくと良いです。

[サンプル アプリケーションからの Cloud Run サービスの作成 | Cloud Code for VS Code | Google Cloud](https://cloud.google.com/code/docs/vscode/creating-a-cloud-run-service?hl=ja)

# ソース

CloudRunように作っています。CloudFunctionsでも手直せば動くと思う。
言語はPythonです。

```python
import os
from functions.upload_file import upload_gcs
from flask import Flask, request

# pylint: disable=C0103
app = Flask(__name__)

@app.route('/upload-gcs', methods=['GET', 'POST'])
def local_upload_gcs():
    return upload_gcs(request)

if __name__ == '__main__':
    server_port = os.environ.get('PORT', '8080')
    app.run(debug=False, port=server_port, host='0.0.0.0')
```

肝心のアップロード処理はこんな感じで

```python
import json
from apiclient import discovery
from googleapiclient.http import MediaIoBaseUpload
from oauth2client.client import GoogleCredentials

def upload_gcs(request):
    if request.args and 'image' in request.args:
        image = request.args.get('image')
    else:
        image = request.files.get('image')
    if request.args and 'bucketname' in request.args:
        request_bucketname = str(request.args.get('bucketname'))
    elif request.form and 'bucketname' in  request.form:
        request_bucketname = str(request.form.get('bucketname'))

    # Retrieve credentials
    credentials = GoogleCredentials.get_application_default()
    # Create service object
    service = discovery.build('storage', 'v1', credentials=credentials)
    # Create media object
    media = MediaIoBaseUpload(
        image,
        mimetype=image.mimetype
    )
    # Create request
    request = service.objects().insert(
        bucket=request_bucketname,
        name=image.filename,
        media_body=media
    )
    # Execute request - store file on GCS
    results = request.execute()
    return_json = json.dumps(results, ensure_ascii=False)
    return return_json
```

# 参考URL

参考にしたホムペはもちろんあるのですが、日が空いてしまって、どこだかわからず…
もしもわかったら追記します。
情報セキュリティマネジメント試験合格までにしたこと

## はじめに
先日、情報セキュリティマネジメント試験を受験しました。
正式な合格発表はまだですが、スコアレポートでは合格点を超えていたので行った勉強を公開します。

## この記事の対象者
・IT企業に就職する学生
・未経験でIT業界への転職を考えている方
・社内のセキュリティ担当
・初級エンジニア

## 筆者のレベル
社内のISMS管理責任者として2年の経験があります。
基本情報、応用情報を保有しており、IPAの試験にもある程度慣れています。

## 試験の概要
試験の概要を記載します。

令和4年度上期情報セキュリティマネジメント試験CBT方式
試験会場：各地にあるプロメトリックのテストセンター
受験手数料：￥7,500（消費税込み）
合否発表：メールで即時
試験時間：（午前）90分、（午後）90分
出題方式：午前午後ともに多肢選択式（四肢択一）
問題数：（午前）50問、（午後）3問
合格点：（午前）60点/100点、（午後）60点/100点

## 午前試験
#### 午前試験の結果
正答率64％とかなりギリギリでした。
特にテクノロジ系の正答率が低く、知らないと解けない問題が多かったと思います。
![午前.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266611/6f4b7f14-24dc-054d-e09a-be5582dcd4e6.png)


#### 勉強内容
教科書などは使用せず、いきなり過去問道場で演習を行いました。
175問解いた時点で正解率が71.4%だったので流石に大丈夫だろうと思ってこの時点で勉強を辞めました。（その結果合格点ぎりぎり・・・）
勉強時間は5時間くらいだと思います。

![過去問道場.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266611/2e3f16ac-0733-206f-2764-64b935df4616.png)



## 午後試験
#### 午後試験の結果
正答率89％だったのでかなり余裕を持って合格できたと思います。
全問選択式なので完全に理解していなくても文脈や消去法で解ける問題が多かったです。
基本情報技術者試験の情報セキュリティの問題を難しくしたようなレベルだと思います。
![午後.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266611/511faa49-712a-8b17-66df-c6fdcaaf992f.png)


#### 勉強内容
午後試験対策も過去問道場で進めようと思い、とりあえず令和元年秋試験の問1だけ解いてみましたが、解説がなかったのでこの一問だけしかやりませんでした。
![この.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266611/733500f5-93ee-1029-fcfa-a9e9ee44c1bc.png)

## 所感
試験の合格難易度は、午後試験があるのでITパスポートより難しく、範囲が狭い分基本情報技術者試験よりは簡単だと思います。ある程度セキュリティ分野での実務経験があり、試験慣れしている方なら特に対策しなくても合格できると思います。

## 最後に
以上、情報セキュリティマネジメント試験合格までにしたことでした。
この記事がお役に立てれば幸いです。
【Rails】コメント機能をAjax実装① 準備編 

コメント機能を実装したので、記録を残します___φ(•ᴗ•๑)
間違っている箇所があれば、ご指摘頂けると大変助かります。

実装内容
---
・投稿記事に対してコメント機能をつける
・ログインユーザーのみコメント可能
・投稿・削除・更新を非同期で実装する


前提
-----
・Rails6
・Devise導入済
・jQuery導入済
・Bootstrap5
・記事投稿機能を実装済

準備
---
#### （1）Commentモデルを作成

Commentモデルに、user_idとpost_idを忘れずに追加します。
```
rails g model Comment body:text user_id:integer post_id:integer
rails g db:migrate
```

モデルにアソシエーションとバリデーションを追加します。
```ruby:comment.rb
class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :post

  validates :body, presence: true
  validates :user_id, presence: true
  validates :post_id, presence: true
end
```
Postモデルもhas_many :commentsを追加
```ruby:Post.rb
class Post < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy
  #~~省略~~
end
```

#### （2）Commentコントローラーを作成
```
 rails g controller comments
```

#### (3)ルーティングの定義
postsの中にcommentsをネストします。
```ruby:routes.rb
Rails.application.routes.draw do
   #~~省略~~
  resources :posts do
    resources :comments
  end
  #~~省略~~
end
```

以上で準備が整いましたので、実際に投稿機能を実装します。
続きはこちら→[【Rails】コメント機能Ajax実装② 投稿編](https://qiita.com/coneco12_/items/61174a80a611b7e0049e)

関連記事
----
[【Rails】コメント機能Ajax実装② 投稿編](https://qiita.com/coneco12_/items/61174a80a611b7e0049e)
[【Rails】コメント機能Ajax実装③ 削除編](https://qiita.com/coneco12_/items/f97495e158150b533b78)
[【Rails】コメント機能Ajax実装④ 更新編](https://qiita.com/coneco12_/items/5afa9c0788ec65c3bcbe)
あなたの人生の残りの間、あまり疲れて生きてはいけません、遅すぎて眠らないでください

私は次のような文章を読みました。「私は若い頃、日中は遊ぶことができたので、日が好きで夜が嫌いでしたが、夜はそんなに早く寝たくありませんでした。大人になると、日中は疲れすぎて仕事ができず、夜は眠れなかったので、昼間は夜が怖かった」と語った。

いつから、大人の生活はこのようになっているのかわからない：

手元には未完成の仕事が常にあり、目が眠くて開けられず、あえて眠りません。一日の情報を待っていましたが、まだ寝る前に電話を見つめながら待っていませんでした。眠りにつくことを拒否します。

人生はとてもストレスがたまり、まだまだ先は長いと感じています。

実際、多くの人の生活は同じであり、誰も特に簡単ではありません。

誰かが言った：「人生は遅い打撃プロセスです。」

浮き沈み、人生、老年、病気と死、誰もが遅かれ早かれそれを経験するでしょう。

それなら、ゆっくりと時間をかけて、しばらく急いでみませんか？

今日やっていることを終わらせられないなら、明日やろう。今日人に会わないなら、明日約束をする。今日の願いが叶わないなら、明日も頑張ってね。

花が解けない場合は、花が落ちるのを待ちます。

疲れたら休んで、眠いときは早く寝て、今日の隅に無理やり押し込んでみませんか？

私たちには精神が必要です。この人生で最善を尽くしても、私たちはまだ普通の人であり、普通の人を許すことを学ばなければなりません。

速度を落とし、手放し、ストレスをかけすぎないようにしてください。

「世界は鏡のようなものです。それに眉をひそめ、あなたに眉をひそめます。それに微笑み、あなたに微笑みます。」ということわざがあります。

息を切らしていると感じることもありますが、それは心を引き締め、不愉快な過去、人生の困難、そして未来への不安を心に蓄積してきたからです。

実際、人生はいつも悲惨なわけではなく、人生にもゴージャスな瞬間があります。

本来の人生の味を生きるために、心をリラックスさせ、心配を減らし、笑顔を増やしてください。

物語を読む。

若い男が靴職人に古い革の靴を渡した。靴職人は手でそれに触れ、何気なくどこから来たのかを言った。

若い男はびっくりしました。靴職人は「以前は革靴工場の整備士だったので、革製品工場を開設しました。その後、危機に見舞われて革製品工場が閉鎖されたのですが、来ました。ここに靴を修理するための屋台を設置します。」

靴職人の口の中での人生の浮き沈みは軽いもののようで、彼は靴を巧みに修理し、それは彼とは何の関係もないようです。

よく考えてみると、人の生活は動いている電車に乗るようなもので、どんな状況でもしばらくそこにとどまり、口笛を吹くようなものです。

この時点で、私たちがする必要があるのは、車の中に静かに座って、次の乗車に連れて行くのを待つことだけです。

人生は長く、未来は長く、私たちはずっと休まなければなりません。

それらの世俗的な名声と富は奪われるべきではありませんが、多かれ少なかれ得るために、もはや気にしないでください。

死すべき世界のそれらの人々や物事は気にしません、しかし彼らがとどまるか行くかにかかわらず、彼らはもう気にしません。

太陽が沈み、窓辺にそよ風が吹き、夜の野原で鳥が歌い、星が輝いています。

ほら、この世界は悪くはない、それは私たちの永遠の愛と期待に値する。

人生において、あなたは平和な心を持っていなければなりません、そしてあなたがそれを買う余裕があり、それを手放し、それを公然と見て、そしてそれを安定させることができればあなたは快適に生きることができます。

あなたの人生の残りの間、あなたが親切で、心配が少なく、そしてもっと笑うことができますように。

https://sawkasetworld.net/read-blog/1778

https://www.cheddrbox.com/read-blog/49816
AWSではじめるインフラ構築入門ハンズオンその１「IAMでのユーザー管理」


## サマリー
やること：AWSの初心者がIAMでルート権限の設定やユーザー作成、MFAの設定を行う記事です。

結果：一般的なAWSの原則に基づいたユーザー権限の初期設定が実際に行えるようになった。

## (前置き)AWSではじめるインフラ構築入門とは？

https://amzn.to/3A794vJ

翔泳社さんから出ているAWSでのインフラ構築初心者向けの本です。

この本のコンセプトは「初心者向けでありつつ本格的であること」

レベル感や想定読者は以下のような感じです。

①インフラやネットワークについて学んだことがある。
（基本情報の教科書に書いてある知識よりも少しあると良さそう）
②AWSソリューションアーキテクトの資格を持っている。
③AWSハンズオンは簡単なものしかやったことがない。
④Linuxコマンドを多少知っている（Lpic−1に満たない程度）

私は最近AWSの資格を勉強し始め、5月にクラウドプラクティショナー→ソリューションアーキテクト、6月に高度なネットワーキングを合格しました。
そんな中で、体系的なハンズオンを行った経験が少ないことに気がつきました。
このまま知識をつけるための勉強を続けることも考えました。
しかし知識＞＞実技のバランスが大きく崩れ頭でっかちになるのも避けたいのでこの本を通して実践力を少しでもつけようと考えたいうわけです。

というわけで私の学ぶ目的としては以下のような感じ。

①AWSはツールであり、ツールは実践によって使用する能力が向上する。
②次回受験するAWSSysOpsアドミニストレーターアソシエイトにハンズオンを行うLab形式の問題が出題されるので実践力を鍛えたい。
③AWSを扱えるアピールのため（社会人は資格取得以外にこういうアッピルもしないといけない！辛い！）

※記事作成はがんばりたくないのでなるべくがんばりません。

さあ、AWS学んでいきます。

## なぜルートユーザーを日常的に使うべきではないか？

AWSアカウントを作成した時に最初に作られるユーザーをルートユーザーと言います。

AWSアカウントを作成したらまずはルートユーザーに適切な設定を必ず行いましょう。

ルートユーザーは「（自分の）AWS上のリソース全てにアクセス可能」という強力な権限を持っています。

設定を行う前に「なぜルートユーザーを使わない方がいいのか？」についても書いておきます。
（※ベストプラクティスなども参考にしましたが、推測も混じっていますので誤りがあればご指摘ください）

https://amzn.to/3tZAcsL

AWSのセキュリティの知識に関しましてはこちらの書籍が資格の取得的な意味でも非常に参考になります。
今回も参考にさせていただきました。

それは「ルートユーザーの日常的な使用→アカウントの共有に繋がる」からだと考えられます。
これの何が問題か？不便か？については以下のような感じです。
①この状態だと営業部が販売部のデータを見ることできるなどコンプライアンス上よくないです。。
②ルートユーザーのパスワード管理責任が曖昧になります。外部の人間にもルートユーザーのパスワードを教えるなんて怖すぎですね。
③リソース操作に対する責任が追跡できません（だって全部の操作はルートユーザーが行った記録だから）。
④そもそもルートユーザーは１人分の操作しか行えないのでかなり不便です。
など一般的なセキュリティの原則に反する状態＋不便な状態になります。

以上のような理由から、AWSではルートユーザーはあくまで管理のために使い、各リソースの操作にはそれを行うための最小権限を付与しらユーザーを使用することが推奨されています。

## ルートユーザーへの不正アクセスを防ぐための初期設定を行う

ルートユーザーへ行うべき設定は主に以下です。
（所属会社・部署によって変わる可能性があります。）

①アクセスキーの削除（初期設定では作成されませんが、何かの操作で作成されている場合は削除を推奨します）
②MFAを有効化

こちらの設定へはAWSのセキュリティ認証情報の欄からアクセス可能です。
MFAの仮想デバイスはOktaで設定いたしました。

## IAMユーザーを作成する＋権限割り当て

この辺は各自の裁量における設定が多いのと、全てを紹介してしまうと著者様にご迷惑がかかるため、結果を要約していきます。

①IAMのマネジメントコンソールからユーザーを作成。
（自動生成パスワード＋AWSマネジメントコンソールへのアクセス）

今回はユーザーグループ未所属の、何にもアクセスできないアカウントを作成しました。

②グループを作成
任意のグループ名を決めて、ポリシーにPowerUserAccessとIAMFullAccessを追加します。
※これは今後の学習のための権限付与であり、最小権限の原則には反していると思います。必ずMFA認証を追加する。使わない時は権限を取り上げるなどしましょう。

③ユーザーを作成したグループにアタッチ

④パスワードポリシーをAmagasaki2022にできないようなパスワードポリシーに変更します。

⑤作成したユーザーのMFA認証を有効にする


ここまでで書籍の内容は終了になります。

企業などでは、アクセスコントロール専用のスタッフがいるくらい権限付与は重要なので基本的な動作をおさらいできたのは良かったです。

https://amzn.to/3tZAcsL

ついでにAWSセキュリティの専門知識の資格本を読むことで、深い理解につなげようと思います。
（※このシリーズは試験対策として非常におすすめです。）