Update Authz::RedactionService with explicit ability and new resource types
What does this MR do and why?
Updates Authz::RedactionService to accept explicit ability names and adds all resource types needed for Knowledge Graph indexing.
See the larger implementation notes: $5936072
Decision from sync with Ian and Jay
In a sync with @jayswain and @imand3r, we decided to always pass in the ability name. If no ability is provided, access is denied (fail-closed). This replaces the visible_result? pattern that derived the ability from to_ability_name.
What changed
- Each resource type config now accepts an
abilityfield. The ability is required -- if omitted, the resource is denied (fail-closed). - Resource type keys are now singular to match the Ruby model underscore convention (
'issues'->'issue','merge_requests'->'merge_request'). - Input format is
{ 'type' => { 'ids' => [...], 'ability' => '...' } } - New CE types:
user,group - New EE types:
ci_pipeline,ci_stage,ci_build,label,note,security_scan,security_finding,vulnerability_scanner,vulnerability_occurrence,vulnerability_identifier
Why explicit ability?
The old visible_result? pattern derived the ability from resource.to_ability_name, which only supported read_* checks. With explicit ability names:
- The Knowledge Graph server controls which ability to check per resource type
- Different abilities can be checked for the same resource type (e.g.
read_codefor projects that contain file/directory resources) - If the ability is missing or empty, access is denied -- always fail-closed
Resource type keys
Resource type keys are now singular and match the Ruby model underscore convention:
| Ruby Model | Key |
|---|---|
Issue |
issue |
MergeRequest |
merge_request |
Project |
project |
Milestone |
milestone |
Snippet |
snippet |
User |
user |
Group |
group |
Epic |
epic |
Vulnerability |
vulnerability |
Ci::Pipeline |
ci_pipeline |
Ci::Stage |
ci_stage |
Ci::Build |
ci_build |
Label |
label |
Note |
note |
Security::Scan |
security_scan |
Security::Finding |
security_finding |
Vulnerabilities::Scanner |
vulnerability_scanner |
Vulnerabilities::Finding |
vulnerability_occurrence |
Vulnerabilities::Identifier |
vulnerability_identifier |
References
- Part of #583850 (closed)
- Extracted from !221417 (closed) (GKG feature branch)
- Original service MR: !216240 (merged)
How to set up and validate locally
1. Basic redaction check
Open a Rails console and test with accessible vs inaccessible resources:
user = User.where(admin: false).first
public_project = Project.find_by(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
private_project = Project.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
.where.not(id: user.authorized_projects.select(:id)).first
service = Authz::RedactionService.new(
user: user,
resources_by_type: {
'project' => {
'ids' => [public_project.id, private_project.id],
'ability' => 'read_project'
}
},
source: 'console_test'
)
result = service.execute
# => { 'project' => { <public_id> => true, <private_id> => false } }
2. Verify fail-closed behavior
When no ability is provided, all resources are denied:
service = Authz::RedactionService.new(
user: user,
resources_by_type: {
'project' => { 'ids' => [public_project.id, private_project.id] }
},
source: 'console_test'
)
result = service.execute
# => { 'project' => { <public_id> => false, <private_id> => false } }
# Both denied because no ability was specified
3. Verify issue redaction
user = User.where(admin: false).first
accessible_issue = Issue.joins(:project)
.where(projects: { visibility_level: Gitlab::VisibilityLevel::PUBLIC })
.where(confidential: false).first
inaccessible_issue = Issue.joins(:project)
.where(projects: { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
.where.not(project_id: user.authorized_projects.select(:id)).first
service = Authz::RedactionService.new(
user: user,
resources_by_type: {
'issue' => {
'ids' => [accessible_issue.id, inaccessible_issue.id],
'ability' => 'read_issue'
}
},
source: 'console_test'
)
result = service.execute
# => { 'issue' => { <accessible_id> => true, <inaccessible_id> => false } }
4. Verify supported types
Authz::RedactionService.supported_types.sort
# => ["ci_build", "ci_pipeline", "ci_stage", "epic", "group", "issue",
# "label", "merge_request", "milestone", "note", "project",
# "security_finding", "security_scan", "snippet", "user",
# "vulnerability", "vulnerability_identifier",
# "vulnerability_occurrence", "vulnerability_scanner"]
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.