Skip to content
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

[WIP] Introduce Role-Based Authentication for Repository Management #1060

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

minwoox
Copy link
Member

@minwoox minwoox commented Nov 14, 2024

Motivation:
To address the migration of mirroring configurations from projects to repositories and to simplify access management,
we decided to:

  • Hide the meta repository.
  • Replace permission-based authentication with a role-based system using RepositoryRole (READ, WRITE, ADMIN). The ADMIN role has access to the configurations.

This change resolves the issue where users with WRITE permission for the meta repository were limited to creating mirroring configurations.

With RepositoryRole, access becomes more structured and extensible for future enhancements (e.g., introducing custom roles). While permission-based authentication is replaced here, this does not preclude the future coexistence of role-based and permission-based systems.

Modifications:

  • Added RepositoryRole with hierarchical roles (READ, WRITE, ADMIN).
  • Replaced RequiresPermission annotations with RequiresRepositoryRole.
  • Renamed RequiresRole to RequiresProjectRole.
    • Updated it to accept a single ProjectRole, utilizing the hierarchical model to avoid redundant role specifications.
  • Removed APIs for managing permissions, replacing them with role management APIs.

Result:

  • Role-based access simplifies management and aligns with repository-specific mirroring configurations.
  • (Breaking) APIs for managing permissions are removed.

To-do:

  • Update the documentation to reflect the new systme, including updated screenshots

Migration plan:

  • Deploy PR, which supports deserialization of both legacy and new metadata format.
  • Deploy intermediate commit supporting both permission and role APIs, ensuring metadata is stored in the new format.
    • The commit also migrate the legacy format to new format.
  • Deploy this commit, which exclusively supports role-based APIs.

@minwoox minwoox added this to the 0.72.0 milestone Nov 14, 2024
minwoox added a commit to minwoox/centraldogma that referenced this pull request Nov 14, 2024
Motivation
To ensure smooth compatibility with line#1060, the `PerRolePermissions` and `RepositoryMetadata` structure need an update to support changes.

Modifications:
- Enhanced the `PerRolePermissions` and `RepositoryMetadata` deserializers to accept both an array or permissions and a permission.
- Added `REPO_ADMIN` `Permission`.
- Removed `MetadataApiService.updateSpecificUserPermission` and `updateSpecificTokenPermission`.
  - They are not used in the UI and we don't even have test cases for that.
  - Will add those APIs later when we need it.

Result:
- The `PerRolePermissions` and `RepositoryMetadata` structures now support the upcoming changes in line#1060.
@minwoox minwoox changed the title [WIP] Use the highest authority permission Simplify Permission Configuration by Using Highest Authority Nov 18, 2024
@minwoox minwoox changed the title Simplify Permission Configuration by Using Highest Authority [WIP] Simplify Permission Configuration by Using Highest Authority Nov 21, 2024
@RequiresRole(roles = { ProjectRole.OWNER, ProjectRole.MEMBER })
public CompletableFuture<ProjectMetadata> getProjectMetadata(
@Param String projectName,
@Param("checkPermissionOnly") @Default("false") boolean isCheckPermissionOnly) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parameter was introduced here but has not been used anywhere. Let me just remove that.

@minwoox minwoox changed the title [WIP] Simplify Permission Configuration by Using Highest Authority Introduce Role-Based Authentication for Repository Management Nov 22, 2024
// }
// }
// }
final JsonPointer path = JsonPointer.compile("/repos" + encodeSegment(repoName) + "/roles/projects");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this code will be applied after the migration is complete.

Comment on lines +1125 to +1128
// }
// "tokens": {
// "my-token": "WRITE"
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// }
// "tokens": {
// "my-token": "WRITE"
// }
// },
// "tokens": {
// "my-token": "WRITE"
// },

// }
// }
// }
final JsonPointer path = JsonPointer.compile("/repos" + encodeSegment(repoName) + "/roles/projects");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: It would be nice to have a DSL/builder to build a JSON pointer type-safely. Let's consider it later.

JsonPointers
  .meta()
  .repos(repoName)
  .roles()
  .projects()
  .compile();

JsonPointers
  .meta()
  .members(repoName)
  .compile();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good suggestion. By the way, this PR is in WIP and I forgot to tell you about it.
Would you mind reviewing #1064, beforehand?

return repositoryMetadata.perRolePermissions().guest();
@Nullable
private static RepositoryRole repositoryRole(Roles roles, @Nullable RepositoryRole repositoryRole,
@Nullable ProjectRole projectRole) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

projectRole seems not null always in the current usage.

Suggested change
@Nullable ProjectRole projectRole) {
ProjectRole projectRole) {

if (memberOrGuestRole == null) {
return repositoryRole;
}
if (memberOrGuestRole == RepositoryRole.WRITE || repositoryRole == RepositoryRole.WRITE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say a-member-user is granted to READ role and projects.member is granted to WRITE. Is WRITE given for a-member-user?

{
  "repos": {
    "my-repo": {
      "name": "my-repo",
      "roles": {
        "users": {
          "a-member-user": "READ"
        }
        "projects": {
          "member": "WRITE",
          ...
       }
      }
    }
  }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is WRITE given for a-member-user?

That is correct, as similar to how GitHub handles it.
The role with the highest authority will take precedence.


@Override
public String toString() {
return MoreObjects.toStringHelper(this).omitNullValues()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
return MoreObjects.toStringHelper(this).omitNullValues()
return MoreObjects.toStringHelper(this)

@minwoox minwoox changed the title Introduce Role-Based Authentication for Repository Management [WIP] Introduce Role-Based Authentication for Repository Management Dec 2, 2024
@minwoox minwoox modified the milestones: 0.72.0, 0.73.0 Dec 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants