Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

topic/create script for collecting threats data #517

Merged
merged 3 commits into from
Dec 10, 2024

Conversation

TsurutaYoshiki
Copy link
Collaborator

@TsurutaYoshiki TsurutaYoshiki commented Dec 9, 2024

PR の目的

  • 特定のサービスに紐づく脆弱性とパッケージ情報を jsonで返すスクリプトの作成しました

経緯・意図・意思決定

  • 出力形式: json
  • 出力内容
{
    "pteam_id": "",
    "pteam_name": "",
    "service_id": "",
    "service_name": "",
    "service_description": "",
    "threats": [
        {
            "threat_id": "",
            "topic_id": "",
            "cve_id": [
                "CVE-xxxxx",
                "CVE-xxxxx"
            ],
            "tag_id": "",
            "tag_version": "",
            "tag_name": "axios:npm:npm"
        },
        {
            "threat_id": "",
            "topic_id": "",
            "cve_id": [
                "CVE-xxxxx",
                "CVE-xxxxx"
            ],
            "tag_id": "",
            "tag_version": "",
            "tag_name": "axios:npm:"
        }
    ]
}
  • スクリプト実行時にAPI_BASE_URL、token、pteam_id、service_idを指定してもらうようにしました
  • cve_id内に"CVE-xxxxx"がなかった場合、threatごと取り除いています
  • ファイルの出力名をcollect_threats_data + service_idにしています

@TsurutaYoshiki TsurutaYoshiki marked this pull request as ready for review December 9, 2024 08:53
service_id=service["service_id"],
service_name=service["service_name"],
service_description=service["description"],
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

service_id が見つかったら、他のserviceに用がないのでbreakした方が良い

tag_id=dependency["tag_id"], tag_version=dependency["version"], tag_name=tag["tag_name"]
)
del threat["dependency_id"]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引数のthreatsの値が変わる、という挙動は推奨しない。
新しいlistを作って返す方が分かりやすい。
〇理由
・1つの変数が場所によって状態が変わる、というコードは読みにくい。状態が変わっている箇所を全部追いかけないと理解できないため。定義時から値が変わらなければ、定義箇所を見れば変数の中身が分かって読みやすい。
・getXXX関数は戻り値を返す、その他状態を更新しない、というケースが多く、この慣習に従い、適切な関数名を付けていると、呼び出し元を見るだけでコードの意味が分かる。

_threats = get_misp_tag(tc_client, threats)
output_data.update(threats=_threats)
output_json_file(output_data, args.pteam_id, args.service_id)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threats、_threats は変数名を見ても違いが分からない。
多少長くなっても良いので、違いが分かるような名前が良い。
threats_with_tag_data, threats_with_topic_data とか

@dejima-shikou
Copy link
Collaborator

dejima-shikou commented Dec 10, 2024

エラー時の挙動を設計してください
・get_pteam
 →見つからなければエラーメッセージを表示して異常終了
  ※serviceも見つからなければ同様
・get_threats
 →見つからなければエラーメッセージを表示して異常終了
  or
  0件なので特にエラー処理せず、結果戻り値[]
・get_dependency
 →エラーメッセージは出すが、他のthreatの処理は続行
・・・

return _threats


def output_json_file(threats: dict, pteam_id: str, service_id: str):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引数pteam_idは使ってないので消すべき

Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数設計が統一されてないので意図が伝わりにくいです。output_dataを受け取って加工しする関数があったり、データを返してmain側でoutput_data を加工したりと挙動がバラバラです。
最終的なデータ構築の責務はmain側に持たせた方がいいと思います

またthreats という辞書の中身がどんどん変化するので関数の中まで見ないと混乱します。関数の中で辞書を書き換えるのは意図せぬ挙動の元なので極力避けた方がいいと思います

Comment on lines 159 to 177
def get_misp_tag(tc_client: ThreatconnectomeClient, threats: list):
"""
Remove threat that did not have cve_id in missp_tag.
"""
_threats: list = []
for threat in threats:
topic = tc_client.get_topic(threat["topic_id"])
cve_id: list = []
for misp_tag in topic["misp_tags"]:
if misp_tag["tag_name"] and misp_tag["tag_name"].startswith("CVE"):
cve_id.append(misp_tag["tag_name"])

if len(cve_id) == 0:
continue
else:
threat.update(cve_id=cve_id)
_threats.append(threat)

return _threats
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

misp_tag の取得と cve_id という値をデータに付与する責務を持っています。関数名がじつ挙動を表してません。責務を分けた方がいいと思います

@TsurutaYoshiki
Copy link
Collaborator Author

TsurutaYoshiki commented Dec 10, 2024

@mshim03
スクリプトを修正しました
以下の部分を変更しました

全体的な修正

  • output_dataをmain関数内で追加、変更を行うようにしました
  • threats という辞書型のデータを加工していくのではなく、関数ごとに新しい変数をリターンするようにしました
  • 関数名を変更しました
    • get_tags_data → add_tag_data_to_threat
    • get_misp_data → add_cve_data_to_threat

部分的な修正

  • def get_pteam_and_service_data()内にbreakを追加
  • for文の引数を処理中にdelを用いて削除するのをやめました
  • def output_json_file()の引数にあるpteam_idの削除
  • pteam_id、service_idが間違っていた時のエラー出力

上記のPRでの記載忘れ

  • スクリプトを実行する際に必要なコマンドの説明をREADMEに追加しました

try:
response = self._retry_call(requests.get, f"{self.api_url}/threats", params=params)
except APIError as error:
sys.exit("Is the service_id correct?\n" + str(error))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

service_id は正しいが、そのserviceにthreatが1件も無い場合もあるので、
ここではservice_idに紐づくthreatが取得できなかった、とのメッセージが良いと思います。

@TsurutaYoshiki
Copy link
Collaborator Author

エラーメッセージを変更しました
Is the service_id correct?

There is no threat tied to service_id

Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mshim03 mshim03 merged commit 35f0604 into main Dec 10, 2024
4 checks passed
@mshim03 mshim03 deleted the topic/create-script-for-collecting-threats-data branch December 10, 2024 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants