chore: add acl config (#2128)

This commit is contained in:
boojack 2023-08-13 00:06:03 +08:00 committed by GitHub
parent 0bb5f7f972
commit e266d88edd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 18 deletions

View file

@ -27,30 +27,16 @@ const (
UserIDContextKey ContextKey = iota
)
var authenticationAllowlistMethods = map[string]bool{
"/memos.api.v2.SystemService/GetSystemInfo": true,
"/memos.api.v2.UserService/GetUser": true,
"/memos.api.v2.MemoService/ListMemos": true,
}
// IsAuthenticationAllowed returns whether the method is exempted from authentication.
func IsAuthenticationAllowed(fullMethodName string) bool {
if strings.HasPrefix(fullMethodName, "/grpc.reflection") {
return true
}
return authenticationAllowlistMethods[fullMethodName]
}
// GRPCAuthInterceptor is the auth interceptor for gRPC server.
type GRPCAuthInterceptor struct {
store *store.Store
Store *store.Store
secret string
}
// NewGRPCAuthInterceptor returns a new API auth interceptor.
func NewGRPCAuthInterceptor(store *store.Store, secret string) *GRPCAuthInterceptor {
return &GRPCAuthInterceptor{
store: store,
Store: store,
secret: secret,
}
}
@ -68,11 +54,23 @@ func (in *GRPCAuthInterceptor) AuthenticationInterceptor(ctx context.Context, re
userID, err := in.authenticate(ctx, accessTokenStr)
if err != nil {
if IsAuthenticationAllowed(serverInfo.FullMethod) {
if isUnauthorizeAllowedMethod(serverInfo.FullMethod) {
return handler(ctx, request)
}
return nil, err
}
user, err := in.Store.GetUser(ctx, &store.FindUser{
ID: &userID,
})
if err != nil {
return nil, errors.Wrap(err, "failed to get user")
}
if user == nil {
return nil, status.Errorf(codes.Unauthenticated, "user ID %q not exists in the access token", userID)
}
if isOnlyForAdminAllowedMethod(serverInfo.FullMethod) && user.Role != store.RoleHost && user.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "user ID %q is not admin", userID)
}
// Stores userID into context.
childCtx := context.WithValue(ctx, UserIDContextKey, userID)
@ -110,7 +108,7 @@ func (in *GRPCAuthInterceptor) authenticate(ctx context.Context, accessTokenStr
if err != nil {
return 0, status.Errorf(codes.Unauthenticated, "malformed ID %q in the access token", claims.Subject)
}
user, err := in.store.GetUser(ctx, &store.FindUser{
user, err := in.Store.GetUser(ctx, &store.FindUser{
ID: &userID,
})
if err != nil {

26
api/v2/acl_config.go Normal file
View file

@ -0,0 +1,26 @@
package v2
import "strings"
var authenticationAllowlistMethods = map[string]bool{
"/memos.api.v2.SystemService/GetSystemInfo": true,
"/memos.api.v2.UserService/GetUser": true,
"/memos.api.v2.MemoService/ListMemos": true,
}
// isUnauthorizeAllowedMethod returns whether the method is exempted from authentication.
func isUnauthorizeAllowedMethod(fullMethodName string) bool {
if strings.HasPrefix(fullMethodName, "/grpc.reflection") {
return true
}
return authenticationAllowlistMethods[fullMethodName]
}
var allowedMethodsOnlyForAdmin = map[string]bool{
"/memos.api.v2.UserService/CreateUser": true,
}
// isOnlyForAdminAllowedMethod returns true if the method is allowed to be called only by admin.
func isOnlyForAdminAllowedMethod(methodName string) bool {
return allowedMethodsOnlyForAdmin[methodName]
}