Skip to content

Add security-manager to github_org.rb #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/entitlements/backend/github_org.rb
Original file line number Diff line number Diff line change
@@ -12,7 +12,8 @@ class GitHubOrg
ORGANIZATION_ROLES = {
"admin" => "ADMIN",
# `billing-manager` is currently not supported
"member" => "MEMBER"
"member" => "MEMBER",
"security_manager" => "SECURITY-MANAGER"
}

# Error classes
10 changes: 9 additions & 1 deletion lib/entitlements/backend/github_org/provider.rb
Original file line number Diff line number Diff line change
@@ -104,7 +104,15 @@ def role_name(role_identifier)
# Returns an Entitlements::Models::Group object.
Contract String => Entitlements::Models::Group
def role_to_group(role)
members = github.org_members.keys.select { |username| github.org_members[username] == role }
# The security_manager role is a special case because it is not a role that is
# part of the org membership API. Instead, it is a role that is assigned to users via
# the org role API.
if role == "security_manager"
members = github.users_with_role(role)
else
members = github.org_members.keys.select { |username| github.org_members[username] == role }
end

Entitlements::Models::Group.new(
dn: role_dn(role),
members: Set.new(members),
30 changes: 29 additions & 1 deletion lib/entitlements/backend/github_org/service.rb
Original file line number Diff line number Diff line change
@@ -35,6 +35,23 @@ def sync(implementation, role)

private

Contract String, String => C::HashOf[Symbol, C::Any]
def add_user_to_role(user, role)
if role == "security_manager"
octokit.add_role_to_user(user, role)

# This is a hack to get around the fact that the GitHub API
# has two different concepts of organization roles,
# and the one we want to use is not present in organization memberships.
#
# If we get here, we know that the user is already member of the organization,
# and we know that the user has been successfully granted the role.
{ user:, role:, state: "active" }
else
octokit.update_organization_membership(org, user:, role:)
end
end

# Upsert a user with a role to the organization.
#
# user: A String with the (GitHub) username of the person to add or modify.
@@ -46,10 +63,21 @@ def add_user_to_organization(user, role)
Entitlements.logger.debug "#{identifier} add_user_to_organization(user=#{user}, org=#{org}, role=#{role})"

begin
new_membership = octokit.update_organization_membership(org, user:, role:)
new_membership = add_role_to_user(user, role)
rescue Octokit::NotFound => e
raise e unless ignore_not_found

Entitlements.logger.warn "User #{user} not found in GitHub instance #{identifier}, ignoring."
return false
rescue Octokit::UnprocessableEntity => e
# Two conditions can cause this:
# - If the role is not enabled, we'll get a 422.
# - If the user is not a member of the organization, we'll get a 422.

# We'll loop this under ignore_not_found
# since this affects the case where we want to add a user to security_manager role
raise e unless ignore_not_found

Entitlements.logger.warn "User #{user} not found in GitHub instance #{identifier}, ignoring."
return false
end
26 changes: 26 additions & 0 deletions lib/entitlements/service/github.rb
Original file line number Diff line number Diff line change
@@ -394,6 +394,32 @@ def max_graphql_results
MAX_GRAPHQL_RESULTS
end
# :nocov:

Contract C::None => C::ArrayOf[Hash]
def org_roles
Entitlements.cache[:github_org_roles][org_signature] ||= begin
octokit.get("/orgs/#{@org}/organization-roles")
end
end

Contract String => C::Maybe[Hash]
def org_role(role)
org_roles.find { |r| r[:name] == role }
end

Contract String, String => C::Any
def add_role_to_user(user, role)
role_id = org_role(role)[:id]
octokit.put("/orgs/#{org_name}/organization-roles/users/#{user}/#{role_id}")
end

Contract String => C::ArrayOf[Hash]
def users_with_role(role)
role_id = org_role(role)[:id]
Entitlements.cache[:github_org_role_users][org_signature][role] ||= begin
octokit.get("/orgs/#{org_name}/organization-roles/#{role_id}/users")
end
end
end
end
end
Loading
Oops, something went wrong.