Help us learn about your current experience with the documentation. Take the survey.

实例范围的合规和安全策略管理

  • Tier: Ultimate
  • Offering: GitLab Self-Managed
  • Status: Beta

此功能的可用性由功能标志控制。 更多信息,请查看历史记录。 此功能可能会发生变化,可能不适合生产环境使用。

要从单一的中心化位置在多个群组和项目中应用安全策略,实例管理员可以指定一个合规和安全策略(CSP)群组。这使实例管理员能够:

  • 创建和配置自动在整个实例中应用的安全策略。
  • 创建合规框架,使其可供其他顶级群组使用。
  • 将策略范围应用于合规框架、群组、项目或整个实例。
  • 查看全面的策略覆盖范围,了解哪些策略处于活动状态以及它们在何处生效。
  • 保持集中控制,同时允许团队创建自己的额外策略。

Prerequisites

  • GitLab 自托管版。
  • GitLab 18.2 或更高版本。
  • 您必须是实例管理员。
  • 您必须有一个现有的顶级群组作为合规和安全策略群组。
  • 要使用 REST API(可选),您必须拥有具有管理员访问权限的令牌。

Set up instance-wide compliance and security policy management

要设置实例范围的合规和安全策略管理,您需要指定一个合规和安全策略群组,然后在群组中创建策略和合规框架。

Designate a compliance and security policy group

您可以使用 GitLab UI 或 REST API 来指定合规和安全策略群组。

Using the GitLab UI

  1. 转到 管理区域 > 设置 > 安全和合规
  2. 指定 CSP 群组 部分,从下拉列表中选择一个现有的顶级群组。
  3. 选择 保存更改

Using the REST API

您也可以使用 REST API 以编程方式指定合规和安全策略群组。该 API 对于自动化或管理多个实例很有用。

To set a compliance and security policy group:

curl --request PUT \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --header "Content-Type: application/json" \
  --data '{"csp_namespace_id": 123456}' \
  --url "https://gitlab.example.com/api/v4/admin/security/policy_settings"

To clear the compliance and security policy group:

curl --request PUT \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --header "Content-Type: application/json" \
  --data '{"csp_namespace_id": null}' \
  --url "https://gitlab.example.com/api/v4/admin/security/policy_settings"

To get the current compliance and security policy settings:

curl --request GET \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/admin/security/policy_settings"

For more information, see the policy settings API documentation.

选定的群组将成为您的合规和安全策略群组,作为在整个实例中管理安全策略和合规框架的中心位置。

Security policy management in the compliance and security policy group

有关安全策略的信息,请参阅 合规和安全策略群组 文档。

User workflows

Instance administrators

实例管理员可以:

  1. 从您现有的顶级群组中 指定合规和安全策略群组
  2. 在指定的群组中 创建安全策略
  3. 配置策略范围 以确定策略适用的位置
  4. 查看策略覆盖范围 以了解哪些策略在群组和项目中处于活动状态
  5. 根据需要 编辑和管理 集中策略

Group administrators and owners

群组管理员和所有者可以:

  • 安全 > 策略 中查看所有适用的策略,包括本地定义和集中管理的策略。
  • 除了集中管理的策略外,还可以创建团队特定的策略。
  • 通过清晰的指标了解策略来源,显示策略是否来自您的团队或中央管理。

策略 页面仅显示当前应用于您群组的合规和安全策略群组中的策略。

Project administrators and owners

项目管理员和所有者可以:

  • 安全 > 策略 中查看所有适用的策略,包括本地定义和集中管理的策略。
  • 除了集中管理的策略外,还可以创建项目特定的策略。
  • 通过清晰的指标了解策略来源,显示策略是否来自您的项目、群组或中央管理。

策略 页面仅显示当前应用于您群组的合规和安全策略中的策略。

Developers

开发者可以:

  • 安全 > 策略 中查看适用于您工作的所有安全策略。
  • 通过对集中强制策略的清晰可见性,了解安全和合规要求。

Beta considerations

  • 性能测试:虽然使用合规和安全策略群组预计不会影响性能,但全面的性能测试仍在进行中。
  • 混合权限场景:某些混合权限的边缘情况可能需要额外的验证
  • 用户体验:某些 UI 元素可能尚未完全完善,未来版本中可能会发生变化
  • 合规框架范围:在 Beta 版本中不支持将策略范围应用于合规框架。

Automate your migration from security policy projects

从安全策略项目自动化迁移

如果您已经使用安全策略项目在多个群组中强制执行策略,您可以将其中一个链接的群组指定为您的合规和安全策略群组。 但是,您应该将安全策略项目与所有非合规和安全策略群组的群组取消链接。否则,相同的策略将在这些群组中被强制执行两次。一次来自链接的安全策略群组,另一次来自合规和安全策略群组。

要将您的群组迁移到合规和安全策略群组的过程自动化,您可以使用以下 csp_designation.rb 脚本。

该脚本将链接到策略项目的所有群组 ID 保存在指定的备份文件中,以供合规和安全策略群组使用。如有必要,这允许您恢复之前的状态,包括与安全策略项目的链接。

Prerequisites:

  • 您必须有一个安全策略项目链接到您要指定为合规和安全策略群组的群组。

To use the script:

  1. 从下一节复制整个 csp_designation.rb 脚本。

  2. 在您的终端窗口中,连接到您的实例。

  3. 创建一个名为 csp_designation.rb 的新文件,并将脚本粘贴到新文件中。

  4. 运行以下命令来分配合规和安全策略群组,更改:

    • <group_id> 为您要设置为合规和安全策略群组的群组的 GitLab ID。
    • 第一个 /path/to/ 实例为您想要的备份文件目录的完整路径。
    • 第二个 /path/to/ 实例为您保存 csp_designation.rb 文件的目录的完整路径。
    CSP_GROUP_ID=<group-id> BACKUP_FILENAME="/path/to/csp_backup.txt" ACTION=assign sudo gitlab-rails runner /path/to/csp_designation.rb
  5. 可选。如果您需要还原整个更改,请运行此命令,使用之前使用的相同群组 ID、备份文件路径和脚本路径:

    CSP_GROUP_ID=<group-id> BACKUP_FILENAME="/path/to/csp_backup.txt" ACTION=unassign sudo gitlab-rails runner /path/to/csp_designation.rb

For more information, see the Rails Runner troubleshooting section.

csp_designation.rb

class CspDesignation
  def initialize(csp_group_id, backup_filename)
    @backup_filename = backup_filename
    @csp_group = Group.find_by_id(csp_group_id)
    @csp_configuration = @csp_group&.security_orchestration_policy_configuration
    @user = @csp_configuration&.policy_last_updated_by
    @spp = @csp_configuration&.security_policy_management_project
  end

  def assign
    check_spp!

    config_ids, group_ids = Security::OrchestrationPolicyConfiguration.for_management_project(@spp)
                                                                      .where.not(namespace: @csp_group)
                                                                      .pluck(:id, :namespace_id)
                                                                      .transpose
    if group_ids.present?
      puts "Saving group IDs to #{@backup_filename} as backup: #{group_ids}..."
      File.write(@backup_filename, "#{group_ids.join("\n")}\n")
    end

    puts "Setting #{@csp_group.full_path} as CSP..."
    Security::PolicySetting.for_organization(Organizations::Organization.default_organization).update! csp_namespace: @csp_group

    if config_ids.present?
      puts "Unassigning the policy project #{@spp.id} from the groups in the background to remove duplicate policies..."
      config_ids.each do |config_id|
        ::Security::DeleteOrchestrationConfigurationWorker.perform_async(
          config_id, @user.id, @spp.id
        )
      end
    end
    puts "Done."
  end

  def unassign
    check_spp!

    puts "Unassigning #{@csp_group.full_path} as CSP..."
    Security::PolicySetting.for_organization(Organizations::Organization.default_organization).update! csp_namespace: nil

    if File.exist?(@backup_filename)
      puts "Reading group IDs from #{@backup_filename} to restore the policy project links..."
      namespace_ids = File.read(@backup_filename).split("\n").map(&:to_i).reject(&:zero?)
      Namespace.id_in(namespace_ids).find_each(batch_size: 100) do |namespace|
        puts "Assigning the policy project to #{namespace.full_path}..."
        result = ::Security::Orchestration::AssignService.new(
          container: namespace, current_user: @user,
          params: { policy_project_id: @spp.id }
        ).execute
        puts "Failed to assign policy project to #{namespace.full_path}: #{result[:message]}" if result.error?
      end
    end
  end

  private

  def check_spp!
    raise "CSP policy project doesn't exist" if @spp.blank?
  end
end

SUPPORTED_ACTIONS = %w[assign unassign].freeze
action = ENV['ACTION']
csp_group_id = ENV['CSP_GROUP_ID']
backup_filename = ENV['BACKUP_FILENAME']
raise "Unknown action: #{action}. Use either 'assign' or 'unassign'." unless action.in? SUPPORTED_ACTIONS
raise "Missing CSP_GROUP_ID" if csp_group_id.blank?
raise "Missing BACKUP_FILENAME" if backup_filename.blank?

CspDesignation.new(csp_group_id, backup_filename).public_send(action)

Troubleshooting

无法指定合规和安全策略群组

  • 验证您是否具有实例管理员权限。
  • 验证该群组是顶级群组(不是子群组)。
  • 验证该群组是否存在且可访问。

Feedback and support

由于这是 Beta 版本,我们积极寻求用户的反馈。通过以下方式分享您的经验、建议和任何问题: