境界線を守る設計思想:デジタル署名による「未承認図面の流出」を物理的に遮断する保存制御の実装
エンジニアリングの現場において、図面は単なる「絵」ではない。それは、数千、数万の意思決定が積み重なった「証跡」であり、企業の責任そのものである。
設計プロセスにおいて、チェック(検図)が完了し、正式な承認を得た図面には「デジタル署名」が付与される。一方で、作業途中の図面は署名を持たない。この「署名の有無」こそが、信頼できるデータか、それとも破棄されるべき未完成データかを分ける絶対的な境界線だ。
しかし、多くの現場ではこの境界線が「人間の注意」という極めて脆弱なものに委ねられている。
「納品フォルダに間違えて作業中のファイルを保存してしまった」「署名のない図面をそのままクライアントに送ってしまった」――。こうしたヒューマンエラーは、時に致命的な品質問題や法的リスクを招く。
本稿では、AutoCAD VBAを用いて、「特定の保存先(納品用フォルダ等)への保存時、デジタル署名の有無を厳格に判定し、未署名図面の保存をシステム的に拒絶する」という、プロフェッショナルな保存制御の実装手法を解説する。
1. 設計思想:なぜ「単なるチェック」では不十分なのか
初心者は「保存ボタンを押した後に、署名がなければ警告を出す」というコードを書こうとする。しかし、それは設計として破綻している。警告が出た後、ユーザーが「OK」を押せば保存は実行されてしまうからだ。
我々が目指すべきは、「保存プロセスそのものを、条件を満たさない限り完了させない(Interception)」という設計である。
アーキテクチャの要件
1. イベント駆動型制御: `Document_BeforeSave` イベントを利用し、ファイルがディスクに書き込まれる直前の「原子的な操作」のタイミングで介入する。
2. パスのホワイトリスト化: 全ての保存を制限すると業務が停滞する。制御対象は「納品用フォルダ」「外部共有フォルダ」などの特定のディレクトリに限定する。
3. Fail-Safe(フェイルセーフ)設計: 万が一、署名判定ロジックでエラーが発生した場合、デフォルトでは「保存を拒否する」方向に倒す。安全側に倒すのがプロの設計だ。
2. 実装コード:堅牢なセキュリティ・ゲートキーパー
以下に、プロダクション環境での使用を想定した、モジュール化されたコードを示す。コードは「設定」「ロジック」「イベントハンドラ」の3層に分離し、保守性を高めている。
Module: `modSecurityConfig` (設定管理)
定数を一箇所に集約することで、組織の運用変更(フォルダ構成の変更など)に即座に対応できるようにする。
Option Explicit
' 制御対象とする納品用ディレクトリのルートパス(末尾に必ず\を付ける)
Public Const DELIVERY_ROOT_PATH As String = "C:\Project\Delivery\"
' 署名チェックに失敗した際のログ出力用
Public Const LOG_FILE_PATH As String = "C:\Project\Logs\security_audit.log"
Module: `modSecurityEngine` (判定ロジック)
判定ロジックをイベントハンドラから分離することで、ユニットテストが可能になり、再利用性も高まる。
Option Explicit
''' <summary>
''' 指定されたパスが制限対象のフォルダ内であるか判定する
''' </summary>
Public Function IsSensitivePath(ByVal targetPath As String) As Boolean
' 大文字小文字を区別せずに比較
IsSensitivePath = (InStr(1, targetPath, DELIVERY_ROOT_PATH, vbTextCompare) > 0)
End Function
''' <summary>
''' 図面のデジタル署名状態を検証する
''' </summary>
Public Function IsDocumentSigned(ByRef doc As AcadDocument) As Boolean
On Error GoTo ErrHandler
' AutoCADのDigitalSignatureオブジェクトを参照
' 注意: 署名が存在しない場合、プロパティアクセス自体がエラーになるケースがあるため
' 厳格なエラーハンドリングが必要
If Not doc.DigitalSignature Is Nothing Then
' 署名が有効(Valid)であることを確認
' ※環境により、署名の有無だけでなく、証明書の有効期限等の検証が必要な場合もある
If doc.DigitalSignature.IsSigned Then
IsDocumentSigned = True
Exit Function
End If
End If
ErrHandler:
' 署名がない、あるいはオブジェクトにアクセスできない場合はFalseを返す
IsDocumentSigned = False
End Function
ThisDrawing (イベントハンドラ)
ユーザーの操作をインターセプトする最前線。
Option Explicit
''' <summary>
''' 保存実行直前に呼び出されるイベント
''' </summary>
Private Sub Document_BeforeSave(ByVal SaveAs As Boolean, ByVal FileName As String)
Dim isSensitive As Boolean
Dim isSigned As Boolean
' 1. 保存先が制限対象のパスかチェック
isSensitive = modSecurityEngine.IsSensitivePath(FileName)
' 制限対象パスでない場合は、即座に処理を抜けて通常の保存を許可する
If Not isSensitive Then Exit Sub
' 2. 署名状態の確認
isSigned = modSecurityEngine.IsDocumentSigned(ThisDrawing)
' 3. 判定結果に基づく制御
If Not isSigned Then
' 未署名図面が制限パスへ保存されようとした場合
MsgBox "【セキュリティ警告】" & vbCrLf & _
"納品用フォルダへの保存には、正式なデジタル署名が必要です。" & vbCrLf & _
"未承認の図面を外部へ送信することは禁止されています。", _
vbCritical, "保存拒絶"
' 保存処理をキャンセルさせるための特殊な命令
' VBAのBeforeSaveイベントにおいて、保存を中断させるには
' 適切なエラーをスローするか、アプリケーションの動作を制御する必要がある。
' AutoCAD VBAにおいて、保存を中断させる最も確実な方法は、
' 実行中の処理をエラーで停止させることである。
Err.Raise vbObjectError + 513, "SecurityEngine", "Unauthorized save attempt blocked."
End If
End Sub
3. プロフェッショナルが陥る罠と回避策
この実装を実務に投入する際、以下の3点に注意しなければならない。
① `SaveAs` と `Save` の違い
`Document_BeforeSave` には `SaveAs` 引数が存在する。ユーザーが「名前を付けて保存」で、既存のファイルとは異なる(署名のない)ファイル名で納品フォルダに保存しようとする動きも、このイベントは確実に捕捉する。設計上、`SaveAs` の有無に関わらずパス判定を行うことが重要だ。
② オブジェクトのライフサイクルとエラーハンドリング
`ThisDrawing.DigitalSignature` オブジェクトは、図面に署名が全く付与されていない状態でプロパティにアクセスしようとすると、ランタイムエラーを吐く場合がある。
「エラーが出たら署名なしとみなす」というロジックは一見合理的だが、「なぜエラーになったのか(ファイルアクセス権限なのか、署名オブジェクトの不在なのか)」をログに残さない設計は、トラブルシューティングを不可能にする。実務では必ず `Err.Raise` やログ出力機能を組み込むこと。
③ パフォーマンスのオーバーヘッド
`BeforeSave` はユーザーが頻繁に行う操作だ。判定ロジックが重すぎると、ユーザーの作業リズムを破壊し、最終的にツールを「無効化」される原因になる。
今回のコードのように、「まずパスを判定し、対象外なら即座に `Exit Sub` する」というショートサーキット(短絡評価)の書き方は、パフォーマンス維持において極めて重要だ。
結論
自動化エンジニアの真の価値は、単に「作業を速くすること」ではない。「間違った作業を物理的に不可能にすること」にある。
デジタル署名の検証を保存プロセスに組み込むことは、単なるコードの実装ではない。それは、設計品質に対する組織のコミットメントを、ソフトウェアという形で具現化するプロセスである。このレベルの設計思想を持って、次なる自動化の領域へ挑んでほしい。
