導入(問題提起)

小規模のWebシステム開発はスピードが命です。しかし「急いで作った」代償として、情報漏えい・アカウント乗っ取り・停止事故が起きれば、信頼と機会損失のダメージは計り知れません。後付けで塞ぐほどコストが膨らむのがセキュリティです。だからこそ、最初の設計段階で“最低限だが確実に効く”基本セットを入れておくことが重要です。本記事では業務システムの初期構築で外せない実務要点を、Pythonを用いた具体的実装とともに体系化します。キーワード(Webシステム開発/業務システム/Python/Excel Web化)を踏まえ、検索意図「安全に小さく始めるには?」に応えます。

課題の詳細説明

現場で頻出する初期不備は次のとおりです。

  • パスワードの平文保存、安易なハッシュ(MD5/SHA1)
  • CSRF/XSS/SQLインジェクション(SQLi)など基本的なWeb脆弱性対策の欠落
  • 権限モデル不在により「誰でも見える・更新できる」状態
  • ログはあるが監査性がない(改ざん容易、検索困難、責任追跡不能)
  • バックアップはあるが“戻せない”(検証なし、同一サーバ保管、世代1)
  • 設定・鍵の平文リポジトリ同梱(APIキー/DBパスワードの漏えい)
  • 依存ライブラリの脆弱性放置、更新計画なし

これらは規模に関わらず基本を押さえるだけで大幅に低減できます。

解決方法

初期構築で入れる“基本セット”を8点に整理します。

  1. 認証:強固なハッシュ(Argon2/BCrypt)とアカウントロック、可能なら2段階認証(TOTP)
  2. セッション:HTTPS/TLS必須、Secure/HttpOnly/SameSite Cookie、CSRFトークン、適切なTTL
  3. 入力検証:サーバ側の型・範囲チェック、ORM/プレースホルダでSQLiを防止、出力エスケープでXSS対策
  4. 権限:RBAC(ロールベースアクセス制御)で最小権限、職務分掌(SoD)を設計
  5. 監査:操作ログと監査ログを分離し、不可逆性(ハッシュ鎖/外部出力)を確保
  6. バックアップ/DR:複数世代・異ロケーション・四半期リストア訓練(詳細は「バックアップとDR」を参照)
  7. 秘匿情報:環境変数/キーストアで安全保管。リポジトリに含めない
  8. 更新:依存の脆弱性スキャン(pip-audit等)と月次/四半期更新計画

具体例

Excel Web化で始まる社内向けPython Webアプリ(Bottle/FastAPI)でも、以下のように“最小で堅い”構成が実現できます。

  • HTTPS/TLS:Let’s Encryptの自動更新、HSTS有効化
  • パスワード:BCrypt/Argon2でハッシュ化、ログイン試行回数制限、CAPTCHA
  • CSRF対策:フォームトークンとSameSite=Lax/Strict設定
  • RBAC:閲覧/登録/承認/管理のロール分離、重要操作は再パスワード入力
  • 監査:モデルにcreated_by/updated_by/at、操作ログテーブル、外部ストレージへの定期エクスポート
  • バックアップ:日次スナップショット、別リージョン保管、リストア検証

技術的な解説

データモデル(ユーザ、ロール、監査)


CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  is_active INTEGER DEFAULT 1
);

CREATE TABLE roles (
  id INTEGER PRIMARY KEY,
  name TEXT UNIQUE NOT NULL
);

CREATE TABLE user_roles (
  user_id INTEGER,
  role_id INTEGER,
  PRIMARY KEY (user_id, role_id)
);

CREATE TABLE audit_logs (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER,
  action TEXT,
  entity TEXT,
  entity_id TEXT,
  at TEXT,
  details TEXT
);

Bottleでの認証・権限チェック例


from bottle import request, abort
import bcrypt

def verify_password(pw, hashed):
    return bcrypt.checkpw(pw.encode(), hashed.encode())

def require_roles(*need):
    def deco(fn):
        def wrapper(*a, **kw):
            roles = request.get_header('X-Roles','').split(',')
            if not all(r in roles for r in need):
                abort(403, 'forbidden')
            return fn(*a, **kw)
        return wrapper
    return deco

FastAPIでの入力検証例


from pydantic import BaseModel, constr

class Customer(BaseModel):
    name: constr(min_length=1, max_length=80)
    email: constr(pattern=r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
    note: constr(max_length=500) | None = None

導入の流れ

  1. 現状棚卸し(データ、ユーザ、権限、ネットワーク、利用端末)
  2. 最小要件定義(認証/権限/監査/バックアップ/更新の方針)
  3. 実装(ライブラリ選定、ミドルウェア、設定分離、ログ整備)
  4. 検証(脆弱性テスト、ログレビュー、リストア訓練)
  5. 運用(定期更新、鍵ローテーション、アカウントライフサイクル管理)

まとめ

  • 規模に関わらず“効く基本”を先に入れると後戻りが小さい
  • RBACと監査で「誰が・いつ・何を」を追跡可能にする
  • バックアップは“戻すまで”がセット。計画的な更新で安全性を維持する

問い合わせ導線

初期構築からのセキュリティ設計は、お問い合わせよりお気軽にご相談ください。Excel Web化を含む業務システムの安全運用まで伴走します。

Webシステム開発のご相談は monou まで