Skip to content

アクセス制御設計

1. 概要

業務委託メンバーが社内GitLabリポジトリにアクセスする際の、適切な権限管理と情報隔離を実現するための設計書。Issue単位での動的アクセス制御、機密情報の保護、委託者間の作業隔離を定義する。

2. GitLabリポジトリアクセス制御

2.1 ロール設計

ロール対象者権限概要
Ownerプロジェクトオーナー(社内管理者)全権限
Maintainer社内開発リードマージ権限、ブランチ保護設定
Developer業務委託メンバーMR作成可、マージ不可、Issue閲覧は割当分のみ
Reporterレビュー専任(該当する場合)閲覧のみ

業務委託メンバーには Developer ロールを付与する。これにより以下が可能となる:

  • コードのクローン・プル
  • ブランチの作成・プッシュ
  • Merge Request(MR)の作成
  • 割り当てられたIssueへのコメント

以下は 不可:

  • mainブランチへの直接プッシュ
  • MRのマージ(Maintainer以上のみ)
  • プロジェクト設定の変更
  • メンバーの招待・削除

2.2 Issue単位でのアクセス付与・剥奪の自動化

フロー概要

Issue割当 → Webhook発火 → アクセス付与API呼出 → Developer権限付与
Issue完了 → Webhook発火 → アクセス剥奪API呼出 → メンバー削除

GitLab Webhook設定

項目設定値
URLhttps://api.internal.example.com/hooks/gitlab/access-control
TriggerIssues events
Secret TokenCI/CD Variablesで管理
SSL verification有効

Webhook受信側の処理ロジック

python
# 擬似コード: Webhook受信時の処理
def handle_issue_event(payload):
    action = payload["object_attributes"]["action"]
    assignee = payload["object_attributes"]["assignee_id"]
    project_id = payload["project"]["id"]

    if action == "open" or action == "update":
        # 新規アサイン時: Developer権限付与
        if assignee and is_outsource_member(assignee):
            grant_access(project_id, assignee, access_level="developer")
            log_audit("ACCESS_GRANTED", assignee, project_id)

    elif action == "close":
        # Issue完了時: アクセス剥奪
        if assignee and is_outsource_member(assignee):
            revoke_access(project_id, assignee)
            log_audit("ACCESS_REVOKED", assignee, project_id)

GitLab API呼出例

bash
# アクセス付与(Developer = access_level 30)
curl --request POST \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "user_id=${USER_ID}&access_level=30&expires_at=${EXPIRY_DATE}" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/members"

# アクセス剥奪
curl --request DELETE \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/members/${USER_ID}"

アクセス有効期限

  • Issue割当時に expires_at を設定(契約終了日 or Issue期限日の早い方)
  • 期限超過時はGitLabが自動的にアクセスを無効化
  • 日次バッチで期限切れアクセスの棚卸しを実施

2.3 フォーク禁止設定

GitLabプロジェクト設定で以下を適用する:

設定項目説明
Forking無効Settings > General > Visibility > Forking
Visibility LevelPrivate外部からの検索・アクセスを防止
bash
# API経由でのフォーク禁止設定
curl --request PUT \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "forking_access_level=disabled" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}"

2.4 Protected Branch設定

mainブランチへの直接push・マージを制限する。

設定項目
Branchmain
Allowed to mergeMaintainers
Allowed to push and mergeNo one
Allowed to force pushNo
Code owner approvalRequired
bash
# Protected Branch設定
curl --request POST \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "name=main&push_access_level=0&merge_access_level=40&allow_force_push=false" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/protected_branches"

ブランチ命名規則

業務委託メンバーは以下のブランチ命名規則に従う:

feature/issue-{ISSUE_ID}/{short-description}

例: feature/issue-12/add-login-validation

GitLab Push Rulesで命名規則を強制する:

bash
curl --request PUT \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "branch_name_regex=^(feature|fix|hotfix)/issue-[0-9]+/[a-z0-9-]+$" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/push_rule"

3. 情報隔離

3.1 委託者間の作業内容隔離

Issue可視性制御

  • 業務委託メンバーは 自身にアサインされたIssueのみ 閲覧可能
  • GitLab Confidential Issueを活用し、未アサインIssueは非表示
bash
# Issueを作成時にconfidentialフラグを設定
curl --request POST \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "title=タスク名&confidential=true&assignee_ids[]=${USER_ID}" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/issues"

MR可視性制御

  • MRはデフォルトでアサイン者とレビュアーのみ通知
  • GitLab CI/CDのパイプライン結果は自身のMRのみ閲覧可能(Developerロールの標準動作)

3.2 機密コード・設定ファイルへのアクセス制限

.gitattributes による制御

リポジトリルートに .gitattributes を配置し、機密ファイルにフィルターを適用する。

gitattributes
# 機密設定ファイルの制御
config/secrets.yml filter=smudge-secrets
config/credentials/ filter=smudge-secrets
.env.* filter=smudge-secrets

# インフラ設定の制御
terraform/ filter=smudge-infra
k8s/production/ filter=smudge-infra

GitLab CI による機密ファイルチェック

MR作成時に、機密ファイルへの変更を検知してブロックする:

yaml
# .gitlab-ci.yml
check_sensitive_files:
  stage: validate
  rules:
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature\/issue-/'
  script: |
    SENSITIVE_PATHS="config/secrets.yml config/credentials/ .env terraform/ k8s/production/"
    CHANGED_FILES=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA)

    for path in $SENSITIVE_PATHS; do
      if echo "$CHANGED_FILES" | grep -q "^$path"; then
        echo "ERROR: 機密ファイル ${path} への変更は禁止されています"
        exit 1
      fi
    done
    echo "OK: 機密ファイルへの変更なし"

CODEOWNERS による保護

機密ファイルに対してコードオーナー承認を必須にする:

# CODEOWNERS
config/secrets.yml    @security-team
config/credentials/   @security-team
.env*                 @security-team
terraform/            @infra-team
k8s/production/       @infra-team
docker-compose.prod*  @infra-team

3.3 環境変数・シークレットの管理

CI/CD Variables設定

変数名TypeProtectedMasked環境説明
DB_PASSWORDVariableYesYesproductionDB接続パスワード
API_SECRET_KEYVariableYesYesallAPIシークレット
DEPLOY_TOKENVariableYesYesproductionデプロイトークン
WEBHOOK_SECRETVariableYesYesallWebhookシークレット
SENTRY_DSNVariableNoNoallエラー監視DSN

設定方針

  • Protected: main ブランチのパイプラインでのみ利用可能(委託メンバーのブランチでは参照不可)
  • Masked: CI/CDログに値が出力されない
  • Group-level Variables: 複数プロジェクト共通のシークレットはGroup Variablesで管理
bash
# CI/CD Variable設定例
curl --request POST \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --data "key=DB_PASSWORD&value=${DB_PASSWORD_VALUE}&protected=true&masked=true&variable_type=env_var" \
  "https://gitlab.example.com/api/v4/projects/${PROJECT_ID}/variables"

ローカル開発環境向けシークレット

  • 委託メンバーには 開発用ダミー値 を記載した .env.example を提供
  • 本番・ステージング用シークレットは一切共有しない
  • 開発環境用のシークレットはプロジェクトWikiの限定ページで管理

4. アクセス制御マトリクス

リソース社内Owner社内Maintainer委託Developer備考
mainブランチ pushNoNoNoCI/CDのみ
mainブランチ mergeYesYesNo-
featureブランチ作成YesYesYes命名規則準拠
MR作成YesYesYes-
MRマージYesYesNo-
CI/CD設定変更YesNoNo-
Protected Variables閲覧YesNoNo-
プロジェクト設定変更YesNoNo-
メンバー管理YesNoNo-
フォークNoNoNo全員禁止
機密ファイル変更YesYes(要承認)No(CIブロック)-

5. 定期棚卸し

項目頻度実施者内容
メンバー権限確認月次プロジェクトOwner不要なアクセス権の削除
Protected Branch設定月次プロジェクトOwner設定の変更有無確認
CI/CD Variables四半期セキュリティチーム不要な変数の削除、ローテーション
CODEOWNERS四半期プロジェクトOwnerオーナー情報の最新化
Webhook四半期インフラチーム不要なWebhookの削除