OmniAICreator/Qiita-1.07M huggingface dataset:
AIチャットボットを爆速開発できるオープンソースの Google 製 LLM PaLM2、Vertex AI デモをリリースしました

![vertex-ai-chatbot-demo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/c7368237-d876-ecde-a0a6-32bd2562a3ab.png)

gm! エルソウルラボのkishi.solです。

AIチャットボットを爆速開発できるオープンソースのSkeetですが、Skeetを使ったデモアプリでGoogle製のLLMであるPaLM2、Vertex AIという製品を使用できるようになりました🙌

デモ上ではChatGPTのGPT-4やGPT-3.5も使えるようになっているため、どのAIがどの用途に適しているのかをお試しいただくことができます。

Skeet デモ: https://skeeter.dev/ja/

## Google 製 LLM の PaLM2、Vertex AI

PaLM2 は Google 製の LLM(大規模言語モデル)で、Google Cloud の Vertex AI で利用できるようになりました。同じく Google 社が提供する Bard という AI チャットサービスの裏側で動いているのもこのモデルです。

PaLM2 は多言語、多様な事前トレーニングデータセットを使用して効率的に学習しており、少ないトークン数や小さいモデルにおいても性能が高いという特長があります。

また、プロンプトの例を教えることによってモデルを微調整することが可能で、ユースケースごとに特化した AI チャットボットを簡単に作成することができます。

![VertexAIChat3JA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/46f64685-58f9-3a96-dc97-6dd5ebceb670.png)


下記リンクからデモをお試しいただけます。PaLM2・Vertex AI はもちろん、Open AI 社の ChatGPT (GPT-3.5, GPT-4)も同時にお試しいただくことができますので、どちらがどのような特徴を持っているか比較検討していただくことができます。

Skeet デモ: https://skeeter.dev/ja/

また、こちらのデモのアプリは Skeet CLI を使えば 5 分でご自身の PC 環境やクラウド環境で動かすことが可能です。

まずはどのようなことができるかデモでイメージしていただき、その後は Skeet CLI を使ってすぐにアプリ開発をスタートできます。

Skeet CLI (GitHub): https://github.com/elsoul/skeet-cli

Skeet は世界中すべてのアプリケーション開発現場の開発・メンテナンスコストを削減、開発者体験を向上させるためにオープンソースとして開発されています。

詳しくは公式ドキュメントを御覧ください。

Skeet ドキュメント: https://skeet.dev/ja/
話題のELYZA（Llama2をベースにしたLLM）をAWS上にデプロイしてチャット環境を構築できるソリューションをOSSで公開しました

AWS内に完結して動作するLLMチャットを構築するソリューションを、GitHubで公開しました。🎉🎉🎉

https://github.com/moritalous/chat-ui


## 動作イメージ

<iframe width="560" height="315" src="https://www.youtube.com/embed/dBgV30pkbAQ?si=uzS3ZHj-P6FQKYlR&amp;controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

文字入力部分は編集していますが、LLMのリクエストレスポンス部分は等速です。かなりレスポンスが良いこともわかるかと思います。

**日本語精度も良いです！ありがとう、ELYZAさん！！**

## 仕組み

Hugging Faceで公開されているLLMモデルをSageMakerにデプロイします。チャット画面は[OSSで公開](https://github.com/huggingface/chat-ui)されている[HuggingChat](https://huggingface.co/chat/)を使用します。

使用するLLMモデルは[elyza/ELYZA-japanese-Llama-2-7b-fast-instruct](https://huggingface.co/elyza/ELYZA-japanese-Llama-2-7b-fast-instruct)です。Llama2をベースに日本語能力を拡張するための追加学習がさてているとのことです。

https://github.com/huggingface/chat-ui

https://huggingface.co/elyza/ELYZA-japanese-Llama-2-7b-fast-instruct

## アーキテクチャ

* AWS
  * EC2 (Amazon Linux 2023, t2.small)
  * SageMaker (ml.g4dn.12xlarge)
  * CDK

* ソフトウェア
  * [HuggingChat](https://github.com/huggingface/chat-ui)
  * [elyza/ELYZA-japanese-Llama-2-7b-fast-instruct](https://huggingface.co/elyza/ELYZA-japanese-Llama-2-7b-fast-instruct)
  * [MongoDB](https://hub.docker.com/_/mongo) (on Docker)

MongoDBはチャット履歴の保存に使用されるようです。DocumentDBの採用を検討しましたが、Partialインデックス機能がサポートされていないとのことで利用できませんでした。

また、HuggingChatの実装は、AWSの認証情報（アクセスキー、シークレットキー）をenvファイルに記述する方式となっていましたが、AWS SDKを使用するように一部修正しています。（[コミット](https://github.com/huggingface/chat-ui/commit/c856fe31ad807e62556e39417df410814a4ce424)）


## デプロイ手順

AWS CloudShellで実行します。

1. ソースを取得
    
    ```shell
    mkdir chatui
    cd chatui
    git clone https://github.com/moritalous/chat-ui.git
    ```

1. デプロイスクリプトを実行
    
    スクリプト内で[SageMakerエンドポイントの作成](https://github.com/moritalous/chat-ui/blob/main/aws/sagemaker/create_endpoint.py)と、[CDK](https://github.com/moritalous/chat-ui/blob/main/aws/cdk)でVPCとEC2の環境を構築します。EC2内の環境は[ユーザーデータ](https://github.com/moritalous/chat-ui/blob/main/aws/cdk/asset/userdata.sh)にてセットアップが実施されます。
    
    ```shell
    cd chat-ui/aws
    sh ./deploy.sh
    ```

    **これだけで構築完了！**

    デプロイスクリプト（SageMakerの作成、CDKの実行）は約10分程度で完了します。CDKの完了後にユーザーデータが実行されます。ユーザーデータの完了までは5分ほどかかります。


環境が構築できたら`http://[EC2パブリックドメイン]:80`へアクセスすることでチャットを開始できます。

:::note warn
HTTPS化や認証機能は含まれていませんのでご注意ください。
:::

## 廃棄手順

1. [削除スクリプト](https://github.com/moritalous/chat-ui/blob/main/aws/destroy.sh)を実行
    
    ```shell
    cd chat-ui/aws
    sh ./destroy.sh
    ```

    廃棄も一発です。

---

よかったら使ってみてください😀
Web開発エンジニア3年目になった振り返り

# 内容
文系大学出身であり完全未経験の自分が、

Web・システム開発エンジニアというキャリアを歩み、早3年…

ということで、これからの自分のために、**何ができたか** を記すことで、

今後のキャリアに活かしていこうと思う。

# 簡単なキャリア
### 2021年1月
見えない数字を追い、多方面からプレッシャーが降り注ぐ営業職から逃げたいと思い、

大学時代のインターン先のエンジニアの大先輩にキャリア相談し、エンジニアに転職を決意。

ここでは、ただ単に「手に職をつけて、稼げる分だけ稼いでいけるかな」という、

なんとも安易な考えをしていた。（間違ってはいないが…w）

退社後はすぐにSES企業に就職し、現場を3つほど経験。

### 2023年1月

現場面談に参加はするが、一言も話さない自社営業に

「ん…この人必要か？それにこの人達にマージン取られるんか。。」

と思い（~~元々営業から逃げたから抵抗もあったのかも~~）、だったら自分でやってみるかということで

フリーランスに転身。

現在も常駐案件と、ちょこちょこ副業を探してはコツコツとプログラミングしている。

## 何ができたか
では実際に、あの当時の非エンジニアから現エンジニアまで

**何ができたか**を振り返ってみる。

## 1. 業界・エンジニアという職種を知ることができた
まずはこれに尽きる。

非エンジニア時代は「プログラミングすることこそがエンジニア！」という考えでいた。

コードを書けるようになってきた半年目は、本当にこの部分だけしか注力していなかった。

しかし、プログラミングは「手段」でしかなく、

お客様に最適なモノ・サービスを提供することこそが「目的」であり、

そこにはプログラミングの他にも、予算・人材・工数管理・設計・製造など

様々な要素が複雑に交差している。

その中で、自分がエンジニアとしてまずやるべきなのは、「品質を向上させる」ということに気づき、

ひたすら保守性・可読性を意識したプログラミングをしようと意識した1年目。

オブジェクト指向やDDD、クリーンアーキテクチャについて学び、いかにコーディング量を減らすかを意識した2年目。

そして3年目の今は、パフォーマンスの高いコーディング、セキュリティ等について学習している。

## 2. プログラミングの奥深さを知ることができた

先も述べたが、非エンジニア時代は「プログラミングすることこそがエンジニア！」という考えでいた。

しかし、プログラミングには歴史があり、先人が培ってきたノウハウが世界中に存在している。

その先人が作り上げてきたものをうまく繋ぎ合わせる「接着作業」を

最適に行えるようにしていくことが大切だということを身に染みて感じている。

自分で書くコードなんて少なければ少ないほどいいに決まっている。。


## 3. 日常生活にメリハリができた
今までかなりネガティブ要素なことを書いてきたが、実はエンジニアになってかなりポジティブに生きられるようになっている。

その理由がこれである。

日々の開発では、**納期**が常に存在しているため、

「今日はこれをしなければいけない」「今日はここまでしよう」という

自分のタスクを細分化しなければいけない。

これを癖付けると、プライベートでも同じことができるようになり、

「今日は何時まで、仕事でわからなかったことをローカルでやってみよう」「今日は1日遊ぼう」

というメリハリをつけることができるようになった。

# 未来の自分へ

知れば知るほど広いこの世界で、

焦らずゆっくり頑張ってくださいw

あと、先人の知恵はマジで偉大なので、

迷ったら（迷わなくても）、目を向け耳を傾けてください。

もっともっとこの業界が好きになりますように
Blazor WASMでTailwind CSSを使う

# 動機
BlazorにはデフォルトでBootstrapが組み込まれています。
これは古より使われてきたフレームワークですが、ここはBlazor用に構築されたフレームワークを使いたいところ
通常はBootstrapを削除して、[MudBlazor](https://mudblazor.com/)を利用しています
しばらく使っていると、同じボタンの形状、細かいデザインについて不満が出てきました
そこでTainwind CSSを使えないかとなりました
結果使うことが出来ました

## MudBlazorについて
Blaor用に開発されておりMIT License、Start 5.9kとなかなか好評とみました。
実際Blazorのプロジェクトを作成し、後から自分でMudBlazorを組み込む方法や、テンプレートを使う方法があり、使いやすいフレームワークとなっています。

## Tailwind CSSを使う
1. Tailwind CSSをインストール
1. 設定
1. ビルド
の流れです。

では見ていきましょう。Bootstrapは不要な場合削除しちゃいましょう。

### Tailwind CSSをインストール
Blaorのcsprojファイルがあるディレクトリで
```
npx tailwindcss init
```
を実行
すると
tailwind.config.jsファイルが作成されます

tailwind.config.jsを開き

``` tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ['./**/*.{razor,html}'],//ここを変更
  theme: {
    extend: {},
  },
  plugins: [],
}
```

Stylesディレクトリを作成
その中に
app.css
ファイルを作成し開きます

```app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
とします

``` wwwroot/index.html
<link href="css/app.css" rel="stylesheet" /> <--追加
```

PowerShellで

```
npx tailwindcss -i .\Styles\app.css -o .\wwwroot\css\app.css --watch
```
を実行

このコマンドはtailwind.config.jsのcontentが変更されると/wwwroot/css/app.cssを更新するプログラムです
このコマンドは開発中は実行させておきましょう（時々落ちることがあるので要確認）

## 実行確認
index.razorを開き

```index.razor
@page "/"

<PageTitle>Index</PageTitle>

<h3 class="font-extrabold text-3xl">もろたで</h3>

```
に変更し実行しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/9a7236cc-91c1-650d-8693-e5dd12f82505.png)
とを表示されるはずです
これでTailwindが適用されました

次にボタン
``` html
    <button type="button" class="px-8 py-3 font-semibold rounded-full dark:bg-blue-100 dark:text-gray-800">Rounded</button>

```
をindex.razorにペーストしましょう
すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/d3e2c616-d896-e816-e4b5-83afd574706f.png)
と薄青で角が丸いボタンが設置出来ました
BlazorではボタンなどはComponentとして定義し使いまわすのでいいでしょう。

下記のFlowBiteなどのサイトではコードも記載されておりり、気に入ったものをコピペで使うことが出来ます
[FlowBite](https://flowbite.com/)


``` html
    <button type="button" class="relative px-8 py-4 ml-4 overflow-hidden font-semibold rounded dark:bg-gray-100 dark:text-gray-900">
        With banner
        <span class="absolute top-0 right-0 px-5 py-1 text-xs tracki text-center uppercase whitespace-no-wrap origin-bottom-left transform rotate-45 -translate-y-full translate-x-1/3 dark:bg-violet-400">New</span>
    </button>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/0011a7f4-0be0-dd1d-7d66-e6a99036cde2.png)
こういったオシャレボタンを見つけてコピペで使うことが出来ます

## Tailwind CSSだけじゃ
ここで問題が
DialogなどのComponentはTailwindにはなく作る必要があるようです
FlowBiteのサイトには例がありますが、別途Javascriptを使う必要があり面倒

現状、MudBlazorとTailwindCSSの両方を使うので良いかなと思っています

Dialogなどの見えないComponentはMudBlaor
ボタンなどの見た目のComponentはTailwind

MudBlazorで作ったDialogにTailwindのボタンを乗せています


## 参考URL
[MANBA UI](https://mambaui.com/)
[FlowBite](https://flowbite.com/)
[@aki426(金田 アキヒロ)さんのページ](https://qiita.com/aki426/items/68c429aef11603389f74)
OpenJDKソースコード上でのJava起動オプションの扱い

# 概要

Javaの起動オプション(以下、オプション)がOpenJDKのソースコード上でどのように扱われているか、どのように定義されているかについて説明します。
これによりソースコードをよむ手がかりをつかむことができます。
ここでのオプションは -XX: で始まる(-XX:+UseG1GC、-XX:MaxHeapSize= など)拡張オプションが対象です。

コースコードはOpenJDK11を対象としています。基本的なところはOpenJDK20でも変わっていません。
https://github.com/openjdk/jdk11/tree/master/src/hotspot 配下のものです。
C++言語で記述されています。

# オプションのソースコード上での扱い

オプションはオプション名と同名のグローバル変数として定義されます。
例えば -XX:+UseG1GC なら変数名は UseG1GC など。

オプションは大きく分けて以下の2種類あります。
- "-" または "+" で指定され真偽値を持つもの(例 -XX:+UseG1GC)
- "=" の後に値を指定するもの(例 -XX:MaxHeapSize=)

真偽値をもつものは bool 型で定義され、値を持つものはその値によって int 型などで定義されます。

# オプションの定義

主にソース share/runtime/globals.hpp (https://github.com/openjdk/jdk11/blob/master/src/hotspot/share/runtime/globals.hpp)
で定義されています。
他にオプションの内容によって
share/gc/shared/gc_globals.hpp (GC用)
share/c1/c1_globals.hpp (C1コンパイラ用)
などに分かれています。

オプションはマクロによって定義されています。
マクロには product、product_pd、develop、notproduct などがありますが、 product、product_pd 以外で定義されたオプションは製品版のjavaでは使えないオプションです。(例えばデバッグ用にビルドした場合に使えるなど)

product マクロの引数は以下の形式です。
|引数|内容|
|---|---|
|第1引数| 変数の型|
|第2引数| 変数名(オプション名)|
|第3引数| デフォルト値(※)|
|第4引数| 変数の説明|
|第5引数| 値の取り得る範囲(省略可)|

(※)
デフォルト値はオプションによってはエルゴノミクス処理や他のオプションの影響で別の値に再設定される場合があります。

マクロの例

```cpp:UseG1GCの場合
  product(bool, UseG1GC, false,                                             \
          "Use the Garbage-First garbage collector")                        \
```

UseG1GCは bool 型でデフォルト値は false 。

```cpp:MaxRAMPercentageの場合
  product(double, MaxRAMPercentage, 25.0,                                   \
          "Maximum percentage of real memory used for maximum heap size")   \
          range(0.0, 100.0)                                                 \
```

MaxRAMPercentageは double 型でデフォルトは  25.0 、値の取り得る範囲は 0 ～ 100。

# ソースコード上での使用例

オプションの値を判定に使う
```cpp:share/gc/shared/collectorPolicy.cpp
   if (SurvivorRatio < 1 || NewRatio < 1) {
     vm_exit_during_initialization("Invalid young gen ratio specified");
   }
```

オプションの値を計算に利用。
```cpp:share/gc/parallel/psYoungGen.cpp
    size_t survivor_size = size / InitialSurvivorRatio;
```

オプションの値を変数に代入。
```cpp:share/gc/shared/collectorPolicy.cpp
   if (NewSize > MaxNewSize) {
.....
     _max_young_size = MaxNewSize;
   }
```
Javaで「コンストラクタとは」の動作を確認してみた

# 概要
Javaで「コンストラクタとは」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/constructor/index1.html

# 実装
以下のファイルを作成しました。
```CTest8.java
class CTest8{
  public static void main(String args[]){
    Television tv1 = new Television();

    tv1.dispChannel();
  }
}

class Television{
  private int channelNo;
  private String housouKyoku;

  Television(){
    channelNo = 1;
    housouKyoku = "FujiTV";
  }

  public void setChannel(int newChannelNo){
    channelNo = newChannelNo;
    if (channelNo == 1){
      housouKyoku = "FujiTV";
    }else if (channelNo == 3){
      housouKyoku = "NHK";
    }
  }

  public void dispChannel(){
    System.out.println("現在のチャンネルは" + housouKyoku + "です");
  }
}
```
以下のコマンドを実行しました。
```
$ javac CTest8.java 
$ java CTest8 
現在のチャンネルはFujiTVです
```

# まとめ
何かの役に立てばと。
医療機関の電子カルテ・予約管理システムから個人情報が漏洩中

別サービスで10万社の導入を誇る企業が開発する医療機関向け電子カルテ・予約管理システムから、1名分の個人情報が第三者に漏洩しました。なお私に届いたのは1名分ですが、更に多くの個人情報漏洩が発生する（発生している）可能性が高いです。

## 漏洩した個人情報
### 予約管理システム上で漏洩した情報

1. 本名
1. 生年月日
1. 電話番号
1. 自宅住所

### 漏洩した情報を検索し入手できた情報

1. 勤務先
1. 本人写真（たまたま、ウェブ上に写真が出る立場にいる方）

なお予約のキャンセルも第三者が操作することが可能と思われる（他人の予約なので実際に操作はしていない）。

## 漏洩の原因

システム登録時のメールアドレス記入ミス

## 漏洩経路

予約管理システムが自動送信するメールに記載された予約確認ページ

## 漏洩原因の考察

同システムを利用するクリニックにおいて、下記のいずれかにより第三者のメールアドレスが紐付けられてしまったと思われる。

1. 患者本人がシステムに誤入力した
1. 患者の手書き情報を医療事務スタッフが電子化する際に誤入力した

## 漏洩予防の推奨対策

1. アカウント作成時の本人確認（メールアドレスやSMS）
1. 予約通知メールへの予約確認ページURLの記載停止
1. 予約確認URLを開く際の本人確認を必須化

この記事を読んだ情報セキュリティ担当の方は、今すぐにでも似た仕様のシステムを利用していないか？をご確認ください。あるある事例だと思います。

## 個人情報保護委員会への報告義務

個人情報が漏洩した場合には一定条件において報告義務があります。詳しくは下記をご確認ください。

https://www.ppc.go.jp/personalinfo/legal/leakAction/

https://www.businesslawyers.jp/practices/1433

漏洩を発見した個人も気軽に報告できるフォームがあると便利なのですが、基本的には個人情報保護委員会への報告は事業者・行政のみからの受付となっている模様です。

## 医療ISAC

医療分野での情報セキュリティを啓蒙する一般社団法人の存在を今回、問題を指摘するにあたって知りました。医療関連サービスの開発企業は会員登録しておくことをおすすめします。

https://m-isac.jp/%e4%b8%80%e8%88%ac%e7%a4%be%e5%9b%a3%e6%b3%95%e4%ba%ba%e5%8c%bb%e7%99%82isac/%e5%8c%bb%e7%99%82isac%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6/%e8%a8%ad%e7%ab%8b%e8%b6%a3%e6%97%a8/
Pluralithで作成した構成図のChangesをカラーで表示させたい

## はじめに
業務でAWSの構成の一部をTerragruntを使用して管理しているのですが、構成が複雑になってゆくにつれてコードを読んで構成を理解するのが難しい、意図した構成になっているか視覚的になっていないので分かりづらいという問題がありました。
その問題をPlulalithで解消するためにTerraformの勉強と一緒にPlulalithも使ってみようという記事の第三弾です。

TerraformでEC2とEC2周辺のVPCやサブネット、インターネットゲートウェイなどのネットワーク周りの環境を作成するtfファイルを作成し、
作成した環境をもとにPluralithを使用して構成図を作成してみたのですが、新たに発見があったので備忘メモとして残しておきたいと思います。

また、前回同様以下書籍内の「TerraformではじめるAWS構成管理」の手順を参考にして実施しました。
Terraform初心者の方におすすめです。
 - [ソフトウェアデザイン 2022年1月号](https://www.amazon.co.jp/o/ASIN/B09M552FPJ/gihyojp-22)

## これまでに行ったこと
第一弾の前々回はインストール編ということでインストールを実施しました。

https://qiita.com/yuuun/items/33f2217072818516ee56

そして第二弾は実際にTerraformでEC2のみの作成と構成図を作成するというところまでできました。

https://qiita.com/yuuun/items/b4f57aa17833dcd7e990

## やりたいこと
基本的なEC2環境をTerraformで作成し、Pluralithで構成図を作成したい！
そしてあわよくば「Changes」のグレースケールをカラーで表示できるようになりたい！

## 環境
OS：Windows11 Pro
Terraform：v1.5.2
pluralith CLI Version： 0.2.2
pluralith Graph Module Version： 0.2.1
AWS CLI：2.4.23

## 今回作成した環境のコード
実際に記述したコードはこちらになります。
今回は記述したコードについて詳細は省きます。

https://github.com/yuuka51/learn_terraform/tree/main/terraform-chapter2

また、リポジトリ内に「pluralith_graph」というディレクトリを作成したのですがその直下にPluralithで作成した構成図も置いてあります。

## 今回記述したコードでPluralithで構成図を作成してみた結果
毎回```terraform plan```でエラーが起きないことを確認してから```terraform apply```、その後```plulalith graph```という流れで環境の作成と構成図の作成を行っていました。

流れを変えてみようと考え、ネットワーク構成のみapply済みの状態でEC2作成用のec2.tfを作成して```terraform plan```を実行後に
```pluralith graph```を実行したら以下のように表示されました。

![スクリーンショット 2023-08-25 152602.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/944903d0-fb16-75c2-32e0-77749bc620a8.jpeg)

ネットワークのつながりや変更内容が表示されていることが分かります。
とても見やすいです。
このような構成図であれば初見でも環境が理解しやすいかもしれないですね。
が、注目したいのはChangesで今回変更予定の箇所はカラーで、それ以外の作成済みの箇所はグレースケールになっているところです！

![project_pluralith-local-project%2Frun_3880453%2Frun_3880453_1692846343765.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/19792072-207b-d79e-8788-94f2cc9d6c08.png)

ちゃんと変更予定の箇所が反映されています！

## 結論
Changesはいつもグレースケールだったのでなぜなのだろうと思っていたのですが、毎回```terraform apply```を実行した後に構成図を作成してしまっていたからでした。
```terraform plan```実行後に構成図を作成したところ画像のように表示されたので```terraform plan```の後に構成図を作成するのが正しい使い方のようでした。
以下気づいた点です。
 * ```terraform apply```実行前のplan実行後の差分に対してChangesが反映される。
 * ```terraform apply```実行後だとすでに変更されているためChangesは何も無いためすべてグレースケール状態になる。

## 所感
構成図を作成するうえでChangesがずっとグレースケールになっていたのが気がかりだったのですが今回気づくことができて良かったです。
「Costs」についても表示できるようになったので近いうちにまとめたいと思います。

## 参考
 [ソフトウェアデザイン 2022年1月号](https://www.amazon.co.jp/o/ASIN/B09M552FPJ/gihyojp-22)

https://nekopunch.hatenablog.com/entry/2021/12/20/115731

https://github.com/cm-cxlabs/softwaredesign202201

https://docs.pluralith.com/docs/get-started/run-locally/
Azure PrivateEndpointとNATゲートウェイは共存できるのか？

## 結論
出来らあっ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/2933a663-2590-3b32-3707-609f6cc6a603.png)

VNET統合用に用意したサブネットに対してNATゲートウェイも設定することができました。
ルーティングがかち合うかも？と思ったが、PrivateEndpoint作成時にできたプライベートDNSゾーンでの名前解決が優先され、WebApp01への通信は問題なく閉域通信でき、インターネットへのアウトバウンドはNATゲートウェイを通るようになりました。

## 構築手順
特別な設定等は特にないですが、簡単に残しておきます

WebApp01のネットワーク設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/3cb8abca-af2c-e9ed-5176-7799691fd04b.png)

- VNET統合であらかじめ用意した仮想ネットワークにサブネットを作成しておく
- 上記で作成したサブネットに対してNATゲートウェイを新規作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/0a4fda13-6f88-d6de-23ab-307bf2372563.png)

パブリックIPかプレフィックスを設定（なければ作成）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/024050b2-4214-547c-8080-79a9116f13e8.png)

WebApp02ではPrivateEndpointを作成して、パブリックアクセスを無効にしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/8160a973-8af0-f88d-af0b-e2d5d48ddc61.png)

WebApp03ではインバウンドの許可を先程作成したパブリックIPのみ許可するように設定しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/fe7112f6-da45-4236-9a16-719823e0464b.png)

## 疎通確認
WebApp01のSCMにSSHして諸々確認していきます


■ WebApp01⇒WebApp02のプライベート通信
nslookupでプライベートIPが引けています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/21769951-62ef-dbd1-6731-21c720731cb9.png)

■ WebApp01⇒WebApp03のインターネット通信

curlでGETした際にエラーが出なければOKです
```
curl sakaue-test-app-03.azurewebsites.net
```

はじかれている場合は403エラーが返ります
```
<body bgcolor="#00abec">
    <div id="feature">
        <div id="content">
            <h1 id="unavailable">Error 403 - Forbidden</h1>
            <p id="tryAgain">The web app you have attempted to reach has blocked your access.</p>
        </div>
    </div>
</body>
```

※余談
tcppingで疎通確認しようと思いましたが、WebApp単体でネットワークを制限してもtcppingは通ってしまう
WebApp同士の接続検証時は注意

https://jpazpaas.github.io/blog/2018/08/29/webapps-functions-network-utils.html

## 再度結論
- PrivateEndpointとNATゲートウェイは共存できる
- 今回はすべてWebAppで検証したが、本来WebApp01はSQL DBなどインターネットにさらしたくないAzureリソース、WebApp03は別のSaaSなどで接続元を絞っているケースなどが考えられます
- NATゲートウェイへのルーティングは隠蔽されていてよくわかっていないので詳しい人がいれば教えて欲しいです
【Photoshop】「ジェネレーティブ塗りつぶし」で背景を生成してみた！！

## 新AI画像生成機能「ジェネレーティブ塗りつぶし」で背景生成方法について
今回は新AI画像生成機能「ジェネレーティブ塗りつぶし」で**背景を生成**してみたのでその手順について説明してきます。

# 目次
* [Photoshopの新AI画像生成機能「ジェネレーティブ塗りつぶし」](#photoshopの新ai画像生成機能ジェネレーティブ塗りつぶし)
* [背景の生成方法](#背景の生成方法)
    * [カンバス全体を範囲選択する](#カンバス全体を範囲選択する)
    * [生成塗りつぶしを選択](#生成塗りつぶしを選択)
    * [テキストプロンプトに出力させたい背景を入力](#テキストプロンプトに出力させたい背景を入力)
    * [選択した範囲をAIが自動で生成した画像で埋めてくれる](#選択した範囲をaiが自動で生成した画像で埋めてくれる)
*  [最後に](#最後に)

## Photoshopの新AI画像生成機能「ジェネレーティブ塗りつぶし」

PhotoshopのBeta版に新AI画像生成機能「ジェネレーティブ塗りつぶし」が標準搭載されました。


**※新AI画像生成機能「ジェネレーティブ塗りつぶし」は現在(2023/9/3)の時点ではBeta版のみ使用可能なので、Beta版をダウンロードしていない方はダウンロードから初めてください。**

## 背景の生成方法
![スクリーンショット-2023-09-05-18.25.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/a92817c0-f458-a5a2-54e2-5b36376e0bbe.jpeg)
![スクリーンショット-2023-09-05-18.26.27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/355bd24a-ad2f-27b1-6927-0465d930891b.jpeg)
背景の生成方法について画像付きで説明してきます。
今回は一旦カンバス内に背景を生成してみます。

### カンバス全体を範囲選択する

![スクリーンショット-2023-09-05-18.26.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/64f965d0-223e-bb5c-2b2e-9912a7daa6c0.jpeg)
それぞれ以下のコマンドでカンバス全体を選択してください。
Windows：［Ctrl］＋［A］、mac：［command］＋［A］
### 生成塗りつぶしを選択
![スクリーンショット 2023-09-05 18.27.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/85951016-7615-d0cc-f883-4e946a363edd.png)

生成拡張ボタンを押すことでテキストプロンプトが表示されます。
※「生成塗りつぶし」→「ジェネレーティブ塗りつぶし」の場合もあります。それぞれ妥当のものを選択してください。

### テキストプロンプトに出力させたい背景を入力
![スクリーンショット 2023-09-05 18.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/81db45f5-e5fd-1854-e41f-8226a236b3ab.png)
![スクリーンショット 2023-09-05 18.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/c11a7ff9-49f6-3f9d-8ec6-3a83367e206d.png)
テキストプロンプトに出力させたい背景を入力してください。
今回は「芝生」と入力しました！
生成を押すと1分もかからず生成してくれます。

※英語でも日本語でもできます！
### 選択した範囲をAIが自動で生成した画像で埋めてくれる
![スクリーンショット-2023-09-05-18.28.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/ae7da978-fec3-0dc2-571f-8b58bae9f184.jpeg)
入力した内容をAIが生成してくれます。
左右の矢印ボタンを押すことで生成されたオブジェクトパターンを切り替えることができます。
## 最後に
以上となります！
簡単に背景を生成してくれます！是非試してみてください！
【ちょっと便利な小技_part 8】 お気に入り自作スニペット編

今回は下記の２つの記事の内容を合わせた自分のお気に入り自作スニペットを紹介します。
コピペで使えるので是非使ってみてください。
* [【ちょっと便利な小技_part 6】VSCodeのカスタムSnippet編](https://qiita.com/nakamura_slj/items/bbad445bb213545c82a9)
* [【ちょっと便利な小技_part 7】Snippetでファイル名に合わせたクラス名を表示させよう](https://qiita.com/nakamura_slj/items/3fce833ae97218bcc150)

## コピペで使えるお気に入り自作スニペット紹介

### StatelessWidget+ファイル名に合わせたクラス名+import
```ruby:dart.json
"Stateless tmp": {
		"prefix": "lesstmp",
		"body": [
			"import 'package:flutter/material.dart';",
			"",
			"class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends StatelessWidget {",
			"  const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}({Key? key}) : super(key: key);",
			"",
			"  @override",
			"  Widget build(BuildContext context) {",
			"    return Scaffold(",
			"      appBar: AppBar(",
			"        title: Text(\"\"),",
			"      ),",
			"      body: Container(),",
			"    );",
			"  }",
			"}"
		],
		"description": "Stateless tmp"
	},
```

### StatefulWidget+ファイル名に合わせたクラス名+import
```ruby:dart.json
"Stateful tmp": {
		"prefix": "fultmp",
		"body": [
			"import 'package:flutter/material.dart';",
			"",
			"class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends StatefulWidget {",
			"  const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}({Key? key}) : super(key: key);",
			"",
			"  @override",
			"  State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}State();",
			"}",
			"",
			"class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}> {",
			"  @override",
			"  Widget build(BuildContext context) {",
			"    return Scaffold(",
			"      appBar: AppBar(",
			"        title: Text(\"\"),",
			"      ),",
			"      body: Container(),",
			"    );",
			"  }",
			"}"
		],
		"description": "Stateful tmp"
	},
```
AIアルゴリズムはトレーディングをどう変えるのか

本記事は、[Entrepreneur](https://www.entrepreneur.com/en-in/technology/how-ai-algorithms-are-changing-trading-forever/377985)により翻訳された記事です。
![QQ20230831121152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2298092/d2300bbd-d6cc-31ca-d551-b13e6fd16189.png)


一般的にトレーディングとは、利益を上げるために資産の取引に関する意思決定を行うことです。すべてのテクニカル分析は、統計データ、過去の市場行動、反応に基づいています。その結果、分析およびいくつかの市場パターンの検索は、人だけでなく、コンピュータや人工知能によって実行することができます。

トレーディング・ロボットが、トレンドやチャネル内の値動きに着目して、長い間株式市場で活躍してきたことは周知の事実である。2020年のJPMorganの調査によると、1,000万ドル以上の取引の60％以上がアルゴリズムを使って執行されています。アルゴリズム取引市場は2024年までに40億ドル成長し、総取引高は190億ドルに達すると予想されています。

その数はかなり膨大ですが、そのダイナミクスを注視することはさらに重要です。 取引ボットやアルゴリズムが市場に氾濫する理由は何でしょうか？トレーダーの主な仕事は資産投機でお金を稼ぐことであり、リスク管理は成功する取引戦略の要である。では、ここで答えを確かめよう。

Aiteグループは、その報告書『ヘッジファンド調査、2020年：アルゴリズム取引』の中で、取引におけるアルゴリズムの人気が高まっている主な理由は、市場のボラティリティが高いため、人的要因の影響を最小限に抑えようとする試みであると論じています。 COVID-19の経済的影響は、米国、欧州、中国で記録的な株安をもたらしました。 そしてわずか数ヵ月後、景気刺激策によって下落を食い止め、反転させることができました。

このようにして、アルゴリズム取引の第一の課題である、ボラティリティの高い市場におけるリスクの低減を実現しています。 アルゴリズム取引の2つ目の世界的な利点は、取引が市場に与える潜在的な影響を分析できることです。 これは、値動きに顕著な影響を与えうる大金を扱うヘッジファンドや機関投資家にとって特に有用である。

取引アルゴリズムの3つ目の基本的な利点は、感情からの解放である。 トレーダーや投資家は、生きているすべての人間と同じように、恐怖、貪欲、利益喪失などの感情を経験します。 こうした感情は、パフォーマンスや結果に悪影響を及ぼす可能性があります。 例えば、2008年の世界金融危機の前夜、金融市場は差し迫った災害の最初の兆候を示していましたが、ほとんどの人はそれを無視し、2000年代半ばから続いていた強気市場の幸福感に浸っていました。 アルゴリズムは、すべての取引が事前に定義されたルールに従うようにすることで、この問題を解決します。

機関投資家はこうした利点を把握しています。 現在、米国の取引所における取引業務の約80％はアルゴリズムによって行われています。 されに今、企業はこうした機会を個人投資家に提供していて、最初の大きな成果はすでに現れています。RegalXはすでにこの技術を利用している取引プラットフォームのひとつです。

取引アルゴリズムの採用はトレーダーや投資家たちに利益をもたらします。 しかも、これらは無名の開発者によるボットでも、この業界の初心者による自動売買シグナルでもありません。 透明性が高く、本当に強力な市場参加者によって開発されたと思われるアルゴリズムを使用した、より高度な機械学習システムは、現在、個人トレーダーが利用できるようになっているようです。

以上、AIアルゴリズムはトレーディングをどう変えるのかについて紹介しました。AIアルゴリズムは今トレーディングだけではなく、[画像加工](https://vanceai.com/ja/)ジャンルにも応用できるようになりました。興味のある方はぜひそういうツールを試してください。
peft環境作成（cudaサポートbitsandbytes 0.41.1）

以下の requirements.txt を作成する。

```requirements.txt
torch --index-url https://download.pytorch.org/whl/cu118
torchvision --index-url https://download.pytorch.org/whl/cu118
transformers
accelerate
sentencepiece
einops
xformers
protobuf==3.20.*
bitsandbytes==0.41.1; platform_system != "Windows"
https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.1-py3-none-win_amd64.whl; platform_system == "Windows"
peft
datasets
```

さらに以下のバッチファイルを作る。

```install.bat
python -m venv venv
call venv\Scripts\activate
pip install -r requirements.txt
```

install.batを実行する。

シェルスクリプトなら多分こう。

```install.sh
#!/bin/bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
【Redash】クエリパラメータを使うと、非エンジニアの方でも集計が簡単に！

# はじめに
Redashを使う中で、「クエリパラメータ」を使うことで非エンジニアの方でも簡単に月次（週次、日次）集計が行えるようになったので、備忘録も兼ねて紹介したいと思います。

# 解決したい課題
- 非エンジニアにとってSQLは、暗号にしか見えない...そもそも見たくない。
- 定時集計のたびにクエリを作成したくない。（極力、1つのクエリを使いまわしたい）

クエリパラメータを使うことで、上記の内容が解決できます。

# クエリパラメータ
クエリパラメータとは、クエリの一部をパラメータ化して、任意の数値や文字列を与えることの出来る機能です。

# 実際にクエリパラメータを使った例
クエリパラメータをSQLの中に仕込むことで、Redashの画面上から集計したい期間が選択可能になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552488/86188135-5682-6680-8cfc-9ac2563dd2d6.png)


非エンジニアの方でも、暗号のようなSQL文に触ること無く、簡単に集計したい期間を選択することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552488/5b8d7342-224f-8732-e238-2529216492d7.png)

# 未経験からのSQLの勉強法について
いちばん重要なのは、とにかく手を動かすことです！
以下の記事内容に沿って、進めていくと習得しやすいです！

[ビジネスサイドがSQLを学ぶ意義と、その勉強方法](https://note.com/u_ta_iwamoto/n/n3d87804706bd)


# 参考
公式ドキュメント 
https://redash.io/help/user-guide/querying/query-parameters
Raspberry PiのCPU温度を測る

## コマンド
```bash
vcgencmd measure_temp
```
結果
```bash
temp=57.4'C
```

## 常時監視
```bash
watch vcgencmd measure_temp
```

```bash
Every 2.0s: vcgencmd measure_temp                   alma-lamp: Tue Sep  5 18:09:42 2023

temp=56.4'C
```
Linux機に他の人のアカウントを公開鍵認証で追加する時の私のやり方

https://qiita.com/aokomoriuta/items/ba40249885f18a3e5f4c

で昔のやり方をメモしていたが、最近は、やり方が変わったのでメモがてら共有。変更点の特徴は

* 公開鍵認証にした
* パスワードは空で渡す（自分でpasswdコマンドで設定してもらう）

という感じです。

```bash
# アカウント名"taro.yamada"で作成する
$ sudo useradd -m -s /bin/bash -p "" taro.yamada

# .sshディレクトリを設定する。オーナー・グループ・パーミッションも変更
$ sudo mkdir /home/taro.yamada/.ssh
$ sudo chown taro.yamada:taro.yamada /home/taro.yamada/.ssh
$ sudo chmod 700 /home/taro.yamada/.ssh

# 公開鍵を登録する。nanoエディタが開くので、所定のもの（例えばgithub.keys）をコピペ
$ sudo nano /home/taro.yamada/.ssh/authorized_keys

# 公開鍵のオーナー・グループ・パーミッション変更
$ sudo chown taro.yamada:taro.yamada /home/taro.yamada/.ssh/authorized_keys
$ sudo chmod 600 /home/taro.yamada/.ssh/authorized_keys

# あとは登録した公開鍵で接続できるはず

# おまけ。sudoグループに入れてsudo実行権限を渡す
$ sudo gpasswd -a taro.yamada sudo
```

手打ちは面倒なので

```bash
#!/bin/bash

# Usage: $ sudo bash adduser.bash taro.yamada

USER=${1}

sudo useradd -m -s /bin/bash -p "" ${USER}
sudo mkdir /home/${USER}/.ssh
sudo chown ${USER}:${USER} /home/${USER}/.ssh
sudo chmod 700 /home/${USER}/.ssh
sudo nano /home/${USER}/.ssh/authorized_keys
sudo chown ${USER}:${USER} /home/${USER}/.ssh/authorized_keys
sudo chmod 600 /home/${USER}/.ssh/authorized_keys

sudo gpasswd -a ${USER} sudo
```

というようにadduser.bashとかに保存して使うと良いかも
ElectronのAppXファイル作成ではまったこと

# パッケージ化したAppXを配布前にテストしたい

1. 作成したAppXファイルを右クリック、プロパティ
1. デジタル署名、署名クリック、詳細
1. 証明書の表示
1. 証明書のインストール
1. ローカルコンピューター、証明書を全ての次のストアに配置する、参照
1. 信頼されたルート証明機関、OK
1. 上記おわったらappxファイルをダブルクリック


# 開発用PCだと動くのに、実験機だと動くやつと動かないやつがある。

'.node'ファイルが見つからない？特定できない？感じのエラー

```
Error: The specified module could not be found.

\\?\C:Program Files\...........\xxxx.node
```

該当のパスを見てみるけどファイルは存在しているようだった。

問題は、xxxx.nodeはバイナリで、そいつが別のdllを呼び出しているが、そのdllが実験機に存在しないせいだった。

dumpbinコマンドで、どのdllをそのモジュールが必要としているかがわかる。

1. dumpbinコマンドを実行できるように、VisualStudioのパスを環境変数に通す
```
例えば
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.37.32822\bin\Hostx86\x64
を環境変数Pathに設定
```
1. .nodeファイルのあるフォルダで、下記コマンドを実行する
```
dumpbin /dependents .\xxxx.node
```
実行結果として次のような感じ
```
PS C:\Users\......\node-aead-crypto-win32-x64-msvc> dumpbin /dependents .\node-aead-crypto.win32-x64-msvc.node
Microsoft (R) COFF/PE Dumper Version 14.37.32822.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file .\node-aead-crypto.win32-x64-msvc.node

File Type: DLL

  Image has the following dependencies:

    bcrypt.dll
    KERNEL32.dll
    VCRUNTIME140.dll
    api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-heap-l1-1-0.dll

  Summary

        1000 .data
        E000 .pdata
       36000 .rdata
        1000 .reloc
      118000 .text
```

これで、VCRUNTIME140.dll必須であることが認識できる。

これを実験機にインストールする。

## AppXにDLL内包したい

上記と絡むが、Visual C++の再頒布パッケージのDLLを内包したAppXを作りたい。

exeの位置にDLLを置きたいが、extraFilesオプションだとasarの内部になってうまくいかない。

いろいろ調べたけどあまりよさそうなオプションがなく、hookでやれという感じだった。

https://www.electronforge.io/config/hooks

```json:forge.config.js
  hooks: {
    postPackage: async (config, packageResult) => {
      if (packageResult.platform == 'win32') {
        let src = path.join(__dirname, 'appx', 'vcruntime140.dll');
        let dst = path.join(__dirname, 'out', '<app>-win32-x64', 'vcruntime140.dll');
        fs.copyFileSync(src, dst);
      }
    }
  }
```

こんな感じで、win32コンパイルの時だけDLL付きにすることができそう。

## Asar:trueにすると *.node が見つからないというエラーで落ちる

Native Electron ModuleはAsarに入れるとだめらしい。

asarを直接つかうならこんな感じ

```bash:direct
$ asar pack app app.asar --unpack *.node
```

electron-forgeとか使ってるなら@electron-forge/plugin-auto-unpack-nativesでやる。

Auto Unpack Native Modules Plugin,
https://www.electronforge.io/config/plugins/auto-unpack-natives

```bash:install
npm i -D @electron-forge/plugin-auto-unpack-natives
```

でインストールして、設定ファイルは、

```json:forge.config.js
  packagerConfig: {
    asar: true
  },
  plugins: [
    {
      name: '@electron-forge/plugin-auto-unpack-natives',
      config: {}
    }
  ]
```

configは空でいいみたい。
Ansible（rawモジュール）でFotigateの"diagnose test ～"の結果を取得。なんとか出来た。

# やりたかった事
背景はひとまず横に置いておいて、
とにかくFortigateの**DNSキャッシュの表示とフラッシュ**をAnsibleで取得&実行したかった。

ForigateのCLIでは
```
# キャッシュ表示
diag test application dnsproxy 7

# キャッシュフラッシュ
diag test application dnsproxy 1
```
で出来る事自体は分かっていたので、
「Ansibleからでも割とさくっと出来るはずだ!!」
と何の根拠も無く思っていたら、大分苦しんだ。

という事で未来の自分のためにブログ投下しておく。
（10数年ぶりのブログ投稿・・そして技術系ブログとしては人生初投稿なのでどうぞ暖かい目で）


# なんとか出来たけど・・
先に申し上げますと、Ansibleというか「SSHの所でハマった話」です。


#### ちなみに・・・
-　[FortiOSコレクション(モジュール)](https://ansible-galaxy-fortios-docs.readthedocs.io/en/latest/index.html)は使ってません。（そもそもAPI経由では"diagnose test ～"系のコマンドはほとんど対応して無さそうだったので)　
-　FortigateはAWS上の公式AMI　OS Ver 7.4.0
-　Ansible側のOSはRHEL9系
です。


## ハマったこと
上記の通り、”FortiOSモジュール以外の何か”の方法で実装しようとしました。

なので[FortiOSコレクションのFAQ](https://ansible-galaxy-fortios-docs.readthedocs.io/en/latest/faq.html#how-to-work-with-raw-fotios-cli)に書いてある、
"rawモジュール×ssh(sshpass)"
の方法で試した所、上手く行きませんでした・・・


なにが上手く行かないかっていうと、-vvvとかで見てもコマンドの実行結果が**表示されない。。。**

一旦Ansibleは置いといて、rawモジュールで実行した内容（sshpass -p～　diagnose test ～）をOSのターミナルから直接実行しても、
実行結果が**表示されない・・・**
なんだとーー!!!
（当然、普通に手動でsshしてから、Fortigate上で実行すると表示される）
そして、（sshpass -p～　**何か他のコマンド**）だと**普通に表示される!!**


詰んだ・・・・

と思って諦め・・・
・・
・・
・・
無い!!悔しい!!
と、思っていると
Fortinetコミュニティサイトに、
[Configuration Example: FortiGate remote monitoring and logging CLI command output into a file](https://community.fortinet.com/t5/FortiGate/Configuration-Example-FortiGate-remote-monitoring-and-logging/ta-p/189892)
なる投稿を発見。んん？なんか```diag```系コマンドをsh化して実行してるぞ？しかもssh(sshpass)もつかってるぞ？コレなんじゃないか？

と、いう事で、コレでした！

## ポイントとしては下記↓
- **-t　オプションを（二回）使ってSSHする**

結局のところ
```
diag test application dnsproxy 7
```
は、
```
diag test application dnsproxy
の後に、、表示される選択肢（オプション）の内、　7　を選択している、

1. Clear DNS cache
2. Show stats
3. Dump DNS setting
4. Reload FQDN
5. Requery FQDN
6. Dump FQDN
7. Dump DNS cache
8. Dump DNS DB
9. Reload DNS DB
10. Dump secure DNS policy/profile
11. Dump Botnet domain
12. Reload Secure DNS setting
13. Show Hostname cache
14. Clear Hostname cache
15. Show SDNS rating cache
16. Clear SDNS rating cache
17. DNS debug bit mask
99. Restart dnsproxy worker
```

**「対話的な操作（疑似端末）が必要になるコマンドだった」**
という事だと思っています。多分。


後は、FAQに乗っている書き方より、上記Forinetコミュニティサイトのように、
- 実行したいコマンドを予め別ファイルで用意する（ex: ./Script/script-fg-spm.sh）
※特定の1コマンドとかで良いならファイル化しなくても echo "XXXX" | って感じで渡せばOK
- ファイル名 | ssh  でコマンドを実行させる

した方が柔軟＆汎用性があるかなと思います。

### 実際のシェル&Playbookはこんな感じ↓↓
```:./Script/script-fg-spm.sh
#! /bin/bash
        sleep 1
        echo exec time
        sleep 1
        echo diagnose test application dnsproxy 7
        sleep 1
        echo exit
#End of Script
```


```:Playbookのtasks
- name: Execute The Debug Test Commands
  ansible.builtin.raw: |
    (./Script/script-fg-spm.sh) | sshpass -p "password" ssh -t -t -o StrictHostKeyChecking=no admin@10.1.1.151 > dnscache_and_time.txt
  args:
    executable: /bin/bash

```

# 最後に
フィジビリティチェックって大事。。。

以上です。
Fortigateは大分好きなので今後もハマって行きたいと思います。
Docusaurusでヘッダーとサイドバーをカスタマイズする

最近、Docusaurusでマニュアル的なものを書く機会がありました。
簡単ではありますが、そのときに工夫したり、手こずったところを投稿します。

## 環境
Docusaurus 2.4.1

## サイドバーの開閉を無効にする
ドキュメントのメニューを表示するサイドバーの開閉を "hideable" で設定できるようです。

- 有効/無効な状態（true/false）
無効な場合、右のように開閉ボタンが表示されなくなります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/49e36957-460e-137a-970c-a963d58d25f3.gif" width=300>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/9d9a9965-952c-57ce-6af3-3a5cd616b793.png" width=300>

- 設定方法
プロジェクト直下にある docusaurus.config.js の themeConfig - docs - sidebar - hideable で設定します。
![sidebar_openclose_code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/b0d9877c-3202-a93e-d042-aef4263566f1.png)

## サイドバーでいずれかのアコーディオンを開いたときに、別のアコーディオンを閉じるようにする
- 実現したいこと
![accordion.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/5460c10f-7e6f-55ea-a6fd-98058196067b.gif)

- 設定方法
設定はこれについても、プロジェクト直下にある docusaurus.config.js で行います。
themeConfig - docs - sidebar - autoCollapseCategories で設定します。
![accordion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/b0ccb2e7-aff3-34a0-6c87-43f45e5e9012.png)

## カラーモードの切り替えを無効にする
デフォルトではカラーモードの切り替えが有効になっています。ヘッダー右にあるおひさまマークで切り替えができます。私は必要なかったので、無効にする設定をしました。

- 実現したいこと
おひさまマークの表示をなくして、切り替えをできないようにします。
![color_switch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/f265ab2b-9d81-a2cb-25d4-ef9425db9c16.png)

- 設定方法
これも同様に、プロジェクト直下にある docusaurus.config.js で行います。
themeConfig - docs - colorMode - disableSwitch で設定します。"disable"Switchなので、trueで無効になります。
また、defaultMode でデフォルトのカラーモードを指定できます。（"light" or "dark"）
![color_switch_code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/43edd5ab-fad3-9a21-52ba-f20182752bdf.png)

## デフォルトの文字色を真っ黒から変更する
デフォルトの文字色は真っ黒なので、雰囲気を出すためにちょっと薄くしました。

- 設定方法
src/css/custom.css で設定できるようです。
:root に color を追加します。
![letter_color_code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641121/d51ee935-2242-0c7b-0b90-a545005e8cca.png)
個人的には、オール75くらいがちょうどよいかなと思っています。

## まとめ
docusaurus自体が簡単に構築できて便利ですし、カスタマイズもやりやすいのかなと。
またなにか出てきたら、書き足していきたいと思います。
Google Cloud (GCP)資格受ける前に必読：Professional Data Engineer 編

皆さんこんにちは！iret Global Solutions 事業部の浜田です。今回はProfessional Machine Learning Engineerをと同じでもう直ぐ(9月19日)ベータ版が出るProfessional Data Engineerについて書いてみました。なかなか難しい試験ですが皆さんのお力になれたら嬉しいです。

<h1>前提条件</h1>
本記事は既にVPC, Google Compute Engine, Cloud Functions,
Cloud storageなどの基本的なGCPのサービスを知っていることを前提としています。


<h1>試験概要</h1>
他の試験と同様、試験時間は2時間で問題数は50問です。AWSは65問あるのに対しGCPは少し問題数が少ないのでありがたいですね。

https://cloud.google.com/learn/certification/data-engineer?hl=ja

<h1>絶対覚えておいた方がいいサービス</h1>


<strong>BigQuery</strong>
BigQuery は、サーバーレスで費用対効果に優れたGoogle Cloudが提供するデータウェアハウスです。
データウェアハウスの移行や、リアルタイム分析、BigqueryMLを使った予測分析などさまざまな用途に使用されます。

<strong>BigTable</strong>
Google Cloudが提供するNoSQL型のデータベースです。AWSで言うところのDynamoDBになってきます。
時系列データ, 購入履歴, IoT等のデータに適しており高スループットも有しています。実際の試験ではCloud SQLやDatastore, Cloud Spannerについても聞かれるのでそれぞれのユースケース等はしっかり覚えておきましょう。

<strong>Dataflow</strong>
Google Cloudが提供するETLサービスです。わかりやすく言うと、Extract （抽出）、Transform（変換・加工）、Load（格納）」の頭文字をとった言葉で、いろんなところに散らばっているデータを統合的に管理するための仕組みです。データの取得、取得したデータの変換や加工、変換・加工されたデータの格納といった一連の流れを行ってくれます。ユースケースとしてはBigqueryをプラスしてリアルタイム分析を行ったり、機械学習ツールであるTensorFlow Extended （ TFX ）にストリーミングイベントを送信して、 AI によるリアルタイムな予測分析や問題検出などがあったりします。

<strong>Pub/Sub</strong>
Google Cloud が提供する信頼性とスケーラビリティに優れた非同期メッセージサービスです。システム間で送信てから受信先に送られてくるごちゃごちゃしたリクエストや命令文、データを間にpub/subを入れてを順番通り管理することでセキュアで拡張性のある送受信を行うことが可能です。データ分析に関連したユースケースとしては、pub/sub + Dataflow + Bigqueryでリアルタイム分析の構成がよく使われます。

<strong>Cloud Composer</strong>
Cloud Composer は、フルマネージドのワークフロー オーケストレーション サービスです。クラウドとオンプレミス 間でのデータパイプライン作成、スケジューリング、モニタリング、管理ができるのが特徴です。実際の内部の仕組みとしては Apache Airflowが使われています。

<strong>Dataproc</strong>
DataFlowではなくApache Hadoop、Apache Spark、Apache Flink、Prestoを使ってデータの解析をしたい人向けのサービスです。

<strong>Dataprep </strong>
GUI操作で機械学習に使用する構造化データと非構造化データを視覚的に探索、クリーニング、準備できるサービス、Data Flowとよく一緒に使われます。

<strong>Data Fusion</strong>
こちらもDataflowとDataprepと同じGoogle Cloudが開発するETLサービス。特徴もCloud Data FusionはDataflowとDataprepの中間といった感じでDataflowがコーディングなのに対しDataprepと同様GUIベースの操作で扱いやすいサービスです。逆に扱えるデータソースはDataflowと同じで豊富になっていますがData Fusionパッチ処理が必要になるのでそこは注意してください。

<h1>覚えといた方が良いサービス</h1>

<strong>基本的なGoogle CloudのDB関連サービス</strong>
これは先ほどの繰り返しになっていますがやはり基本的なデータベース関連のサービスは覚えておいた方がいいです。特にBigqueryを使用したユースケースは調べておきましょう。

<strong>機械学習関連</strong>
AWSと同様でやはりデータ分析関連の試験は機械学習と関係性が深い傾向にあります。GCPでも機械学習に関するサービスがある程度聞かれる可能性があるので一通り覚えておいて損はないです。以前、Professional Machine Learning Engineerに合格した際に記事を出したので時間に余裕がある人は参考程度にチェックしておいた方がいいかもです。

https://qiita.com/sina-cloud/items/8c421f3e51f214adde93


<h1>試験対策</h1>
やはりどのGoogle Cloud認定資格も情報をインプットしただけで受かるほど甘くないです。まずはGoogleが出している模擬試験を解きまくりましょう。

https://docs.google.com/forms/d/e/1FAIpQLSd4j4bcgbYenBRFIL6Kb0cvXp13qCQ-z6JzowgDxRaPITn56g/viewform?hl=ja


Udemyではこちらのコースを使用しました。解説がところどころ雑な箇所もありましたが全体的にはとても優れた問題集になっています。

https://www.udemy.com/course/google-cloud-professional-data-engineer-s/


<h1>最後に</h1>

さて、今回の記事は以上になりますがデータ分析関連の資格は機械学習同様前提知識が肝となってくるのでGoogle Cloudのリソース以外にもデータ分析の基礎的な流れなどをしっかり理解して試験に臨むのが得策です。

他のGoogle Cloud の試験に興味がある方は以下に難易度順のランキングを載せているので参考程度に是非。

https://qiita.com/sina-cloud/items/bbe1d263c6b69954867f

それでは皆さん、ご武運を。
【初心者向け】DynamoDBについて学んだこと

# はじめに
DynamoDBでテーブル設計を行うにあたって、色々学んだのでまとめてみることにします。

# DynamoDBとは
> Amazon DynamoDB とは、ハイパフォーマンスなアプリケーションをあらゆる規模で実行するために設計された、フルマネージドでサーバーレスの key-value NoSQL データベースです。DynamoDB は、内蔵セキュリティ、継続的なバックアップ、自動化されたマルチリージョンでのレプリケーション、インメモリキャッシング、データのインポートとエクスポートツールを提供します。

## key-value NoSQL データベース
- key-value検索により高速なデータアクセスが可能。一方で複雑なクエリによるデータアクセスには対応しない

## マルチリージョンでのレプリケーション
- 複数のアベイラビリティゾーンにまたがってデータを分散して保存しているため、可用性と分断耐性に優れている
- その代わりに一貫性が下がる※(ノードの故障や通信エラーにより、複数のノード間で整合性がとれないことがある)

※ReadRepair機能(読み込み時に最新のデータで古いノードのデータを更新や、
Quorumを使って結果整合性(不整合が出た場合に、なるべく多く一致したデータを判定する)をとる方法などで対応可能

## データの配置について
- DynamoDBはデータをパーティションという単位に分散して保存する
    - データアクセス時の負荷分散が抑えられることと、単一障害を回避することができる
- データがどのパーティションに属するかはパーティションキーで指定している
    - パーティションキー以外でデータを検索することができない。検索の必要に応じてソートキーを利用、あるいはインデックスを作成することで対応可能

## テーブルを構成する要素
- プライマリーキー
    - パーティションキー(PK)
    - ソートキー(SK)
- セカンダリーインデックス(SI)
- 属性

### プライマリーキー
- パーティションキー(必須):　テーブル内のデータを物理的に分割するために使用
- ソートキー:　パーティション内のデータを論理的にソートするために使用

### セカンダリーインデックス
- データへのアクセスをプライマリーキー以外の属性で行うことができる
- ローカルセカンダリインデックス(LSI)とグローバルセカンダリインデックス(GSI)の2種類が存在
- 1つのテーブルにLSI/GSIはそれぞれ5つまで作成可能

| 特徴                             | LSI            | GSI                |
|----------------------------------|----------------|-------------------|
| PKとSKの設定                     | SKのみ可能 | PK、SK共に可能 |
| PKとSKの一意性                   | 必須でない   | 必須               |
| テーブル作成後のインデックス作成 | 不可           | 可能               |
| GetItemおよびBatchGetItemの使用  | 不可           | 可能               |

### 属性
- テーブル内のデータを表す要素

## DynamoDB API
- GetItemやCreateTableについてはこちら
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.API.html

# 設計例
ここではユーザーのパスワード変更機能について考えてみたいと思います
ユーザー認証にはトークンとメールアドレスを用いることにします

## 要件
- メールアドレスが存在かつトークンが有効なとき、パスワードが変更できること
- メールアドレスが存在かつトークンが無効なとき、パスワードが変更できないこと
- メールアドレスが存在しないとき、パスワードが変更できないこと

- パスワード変更後はメールアドレスに紐づくトークンデータが削除されること

## データの利用パターン(tokenからemailを検索したい)

①token(DataValue)で検索し、IDを取得

②IDで検索し、DataType(token/email/created_at)を取得

- パスワード変更後はemail(DataValue)で検索し、IDのDataType(token/email/created_at)を削除

## 設計の考え方

①まずtoken(DataValue)で検索し、IDを取得する
- token(DataValue)で検索できるようにPKとして設定
- PKは一意である必要があるため、IDをSKとして設定(emailが重複する可能性があるため)

②次にIDで検索し、DataType(token/email/created_at)を取得する
- IDをGSIのPKに、DataTypeをGSIのSKとして設定

## 設計したテーブル
| ID     　| DataType | DataValue        |Created_At|
|:------- | -------- | ---------------- |----------------|
| String 　| String   | string           | string
| SK,GSI-PK| GSI-SK | PK              ||
| 1      　| token    | aaa              | 2023/09/05 12:00 |
| 1      　| email    | sample@hoge.jp | 2023/09/05 12:00 |

# おわりに
テーブルを設計するにあたって事前にデータの利用パターンを考える必要があったり、DynamoDBの特徴や設計に関わってくる背景について学ぶことができました。まだまだなので引き続き経験を積んでいきたいと思います。


# 参考
https://zenn.dev/reds/articles/5331f1219394f1

https://qiita.com/d0raem0n/items/c2af7d3d55093134bac3
【xarray】DataArrayをpickleで保存する

`Python`の標準ライブラリである`pickle`を用いると、オブジェクトを「そのまま」ファイルに保存し、別のプログラムから読み込むことができる。

# 注意
`pickle`を用いて`xarray`を**長期保存**するのは**非推奨**である。

>ピックルを復元するには、ピックルされたデータの型の内部構造が変更されていない必要があります。xarrayの内部設計はまだ改良中であるため、このバージョンのxarrayでピックルしたオブジェクトが将来のバージョンでも動作することを（現時点では）保証しません。（DeepL翻訳）

https://docs.xarray.dev/en/stable/user-guide/io.html#pickle


# 書き込み
`array`という名前の`DataArray`を`hoge.bin`というファイルに保存する方法は次の通り。
`hoge.bin`が存在しない場合は、新規作成される。

```Python
import pickle
with open('hoge.bin', 'wb') as f:
    pickle.dump(array, f)
```


# 読み込み
```Python
import pickle
with open('hoge.bin', 'rb') as f:
    load_array = pickle.load(f)
```
【D365 ERP】量産型の製品を扱う製造業をモデルとしたシナリオ設定

こんにちは、FrogFishです。前回から少し時間が経ってしまいました。D365を検討するにあたって、具体的なビジネスケースをもって説明したく本ブログをはじめました。早速ビジネスケースを設定します。本ページはD365の機能説明のネタに応じて刻々と変わっていきます（笑）


会社について
KAGOMARU株式会社電機製品を生産販売する株式会社。掃除機の生産を自社ブランドで行い、販売しています。
・KAGOMARUグループ事業内容
1.掃除機の生産、販売

・各事業部の役割
1.家電生産本部
2.営業本部
3.物流本部

扱っている製品
・掃除機
-----
では、次回からD365の機能をご紹介してまいります。
Unable to find method ''boolean org.gradle.StartParameter.isConfigurationCache 的なエラーが出た時の備忘録

## 概要

```
Unable to find method ''boolean org.gradle.StartParameter.isConfigurationCache ...
```

みたいなエラーが、
gradle をsync しようとした時に起きました。



## 解決策

```
Project >> App >> gradle >> wrapper >> gradle-wrapper.properties
```

に進み（例えば下の場所です。）

![Screenshot 2023-09-05 at 17.23.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1840635/b6e75494-17a3-5998-3243-70c8eb68148a.png)


```
https\://services.gradle.org/distributions/gradle-7.4-bin.zip
```

だったものを、

```
https\://services.gradle.org/distributions/gradle-8.0-bin.zip
```

とすることでsync できる様になりました。
JavaでWord文書を結合する方法

## はじめに
Word文書を結合することは、複数のWord文書を1つの文書にまとめることができます。この操作により、関連する複数の文書を一元管理し、情報をより簡単に共有することができます。結合する際には、文書全体を挿入する方法や、文書の内容のみをコピーして結合する方法があります。以下に、詳細な手順をご紹介します。
## ツール
* IntelliJ IDEA 2018 (jdk 1.8.0)
* [Free Spire.Doc for Java](https://www.e-iceblue.com/Introduce/free-doc-for-java.html)

## Jarファイルの導入
* [Free Spire.Doc for Java](https://www.e-iceblue.com/Download/doc-for-java-free.html)をダウンロードして解凍します。
* IDEAで新しいプロジェクトを作成します。
* 「File」>「Project Structure」>「Modules」>「Dependencies」をクリックします。
* 「+」の「JARs or Directories」を選択します。
* 「Spire.doc.jar」を見つけてプロジェクトにインポートします。

## 文書全体を挿入する
```java
import com.spire.doc.*;

public class MergeByInserting {
    public static void main(String[] args) {

        //Documentのオブジェクトを作成し、Wordドキュメントを読み込む
        Document document = new Document("sample 1.docx");

        //別のWordドキュメントをこのドキュメントに完全に挿入する
        document.insertTextFromFile("sample 2.docx", FileFormat.Docx_2013);

        //結果ドキュメントを保存する
        document.saveToFile("result 1.docx", FileFormat.Docx_2013);
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/46d3321f-1a07-fd10-e26a-e902ce0417d4.png)
## 文書の内容をコピーする
```java
import com.spire.doc.*;

public class MergeByCopying {
    public static void main(String[] args) {

        //2つのDocumentオブジェクトを作成し、2つのWordドキュメントを読み込む
        Document document1 = new Document("sample 1.docx");
        Document document2 = new Document("sample 2.docx");

        //2つ目のドキュメントをループして、すべてのセクションを取得する
        for (Object sectionObj : document2.getSections()) {
            Section sec=(Section)sectionObj;

            //2つ目のドキュメントのセクションをループして、その子オブジェクトを取得する
            for (Object docObj : sec.getBody().getChildObjects()) {
                DocumentObject obj=(DocumentObject)docObj;

                //最初のドキュメントの最後のセクションを取得する
                Section lastSection = document1.getLastSection();

                //最初のドキュメントの最後のセクションに子オブジェクトを追加する
                Body body = lastSection.getBody();
                body.getChildObjects().add(obj.deepClone());
            }
        }

        //結果ドキュメントを保存する
        document1.saveToFile("result 2.docx", FileFormat.Docx_2013);
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/fb765db5-1145-6448-6be9-a1b5f94def07.png)
WorkSpacesからMWAAのAirflow UIにプライベートアクセスする

# はじめに
MWAAのプライベートネットワークアクセスモードで接続する際は、以下に記載があるようにVPNやDX/Linux踏み台サーバー/ロードバランサーを使った方法があると思います。

https://repost.aws/ja/knowledge-center/mwaa-connection-timed-out-error

この中だとまぁ大体の人がロードバランサーを使うと思います。踏み台サーバーは管理が大変なので。
ただ、そうすると以下のコンソール画面からAirflow UIにワンクリックで飛べなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/0aa66ce6-69d5-b7ca-4a42-032a2dd3672a.png)

理由は、このリンク押した時の遷移先がWeb ServerのVPCエンドポイントになってしまっているからですね（以下の画像参照）。せっかくこのVPCエンドポイントの前にロードバランサーを置いたのでそっちに飛んでほしいんですが･･･。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/c3117428-fa46-7a7b-61eb-3792c7d15662.png)

なので、ロードバランサーを置いた場合はAirflowのWebログイントークンを発行して、それを使ったURLを自身で作って接続しないといけないんですよね。ちょっとめんどい。**プライベートアクセスでもコンソールからワンクリックでAirflow UIに接続したい！！**

https://docs.aws.amazon.com/ja_jp/mwaa/latest/userguide/call-mwaa-apis-web.html


なので、第4の方法として**WorkSpacesから接続する**、という方法を試してみたいと思います。
VPC内のWorkSpacesからなら、プライベートアクセスで接続できるはず。つまり、コンソールからワンクリックでAirflow UIに接続できるはず！

# 前提
- Airflowバージョン 2.5.1
- 事前にプライベートアクセスで環境作成済み
- VPCは環境作成する際に自動で作成したもの
- WorkSpacesはWindows10（WindowsServer2016ベース）で作成

# やってみる
## WorkSpacesを作成する

https://dev.classmethod.jp/articles/simple-ad-workspaces-2022/

こちらを参考に、Simple ADを使用して作成しました。
ディレクトリにサブネットを紐づけることが出来るので、MWAAの環境作成するときに作った2つのプライベートサブネットを指定しています。

## MWAAのセキュリティグループを修正する ★ポイント
ここがポイントです。

以下の図はWorkSpacesのBlackBeltから引用しています。
WorkSpacesのディレクトリをサブネットに紐づけると、そのサブネットにENIが出来ます。**ENIにはセキュリティグループが付与される**ので、そのセキュリティグループからMWAAにアクセスできるようにしなければいけません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/05ce1da1-d249-6d70-4304-2b3ae64a8dad.png)

https://pages.awscloud.com/rs/112-TZM-766/images/20190226_AWS-BlackBelt_Amazon_WorkSpaces.pdf

実際にENIを探してみると、いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/f00c59ae-e86d-d9a4-abee-9f49fc7146fb.png)

WorkSpacesのドキュメント見ると
>WorkSpaces のセキュリティグループの名前は、ディレクトリ識別子の後に _workspacesMembers が続きます (たとえば、d-123456fc11_workspacesMembers)。

とあるので、セキュリティグループ名からしてもこいつで間違いなさそうです。

https://docs.aws.amazon.com/ja_jp/workspaces/latest/adminguide/amazon-workspaces-security-groups.html

このセキュリティグループを、MWAA側のセキュリティグループのインバウンドで許可してあげたら、WorkSpacesからMWAAのAirflow UIにプライベートアクセスできました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/9c10760e-4d05-bb1d-f4e8-2ed6d11f41cb.png)

# おわりに
WorkSpacesもMWAAもVPC内に作成したはずなのに最初接続できず、なぜだろうと思っていたのですが、セキュリティグループが問題でした。
「VPC内に作成する」と言っても、実際はENIが作成されてそこが通信もとになっているパターンは他にもありそうなので、注意が必要ですね。