From cd8f55a930ec229f175dd12d9f71bf58f13c9604 Mon Sep 17 00:00:00 2001 From: kyosu-1 Date: Thu, 23 May 2024 01:58:59 +0900 Subject: [PATCH 1/6] =?UTF-8?q?client=20credentials=20grant=E3=82=92?= =?UTF-8?q?=E5=88=A9=E7=94=A8=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/middlewares/access_control.go | 11 +++++++++++ router/middlewares/user_authenticate.go | 6 ++++++ service/rbac/role/client.go | 15 +++++++++++++++ service/rbac/role/role.go | 5 +++++ 4 files changed, 37 insertions(+) create mode 100644 service/rbac/role/client.go diff --git a/router/middlewares/access_control.go b/router/middlewares/access_control.go index a8607f7e8..eebbd714f 100644 --- a/router/middlewares/access_control.go +++ b/router/middlewares/access_control.go @@ -14,6 +14,7 @@ import ( "github.com/traPtitech/traQ/service/message" "github.com/traPtitech/traQ/service/rbac" "github.com/traPtitech/traQ/service/rbac/permission" + "github.com/traPtitech/traQ/service/rbac/role" ) // AccessControlMiddlewareGenerator アクセスコントロールミドルウェアのジェネレーターを返します @@ -33,6 +34,16 @@ func AccessControlMiddlewareGenerator(r rbac.RBAC) func(p ...permission.Permissi // ユーザー権限検証 user := c.Get(consts.KeyUser).(model.UserInfo) + if user == nil { + for _, v := range p { + if !r.IsGranted(role.Client, v) { + // NG + return echo.NewHTTPError(http.StatusForbidden, fmt.Sprintf("you are not permitted to request to '%s'", c.Request().URL.Path)) + } + } + + return next(c) // OK + } for _, v := range p { if !r.IsGranted(user.GetRole(), v) { // NG diff --git a/router/middlewares/user_authenticate.go b/router/middlewares/user_authenticate.go index e615370e4..0dfd8f271 100644 --- a/router/middlewares/user_authenticate.go +++ b/router/middlewares/user_authenticate.go @@ -47,6 +47,12 @@ func UserAuthenticate(repo repository.Repository, sessStore session.Store) echo. } c.Set(consts.KeyOAuth2AccessScopes, token.Scopes) + if token.UserID == uuid.Nil { + // client credentials grant の場合ユーザーが存在しない + c.Set(consts.KeyUser, nil) + c.Set(consts.KeyUserID, uuid.Nil) + return next(c) + } uid = token.UserID } else { // Authorizationヘッダーがないためセッションを確認する diff --git a/service/rbac/role/client.go b/service/rbac/role/client.go new file mode 100644 index 000000000..db3fc94fd --- /dev/null +++ b/service/rbac/role/client.go @@ -0,0 +1,15 @@ +package role + +import ( + "github.com/traPtitech/traQ/service/rbac/permission" +) + +// Cliet Clientロール (for OAuth2 client credentials grant) +const Client = "client" + +var clientPerms = []permission.Permission{ + permission.GetUser, + permission.GetUserTag, + permission.GetUserGroup, + permission.GetStamp, +} diff --git a/service/rbac/role/role.go b/service/rbac/role/role.go index 77794c9dd..f1cb05597 100644 --- a/service/rbac/role/role.go +++ b/service/rbac/role/role.go @@ -48,6 +48,11 @@ func GetSystemRoles() Roles { oauth2Scope: true, permissions: permission.PermissionsFromArray(profilePerms), }, + Client: &systemRole{ + name: Client, + oauth2Scope: true, + permissions: permission.PermissionsFromArray(clientPerms), + }, } } From 970e651c9f6c3050bfa0180d659bc2137adb6cab Mon Sep 17 00:00:00 2001 From: Abe-0123 <78936861+kyosu-1@users.noreply.github.com> Date: Fri, 21 Jun 2024 19:19:22 +0900 Subject: [PATCH 2/6] fix typo Co-authored-by: Hibiki Seki --- service/rbac/role/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/rbac/role/client.go b/service/rbac/role/client.go index db3fc94fd..ad0514ea9 100644 --- a/service/rbac/role/client.go +++ b/service/rbac/role/client.go @@ -4,7 +4,7 @@ import ( "github.com/traPtitech/traQ/service/rbac/permission" ) -// Cliet Clientロール (for OAuth2 client credentials grant) +// Client Clientロール (for OAuth2 client credentials grant) const Client = "client" var clientPerms = []permission.Permission{ From d2691c3d8820304cf1a41d10e9a51afecb12f173 Mon Sep 17 00:00:00 2001 From: kyosu-1 Date: Sat, 22 Jun 2024 05:08:24 +0900 Subject: [PATCH 3/6] feat: migrate client role --- migration/current.go | 1 + migration/v36.go | 68 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 migration/v36.go diff --git a/migration/current.go b/migration/current.go index 0967937c0..20f99661e 100644 --- a/migration/current.go +++ b/migration/current.go @@ -46,6 +46,7 @@ func Migrations() []*gormigrate.Migration { v33(), // 未読テーブルにチャンネルIDカラムを追加 / インデックス類の更新 / 不要なレコードの削除 v34(), // 未読テーブルのcreated_atカラムをメッセージテーブルを元に更新 / カラム名を変更 v35(), // OIDC実装のため、openid, profileロール、get_oidc_userinfo権限を追加 + v36(), // OAuth Client Credentials Grantの対応のため、clientロールを追加 } } diff --git a/migration/v36.go b/migration/v36.go new file mode 100644 index 000000000..96d71782c --- /dev/null +++ b/migration/v36.go @@ -0,0 +1,68 @@ +package migration + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// v36 OAuth Client Credentials Grantの対応のため、clientロールを追加 +func v36() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "36", + Migrate: func(db *gorm.DB) error { + roles := []v36UserRole{ + { + Name: "client", + Oauth2Scope: true, + System: true, + Permissions: []v36RolePermission{ + { + Role: "client", + Permission: "get_user", + }, + { + Role: "client", + Permission: "get_user_tag", + }, + { + Role: "client", + Permission: "get_user_group", + }, + { + Role: "client", + Permission: "get_stamp", + }, + }, + }, + } + for _, role := range roles { + err := db.Create(&role).Error + if err != nil { + return err + } + } + return nil + }, + } +} + +type v36UserRole struct { + Name string `gorm:"type:varchar(30);not null;primaryKey"` + Oauth2Scope bool `gorm:"type:boolean;not null;default:false"` + System bool `gorm:"type:boolean;not null;default:false"` + + Permissions []v36RolePermission `gorm:"constraint:user_role_permissions_role_user_roles_name_foreign,OnUpdate:CASCADE,OnDelete:CASCADE;foreignKey:Role;references:Name"` +} + +func (*v36UserRole) TableName() string { + return "user_roles" +} + +type v36RolePermission struct { + Role string `gorm:"type:varchar(30);not null;primaryKey"` + Permission string `gorm:"type:varchar(30);not null;primaryKey"` +} + +func (*v36RolePermission) TableName() string { + return "user_role_permissions" +} From 25154acb7b72c3932a8f47e4e0a04eb8bc59f132 Mon Sep 17 00:00:00 2001 From: kyosu-1 Date: Sat, 22 Jun 2024 06:44:23 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20oauth2=20scope=E3=81=A7=E3=81=AF?= =?UTF-8?q?=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- migration/v36.go | 2 +- service/rbac/role/role.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/v36.go b/migration/v36.go index 96d71782c..008934bb0 100644 --- a/migration/v36.go +++ b/migration/v36.go @@ -13,7 +13,7 @@ func v36() *gormigrate.Migration { roles := []v36UserRole{ { Name: "client", - Oauth2Scope: true, + Oauth2Scope: false, System: true, Permissions: []v36RolePermission{ { diff --git a/service/rbac/role/role.go b/service/rbac/role/role.go index f1cb05597..375c2ef56 100644 --- a/service/rbac/role/role.go +++ b/service/rbac/role/role.go @@ -50,7 +50,7 @@ func GetSystemRoles() Roles { }, Client: &systemRole{ name: Client, - oauth2Scope: true, + oauth2Scope: false, permissions: permission.PermissionsFromArray(clientPerms), }, } From e5b3d293926bff8be3746c9aa98331c48a35eb76 Mon Sep 17 00:00:00 2001 From: kyosu-1 Date: Sat, 22 Jun 2024 07:09:04 +0900 Subject: [PATCH 5/6] =?UTF-8?q?chore:=20client=E3=81=AE=E6=A8=A9=E9=99=90?= =?UTF-8?q?=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E6=B3=A8=E6=84=8F=E4=BA=8B?= =?UTF-8?q?=E9=A0=85=E3=82=92=E8=A8=98=E8=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/rbac/role/client.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service/rbac/role/client.go b/service/rbac/role/client.go index ad0514ea9..4f1233624 100644 --- a/service/rbac/role/client.go +++ b/service/rbac/role/client.go @@ -7,6 +7,9 @@ import ( // Client Clientロール (for OAuth2 client credentials grant) const Client = "client" +// 自分自身以外の参照系は許可するようにしたいが、https://github.com/traPtitech/traQ/pull/2433#discussion_r1649383346 +// の事情から許可できる権限が限られる +// https://github.com/traPtitech/traQ/issues/2463 で権限を増やせるよう対応予定 var clientPerms = []permission.Permission{ permission.GetUser, permission.GetUserTag, From 42797d0e6e9e1ebdd5a5cfab18d81a323a28f75a Mon Sep 17 00:00:00 2001 From: kyosu-1 Date: Sat, 22 Jun 2024 07:14:21 +0900 Subject: [PATCH 6/6] fix lint error --- service/rbac/role/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/rbac/role/client.go b/service/rbac/role/client.go index 4f1233624..d8768a90c 100644 --- a/service/rbac/role/client.go +++ b/service/rbac/role/client.go @@ -7,7 +7,7 @@ import ( // Client Clientロール (for OAuth2 client credentials grant) const Client = "client" -// 自分自身以外の参照系は許可するようにしたいが、https://github.com/traPtitech/traQ/pull/2433#discussion_r1649383346 +// 自分自身以外の参照系は許可するようにしたいが、https://github.com/traPtitech/traQ/pull/2433#discussion_r1649383346 // の事情から許可できる権限が限られる // https://github.com/traPtitech/traQ/issues/2463 で権限を増やせるよう対応予定 var clientPerms = []permission.Permission{