K-ornata

iMac の純正マウスがある日突然つながらなくなったので、マウスの裏にあるスイッチをオフ・オンしたら再接続できた件

ある日突然、iMac で使っていた純正マウスが Bluetoothで接続されなくなりました。

しばらくは原因がわからず、有線のマウスで対応していましたが、そのあとマウスの裏にスイッチ(下図の赤枠部分)があることに気がつき、一度そのスイッチをオフ・オンしたところ無事に再接続されました。

Mac純正マウス

なお、上記のオフ・オンのタイミングで、Macの「システム環境設定」にある「マウス」の設定画面に「System Administrator’s Mouse」が表示され、接続済みとなりました。

iMac マウス設定画面

マウスのオフ・オンでもダメな場合は、上記の設定を確認してみることをおすすめします。

Open Interpreter を Macにインストールしようとしたらエラーがでた話

最近 Open Interpreterの記事をいろいろ見つけたので自分のMacにもインストールしようとしてみたところ、以下のようなエラーが出ました。

エラーが大量発生

% pip install open-interpreter
ERROR: Ignored the following versions that require a different python version: 0.0.1 Requires-Python >=3.10,<4.0; 0.0.2 Requires-Python >=3.10,<4.0; 0.0.21 Requires-Python >=3.10,<4.0; 0.0.22 Requires-Python >=3.10,<4.0; 0.0.221 ・・・
・・・
Requires-Python >=3.10,<4.0; 0.1.4 Requires-Python >=3.10,<4.0
ERROR: Could not find a version that satisfies the requirement open-interpreter (from versions: none)
ERROR: No matching distribution found for open-interpreter

Pythonのバージョンを3.10.0にアップして成功

結論としては、どうやら Macの Pythonのバージョンが Python 3.8.3 のままになっていたのが原因のようでした。

以下の要領で 3.10.0 にアップしたところ、Open Interpreterを正常にインストールすることができました。

% python --version
Python 3.8.3
% pyenv install -list
Available versions:
・・・
  3.10.0
  3.10-dev
  3.11-dev
・・・
  stackless-3.7.5
% pyenv install 3.10.0
python-build: use openssl@1.1 from homebrew
・・・
Installed Python-3.10.0 to /・・・/.pyenv/versions/3.10.0
% pyenv local 3.10.0
% Python -V
Python 3.10.0
% pip install open-interpreter
Collecting open-interpreter
  Downloading open_interpreter-0.1.4-py3-none-any.whl (35 kB)
・・・
WARNING: You are using pip version 21.2.3; however, version 23.2.1 is available.
You should consider upgrading via the '/Users/katsuhiro.kurita/.pyenv/versions/3.10.0/bin/python3.10 -m pip install --upgrade pip' command.

Marmaid でシーケンス図を作成してみた

シーケンス図とか最初はPower Pointで作っていましたが、条件分岐とか複雑なものをつくり始めたらつらくなってきたので、Marmaidというツールを試しに使ってみました。

1.mermaid live editorにアクセス

mermaid live editorはオンラインにてフリーで利用でき、アカウントも作成する必要がないので、誰でも自由に Markdown形式の記述からシーケンス図を作成できてしまいます。

mermaid live editor
https://mermaid-js.github.io/mermaid-live-editor/edit

2.Markdown形式でシーケンスを作成

Markdown形式ってなんだか難しそうに聞こえますが、意外と簡単です。

初めて作成した私でも下記の記述程度であれば、見よう見までで30分〜1時間程度でかけてしまいました。

sequenceDiagram ← シーケンズ図であることを宣言
    Ar->>Xs: data ← ArからXsにメッセージ(data)を渡す場合はこう書く
    Note right of Ar: IoC etc ← 黄色い付箋にノートが書ける
    Xs->>Xs: data check
    alt C2 ← 条件分岐を記載
        Xs ->> Xs: transparent check;
        alt blocked
            Xs->>Xs: write down
        else passed
            Xs->>So: investigation request
        end
    else phishing
        Xs ->> Xs: transparent check
        alt blocked
            Xs->>Xs: write down
        else passed
            Xs->>So: investigation request
        end
    else others
        Xs ->> Vi: evaluation check
        Vi ->> Xs: result
        Xs ->> Xs: result check
        alt benign
            Xs ->> Xs: write down
        else malignant
            Xs ->> So: investigation request
        end
    end
    Xs ->> Ar:investigation result
    So ->> So:investiogate
    So ->> Cs:investigation result
    So ->> Ar:investigation result
    Cs ->> Cs:traffic number check
    alt over N
        Cs ->> Si: white regist
    else under N
        Cs ->> Cs: block request
    end
    Cs ->> Ar: result

3.できあがったシーケンス図を確認

mermaid live editorの左ペインで、2.に掲載したMarkdown形式のシーケンスを書いていると、右ペインにリアルタイムでシーケンス図が描かれます。

これはおもった以上に便利ですね。

mermaid live editor

いきなりPower Point でこのシーケンス図を描こうとするとかなり難儀ですが、一旦、mermaid live editorで作成しておいて、後で Power Point で清書するという使い方もありかと思います。

Power Point 形式でデータ出力してくれるとありがたいですが。。。。

参考サイト:

・エクセルでシーケンス図書くのやめませんか?mermaidが便利ですよ(Qiita)
https://qiita.com/naoki114/items/f46082e488fcb1562662

・markdownでシーケンス図を書こう
https://qiita.com/konitech913/items/90f91687cfe7ece50020

サンプル2:

sequenceDiagram
    Ar->>Xs: data
    Note right of Ar: IoC etc
    alt C2
        Xs->>Xs: write down
    else phishing
        Xs ->> Xs: transparent check
        Xs->>Xs: write down
    else others
        Xs ->> Vi: evaluation check
        Vi ->> Xs: result
        Xs ->> Xs: result check
    end
    Xs ->> So:investigation request
    Xs ->> Ar:investigation result
    So ->> So:investiogate
    So ->> Cs:investigation result
    So ->> Ar:investigation result
    Cs ->> Cs:remediation dicision
    alt benign
        Cs ->> Cs: block request
    else malignant
        Cs ->> So: quarantine request
        Cs ->> As: quarantine report
        So ->> So: quarantine execute
        So ->> Ci: quarantine fin report
        As ->> Cs: status report
    end
    Cs ->> Ar: result

MACでスクリーンショットを撮った後も画面が暗いままになっている場合の対処方法

先日、Macにて control+shift+5 でスナップショットを撮ってみたところ、スナップショットを撮り終わっているにもかかわらず、画面が暗いままになっている事象が発生しました。

しばらくは Macのバグだろうとおもっていたのですが、どうやら使い方を間違っているようでしたのでここに記録しておきます。

スナップショットではなく録画になっている可能性あり

もし上記の現象が発生している場合は、control+shift+5 を押した時に下部に表示されるツールバーの右端が、「収録」ではなく「取り込む」になっているか確認してください。

もし「収録」となっている場合は「スナップショットモード」ではなく「録画モード」になっていますので、そのツールバーの左から3番目(選択部分を取り込む)などを選択し直すと改善されます。

すごくささいなミスですが、意外と気がつかないですね。

Python で requests を使って Webサイトにアクセスする際に、タイムアウトを設定してみた

前のブログで bandit を利用し、Webサイトのスクレイピングを行っている pythonプログラムのセキュリティチェックを行ってみました。

http://k2-ornata.com/python_security_check_with_bandit/

すると、上記ブログにも記載したとおり「Requests call without timeout」という警告が出てしまった為、警告の指示通り、requests の部分に timeout を設定してみることにしました。

1.修正前

修正前は、ただ「requests.get(url)」としているだけでした。

response = requests.get(url)
html = response.content.decode("utf-8")

2.修正後

「requests.get(url)」としていた部分を「requests.get(url, timeout=(6.0, 10.0))」とし、タイムアウトが発生した際の例外処理を行っています。

from requests.exceptions import Timeout
・・・
# Get the HTML content of the top page
try:
    response = requests.get(url, timeout=(6.0, 10.0))
    html = response.content.decode("utf-8")
except Timeout:
    print(f"\n[Timeout {url}]")

なお、timeout の後ろに2つ数字を書いている理由ですが、
timeoutには、connect timeout(前) と read timeout(後) の2種類がある為です。

この2種類のタイムアウトについては、以下のサイトで詳しく説明されていますのでご紹介しておきます。(ありがとうございました!)

【Python】requestsを使うときは必ずtimeoutを設定するべき(Cosnomi Blog)https://blog.cosnomi.com/posts/1259/

3.bandit 実行結果

以下が修正後の pythonプログラムに対する実行結果です。

「Test results:」が「No issues identified.」となっており、問題が解消されたことが確認できました。

% bandit test.py
[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.8.3
[node_visitor]	WARNING	Unable to find qualified name for module: test.py
Run started:2023-08-14 08:04:48.814175

Test results:
	No issues identified.

Code scanned:
	Total lines of code: 53
	Total lines skipped (#nosec): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 0
		Medium: 0
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 0
		Medium: 0
		High: 0
Files skipped (0):
%

bandit を使って pythonコードのセキュリティチェックを行ってみた

python言語ってC言語などにくらべると安全そうなイメージがありますが、やはりセキュリティには気をつけないといけない、ということで 開発した python コードが安全かどうか調べるツールがないか調べてみました。

すると、bandit というツールが無償で利用できることがわかりました。

そこでこのツールを使って自分で開発した python プログラムのセキュリティチェックを行ってみましたのでここに記録しておきます。

なお、この bandit でチェックする前に、python のコーディング規約チェッカーである PEP 8 を使ってある程度(- -; コーディング規約に従うようにプログラムを修正しております。

この PEP 8 の PyCharm での利用方法については以下のサイトに記載しております。

http://k2-ornata.com/pychart_pep-8_check/

それでは bandit をインストールするところから行きたいと思います。

1.bandit のインストール

bandit のインストールは非常に簡単です。

pip がインストールされていれば、以下のコマンドを実行するだけです。

$ pip install pandit

なお、私の環境では pythonのバージョンがデフォルトで 2.X系になってしまっていた為、以下のような警告が出てしまいました。

bandit インストール時の警告

これを3系に変えようと思い pyenv を利用してみましたが一筋縄ではいかず、以下のサイトに助けていただきうまくいきました。ありがとうございました。m(_ _)m

pyenvでPythonのバージョンが切り替わらないときの対処方法【Mac Apple silicon環境】(ヒトリセカイ)https://hitori-sekai.com/python/error-pyenv/

2.banditの実行

bandit の実行も非常に簡単です。以下のとおりコマンドを打つだけです。

$ bandit <プログラム名>

実際に自分で作成したスクレイピングを行う pythonプログラムに対して実行してみた結果は以下の通りです。

bandit 実行結果

ちょっと上の画像は見にくいので、テキストでも掲載しておきます。

% bandit test.py
[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.8.3
[node_visitor]	WARNING	Unable to find qualified name for module: test.py
Run started:2023-08-14 01:37:45.050500

Test results:
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: test.py:31:11
30	# Get the HTML content of the top page
31	response = requests.get(url)
32	html = response.content.decode("utf-8")

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: test.py:62:15
61
62	    response = requests.get(link)
63	    html = response.content.decode("utf-8")

--------------------------------------------------

Code scanned:
	Total lines of code: 46
	Total lines skipped (#nosec): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 0
		Medium: 2
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 2
		Medium: 0
		High: 0
Files skipped (0):
%

3.bandit 実行結果の考察

どうやら「Test results:」という部分にプログラムの問題点が列挙されているようです。

2つ「Issue」が記載されていますが、どちらも Requests call without timeout となっています。

実際このプログラムでは指定したWebサイトからデータを取ってきているのですが、その時にタイムアウトの処理をしていませんでした。

たしかにこのままだと、Webサイトから応答が返ってくるまで繋ぎっぱなしになってしまい、そのまま何度もこのプログラムを実行するとサーバもクライアントもリソーズ不足になってしまいそうです。

改めて、こういったセキュリティチェック(ツール)の重要性を認識することができました。

PyChart のPEP 8(コーディング規約)チェックを強化してみた(Mac版)

最近たまにPythonのプログラムを作成することがあるのですが、そんな中、PEP 8 というPythonのコーディング規約があることを知りました。

そこで PEP 8 を試しに使ってみようと思い調べていたところ、pythonなどの開発環境であるPyChart には、すでにそのチェック機能が実装されているとのことでした。

しかしながらそのチェック(警告)の設定がデフォルトでは「Weak Warning」となっており、あまり目立たなくなっていた為、試しに「Error」となるように設定変更してみました。

1.PyCharmの「Preference」から設定変更

PyCharmの「Preference」を選択すると、以下のポップアップ画面が表示されますので、その中から下図の通り、

「Editor」-「Inspections」-「PEP 8 coding style violation」

と選択していきます。

PyCharm – Preference

すると Severity を設定するところがありますので、「Weak Warning」から「Error」 に変えてみました。(「Warning」でもよかったですが。。)

2.自作のpythonをチェックしてみる

1.の設定変更後、PyChart の編集画面にて自作の pythonを表示させてみたところ、下図の赤枠の通り、右上にエラーが11件あることが表示されていました。

PyChart – PEP 8 エラー警告

さらにその赤枠の部分をクリックすると、画面下に新しいウィンドウが開き、エラーの一覧が表示されました。

大半が “,(カンマ)” や “#(コメント)”の後ろに「スペース」が無いというものでしたが、複数の人間で共同開発する場合は、こういった規約に従うことが重要なのだと思います。

CISSP の CPE を稼ぐ(2023〜2024)自分のセキュリティブログを申請したら簡単に10ポイントゲットできました

2023年にはいってから、それまでISC2のサイトで提供されていた Professional Magazine が News and Insights に変わってしまい、CPE ポイントを稼ぎづらくなってしまいました。(ここは個人的な感想ですが。)

その為、約1時間の視聴で1ポイント稼げる Webinarsを頼りにしてきましたが、インターネットを調べていると、自分が書いたセキュリティ関連のブログでも申請できる(しかも10ポイント!)ようなので、さっそくこのサイトで書いたブログについて申請してみました。

1.申請カテゴリの選択

ISC2のサイトにログイン後、CPE の申請画面から該当するブログの作成日付を選びます。

すると次に申請カテゴリを登録する画面が表示されますので、赤枠で囲った通り申請しました。

ISC2 – Add New CPE – Category

2.ブログ情報の詳細入力

1.で「Writing, Researching, Publishing」を選択し、下にスクロールするとタイトルなどを入れるフィールドが出てきますので、1つ1つ入れていきます。

なお、Publisher の部分は個人ブログなのでどう書こうかすこし悩みましたが、インターネットの情報を参考にして、ブログのURLを記載しておきました。
Credits の部分は、もちろん10ポイントにしました!

ISC2 – Add New CPE – Details

その後はいつも通り Domain を適当に選んで申請しました。

3.無事申請が受付られました

申請するとすぐに以下の赤枠のとおり通り受け付けられました。
残り3ヶ月で13ポイントくらい稼がないといけなかったので、この10ポイントは大きいですね。

ISC2 – CPE List

<参考サイト>

・ブログ記事を書いてCPEを申請する(晴耕雨読)https://tex2e.github.io/blog/security/cpe-credit-blo

スクレイピング:指定した文字と文字の間のhtmlデータを全て取り出す

タイトルの通り、何かのhtml タグではなく、ブラウザに表示される文字列のスタート部分とエンド部分を指定して html データを抜き出してみました。

1.Pythonプログラム

# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import requests
import re
from bs4 import BeautifulSoup

# Set the day before yesterday's date
beforeyesterday = datetime.now() - timedelta(days=17)
beforeyesterday_str = beforeyesterday.strftime("%Y/%m/%d")

# URL of the top page
url = "https://www.xxx.jp/"・・・スクレイピングサイト"/"付き
domain ="https://www.xxx.jp"・・・スクレイピングサイト"/"無し

# start_string と end_string の間のストリングを取得する
start_string = "○○の一例:"
end_string = "○○○した場合は、○○○までご連絡ください。"

# Get the HTML content of the top page
response = requests.get(url)
html = response.content.decode("utf-8")

# Use BeautifulSoup to parse the HTML content
soup = BeautifulSoup(html, "html.parser")

# Find the parent element with the "○○○情報" title
security_info = soup.find('h1', string="○○○情報").parent
#print(security_info)

# Find all <h3> tags within the parent element
h3_tags = security_info.find_all('h3')

filtered_links = [tag.a['href'] for tag in h3_tags if tag.a is not None and beforeyesterday_str in tag.a.text]

for link in filtered_links:
    if link.startswith('http'):
        print(link)
    else:
        link = domain + link
        print(link)

    # トップページから取得した指定日の記事を読み込む
    response = requests.get(link)
    html = response.content.decode("utf-8")

    # BeautifulSoupを使ってHTMLを解析
    # soup = BeautifulSoup(html, 'html.parser')
    # article = soup.find('article', class_="nc-content-list")
    # print(article)

    # texts_p = [c.get_text() for c in article.find_all('p')]
    # print(texts_p)

    # Split the target text on the start and end strings and take the middle part
    target_text = html.split(start_string)[1].split(end_string)[0].split("</p>")[0]

    print(target_text)

    # 改行コードを空文字列に置換して一つのテキストにする
    target_text = target_text.replace('\n', '')

    # <br />タグを区切り文字として順番に配列に入れる
    result_array = [text for text in target_text.split('<br />') if text]

    # 結果の出力
    print(result_array)

2.プログラムのポイント

ChatGPTと相談しながらつくったのではっきりわかってないところはありますが^^、大体以下の意味合いかと思います。

タグとストリングで検索し親タグを含めたデータを取得

# この方法<p>タグなどには使えないかもしれません。

27行目:security_info = soup.find(‘h1’, string=”○○○”).parent
これは”○○○”というストリングが含まれる<h1>タグを見つけて、その1つ上位層のタグまでのデータをsecurity_infoに渡してくれているようです。

31行目:h3_tags = security_info.find_all(‘h3’)
21行目のsecurity_infoから<h3>タグの部分だけ抜き出してh3_tagsに入れてくれているようです。

33行目:filtered_links = [tag.a[‘href’] for tag in h3_tags if tag.a is not None and beforeyesterday_str in tag.a.text]
ここやたら長いですが、結果的には
h3_tagsからbeforeyesterday_strが含まれるhrefのリンクデータのみ抜き出し、filtered_linksに入れてくれているようです。

スタートとエンドの文字列を指定して抜き出し、お尻の不要なデータを削除

57行目:target_text = html.split(start_string)[1].split(end_string)[0].strip().split(“</p>”)[0]
ここも長いですが、
htmlに読み込まれているWebページのデータについて、start_string から end_stringまでのデータを抜き出してくれているようです。
また、split(“</p>”)[0]をつけることで、お尻にくっついていた</p>タグ以降を削除しています。

3.実行例

以下、実際にプログラムを実行した際の出力結果です。

https://web.xxx.jp/faqs/xxxx
○○○のサイズがクォータ制限に達しました<br />○○○のストレージ容量が少ない<br />~ 受信メールエラー<br />○○○のストレージがいっぱいです、○○○が一時停止されています
['○○○のサイズがクォータ制限に達しました', '○○○のストレージ容量が少ない', '~ 受信メールエラー', '○○○のストレージがいっぱいです、○○○が一時停止されています']

スクレイピング:Webページの指定したH5タグの配下にあるデータを抽出する

WebページのHTMLの指定した<h5>タグの配下の、<div>タグの中のデータを取得するプログラムを作成しましたので、記録として残しておきます。

<h5 class="alert_h5">○○○の件名</h5>
<div class="dit_a">
<p>【重要】(○○○)<br>
【重要・緊急】○○○のお知らせ<br>
【○○○】○○○等の確認について<br>
<br>
※○○○<br></font></p>
</div>

1.作成したPythonプログラム

以下作成したサンプルプログラムです。

# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import requests
import re
from bs4 import BeautifulSoup

# Set the day before yesterday's date
beforeyesterday = datetime.now() - timedelta(days=15)
beforeyesterday_str = beforeyesterday.strftime("%Y%m%d")
mail_line_pattern = "From: \"[a-zA-Z0-9_.+-]+.+[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+\""
mail_pattern = "^[0-9a-zA-Z_.+-]+@[0-9a-zA-Z-]+\.[0-9a-zA-Z-.]+$"
env_mail_pattern = "<+[0-9a-zA-Z_.+-]+@[0-9a-zA-Z-]+\.[0-9a-zA-Z-.]+>"
subject_line_pattern = "Subject:"

# Initialize an empty list to store the articles
articles_beforeyesterday = []
text_beforeyesterday = []
link_beforeyesterday = []
mail_list = []
email_list = []
env_email_list = []
subject_list = []
title_list = []

# URL of the top page
url = "https://www.xxx.jp/news/"
domain ="http://www.xxx.jp"

# Get the HTML content of the top page
response = requests.get(url)
html = response.content.decode("utf-8")

# Use BeautifulSoup to parse the HTML content
soup = BeautifulSoup(html, "html.parser")

# Find all <a href> elements in the HTML
for a in soup.find_all("a",href=re.compile(beforeyesterday_str)):
    if a in articles_beforeyesterday:
        print("duplicated")
    else:
        text=a.getText()
        link=a.get("href")
        articles_beforeyesterday.append(a)
        text_beforeyesterday.append(text)
        link_beforeyesterday.append(link)

print(link_beforeyesterday)

for link in link_beforeyesterday:
    # Get the HTML content of the top page

    if link.startswith('http'):
        print(link)
    else:
        link = domain + link
        print(link)

    response = requests.get(link)
    html = response.content.decode("utf-8")

    # Use BeautifulSoup to parse the HTML content
    soup = BeautifulSoup(html, "html.parser")

    h5_tags = soup.find_all('h5', class_='alert_h5')

    for tag in h5_tags:
        if tag.get_text() == '○○○の件名':
            print(tag.find_next('p').get_text())

2.プログラムの解説

今回のポイントは2つあります。

データが指定した文字で始まっているか確認

1つ目は53 から57行目になります。

「if link.startswith(‘http’):」でlinkに入っているデータが’http’で始まっている場合、printしているだけですが、始まっていない場合、”http://www.xxx.jp”というデータを頭にくっつけています。
 これは今回対象となったサイトのリンクがいきなりディレクトリで始まっていた為です。

指定したデータが含まれるタグ配下のデータを取得

2つ目のポイントは最後の4行になります。

 「○○○の件名」が含まれる “h5″タグを見つけて、その配下の “p”タグで囲まれた文字列をピックアップしています。

3.実行結果

このプログラムの実行結果(出力)例は以下の通りです。

duplicated
['/news/xxxxxx_20230728.html', 'http://www.xxx.jp/news/xxxxx_20230728.html']
http://www.xxx.jp/news/xxxxxx_20230728.html
【重要】(○○○)
【重要・緊急】○○○のお知らせ
【○○○】○○○等の確認について

※○○○
http://www.xxx.jp/news/xxxxxx_20230728.html
【重要】(○○○)
【重要・緊急】○○○のお知らせ
【○○○】○○○等の確認について

※○○○