やかんです。

週末は取り組みが少なかったので、まとめて日記にしています。

ようやく学科終わった。

教習所の学科がようやく終わりました。

やったことについて

エンジニア業務

予定としては、今日はgcloud sdkとの格闘。

  • OSアプデして、Macbook airとproのバージョン揃えたら、またディスプレイ繋がりました。これが便利すぎる。。
  • proの方は、githubの認証周りで色々設定しないといけないのか。この辺あんまり仕組みわかってないんだよなあ。
    • まあ、前よりはわかってきている気がする。
    • こちらのqiitaがわかりやすかった。
  • 今日のテーマはgcloud sdkについてっぽいよな。
  • まずはデプロイして、そこからCI/CDを考えよう。
  • rate limitの設定はしておくか。開発中だしまだ。
  • コンテナの中でpip installとかした場合、ファイルシステムがコンテナとローカルマシンで独立しているから、そのままじゃ多分動かないよね。パスが見れなくて。
    • これそもそも、コンテナの中の開発ってホットリロードとか適用されるのか?
    • されてた。
  • コンテナないで、作業はできるが、pushがまだできない。ネットワークシステムに踏み込むから難しそうだよなあ。
    • ユーザーの概念が大事になってくるわけか。マシンにはユーザーが存在する。このユーザーの概念はOSの概念なのか?
    • sshクライアントが必要なのか。できたー。
    • 感動的だ。。
    • sshクライアントとは、ssh通信を行うために必要なソフトウェア。
  • 権限の最小値を探す営みって大変だなあ。
    • cloud storageとIAMの権限設定は同期させる必要があるんだな。
  • app engineは裏側でcloud buildが動いているのか。
  • github actionsを使ってCI/CDを実現すると、リポジトリのコードとデプロイされて動いているコードの一貫性が容易に保たれる。こ、github actionsを使わないとなると面倒だよな。

オペレーティングシステム(自学)

  • 条件変数について課題に取り組むことを通じて復習。
    • 復習前に覚えていることを挙げておくと、確か、要点は「メモリを容量よく使うために、実行される必要がないとわかっているスレッドはブロックしておく」ということだったと思う。
    • あとは普通のmutexっぽく使えるんだった気がする。
  • pthread_cond_waitだっけ?
    • シンプルに考えれば、「CPUコアの解放とスレッドのブロック」を一連の処理として行いたいわけだよな。
    • pthread cond wait(第一引数, 第二引数)
    • ↑第一については、条件変数へのポインタ。第二引数は、ミューテックスオブジェクトへのポインタ。つまりこれは、ミューテックスオブジェクトが利用されていることが当然に前提されているということ。
  • OpenMPの実行時には、gcc-13を使う。-fopenmp忘れずに。まあ、この環境限定の話なんだけど。
  • 条件変数の初期化ってどうやるんだ?
    • 動的初期化の方がいいかな。
    • 飽和カウンタについて。
    • 条件変数について、条件が満たされているかどうかというのは基本的にループ処理において確認するらしい。
    • 条件変数について、スレッドのブロックとCPUコアの解放だけを考えるとよくわからなくなる。この時、スレッドを実行可能にするロジックを忘れてはいけない。実行可能になったときに、ブロックされていたスレッドは、ブロックされた時に実行していた行の次の行から実行する。
  • 今までの自分の学習の浅さが際立って苦しい。。多分、アルゴリズムとデータ構造についても学習が浅いんだろうな。。うおー、まじか。
    • まあ、今気づけてよかったです。
  • pthread_cond_signal()は、どのスレッドを起こすか選べないってことか?
    • そのようだ。使い所が難しいな。
  • 条件変数と条件は一対一に対応している。つまり、新しい条件をスレッドに追加したい場合は、新しい条件変数を定義する必要があるということだ。

pthread_mutex_unlockし忘れて沼りましたが、無事課題提出完了。

オペレーティングシステム(自学)

  • メモリについて。
  • メモリ管理ユニットが頑張ってくれているんだよな。
    • 仮想アドレス空間から物理アドレス空間への写像だったと記憶している。
  • ページの概念だよな、理解するべきは。
    • ページングと、ネットワークのルーティング、なんか似ている気がするな。
    • 仮想アドレスの物理アドレスへのマッピングは、段階的に具体性を上げていくことで効率化を図っている。
    • つまり、ページという概念は、物理メモリの抽象化と言うことができるだろう。
  • ページフォルトは、仮想アドレスが物理アドレスにマッピングできない時に生じる状態のこと。これが起きたら、OSはスワッピングなどで物理メモリ領域の確保を行い、プログラムを再開する。
  • ページフォルトの数というのは、仮想アドレスの論理アドレスへの写像が失敗した回数。
  • 1ページあたりのサイズは、基本的に4096バイト。
  • ページフォルト時は物理メモリ領域の確保のための時間がかかる。結果として、そのメモリへのアクセス時間は長くなる。
    • ということは、初回アクセス(マイナーページフォルトの発生)を過ぎればメモリへのアクセスは高速になるということだよな?
  • ページフォルトには2種類ある。少なくとも。マイナーページフォルトとメジャーページフォルト。メモリへの初回アクセス時に生じるのがマイナーページフォルト。
  • いやいや、すごいけどむずいなあ。。メモリって目に見えないからな。見えないよね?
    • これはもう、自分でプログラムを書きながらなぞるのがいいのかなあ。理解したい。
  • ページテーブルってなんだ?

アルゴリズムとデータ構造(自学)

  • まずはバブルソート。これは、何番目に大きいあるいは小さい要素について扱っているかを大事にしながら実装すればなんとなかった記憶。
  • vectorについてはswapが使える。
  • 多分、バブルソートはこんな感じ。
void bubble_sort(vector<int>& array){
  int size = array.size();

  for(int i = 0; i < size - 1; i++){
    for(int j = size - 1; j >= i + 1; j--){
      int current = array[j];
      int former = array[j -1];

      if(current < former){
        swap(array[j], array[j - 1]);
      }
    }
  }
}
  • じゃあ次クイックソート。
  • 一応これも、ナイーブな方法は実装簡単。多分こんな感じ。
#include <iostream>
#include <vector>

using namespace std;

vector<int> quick_sort(vector<int>& array){
  int size = array.size();

  if(size <= 1) return array;

  int pivot = (array[0] < array[1]) ? array[1] : array[0]; // 最初の二つの要素のうち大きい方をpivotに指定。

  vector<int> array_left;
  for(int i = 0; i < size - 1; i++){
    if(array[i] < pivot) array_left.push_back(array[i]);
  }

  vector<int> array_right;
  for(int i = 0; i < size - 1; i++){
    if(array[i] >= pivot) array_right.push_back(array[i]);
  }

  vector<int> array0 = quick_sort(array_left);
  vector<int> array1 = quick_sort(array_right);

  array0.push_back(pivot);
  array0.insert(array0.end(), array1.begin(), array1.end());

  return array0;
}

int main(){
  // ランダムに10の要素を持つ配列を作成
  vector<int> array;
  for(int i = 0; i < 10; i++){
    array.push_back(rand() % 100);
  }

  // ソート前の配列を出力
  for(int i = 0; i < 10; i++){
    cout << array[i] << " ";
  }
  cout << endl;

  // ソート
  array = quick_sort(array);
  // ソート後の配列を出力
  for(int i = 0; i < 10; i++){
    cout << array[i] << " ";
  }

  return 0;
}
  • だがこれだと効率が悪いと。改善をする必要がある。
    • 配列がめっちゃ増える。だから、配列を増やさない、つまりswapみたいにして実現できれば嬉しい。
  • でもこれどうやって実装するんだ?
    • なるほど。本当に配列を新たに宣言しないんだ。ちょっとわかってきた。
    • 全てポインタ操作でいけるよな。だから、再帰関数の中で配列を返り値にする必要がない。返り値不要。
  • 難しく見えるけど、そんなに難しいことじゃない気がしてきた。
  • 若干怪しいけどとりあえず実装はできる。
    • いや、これ、無限ループに陥らないように調整するのが難しいな。
  • こういうとき、具体例をたくさんいじっていればいつか理解できるという話がある。
    • まずlを決めて、それからrを決めるという順番がある。順序がある。同時に決まるわけではないから、ここは順序立ててそれぞれのフェーズを独立したものとして考えることができる。
    • 色々いじってみて、バグケースがわかってきた。やはりいじってみるしかないよなあ。
    • 重複があったら面倒だな。。
  • 以下のクイックソートもどきは、pivotが重複する場合プログラムが終わらなくなる。
#include <iostream>
#include <vector>
#include <map>

using namespace std;

int find_pivot(vector<int>& array, int i, int j){
  int pivot_index = rand() % (j - i + 1) + i;
  int pivot = array[pivot_index];

  return pivot;
}

int partition(vector<int>& array, int l, int r, int pivot){
  while(1){
    while(array[l] < pivot){
      l++;
    }
    while(pivot < array[r]){
      r--;
    }

    if(l >= r) return l;

    swap(array[l], array[r]);
  }
}

void quick_sort(vector<int>& array, int i, int j){
  if(i >= j) return;  

  int pivot = find_pivot(array, i, j);
  printf("pivot: %d\n", pivot);

  int k = partition(array, i, j, pivot);

  quick_sort(array, i, k - 1);
  quick_sort(array, k + 1, j);
}

int main(){
  int size = 10;

  // ランダムに10の重複のない要素を持つ配列を作成
  vector<int> array;
  for(int i = 0; i < size; i++){
    array.push_back(rand() % 10);
  }

  // ソート前の配列を出力
  for(int i = 0; i < size; i++){
    cout << array[i] << " ";
  }
  cout << endl;

  // ソート
  quick_sort(array, 0, array.size() - 1);
  // ソート後の配列を出力
  for(int i = 0; i < size; i++){
    cout << array[i] << " ";
  }

  return 0;
}
  • できたー。。できたと思っている。
#include <iostream>
#include <vector>
#include <map>

using namespace std;

int find_pivot(vector<int>& array, int i, int j){
  int pivot_index = rand() % (j - i + 1) + i;
  int pivot = array[pivot_index];

  return pivot;
}

int partition(vector<int>& array, int l, int r, int pivot){
  while(1){
    bool left_eaquls_pivot = false;
    bool right_equals_pivot = false;

    while(1){
      if(array[l] < pivot){
        l++;
      } else if(array[l] == pivot){
        left_eaquls_pivot = true;
        break;
      } else {
        break;
      }
    }

    while(1){
      if(pivot < array[r]){
        r--;
      } else if(array[r] == pivot){
        right_equals_pivot = true;
        break;
      } else {
        break;
      }
    }

    if(l >= r) return l;

    if(left_eaquls_pivot && right_equals_pivot){
      if(l + 1 == r) return l;

      l++;
    }

    swap(array[l], array[r]);
  }
}

void quick_sort(vector<int>& array, int i, int j){
  if(i >= j) return;  

  int pivot = find_pivot(array, i, j);
  printf("pivot: %d\n", pivot);

  int k = partition(array, i, j, pivot);

  quick_sort(array, i, k - 1);
  quick_sort(array, k + 1, j);
}

int main(){
  int size = 10;

  // ランダムに10の重複のない要素を持つ配列を作成
  vector<int> array;
  for(int i = 0; i < size; i++){
    array.push_back(rand() % 10);
  }

  // ソート前の配列を出力
  for(int i = 0; i < size; i++){
    cout << array[i] << " ";
  }
  cout << endl;

  // ソート
  quick_sort(array, 0, array.size() - 1);
  // ソート後の配列を出力
  for(int i = 0; i < size; i++){
    cout << array[i] << " ";
  }

  return 0;
}
  • ↑partition関数がやたら複雑なのが気になるが、まあ挙動としては正しいはず。。
  • OK。クイックソート完了。

次はマージソートかな。

アルゴリズムとデータ構造(授業)

  • 基数ソートは、「知っていないと解けない」系な気がするが、読めばわかる。実装どうやるのかはわからんが。
  • 集合やってソートやって、今からグラフをやる。
    • 探索
    • 連結性
    • 最小木
    • 最短経路
  • ↑なんかの聴講でちょろっとやった記憶。
  • 最小木は有向グラフにはない。それ以外は両方にある。
  • まずは、グラフの探索について。
    • 探索は、木以外のグラフについても適用可能なのか?
    • トポロジカルソートすごいな、
  • 幅優先探索は深さよりもわかりにくい。
  • 反復深化探索、微妙では?
    • 使い所ってあるのか?

サイバーセキュリティ3(授業)

  • 弁護士の人のゲストスピーキング。
  • ランサムウェア攻撃。身代金のやつ。
    • FBIでもCIAでも復元不可能なのか。。まじか。
    • データを盗んで、公開するよっていうケースも。
    • 企業は、機密保持契約を結んでいることが多いから、データが盗まれて公開されると企業はめっちゃ困る。お金を払えば基本的に公開を差し止めてくれるらしい。
  • お若いのにすごいな。
  • lockbitというサイトがあるのか。リークサイト。
  • ランサムウェア集団が存在していて、それぞれがリークサイトを運営していたりするのか。。
    • ほぼロシア系らしい。
    • マルウェアを解析してみると、ロシア語はスキップするように組まれているらしい。
  • 最近はデータの暗号化だけじゃなくて、公開もセットでランサムウェアが行われている。
    • 企業からしたら、支払いのインセンティブが増す。
  • ランサムウェア、githubで管理していたら大丈夫みたいな話はないのか?
  • 中国で一番でかい銀行もランサムウェア攻撃に合っているのか。。9000億円の取引が止まったらしい。倒産の危機にあったらしいが、すぐに身代金を払ったことで復旧したらしい。
    • 金融機関もやばいのか。。
    • 金融機関震え上がるよなこれ。具体的な対策が気になるよな。
  • ランサムウェア攻撃の復旧には1億かかるくらいザラなのか。。
  • ランサムウェア攻撃と自然災害は、変わらない、同程度である側面が大きい。もっというと、人為的なものであるため発生頻度も高い。かつ、犯人の捕獲は難しい。
    • リスクとして最大級のものなんだ。
    • 経営者の多くは個人情報の漏洩などを情報リスクと考えていることが多いらしい。が、ランサムウェア攻撃は会社の事業自体が止まってしまう可能性がある。
  • 上場企業のうちでは、サイバーセキュリティの重要性が高いものであるというのが一般認識とも言えそう。
  • 事前に、ランサムウェア攻撃とかへの対策を考えておけば、速やかに動けるわけか。
    • データのバックアップがあれば、公開部分はどうしようもないが、暗号化部分はどうにかなる。
    • ネットワークの隔離など。
  • RaaSなんて言葉があるのか、、!
    • Ransomware as a Service
    • 誰でも簡単にランサムウェア攻撃を行うことができる。
    • これの存在により、攻撃対象がそこまで大規模じゃなくてもいいのか。手軽にできるようになっているのか。。
    • フィジカルな世界では逮捕されやすい世の中。それがサイバー空間においてはまだ逮捕されにくいということか。闇バイト。
  • コロナ禍になり、VPNがはやった。これが普及した結果、ハッカーはVPNを狙った。
  • マルウェアの感染が広がるってどういうことだろうか。
  • 身代金、72億円とかのケースがあるのか。。
    • すごい儲かるから、手足も増える。
    • て考えると、被害というか、攻撃は増える一方だよなあ。。
  • ORVXというリークサイトもある。
    • サイトによっては、マルウェア作って納品することが試験になっているものもあるらしい。マルウェア作る技術力ある人だけが参加できる、みたいな。
    • IDパスワードとか、盗まれていない方が珍しいんじゃないのか、、?
    • ダークマーケットこわ。
    • ダークマーケットやばいな。。
    • 2段階認証まじで大事だな。
  • CONFIとかが有名らしい。
  • 重層的なセキュリティ。ファイアーウォールでまず捌く、みたいな。
    • でも今は、セキュリティツールの市場は飽和しているらしい。みんな不安だけど何もわからんから、とりあえず買いたくなる。
    • よって、攻撃傾向を踏まえた対策が叫ばれている。
    • VPN経由が多い、などの傾向。
  • VPNとか、具体的な仕組み知らない。知りたい。
  • 多要素認証めちゃめちゃ大事だな。。
  • ほとんどの企業が、地震や津波の対策は持っている。
  • バックアップの確保も大事だなあ。公開部分はどうしようもないけど。
    • バックアップも暗号化されたら意味ないから、バックアップの保管方法も具体的に検討する必要があるよな。
  • OFAC規制というものがある。ランサムウェア攻撃の身代金払っていいの?みたいな。
    • OFAC的には、テロへの資金提供を禁じている感じで、身代金を納めるのはランサムウェア攻撃グループへの支援と考えられ、支払いダメらしい。
    • 域外適用があるっぽい。
    • この辺、国際法もうちょいちゃんと勉強しておけば良かったな。
  • 日本には、OFAC規制のような規制はない。
    • ランサム集団は、日本国内のテロ組織の定義に該当しない。現状。
    • 協力要請的に、「払わないでね」と表明してはいるらしい。
    • 日本は、国際的にみて、身代金払っていない方。18%しか払っていない。アメリカ76%払ってんのかい。OFAC規制あるんじゃないのか。てか、世界支払い率高いな。
    • SDNリストに載っているところの支払いは禁じられているが、ランサム集団については支払い禁止リストに載らないらしい。だから、OFAC規制が発動しないのか。。
    • サイバー保険というものがあるらしい。サイバー攻撃についての損害を払ってくれる保険。この保険あるなら、まあ払っていいか、的な。日本だと、サイバー保険作っちゃまずいらしい。まあでもこの、身代金に保険を適用してもいいというのは近いうちに消えるだろうと考えられている。
    • また、払った方が総じて安くなることもあるらしい。なるほど。利益衡量の問題か。企業の稼働が停止するよりも、身代金払った方が全然安く済んだりする。
    • アメリカは訴訟よく起こる。身代金払わず情報漏洩した方が、リーガルコストがかかる。
  • サイバーセキュリティ裁判とかあるんだ。
    • 日本はこの裁判起きない。まあ、色んな理由があって。これを逆手にとって、日本企業、セキュリティ対策にお金をかけないところも多い。
    • 企業同士の訴訟について。日本企業の場合、契約内容に「セキュリティ要件も含めること」という条項が含まれないことが多いらしい。現状。
    • ハッキングの場合、まあ一番悪なのはハッカー。でも、ハッカーが絶対に捕まらないという前提が如かれるから、被害者間で損害をどうやって分担する?という、責任問題の訴訟になる。過失相殺。みんな少しずつ悪いから、みんなで損害を負担しようという。
    • だから、被害者も負担しなくてはいけない。ハッカーに全部負担させたいところだが、これが不可能だと。
    • 過失の認定が実務上大事なのか。民法の話や。
    • ものによっては、片方が100%悪いということもあるらしい。
  • 法務部が今頑張っていたりするのか。
    • 不可抗力条項というものがある。地震とか、災害レベルの何かが起こってサービスが止まった、などの場合には、補償できないよみたいな。不可抗力はしょうがない、みたいな。ここに、サイバー攻撃も追記される傾向があると。
    • エンドユーザーと企業の間には、賠償責任制限条項がないことが多い。が、企業と、その発注先の企業の間にはあることが多い。この場合、発注元企業はめっちゃ負担が重くなる。
  • AIとサイバーセキュリティの2大巨頭って面白いなあ。。
    • MandiantがGoogleに買収されたらしい。
  • 工学部で司法試験受かってんのか。。すげー!今就活中だそうですが、何年生だろう。
    • 4大弁護士事務所は、やりたい仕事にアサインされるかわからない。が、

疑問。

  • ハッカーは、ターゲットを企業から選ぶのか、脆弱性から選ぶのかどっちなんだろう。脆弱な企業を探すのか、お金の払ってくれそうな企業を探すのか。
  • ランサムウェア攻撃の文脈で、具体的にサイバーセキュリティの対策として企業は何をしていることが多いの?
  • 「脆弱性を見つけるために、色んなとこを公認でハッキングしまくる」みたいな職種あるの?職じゃなくても、ポジション。そんな道があったらぜひ進んでみたい。

やることorやりたいこと

  • グラフ探索アルゴリズム。
  • サイバーセキュリティ受講。

ということで今日含め数日の日記終了。最後までお読みいただき、ありがとうございます。