第10章:セキュリティ対策と安全なGitHub利用
学習目標
この章を読み終える頃には、GitHubを安全に利用するための基本的なセキュリティ対策を理解し、実践できるようになります。また、個人情報やAPIキーなどの機密情報を誤って公開することを防ぐ方法、2要素認証(2FA)の設定、SSH鍵の適切な管理方法を身につけ、安心してGitHubでの開発活動を行えるようになります。
10.1 基本的なセキュリティ概念
なぜセキュリティ対策が重要なのか
日常生活でのセキュリティ意識:
家のセキュリティ
- 鍵をかけずに外出しない
- 貴重品を見えるところに置かない
- 怪しい人に個人情報を教えない
- 防犯カメラやセキュリティシステムを活用
デジタル世界でも同じ考え方が必要:
- パスワードを他人に教えない
- 機密情報を公開しない
- 不審なリンクをクリックしない
- バックアップとログを残す
GitHubでの主要なセキュリティリスク
1. 認証情報の漏洩
- パスワードの盗用やアカウントの乗っ取り
- APIキーやトークンの流出
- データベース接続情報の公開
2. コードの意図しない公開
- 機密性の高いソースコードの流出
- 顧客情報や個人情報の露出
- 企業の知的財産の漏洩
3. サプライチェーン攻撃
- 悪意のある依存関係の混入
- パッケージの改ざん
- 開発環境への侵入
4. ソーシャルエンジニアリング
- なりすましによる情報収集
- フィッシング攻撃
- 信頼関係を悪用した攻撃
GitHubのセキュリティ機能概要
アカウントレベルのセキュリティ:
- 2要素認証(2FA)
- SSH鍵認証
- 個人アクセストークン
- セキュリティログの監視
リポジトリレベルのセキュリティ:
- 公開・非公開設定
- アクセス権限管理
- シークレットスキャン
- 依存関係の脆弱性チェック
組織レベルのセキュリティ:
- チームアクセス管理
- SAML/SCIM連携
- 監査ログ
- セキュリティポリシーの強制
10.2 アカウントセキュリティの強化
強固なパスワードの設定
良いパスワードの条件:
長さと複雑さ
- 最低12文字以上(推奨は16文字以上)
- 大文字・小文字・数字・記号を組み合わせ
- 辞書にある単語を避ける
- 個人情報(誕生日、名前など)を避ける
パスワード作成の実践的な方法:
パスフレーズ方式
例:Coffee-Laptop-Sunny-2024!
意味:コーヒー、ラップトップ、晴れ、2024年
覚えやすく、長くて安全
頭文字方式
文章:「I love GitHub and coding for 5 years since 2019!」
パスワード:「IlGac4y5ys2019!」
悪いパスワードの例:
password123
(単純すぎる)github2024
(サービス名を含む)taro1985
(個人情報を含む)qwerty
(キーボード配列)
2要素認証(2FA)の設定
2要素認証とは: 「知っているもの」(パスワード)+「持っているもの」(スマートフォン)による二重の認証
GitHub での2FA設定手順:
Step 1: 設定画面へのアクセス
- GitHubにログイン
- 右上のプロフィール画像をクリック
- 「Settings」を選択
- 左メニューから「Password and authentication」を選択
- 「Two-factor authentication」セクションを見つける
Step 2: 認証アプリの設定
推奨認証アプリ:
- Google Authenticator(iOS/Android)
- Microsoft Authenticator(iOS/Android)
- Authy(iOS/Android/Desktop)
- 1Password(パスワード管理と統合)
設定手順:
- 「Set up using an app」をクリック
- 認証アプリでQRコードをスキャン
- アプリで生成された6桁のコードを入力
- 「Enable」をクリック
Step 3: リカバリーコードの保存
GitHub Recovery Codes
保存日:2024-01-15
12345-67890
23456-78901
34567-89012
45678-90123
56789-01234
67890-12345
78901-23456
89012-34567
重要:これらのコードは安全な場所に保管し、
他人と共有しないでください。
リカバリーコードの安全な保管方法:
- パスワードマネージャーに保存
- 印刷して金庫に保管
- 複数の安全な場所に分散保存
- 定期的にアクセス可能性を確認
SSH鍵認証の設定
SSH鍵認証のメリット:
- パスワード入力が不要
- より高いセキュリティレベル
- 自動化に適している
- 複数のマシンでの管理が容易
SSH鍵ペアの生成:
Windows(Git Bash)、macOS、Linux共通:
# ED25519鍵の生成(推奨)
ssh-keygen -t ed25519 -C "your_email@example.com"
# RSA鍵の生成(古いシステム対応)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
生成時の重要なポイント:
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# デフォルトの場所を使用するため、Enterを押す
Enter passphrase (empty for no passphrase):
# パスフレーズを設定(推奨)
Enter same passphrase again:
# パスフレーズを再入力
Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
GitHubへの公開鍵登録:
Step 1: 公開鍵の内容をコピー
# macOS
cat ~/.ssh/id_ed25519.pub | pbcopy
# Linux
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
# Windows (Git Bash)
cat ~/.ssh/id_ed25519.pub | clip
Step 2: GitHubでの設定
- GitHub Settings → SSH and GPG keys
- 「New SSH key」をクリック
- Title: わかりやすい名前(例:「My MacBook Pro」)
- Key: コピーした公開鍵を貼り付け
- 「Add SSH key」をクリック
SSH接続のテスト:
ssh -T git@github.com
# 成功時の出力例
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
個人アクセストークン(PAT)の管理
個人アクセストークンが必要な場面:
- HTTPS経由でのGit操作
- GitHub APIの利用
- CI/CDパイプラインでの認証
- 自動化スクリプトでの認証
トークンの作成手順:
Step 1: トークン生成
- Settings → Developer settings → Personal access tokens → Tokens (classic)
- 「Generate new token」→「Generate new token (classic)」
- 設定項目を入力:
- Note: 用途を明記(例:「CI/CD for project X」)
- Expiration: 適切な有効期限を設定
- Scopes: 必要最小限の権限を選択
主要なスコープの説明:
repo: リポジトリへのフルアクセス
- repo:status: コミットステータスの読み書き
- repo_deployment: デプロイメントの管理
- public_repo: 公開リポジトリのみアクセス
user: ユーザー情報への読み書きアクセス
- read:user: ユーザー情報の読み取り
- user:email: メールアドレスの読み取り
admin:org: 組織の管理権限
- read:org: 組織情報の読み取り
- write:org: 組織設定の変更
workflow: GitHub Actionsワークフローの管理
トークンの安全な管理:
環境変数での管理:
# .bashrc または .zshrc に追加
export GITHUB_TOKEN="your_token_here"
# 使用例
git clone https://$GITHUB_TOKEN@github.com/user/repo.git
CI/CDでの利用:
# GitHub Actions
- name: Checkout
uses: actions/checkout@v4
with:
token: $
# 外部CI(Travis CI、CircleCI等)
- git clone https://$GITHUB_TOKEN@github.com/user/repo.git
10.3 機密情報の保護
.gitignoreファイルの活用
.gitignoreの基本概念: Gitの追跡対象から除外するファイルやディレクトリを指定するファイル
重要な除外対象:
認証情報・設定ファイル
# 環境変数ファイル
.env
.env.local
.env.development
.env.production
# 設定ファイル
config.json
secrets.json
database.yml
# APIキー
*api-key*
*secret*
*password*
OS・エディタ固有ファイル
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Linux
*~
# エディタ
.vscode/
.idea/
*.swp
*.swo
*~
言語・フレームワーク固有
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Python
__pycache__/
*.py[cod]
*$py.class
venv/
.pytest_cache/
# Ruby
*.gem
*.rbc
.bundle/
vendor/bundle/
# Java
*.class
*.jar
target/
.gradle/
build/
グローバル.gitignoreの設定:
# グローバル.gitignoreファイルの作成
touch ~/.gitignore_global
# Gitに設定
git config --global core.excludesfile ~/.gitignore_global
環境変数を使った設定管理
環境変数を使う理由:
- コードから機密情報を分離
- 環境ごとに異なる設定値を使用
- バージョン管理システムに機密情報を含めない
- デプロイ時の柔軟性向上
実装例(Node.js):
// config.js
const config = {
database: {
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 5432,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
},
api: {
github: {
token: process.env.GITHUB_API_TOKEN,
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
},
stripe: {
publicKey: process.env.STRIPE_PUBLIC_KEY,
secretKey: process.env.STRIPE_SECRET_KEY
}
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '24h'
}
};
module.exports = config;
.env.exampleファイルの作成:
# .env.example(リポジトリに含める)
# データベース設定
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=your_username
DB_PASSWORD=your_secure_password
DB_NAME=your_database_name
# GitHub API
GITHUB_API_TOKEN=your_github_token_here
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
# Stripe API
STRIPE_PUBLIC_KEY=pk_test_xxxxx
STRIPE_SECRET_KEY=sk_test_xxxxx
# JWT設定
JWT_SECRET=your_very_secure_random_string_here
JWT_EXPIRES_IN=24h
dotenvライブラリの使用(Node.js):
// package.json
{
"dependencies": {
"dotenv": "^16.0.0"
}
}
// app.js
require('dotenv').config();
// これで process.env.VARIABLE_NAME が使用可能
console.log(process.env.DATABASE_URL);
GitHubのシークレット機能
Repository Secretsの設定:
アクセス方法:
- リポジトリの「Settings」タブ
- 左メニューから「Secrets and variables」→「Actions」
- 「New repository secret」をクリック
よく使用されるシークレット例:
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
DATABASE_URL=postgresql://username:password@host:port/database
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxx
DOCKER_USERNAME=your_docker_username
DOCKER_PASSWORD=your_docker_password
GitHub Actionsでの使用例:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: $
aws-secret-access-key: $
aws-region: us-west-2
- name: Deploy to S3
run: |
aws s3 sync ./dist s3://$
- name: Send notification
env:
SLACK_WEBHOOK: $
run: |
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"🚀 Deployment successful!"}' \
$SLACK_WEBHOOK
機密情報流出の対処法
流出を発見した場合の緊急対応:
Step 1: 即座の対応(5分以内)
- 該当するAPIキーやパスワードを無効化/変更
- 影響範囲の初期評価
- 関係者への緊急連絡
Step 2: コミット履歴からの削除
# 特定ファイルを履歴から完全削除
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch secret-file.txt' \
--prune-empty --tag-name-filter cat -- --all
# BFG Repo-Cleaner の使用(推奨)
# https://rtyley.github.io/bfg-repo-cleaner/
java -jar bfg.jar --delete-files secret-file.txt
git reflog expire --expire=now --all && git gc --prune=now --aggressive
# 強制プッシュで履歴を更新
git push --all --force
git push --tags --force
Step 3: セキュリティ監査
- アクセスログの確認
- 不正な活動の有無をチェック
- 影響を受けたシステムの調査
- 必要に応じて外部専門家への相談
Step 4: 再発防止策
- より厳格な.gitignoreルールの設定
- プリコミットフックの導入
- 定期的なセキュリティ監査の実施
- チーム向けセキュリティ教育の実施
10.4 セキュアな開発プラクティス
依存関係のセキュリティ管理
依存関係の脆弱性チェック:
GitHub Dependabotの活用:
# .github/dependabot.yml
version: 2
updates:
# Node.js dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
reviewers:
- "security-team"
assignees:
- "lead-developer"
# Docker dependencies
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
npm auditの定期実行:
# 脆弱性のチェック
npm audit
# 自動修正可能な脆弱性の修正
npm audit fix
# 強制的な修正(バージョンアップを含む)
npm audit fix --force
# 詳細なレポートの出力
npm audit --json > security-report.json
セキュリティ重視のpackage.json設定:
{
"scripts": {
"pretest": "npm audit",
"security-check": "npm audit && snyk test",
"update-deps": "npm update && npm audit fix"
},
"dependencies": {
"helmet": "^7.0.0",
"bcrypt": "^5.1.0",
"jsonwebtoken": "^9.0.0"
},
"devDependencies": {
"snyk": "^1.1000.0",
"@npmcli/package-json": "^4.0.1"
}
}
コードレビューでのセキュリティチェック
セキュリティ観点でのレビューポイント:
認証・認可の確認
// ❌ 悪い例
app.get('/admin', (req, res) => {
// 認証チェックなし
res.render('admin-dashboard');
});
// ✅ 良い例
app.get('/admin', requireAuth, requireRole('admin'), (req, res) => {
res.render('admin-dashboard');
});
入力値検証
// ❌ 悪い例
app.post('/api/users', (req, res) => {
const query = `INSERT INTO users (name, email) VALUES ('${req.body.name}', '${req.body.email}')`;
// SQLインジェクション脆弱性
});
// ✅ 良い例
app.post('/api/users', [
body('name').isLength({ min: 1, max: 100 }).escape(),
body('email').isEmail().normalizeEmail()
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { name, email } = matchedData(req);
// パラメータ化クエリを使用
db.query('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);
});
セキュアなHTTPヘッダー
// Express.js with Helmet
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
自動セキュリティチェックの導入
GitHub Actions での自動セキュリティチェック:
name: Security Checks
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
# npm audit による脆弱性チェック
- name: Run npm audit
run: npm audit --audit-level=moderate
# ESLint security plugin
- name: Run ESLint security check
run: npx eslint . --ext .js,.jsx,.ts,.tsx
# Snyk による脆弱性スキャン
- name: Run Snyk security scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: $
with:
args: --severity-threshold=high
# OWASP ZAP による動的スキャン
- name: OWASP ZAP security scan
uses: zaproxy/action-full-scan@v0.4.0
with:
target: 'http://localhost:3000'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a'
プリコミットフックによるセキュリティチェック:
#!/bin/sh
# .git/hooks/pre-commit
echo "Running security checks..."
# シークレットスキャン
if grep -r --include="*.js" --include="*.json" --include="*.env*" -E "(password|secret|key|token).*=" . | grep -v node_modules; then
echo "❌ Potential secrets found in staged files!"
echo "Please review and remove any sensitive information."
exit 1
fi
# npm audit
if ! npm audit --audit-level=moderate; then
echo "❌ Security vulnerabilities found!"
echo "Please run 'npm audit fix' to resolve issues."
exit 1
fi
echo "✅ Security checks passed!"
exit 0
インシデント対応とモニタリング
セキュリティイベントの監視:
GitHub Security Advisoriesの活用:
- Repository → Security → Advisories
- セキュリティ脆弱性の報告と管理
- CVE(Common Vulnerabilities and Exposures)の取得
- 影響範囲の評価と対応計画
アクセスログの監視:
// Express.js でのセキュリティロギング
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/security.log' })
]
});
// 不審なアクセスの記録
app.use((req, res, next) => {
// 異常なリクエストパターンの検出
if (req.headers['user-agent'].includes('bot') && req.path.includes('admin')) {
logger.warn('Suspicious bot access attempt', {
ip: req.ip,
userAgent: req.headers['user-agent'],
path: req.path,
timestamp: new Date()
});
}
next();
});
インシデント対応計画:
# セキュリティインシデント対応手順
## Phase 1: 検出・報告(0-15分)
- [ ] インシデントの確認と分類
- [ ] インシデント対応チームへの連絡
- [ ] 初期評価と影響範囲の特定
## Phase 2: 封じ込め(15分-1時間)
- [ ] 攻撃の遮断・サービス停止
- [ ] 証拠の保全
- [ ] 被害の拡大防止
## Phase 3: 根絶・復旧(1時間-24時間)
- [ ] 脆弱性の修正
- [ ] システムの復旧
- [ ] セキュリティパッチの適用
## Phase 4: 事後対応(24時間-1週間)
- [ ] インシデントレポートの作成
- [ ] 関係者への報告
- [ ] 再発防止策の実装
- [ ] プロセスの見直し
まとめ
この章では、GitHubを安全に利用するためのセキュリティ対策について学びました:
基本的なセキュリティ概念
- セキュリティリスクの理解と対策の必要性
- GitHubの主要なセキュリティ機能概要
- 多層的なセキュリティアプローチの重要性
アカウントセキュリティの強化
- 強固なパスワードの設定方法
- 2要素認証(2FA)の設定と管理
- SSH鍵認証による安全なアクセス
- 個人アクセストークンの適切な管理
機密情報の保護
- .gitignoreファイルによる情報制御
- 環境変数を使った設定管理
- GitHubシークレット機能の活用
- 機密情報流出時の対処法
セキュアな開発プラクティス
- 依存関係のセキュリティ管理
- コードレビューでのセキュリティチェック
- 自動セキュリティチェックの導入
- インシデント対応とモニタリング
セキュリティ文化の構築
- チーム全体でのセキュリティ意識向上
- 継続的なセキュリティ教育の実施
- プロセスとツールによる自動化
- 定期的な見直しと改善
次の章では、GitHubの高度な機能について学び、より効率的で協力的な開発環境の構築方法を身につけます。
理解度確認:
□ 基本的なセキュリティリスクを理解し、対策を講じることができる
□ 2要素認証とSSH鍵認証を設定し、適切に管理できる
□ 機密情報を適切に保護し、.gitignoreや環境変数を活用できる
□ 依存関係のセキュリティ管理を実践できる
□ インシデント発生時の初期対応を理解している