Resolve Feishu names by verified open ID and scope VPN member access
This commit is contained in:
1 parent
578a58a129
commit
d4eddf7365
19 files changed
+837
-35
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package identityprovider
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"vpn-platform/backend/internal/model"
|
||||
"vpn-platform/backend/internal/service"
|
||||
"vpn-platform/backend/internal/store"
|
||||
)
|
||||
|
||||
// builtinTunnel finds the one tunnel whose OAuth callback owns this redirect.
|
||||
// Ambiguous or missing routes fail closed; a browser redirect alone grants nothing.
|
||||
func builtinTunnel(redirect, base string, cfg model.IdentityProvider) (model.Tunnel, map[string]interface{}, error) {
|
||||
u, err := url.Parse(redirect)
|
||||
if err != nil || u.RawQuery != "" || u.Fragment != "" || u.Path != "/oauth2/callback" {
|
||||
return model.Tunnel{}, nil, errors.New("unknown callback")
|
||||
}
|
||||
var tunnels []model.Tunnel
|
||||
if err := store.DB.Where("protocol = ?", "openvpn").Find(&tunnels).Error; err != nil {
|
||||
return model.Tunnel{}, nil, err
|
||||
}
|
||||
var match model.Tunnel
|
||||
var config map[string]interface{}
|
||||
for _, tunnel := range tunnels {
|
||||
data, err := store.TunnelConfig(&tunnel)
|
||||
if err != nil {
|
||||
return model.Tunnel{}, nil, err
|
||||
}
|
||||
if service.Str(data, "auth_mode") != "oidc" || service.Str(data, "oidc_provider") != "builtin" || service.Str(data, "oidc_issuer") != base || service.Str(data, "oidc_client_id") != cfg.ClientID || strings.TrimRight(service.Str(data, "oidc_base_url"), "/")+"/oauth2/callback" != redirect {
|
||||
continue
|
||||
}
|
||||
if match.ID != 0 {
|
||||
return model.Tunnel{}, nil, errors.New("ambiguous callback")
|
||||
}
|
||||
match, config = tunnel, data
|
||||
}
|
||||
if match.ID == 0 {
|
||||
return model.Tunnel{}, nil, errors.New("unknown callback")
|
||||
}
|
||||
return match, config, nil
|
||||
}
|
||||
|
||||
func admitted(redirect, base string, cfg model.IdentityProvider, subject string) (bool, error) {
|
||||
tunnel, config, err := builtinTunnel(redirect, base, cfg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if raw, present := config["feishu_access_mode"]; present {
|
||||
if _, ok := raw.(string); !ok {
|
||||
return false, errors.New("invalid admission mode")
|
||||
}
|
||||
}
|
||||
switch service.Str(config, "feishu_access_mode") {
|
||||
case "", "all":
|
||||
return true, nil
|
||||
case "allowlist":
|
||||
var count int64
|
||||
err := store.DB.Model(&model.FeishuTunnelGrant{}).Where("tunnel_id = ? AND issuer = ? AND app_id = ? AND subject = ?", tunnel.ID, base, cfg.AppID, subject).Count(&count).Error
|
||||
return err == nil && count == 1, err
|
||||
default:
|
||||
return false, errors.New("invalid admission mode")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user