diff --git a/clientapi/authorization/authorization.go b/clientapi/authorization/authorization.go index 1a46649a7..3fc929565 100644 --- a/clientapi/authorization/authorization.go +++ b/clientapi/authorization/authorization.go @@ -1,6 +1,8 @@ package authorization import ( + "flag" + "github.com/matrix-org/dendrite/authorization" roomserver "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" @@ -9,16 +11,20 @@ import ( ) func NewRoomserverAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) authorization.Authorization { - // Load authorization manager for Zion - if cfg.PublicKeyAuthentication.Ethereum.GetEnableAuthZ() { - auth, err := zion.NewZionAuthorization(cfg, roomQueryAPI) + if flag.Lookup("test.v") == nil { + // normal run + // Load authorization manager for Zion + auth, err := zion.NewZionAuthorization(cfg, roomQueryAPI) if err != nil { - log.Errorf("failed to initialise Zion authorization manager, using default. Error: %v", err) - } else { - return auth + // Cannot proceed without an authorization manager + log.Fatalf("failed to initialise Zion authorization manager, using default. Error: %v", err) } + + return auth + } else { + // run under go test + return &authorization.DefaultAuthorization{} } - return &authorization.DefaultAuthorization{} } diff --git a/setup/config/config.go b/setup/config/config.go index 545f462f7..e520c8112 100644 --- a/setup/config/config.go +++ b/setup/config/config.go @@ -612,14 +612,10 @@ func (config *Dendrite) replaceWithEnvVariables() { config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl = replaceWithEnvVariables(config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl) - config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz = - replaceWithEnvVariables(config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz) - logrus.Infof( - "Loaded config for Ethereum chain_id=%v, network_url=%v, enable_authz=%v", + "Loaded config for Ethereum chain_id=%v, network_url=%v", config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigChainID, config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl, - config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz, ) } } diff --git a/setup/config/config_publickey.go b/setup/config/config_publickey.go index 909f538a0..a2dfcdea5 100644 --- a/setup/config/config_publickey.go +++ b/setup/config/config_publickey.go @@ -21,13 +21,11 @@ func (p EthereumAuthParams) GetParams() interface{} { } type EthereumAuthConfig struct { - Enabled bool `yaml:"enabled"` - Version uint `yaml:"version"` - NetworkUrl string `yaml:"network_url"` // Blockchain network provider URL - ConfigChainID string `yaml:"chain_id"` // Blockchain chain ID. Env variable can replace this property. - ConfigEnableAuthz string `yaml:"enable_authz"` // Enable / disable authorization during development. todo: remove this flag when feature is done. - chainID int - enableAuthz bool // todo: remove this flag when feature is done. + Enabled bool `yaml:"enabled"` + Version uint `yaml:"version"` + NetworkUrl string `yaml:"network_url"` // Blockchain network provider URL + ConfigChainID string `yaml:"chain_id"` // Blockchain chain ID. Env variable can replace this property. + chainID int } func (c *EthereumAuthConfig) GetChainID() int { @@ -43,19 +41,6 @@ func (c *EthereumAuthConfig) GetChainID() int { return c.chainID } -func (c *EthereumAuthConfig) GetEnableAuthZ() bool { - if c.ConfigEnableAuthz != "" { - v := strings.TrimSpace(c.ConfigEnableAuthz) - boolValue, err := strconv.ParseBool(v) - if err == nil { - c.enableAuthz = boolValue - } - // No need to do this again. - c.ConfigEnableAuthz = "" - } - return c.enableAuthz -} - type PublicKeyAuthentication struct { Ethereum EthereumAuthConfig `yaml:"ethereum"` } diff --git a/setup/flags.go b/setup/flags.go index 2004d24d0..a9dac61a1 100644 --- a/setup/flags.go +++ b/setup/flags.go @@ -18,7 +18,6 @@ import ( "flag" "fmt" "os" - "strconv" "github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/setup/config" @@ -29,7 +28,6 @@ var ( configPath = flag.String("config", "dendrite.yaml", "The path to the config file. For more information, see the config file in this repository.") version = flag.Bool("version", false, "Shows the current version and exits immediately.") enableRegistrationWithoutVerification = flag.Bool("really-enable-open-registration", false, "This allows open registration without secondary verification (reCAPTCHA). This is NOT RECOMMENDED and will SIGNIFICANTLY increase the risk that your server will be used to send spam or conduct attacks, which may result in your server being banned from rooms.") - enableAuthorizationChecks = flag.Bool("enable-authz", false, "Enables authorization checks (aka space/channel gating).") ) // ParseFlags parses the commandline flags and uses them to create a config. @@ -55,10 +53,5 @@ func ParseFlags(monolith bool) *config.Dendrite { cfg.ClientAPI.OpenRegistrationWithoutVerificationEnabled = true } - // cmdline --enable-authz flag. env overrides it so that deployment scripts can set it. - // todo: remove this flag when feature is done. - cfg.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz = strconv.FormatBool(*enableAuthorizationChecks) - logrus.Info("--enable-authz flag is set to ", *enableAuthorizationChecks) - return cfg } diff --git a/zion/contract_addresses.go b/zion/contract_addresses.go index 0904aa42e..99b65b6d2 100644 --- a/zion/contract_addresses.go +++ b/zion/contract_addresses.go @@ -14,15 +14,6 @@ type SpaceFactoryContractAddress struct { SpaceFactory string `json:"spaceFactory"` } -func loadSpaceManagerAddresses(byteValue []byte) (*SpaceManagerContractAddresses, error) { - var addresses SpaceManagerContractAddresses - err := json.Unmarshal(byteValue, &addresses) - if err != nil { - return nil, err - } - return &addresses, nil -} - func loadSpaceFactoryAddress(byteValue []byte) (*SpaceFactoryContractAddress, error) { var address SpaceFactoryContractAddress err := json.Unmarshal(byteValue, &address) diff --git a/zion/zion_authorization.go b/zion/zion_authorization.go index 5db68dffc..4a3d5194c 100644 --- a/zion/zion_authorization.go +++ b/zion/zion_authorization.go @@ -3,7 +3,11 @@ package zion import ( _ "embed" "errors" + "fmt" + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum/go-ethereum/ethclient" "github.com/matrix-org/dendrite/authorization" roomserver "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" @@ -14,6 +18,13 @@ import ( var ErrSpaceDisabled = errors.New("space disabled") var ErrChannelDisabled = errors.New("channel disabled") +type ZionAuthorization struct { + chainId int + ethClient *ethclient.Client + store Store + spaceContract SpaceContract +} + func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) (authorization.Authorization, error) { // create the authorization states store := NewStore(roomQueryAPI) @@ -28,9 +39,95 @@ func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEv log.Errorf("Cannot connect to eth client %v\n", cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) return nil, err } - return NewZionAuthorizationV2( - chainId, - ethClient, - store, - ) + + za := &ZionAuthorization{ + chainId: chainId, + ethClient: ethClient, + store: store, + } + switch za.chainId { + case 1337, 31337: + localhost, err := NewSpaceContractLocalhost(za.ethClient) + if err != nil { + log.Errorf("error instantiating SpaceContractLocalhost. Error: %v", err) + return nil, err + } + za.spaceContract = localhost + case 5: + goerli, err := NewSpaceContractGoerli(za.ethClient) + if err != nil { + log.Errorf("error instantiating SpaceContractGoerli. Error: %v", err) + return nil, err + } + za.spaceContract = goerli + default: + errMsg := fmt.Sprintf("unsupported chain id: %d", za.chainId) + log.Error(errMsg) + return nil, errors.New(errMsg) + } + // no errors. + return za, nil +} + +func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { + userIdentifier := CreateUserIdentifier(args.UserId) + + // Find out if roomId is a space or a channel. + roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) + + // Owner of the space / channel is always allowed to proceed. + if roomInfo.IsOwner { + return true, nil + } + + // Check if user is entitled to space / channel. + switch roomInfo.RoomType { + case Space: + isEntitled, err := za.isEntitledToSpace(roomInfo, userIdentifier.AccountAddress, args.Permission) + return isEntitled, err + case Channel: + isEntitled, err := za.isEntitledToChannel(roomInfo, userIdentifier.AccountAddress, args.Permission) + return isEntitled, err + default: + errMsg := fmt.Sprintf("unhandled room type: %s", roomInfo.RoomType) + log.Error("IsAllowed", errMsg) + return false, errors.New(errMsg) + } +} + +func (za *ZionAuthorization) isEntitledToSpace(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) { + // space disabled check. + isDisabled, err := za.spaceContract.IsSpaceDisabled(roomInfo.SpaceNetworkId) + if err != nil { + return false, err + } else if isDisabled { + return false, ErrSpaceDisabled + } + + // space entitlement check. + isEntitled, err := za.spaceContract.IsEntitledToSpace( + roomInfo.SpaceNetworkId, + user, + permission, + ) + return isEntitled, err +} + +func (za *ZionAuthorization) isEntitledToChannel(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) { + // channel disabled check. + isDisabled, err := za.spaceContract.IsChannelDisabled(roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) + if err != nil { + return false, err + } else if isDisabled { + return false, ErrSpaceDisabled + } + + // channel entitlement check. + isEntitled, err := za.spaceContract.IsEntitledToChannel( + roomInfo.SpaceNetworkId, + roomInfo.ChannelNetworkId, + user, + permission, + ) + return isEntitled, err } diff --git a/zion/zion_authorization_v1.go b/zion/zion_authorization_v1.go deleted file mode 100644 index 1db2423af..000000000 --- a/zion/zion_authorization_v1.go +++ /dev/null @@ -1,202 +0,0 @@ -package zion - -import ( - _ "embed" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/matrix-org/dendrite/authorization" - "github.com/matrix-org/dendrite/zion/contracts/zion_goerli" // V1 smart contract - "github.com/matrix-org/dendrite/zion/contracts/zion_localhost" // v1 smart contract - log "github.com/sirupsen/logrus" -) - -// v1 smart contract addresses -// -//go:embed contracts/zion_localhost/space-manager.json -var localhostSpaceManagerJson []byte - -//go:embed contracts/zion_goerli/space-manager.json -var goerliSpaceManagerJson []byte - -// v1 smart contracts. Deprecating. -type ZionAuthorizationV1 struct { - chainId int - ethClient *ethclient.Client - spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost - spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli - store Store -} - -func NewZionAuthorizationV1(chainId int, ethClient *ethclient.Client, store Store) (authorization.Authorization, error) { - za := &ZionAuthorizationV1{ - chainId: chainId, - ethClient: ethClient, - store: store, - } - switch za.chainId { - case 1337, 31337: - localhost, err := newZionSpaceManagerLocalhost(za.ethClient) - if err != nil { - log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) - return nil, err - } - za.spaceManagerLocalhost = localhost - case 5: - goerli, err := newZionSpaceManagerGoerli(za.ethClient) - if err != nil { - log.Errorln("error instantiating ZionSpaceManagerGoerli", err) - return nil, err - } - za.spaceManagerGoerli = goerli - default: - errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) - log.Error(errMsg) - return nil, errors.New(errMsg) - } - // no errors. - return za, nil -} - -func newZionSpaceManagerLocalhost(ethClient *ethclient.Client) (*zion_localhost.ZionSpaceManagerLocalhost, error) { - jsonAddresses, err := loadSpaceManagerAddresses(localhostSpaceManagerJson) - if err != nil { - return nil, err - } - address := common.HexToAddress(jsonAddresses.Spacemanager) - spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, ethClient) - if err != nil { - return nil, err - } - return spaceManager, nil -} - -func newZionSpaceManagerGoerli(ethClient *ethclient.Client) (*zion_goerli.ZionSpaceManagerGoerli, error) { - addresses, err := loadSpaceManagerAddresses(goerliSpaceManagerJson) - if err != nil { - return nil, err - } - address := common.HexToAddress(addresses.Spacemanager) - spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, ethClient) - if err != nil { - return nil, err - } - return spaceManager, nil -} - -func (za *ZionAuthorizationV1) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { - userIdentifier := CreateUserIdentifier(args.UserId) - - // Find out if roomId is a space or a channel. - roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) - - // Owner of the space / channel is always allowed to proceed. - if roomInfo.IsOwner { - return true, nil - } - - switch za.chainId { - case 1337, 31337: - // Check if space / channel is disabled. - disabled, err := za.isSpaceChannelDisabledLocalhost(roomInfo) - if disabled { - return false, ErrSpaceDisabled - } else if err != nil { - return false, err - } - isAllowed, err := za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission) - return isAllowed, err - case 5: - // Check if space / channel is disabled. - disabled, err := za.isSpaceChannelDisabledGoerli(roomInfo) - if disabled { - return false, ErrChannelDisabled - } else if err != nil { - return false, err - } - return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission) - default: - errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) - return false, errors.New(errMsg) - } -} - -func (za *ZionAuthorizationV1) isSpaceChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) { - if za.spaceManagerLocalhost == nil { - return false, errors.New("error fetching localhost space manager contract") - } - switch roomInfo.ChannelNetworkId { - case "": - spInfo, err := za.spaceManagerLocalhost.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) - return spInfo.Disabled, err - default: - chInfo, err := za.spaceManagerLocalhost.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) - return chInfo.Disabled, err - } -} - -func (za *ZionAuthorizationV1) isSpaceChannelDisabledGoerli(roomInfo RoomInfo) (bool, error) { - if za.spaceManagerGoerli == nil { - return false, errors.New("error fetching goerli space manager contract") - } - switch roomInfo.ChannelNetworkId { - case "": - spInfo, err := za.spaceManagerGoerli.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) - return spInfo.Disabled, err - default: - chInfo, err := za.spaceManagerGoerli.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) - return chInfo.Disabled, err - } -} - -func (za *ZionAuthorizationV1) isAllowedLocalhost( - roomInfo RoomInfo, - user common.Address, - _permission authorization.Permission, -) (bool, error) { - if za.spaceManagerLocalhost == nil { - return false, errors.New("error fetching localhost space manager contract") - } - - permission := zion_localhost.DataTypesPermission{ - Name: _permission.String(), - } - isEntitled, err := za.spaceManagerLocalhost.IsEntitled( - nil, - roomInfo.SpaceNetworkId, - roomInfo.ChannelNetworkId, - user, - permission, - ) - if err != nil { - return false, err - } - return isEntitled, nil -} - -func (za *ZionAuthorizationV1) isAllowedGoerli( - roomInfo RoomInfo, - user common.Address, - _permission authorization.Permission, -) (bool, error) { - if za.spaceManagerGoerli == nil { - return false, errors.New("error fetching goerli space manager contract") - } - - permission := zion_goerli.DataTypesPermission{ - Name: _permission.String(), - } - isEntitled, err := za.spaceManagerGoerli.IsEntitled( - nil, - roomInfo.SpaceNetworkId, - roomInfo.ChannelNetworkId, - user, - permission, - ) - if err != nil { - return false, err - } - return isEntitled, nil -} diff --git a/zion/zion_authorization_v2.go b/zion/zion_authorization_v2.go deleted file mode 100644 index 4134b1656..000000000 --- a/zion/zion_authorization_v2.go +++ /dev/null @@ -1,114 +0,0 @@ -package zion - -import ( - _ "embed" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - - "github.com/ethereum/go-ethereum/ethclient" - "github.com/matrix-org/dendrite/authorization" - - log "github.com/sirupsen/logrus" -) - -type ZionAuthorizationV2 struct { - chainId int - ethClient *ethclient.Client - store Store - spaceContract SpaceContract -} - -func NewZionAuthorizationV2(chainId int, ethClient *ethclient.Client, store Store) (authorization.Authorization, error) { - za := &ZionAuthorizationV2{ - chainId: chainId, - ethClient: ethClient, - store: store, - } - switch za.chainId { - case 1337, 31337: - localhost, err := NewSpaceContractLocalhost(za.ethClient) - if err != nil { - log.Errorf("error instantiating SpaceContractLocalhost. Error: %v", err) - return nil, err - } - za.spaceContract = localhost - case 5: - goerli, err := NewSpaceContractGoerli(za.ethClient) - if err != nil { - log.Errorf("error instantiating SpaceContractGoerli. Error: %v", err) - return nil, err - } - za.spaceContract = goerli - default: - errMsg := fmt.Sprintf("unsupported chain id: %d", za.chainId) - log.Error(errMsg) - return nil, errors.New(errMsg) - } - // no errors. - return za, nil -} - -func (za *ZionAuthorizationV2) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { - userIdentifier := CreateUserIdentifier(args.UserId) - - // Find out if roomId is a space or a channel. - roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) - - // Owner of the space / channel is always allowed to proceed. - if roomInfo.IsOwner { - return true, nil - } - - // Check if user is entitled to space / channel. - switch roomInfo.RoomType { - case Space: - isEntitled, err := za.isEntitledToSpace(roomInfo, userIdentifier.AccountAddress, args.Permission) - return isEntitled, err - case Channel: - isEntitled, err := za.isEntitledToChannel(roomInfo, userIdentifier.AccountAddress, args.Permission) - return isEntitled, err - default: - errMsg := fmt.Sprintf("unhandled room type: %s", roomInfo.RoomType) - log.Error("IsAllowed", errMsg) - return false, errors.New(errMsg) - } -} - -func (za *ZionAuthorizationV2) isEntitledToSpace(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) { - // space disabled check. - isDisabled, err := za.spaceContract.IsSpaceDisabled(roomInfo.SpaceNetworkId) - if err != nil { - return false, err - } else if isDisabled { - return false, ErrSpaceDisabled - } - - // space entitlement check. - isEntitled, err := za.spaceContract.IsEntitledToSpace( - roomInfo.SpaceNetworkId, - user, - permission, - ) - return isEntitled, err -} - -func (za *ZionAuthorizationV2) isEntitledToChannel(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) { - // channel disabled check. - isDisabled, err := za.spaceContract.IsChannelDisabled(roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) - if err != nil { - return false, err - } else if isDisabled { - return false, ErrSpaceDisabled - } - - // channel entitlement check. - isEntitled, err := za.spaceContract.IsEntitledToChannel( - roomInfo.SpaceNetworkId, - roomInfo.ChannelNetworkId, - user, - permission, - ) - return isEntitled, err -}