[#287] Support proxy for frostfsid and policy contracts
All checks were successful
/ Builds (1.20) (pull_request) Successful in 1m52s
/ Builds (1.21) (pull_request) Successful in 1m12s
/ DCO (pull_request) Successful in 1m46s
/ Vulncheck (pull_request) Successful in 1m43s
/ Lint (pull_request) Successful in 4m3s
/ Tests (1.20) (pull_request) Successful in 2m24s
/ Tests (1.21) (pull_request) Successful in 2m23s
All checks were successful
/ Builds (1.20) (pull_request) Successful in 1m52s
/ Builds (1.21) (pull_request) Successful in 1m12s
/ DCO (pull_request) Successful in 1m46s
/ Vulncheck (pull_request) Successful in 1m43s
/ Lint (pull_request) Successful in 4m3s
/ Tests (1.20) (pull_request) Successful in 2m24s
/ Tests (1.21) (pull_request) Successful in 2m23s
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
3b6d2bc522
commit
899213b3f3
7 changed files with 71 additions and 8 deletions
|
@ -21,6 +21,7 @@ This document outlines major changes between releases.
|
|||
- Add `namespace` label to billing metrics (#271)
|
||||
- Support policy-engine (#257)
|
||||
- Support `policy` contract (#259)
|
||||
- Support `proxy` contract (#287)
|
||||
|
||||
### Changed
|
||||
- Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221)
|
||||
|
|
|
@ -438,9 +438,10 @@ func (a *App) initMetrics() {
|
|||
func (a *App) initFrostfsID(ctx context.Context) {
|
||||
var err error
|
||||
a.frostfsid, err = frostfsid.New(ctx, frostfsid.Config{
|
||||
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
|
||||
Contract: a.cfg.GetString(cfgFrostfsIDContract),
|
||||
Key: a.key,
|
||||
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
|
||||
Contract: a.cfg.GetString(cfgFrostfsIDContract),
|
||||
ProxyContract: a.cfg.GetString(cfgProxyContract),
|
||||
Key: a.key,
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Fatal(logs.InitFrostfsIDContractFailed, zap.Error(err))
|
||||
|
@ -455,9 +456,10 @@ func (a *App) initPolicyStorage(ctx context.Context) {
|
|||
|
||||
if a.cfg.GetBool(cfgPolicyEnabled) {
|
||||
policyContract, err = contract.New(ctx, contract.Config{
|
||||
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
|
||||
Contract: a.cfg.GetString(cfgPolicyContract),
|
||||
Key: a.key,
|
||||
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
|
||||
Contract: a.cfg.GetString(cfgPolicyContract),
|
||||
ProxyContract: a.cfg.GetString(cfgProxyContract),
|
||||
Key: a.key,
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Fatal(logs.InitPolicyContractFailed, zap.Error(err))
|
||||
|
|
|
@ -213,6 +213,9 @@ const ( // Settings.
|
|||
cfgPolicyEnabled = "policy.enabled"
|
||||
cfgPolicyContract = "policy.contract"
|
||||
|
||||
// Proxy.
|
||||
cfgProxyContract = "proxy.contract"
|
||||
|
||||
// envPrefix is an environment variables prefix used for configuration.
|
||||
envPrefix = "S3_GW"
|
||||
)
|
||||
|
@ -702,6 +705,9 @@ func newSettings() *viper.Viper {
|
|||
v.SetDefault(cfgPolicyContract, "policy.frostfs")
|
||||
v.SetDefault(cfgPolicyEnabled, true)
|
||||
|
||||
// proxy
|
||||
v.SetDefault(cfgProxyContract, "proxy.frostfs")
|
||||
|
||||
// resolve
|
||||
v.SetDefault(cfgResolveNamespaceHeader, defaultNamespaceHeader)
|
||||
|
||||
|
|
|
@ -204,6 +204,10 @@ S3_GW_POLICY_ENABLED=true
|
|||
# Policy contract hash (LE) or name in NNS.
|
||||
S3_GW_POLICY_CONTRACT=policy.frostfs
|
||||
|
||||
# Proxy contract configuration. To enable this functionality the `rpc_endpoint` param must be also set.
|
||||
# Proxy contract hash (LE) or name in NNS.
|
||||
S3_GW_PROXY_CONTRACT=proxy.frostfs
|
||||
|
||||
# Namespaces configuration
|
||||
S3_GW_NAMESPACES_CONFIG=namespaces.json
|
||||
|
||||
|
|
|
@ -241,5 +241,10 @@ policy:
|
|||
# Policy contract hash (LE) or name in NNS.
|
||||
contract: policy.frostfs
|
||||
|
||||
# Proxy contract configuration. To enable this functionality the `rpc_endpoint` param must be also set.
|
||||
proxy:
|
||||
# Proxy contract hash (LE) or name in NNS.
|
||||
contract: proxy.frostfs
|
||||
|
||||
namespaces:
|
||||
config: namespaces.json
|
||||
|
|
|
@ -191,6 +191,7 @@ There are some custom types used for brevity:
|
|||
| `web` | [Web server configuration](#web-section) |
|
||||
| `frostfsid` | [FrostfsID configuration](#frostfsid-section) |
|
||||
| `policy` | [Policy contract configuration](#policy-section) |
|
||||
| `proxy` | [Proxy contract configuration](#proxy-section) |
|
||||
| `namespaces` | [Namespaces configuration](#namespaces-section) |
|
||||
|
||||
### General section
|
||||
|
@ -662,6 +663,19 @@ policy:
|
|||
| `enabled` | `bool` | no | true | Enables using policies from Policy contract to check permissions. |
|
||||
| `contract` | `string` | no | policy.frostfs | Policy contract hash (LE) or name in NNS. |
|
||||
|
||||
# `proxy` section
|
||||
|
||||
Proxy contract configuration. To enable this functionality the `rpc_endpoint` param must be also set.
|
||||
|
||||
```yaml
|
||||
proxy:
|
||||
contract: proxy.frostfs
|
||||
```
|
||||
|
||||
| Parameter | Type | SIGHUP reload | Default value | Description |
|
||||
|------------|----------|---------------|-----------------|------------------------------------------|
|
||||
| `contract` | `string` | no | `proxy.frostfs` | Proxy contract hash (LE) or name in NNS. |
|
||||
|
||||
# `namespaces` section
|
||||
|
||||
Namespaces configuration.
|
||||
|
|
|
@ -9,9 +9,11 @@ import (
|
|||
policyclient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/policy"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy"
|
||||
frostfsutil "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/notary"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
)
|
||||
|
@ -28,6 +30,9 @@ type Config struct {
|
|||
// Contract is hash of contract or its name in NNS.
|
||||
Contract string
|
||||
|
||||
// ProxyContract is hash of proxy contract or its name in NNS to interact with policy.
|
||||
ProxyContract string
|
||||
|
||||
// Key is used to interact with policy contract.
|
||||
// If this is nil than random key will be generated.
|
||||
Key *keys.PrivateKey
|
||||
|
@ -54,8 +59,12 @@ func New(ctx context.Context, cfg Config) (*Client, error) {
|
|||
return nil, fmt.Errorf("create policy rpc client: %w", err)
|
||||
}
|
||||
|
||||
acc := wallet.NewAccountFromPrivateKey(key)
|
||||
act, err := actor.NewSimple(rpcCli, acc)
|
||||
proxyContractHash, err := frostfsutil.ResolveContractHash(cfg.ProxyContract, cfg.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
|
||||
}
|
||||
|
||||
act, err := actor.New(rpcCli, getSigners(key, proxyContractHash, contractHash))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create new actor: %w", err)
|
||||
}
|
||||
|
@ -66,6 +75,28 @@ func New(ctx context.Context, cfg Config) (*Client, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func getSigners(key *keys.PrivateKey, proxyHash, contractHash util.Uint160) []actor.SignerAccount {
|
||||
acc := wallet.NewAccountFromPrivateKey(key)
|
||||
|
||||
return []actor.SignerAccount{
|
||||
{
|
||||
Signer: transaction.Signer{
|
||||
Account: proxyHash,
|
||||
Scopes: transaction.CustomContracts,
|
||||
AllowedContracts: []util.Uint160{contractHash},
|
||||
},
|
||||
Account: notary.FakeContractAccount(proxyHash),
|
||||
},
|
||||
{
|
||||
Signer: transaction.Signer{
|
||||
Account: acc.Contract.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) AddChain(kind policycontract.Kind, entity string, name []byte, chain []byte) (util.Uint256, uint32, error) {
|
||||
return c.policyContract.AddChain(big.NewInt(int64(kind)), entity, name, chain)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue