Merge pull request #974 from CosmWasm/945_access_config_anyof

Introduce new AccessType to allow a set of addresses
This commit is contained in:
Alexander Peters
2022-09-08 15:21:28 +02:00
committed by GitHub
13 changed files with 1172 additions and 204 deletions

View File

@@ -119,7 +119,8 @@ AccessConfig access control type.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `permission` | [AccessType](#cosmwasm.wasm.v1.AccessType) | | |
| `address` | [string](#string) | | |
| `address` | [string](#string) | | Address Deprecated: replaced by addresses |
| `addresses` | [string](#string) | repeated | |
@@ -240,8 +241,9 @@ AccessType permission types
| ---- | ------ | ----------- |
| ACCESS_TYPE_UNSPECIFIED | 0 | AccessTypeUnspecified placeholder for empty value |
| ACCESS_TYPE_NOBODY | 1 | AccessTypeNobody forbidden |
| ACCESS_TYPE_ONLY_ADDRESS | 2 | AccessTypeOnlyAddress restricted to an address |
| ACCESS_TYPE_ONLY_ADDRESS | 2 | AccessTypeOnlyAddress restricted to a single address Deprecated: use AccessTypeAnyOfAddresses instead |
| ACCESS_TYPE_EVERYBODY | 3 | AccessTypeEverybody unrestricted |
| ACCESS_TYPE_ANY_OF_ADDRESSES | 4 | AccessTypeAnyOfAddresses allow any of the addresses |

View File

@@ -19,12 +19,16 @@ enum AccessType {
// AccessTypeNobody forbidden
ACCESS_TYPE_NOBODY = 1
[ (gogoproto.enumvalue_customname) = "AccessTypeNobody" ];
// AccessTypeOnlyAddress restricted to an address
// AccessTypeOnlyAddress restricted to a single address
// Deprecated: use AccessTypeAnyOfAddresses instead
ACCESS_TYPE_ONLY_ADDRESS = 2
[ (gogoproto.enumvalue_customname) = "AccessTypeOnlyAddress" ];
// AccessTypeEverybody unrestricted
ACCESS_TYPE_EVERYBODY = 3
[ (gogoproto.enumvalue_customname) = "AccessTypeEverybody" ];
// AccessTypeAnyOfAddresses allow any of the addresses
ACCESS_TYPE_ANY_OF_ADDRESSES = 4
[ (gogoproto.enumvalue_customname) = "AccessTypeAnyOfAddresses" ];
}
// AccessTypeParam
@@ -37,7 +41,11 @@ message AccessTypeParam {
message AccessConfig {
option (gogoproto.goproto_stringer) = true;
AccessType permission = 1 [ (gogoproto.moretags) = "yaml:\"permission\"" ];
// Address
// Deprecated: replaced by addresses
string address = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ];
repeated string addresses = 3 [ (gogoproto.moretags) = "yaml:\"addresses\"" ];
}
// Params defines the set of wasm parameters.

View File

@@ -73,6 +73,7 @@ func GenesisStoreCodeCmd(defaultNodeHome string, genesisMutator GenesisMutator)
cmd.Flags().String(flagInstantiateByEverybody, "", "Everybody can instantiate a contract from the code, optional")
cmd.Flags().String(flagInstantiateNobody, "", "Nobody except the governance process can instantiate a contract from the code, optional")
cmd.Flags().String(flagInstantiateByAddress, "", "Only this address can instantiate a contract instance from the code, optional")
cmd.Flags().StringSlice(flagInstantiateByAnyOfAddress, []string{}, "Any of the addresses can instantiate a contract from the code, optional")
cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")

View File

@@ -597,27 +597,38 @@ func ProposalUnpinCodesCmd() *cobra.Command {
return cmd
}
func parseAccessConfig(config string) (types.AccessConfig, error) {
switch config {
func parseAccessConfig(raw string) (c types.AccessConfig, err error) {
switch raw {
case "nobody":
return types.AllowNobody, nil
case "everybody":
return types.AllowEverybody, nil
default:
address, err := sdk.AccAddressFromBech32(config)
if err != nil {
return types.AccessConfig{}, fmt.Errorf("unable to parse address %s", config)
parts := strings.Split(raw, ",")
addrs := make([]sdk.AccAddress, len(parts))
for i, v := range parts {
addr, err := sdk.AccAddressFromBech32(v)
if err != nil {
return types.AccessConfig{}, fmt.Errorf("unable to parse address %q: %s", v, err)
}
addrs[i] = addr
}
return types.AccessTypeOnlyAddress.With(address), nil
defer func() { // convert panic in ".With" to error for better output
if r := recover(); r != nil {
err = r.(error)
}
}()
cfg := types.AccessTypeAnyOfAddresses.With(addrs...)
return cfg, cfg.ValidateBasic()
}
}
func parseAccessConfigUpdates(args []string) ([]types.AccessConfigUpdate, error) {
updates := make([]types.AccessConfigUpdate, len(args))
for i, c := range args {
// format: code_id,access_config
// access_config: nobody|everybody|address
parts := strings.Split(c, ",")
// format: code_id:access_config
// access_config: nobody|everybody|address(es)
parts := strings.Split(c, ":")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid format")
}
@@ -642,15 +653,15 @@ func parseAccessConfigUpdates(args []string) ([]types.AccessConfigUpdate, error)
func ProposalUpdateInstantiateConfigCmd() *cobra.Command {
bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "update-instantiate-config [code-id,permission]...",
Use: "update-instantiate-config [code-id:permission]...",
Short: "Submit an update instantiate config proposal.",
Args: cobra.MinimumNArgs(1),
Long: strings.TrimSpace(
fmt.Sprintf(`Submit an update instantiate config proposal for multiple code ids.
Example:
$ %s tx gov submit-proposal update-instantiate-config 1,nobody 2,everybody 3,%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm
`, version.AppName, bech32Prefix)),
$ %s tx gov submit-proposal update-instantiate-config 1:nobody 2:everybody 3:%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm,%s1vx8knpllrj7n963p9ttd80w47kpacrhuts497x
`, version.AppName, bech32Prefix, bech32Prefix)),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {

View File

@@ -0,0 +1,97 @@
package cli
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
func TestParseAccessConfigUpdates(t *testing.T) {
specs := map[string]struct {
src []string
exp []types.AccessConfigUpdate
expErr bool
}{
"nobody": {
src: []string{"1:nobody"},
exp: []types.AccessConfigUpdate{{
CodeID: 1,
InstantiatePermission: types.AccessConfig{Permission: types.AccessTypeNobody},
}},
},
"everybody": {
src: []string{"1:everybody"},
exp: []types.AccessConfigUpdate{{
CodeID: 1,
InstantiatePermission: types.AccessConfig{Permission: types.AccessTypeEverybody},
}},
},
"any of addresses - single": {
src: []string{"1:cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x"},
exp: []types.AccessConfigUpdate{
{
CodeID: 1,
InstantiatePermission: types.AccessConfig{
Permission: types.AccessTypeAnyOfAddresses,
Addresses: []string{"cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x"},
},
},
},
},
"any of addresses - multiple": {
src: []string{"1:cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x,cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"},
exp: []types.AccessConfigUpdate{
{
CodeID: 1,
InstantiatePermission: types.AccessConfig{
Permission: types.AccessTypeAnyOfAddresses,
Addresses: []string{"cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x", "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"},
},
},
},
},
"multiple code ids with different permissions": {
src: []string{"1:cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x,cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", "2:nobody"},
exp: []types.AccessConfigUpdate{
{
CodeID: 1,
InstantiatePermission: types.AccessConfig{
Permission: types.AccessTypeAnyOfAddresses,
Addresses: []string{"cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x", "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"},
},
}, {
CodeID: 2,
InstantiatePermission: types.AccessConfig{
Permission: types.AccessTypeNobody,
},
},
},
},
"any of addresses - empty list": {
src: []string{"1:"},
expErr: true,
},
"any of addresses - invalid address": {
src: []string{"1:foo"},
expErr: true,
},
"any of addresses - duplicate address": {
src: []string{"1:cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x,cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x"},
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
got, gotErr := parseAccessConfigUpdates(spec.src)
if spec.expErr {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
assert.Equal(t, spec.exp, got)
})
}
}

View File

@@ -19,15 +19,16 @@ import (
)
const (
flagAmount = "amount"
flagLabel = "label"
flagAdmin = "admin"
flagNoAdmin = "no-admin"
flagRunAs = "run-as"
flagInstantiateByEverybody = "instantiate-everybody"
flagInstantiateNobody = "instantiate-nobody"
flagInstantiateByAddress = "instantiate-only-address"
flagUnpinCode = "unpin-code"
flagAmount = "amount"
flagLabel = "label"
flagAdmin = "admin"
flagNoAdmin = "no-admin"
flagRunAs = "run-as"
flagInstantiateByEverybody = "instantiate-everybody"
flagInstantiateNobody = "instantiate-nobody"
flagInstantiateByAddress = "instantiate-only-address"
flagInstantiateByAnyOfAddress = "instantiate-anyof-addresses"
flagUnpinCode = "unpin-code"
)
// GetTxCmd returns the transaction commands for this module
@@ -75,7 +76,8 @@ func StoreCodeCmd() *cobra.Command {
cmd.Flags().String(flagInstantiateByEverybody, "", "Everybody can instantiate a contract from the code, optional")
cmd.Flags().String(flagInstantiateNobody, "", "Nobody except the governance process can instantiate a contract from the code, optional")
cmd.Flags().String(flagInstantiateByAddress, "", "Only this address can instantiate a contract instance from the code, optional")
cmd.Flags().String(flagInstantiateByAddress, "", "Deprecated: Only this address can instantiate a contract from the code, optional")
cmd.Flags().StringSlice(flagInstantiateByAnyOfAddress, []string{}, "Any of the addresses can instantiate a contract from the code, optional")
flags.AddTxFlagsToCmd(cmd)
return cmd
}
@@ -97,47 +99,9 @@ func parseStoreCodeArgs(file string, sender sdk.AccAddress, flags *flag.FlagSet)
return types.MsgStoreCode{}, fmt.Errorf("invalid input file. Use wasm binary or gzip")
}
var perm *types.AccessConfig
onlyAddrStr, err := flags.GetString(flagInstantiateByAddress)
perm, err := parseAccessConfigFlags(flags)
if err != nil {
return types.MsgStoreCode{}, fmt.Errorf("instantiate by address: %s", err)
}
if onlyAddrStr != "" {
allowedAddr, err := sdk.AccAddressFromBech32(onlyAddrStr)
if err != nil {
return types.MsgStoreCode{}, sdkerrors.Wrap(err, flagInstantiateByAddress)
}
x := types.AccessTypeOnlyAddress.With(allowedAddr)
perm = &x
} else {
everybodyStr, err := flags.GetString(flagInstantiateByEverybody)
if err != nil {
return types.MsgStoreCode{}, fmt.Errorf("instantiate by everybody: %s", err)
}
if everybodyStr != "" {
ok, err := strconv.ParseBool(everybodyStr)
if err != nil {
return types.MsgStoreCode{}, fmt.Errorf("boolean value expected for instantiate by everybody: %s", err)
}
if ok {
perm = &types.AllowEverybody
}
}
nobodyStr, err := flags.GetString(flagInstantiateNobody)
if err != nil {
return types.MsgStoreCode{}, fmt.Errorf("instantiate by nobody: %s", err)
}
if nobodyStr != "" {
ok, err := strconv.ParseBool(nobodyStr)
if err != nil {
return types.MsgStoreCode{}, fmt.Errorf("boolean value expected for instantiate by nobody: %s", err)
}
if ok {
perm = &types.AllowNobody
}
}
return types.MsgStoreCode{}, err
}
msg := types.MsgStoreCode{
@@ -148,6 +112,65 @@ func parseStoreCodeArgs(file string, sender sdk.AccAddress, flags *flag.FlagSet)
return msg, nil
}
func parseAccessConfigFlags(flags *flag.FlagSet) (*types.AccessConfig, error) {
addrs, err := flags.GetStringSlice(flagInstantiateByAnyOfAddress)
if err != nil {
return nil, fmt.Errorf("flag any of: %s", err)
}
if len(addrs) != 0 {
acceptedAddrs := make([]sdk.AccAddress, len(addrs))
for i, v := range addrs {
acceptedAddrs[i], err = sdk.AccAddressFromBech32(v)
if err != nil {
return nil, fmt.Errorf("parse %q: %w", v, err)
}
}
x := types.AccessTypeAnyOfAddresses.With(acceptedAddrs...)
return &x, nil
}
onlyAddrStr, err := flags.GetString(flagInstantiateByAddress)
if err != nil {
return nil, fmt.Errorf("instantiate by address: %s", err)
}
if onlyAddrStr != "" {
allowedAddr, err := sdk.AccAddressFromBech32(onlyAddrStr)
if err != nil {
return nil, sdkerrors.Wrap(err, flagInstantiateByAddress)
}
x := types.AccessTypeOnlyAddress.With(allowedAddr)
return &x, nil
}
everybodyStr, err := flags.GetString(flagInstantiateByEverybody)
if err != nil {
return nil, fmt.Errorf("instantiate by everybody: %s", err)
}
if everybodyStr != "" {
ok, err := strconv.ParseBool(everybodyStr)
if err != nil {
return nil, fmt.Errorf("boolean value expected for instantiate by everybody: %s", err)
}
if ok {
return &types.AllowEverybody, nil
}
}
nobodyStr, err := flags.GetString(flagInstantiateNobody)
if err != nil {
return nil, fmt.Errorf("instantiate by nobody: %s", err)
}
if nobodyStr != "" {
ok, err := strconv.ParseBool(nobodyStr)
if err != nil {
return nil, fmt.Errorf("boolean value expected for instantiate by nobody: %s", err)
}
if ok {
return &types.AllowNobody, nil
}
}
return nil, nil
}
// InstantiateContractCmd will instantiate a contract from previously uploaded code.
func InstantiateContractCmd() *cobra.Command {
cmd := &cobra.Command{

View File

@@ -0,0 +1,59 @@
package cli
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
func TestParseAccessConfigFlags(t *testing.T) {
specs := map[string]struct {
args []string
expCfg *types.AccessConfig
expErr bool
}{
"nobody": {
args: []string{"--instantiate-nobody=true"},
expCfg: &types.AccessConfig{Permission: types.AccessTypeNobody},
},
"everybody": {
args: []string{"--instantiate-everybody=true"},
expCfg: &types.AccessConfig{Permission: types.AccessTypeEverybody},
},
"only address": {
args: []string{"--instantiate-only-address=cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x"},
expCfg: &types.AccessConfig{Permission: types.AccessTypeOnlyAddress, Address: "cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x"},
},
"only address - invalid": {
args: []string{"--instantiate-only-address=foo"},
expErr: true,
},
"any of address": {
args: []string{"--instantiate-anyof-addresses=cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x,cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"},
expCfg: &types.AccessConfig{Permission: types.AccessTypeAnyOfAddresses, Addresses: []string{"cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x", "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"}},
},
"any of address - invalid": {
args: []string{"--instantiate-anyof-addresses=cosmos1vx8knpllrj7n963p9ttd80w47kpacrhuts497x,foo"},
expErr: true,
},
"not set": {
args: []string{},
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
flags := StoreCodeCmd().Flags()
require.NoError(t, flags.Parse(spec.args))
gotCfg, gotErr := parseAccessConfigFlags(flags)
if spec.expErr {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
assert.Equal(t, spec.expCfg, gotCfg)
})
}
}

View File

@@ -0,0 +1,311 @@
package keeper
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
func TestDefaultAuthzPolicyCanCreateCode(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
config types.AccessConfig
actor sdk.AccAddress
exp bool
panics bool
}{
"nobody": {
config: types.AllowNobody,
exp: false,
},
"everybody": {
config: types.AllowEverybody,
exp: true,
},
"only address - same": {
config: types.AccessTypeOnlyAddress.With(myActorAddress),
exp: true,
},
"only address - different": {
config: types.AccessTypeOnlyAddress.With(otherAddress),
exp: false,
},
"any address - included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress, myActorAddress),
exp: true,
},
"any address - not included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress),
exp: false,
},
"undefined config - panics": {
config: types.AccessConfig{},
panics: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := DefaultAuthorizationPolicy{}
if !spec.panics {
got := policy.CanCreateCode(spec.config, myActorAddress)
assert.Equal(t, spec.exp, got)
return
}
assert.Panics(t, func() {
policy.CanCreateCode(spec.config, myActorAddress)
})
})
}
}
func TestDefaultAuthzPolicyCanInstantiateContract(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
config types.AccessConfig
actor sdk.AccAddress
exp bool
panics bool
}{
"nobody": {
config: types.AllowNobody,
exp: false,
},
"everybody": {
config: types.AllowEverybody,
exp: true,
},
"only address - same": {
config: types.AccessTypeOnlyAddress.With(myActorAddress),
exp: true,
},
"only address - different": {
config: types.AccessTypeOnlyAddress.With(otherAddress),
exp: false,
},
"any address - included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress, myActorAddress),
exp: true,
},
"any address - not included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress),
exp: false,
},
"undefined config - panics": {
config: types.AccessConfig{},
panics: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := DefaultAuthorizationPolicy{}
if !spec.panics {
got := policy.CanInstantiateContract(spec.config, myActorAddress)
assert.Equal(t, spec.exp, got)
return
}
assert.Panics(t, func() {
policy.CanInstantiateContract(spec.config, myActorAddress)
})
})
}
}
func TestDefaultAuthzPolicyCanModifyContract(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
admin sdk.AccAddress
exp bool
}{
"same as actor": {
admin: myActorAddress,
exp: true,
},
"different admin": {
admin: otherAddress,
exp: false,
},
"no admin": {
exp: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := DefaultAuthorizationPolicy{}
got := policy.CanModifyContract(spec.admin, myActorAddress)
assert.Equal(t, spec.exp, got)
})
}
}
func TestDefaultAuthzPolicyCanModifyCodeAccessConfig(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
admin sdk.AccAddress
subset bool
exp bool
}{
"same as actor - subset": {
admin: myActorAddress,
subset: true,
exp: true,
},
"same as actor - not subset": {
admin: myActorAddress,
subset: false,
exp: false,
},
"different admin": {
admin: otherAddress,
exp: false,
},
"no admin": {
exp: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := DefaultAuthorizationPolicy{}
got := policy.CanModifyCodeAccessConfig(spec.admin, myActorAddress, spec.subset)
assert.Equal(t, spec.exp, got)
})
}
}
func TestGovAuthzPolicyCanCreateCode(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
config types.AccessConfig
actor sdk.AccAddress
}{
"nobody": {
config: types.AllowNobody,
},
"everybody": {
config: types.AllowEverybody,
},
"only address - same": {
config: types.AccessTypeOnlyAddress.With(myActorAddress),
},
"only address - different": {
config: types.AccessTypeOnlyAddress.With(otherAddress),
},
"any address - included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress, myActorAddress),
},
"any address - not included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress),
},
"undefined config - panics": {
config: types.AccessConfig{},
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := GovAuthorizationPolicy{}
got := policy.CanCreateCode(spec.config, myActorAddress)
assert.True(t, got)
})
}
}
func TestGovAuthzPolicyCanInstantiateContract(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
config types.AccessConfig
actor sdk.AccAddress
}{
"nobody": {
config: types.AllowNobody,
},
"everybody": {
config: types.AllowEverybody,
},
"only address - same": {
config: types.AccessTypeOnlyAddress.With(myActorAddress),
},
"only address - different": {
config: types.AccessTypeOnlyAddress.With(otherAddress),
},
"any address - included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress, myActorAddress),
},
"any address - not included": {
config: types.AccessTypeAnyOfAddresses.With(otherAddress),
},
"undefined config - panics": {
config: types.AccessConfig{},
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := GovAuthorizationPolicy{}
got := policy.CanInstantiateContract(spec.config, myActorAddress)
assert.True(t, got)
})
}
}
func TestGovAuthzPolicyCanModifyContract(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
admin sdk.AccAddress
}{
"same as actor": {
admin: myActorAddress,
},
"different admin": {
admin: otherAddress,
},
"no admin": {},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := GovAuthorizationPolicy{}
got := policy.CanModifyContract(spec.admin, myActorAddress)
assert.True(t, got)
})
}
}
func TestGovAuthzPolicyCanModifyCodeAccessConfig(t *testing.T) {
myActorAddress := RandomAccountAddress(t)
otherAddress := RandomAccountAddress(t)
specs := map[string]struct {
admin sdk.AccAddress
subset bool
}{
"same as actor - subset": {
admin: myActorAddress,
subset: true,
},
"same as actor - not subset": {
admin: myActorAddress,
subset: false,
},
"different admin": {
admin: otherAddress,
},
"no admin": {},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
policy := GovAuthorizationPolicy{}
got := policy.CanModifyCodeAccessConfig(spec.admin, myActorAddress, spec.subset)
assert.True(t, got)
})
}
}

View File

@@ -20,20 +20,33 @@ var (
var AllAccessTypes = []AccessType{
AccessTypeNobody,
AccessTypeOnlyAddress,
AccessTypeAnyOfAddresses,
AccessTypeEverybody,
}
func (a AccessType) With(addr sdk.AccAddress) AccessConfig {
func (a AccessType) With(addrs ...sdk.AccAddress) AccessConfig {
switch a {
case AccessTypeNobody:
return AllowNobody
case AccessTypeOnlyAddress:
if err := sdk.VerifyAddressFormat(addr); err != nil {
if n := len(addrs); n != 1 {
panic(fmt.Sprintf("expected exactly 1 address but got %d", n))
}
if err := sdk.VerifyAddressFormat(addrs[0]); err != nil {
panic(err)
}
return AccessConfig{Permission: AccessTypeOnlyAddress, Address: addr.String()}
return AccessConfig{Permission: AccessTypeOnlyAddress, Address: addrs[0].String()}
case AccessTypeEverybody:
return AllowEverybody
case AccessTypeAnyOfAddresses:
bech32Addrs := make([]string, len(addrs))
for i, v := range addrs {
bech32Addrs[i] = v.String()
}
if err := assertValidAddresses(bech32Addrs); err != nil {
panic(sdkerrors.Wrap(err, "addresses"))
}
return AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: bech32Addrs}
}
panic("unsupported access type")
}
@@ -46,6 +59,8 @@ func (a AccessType) String() string {
return "OnlyAddress"
case AccessTypeEverybody:
return "Everybody"
case AccessTypeAnyOfAddresses:
return "AnyOfAddresses"
}
return "Unspecified"
}
@@ -147,6 +162,7 @@ func validateAccessType(i interface{}) error {
return sdkerrors.Wrapf(ErrInvalid, "unknown type: %q", a)
}
// ValidateBasic performs basic validation
func (a AccessConfig) ValidateBasic() error {
switch a.Permission {
case AccessTypeUnspecified:
@@ -157,12 +173,39 @@ func (a AccessConfig) ValidateBasic() error {
}
return nil
case AccessTypeOnlyAddress:
if len(a.Addresses) != 0 {
return ErrInvalid.Wrap("addresses field set")
}
_, err := sdk.AccAddressFromBech32(a.Address)
return err
case AccessTypeAnyOfAddresses:
if a.Address != "" {
return ErrInvalid.Wrap("address field set")
}
return sdkerrors.Wrap(assertValidAddresses(a.Addresses), "addresses")
}
return sdkerrors.Wrapf(ErrInvalid, "unknown type: %q", a.Permission)
}
func assertValidAddresses(addrs []string) error {
if len(addrs) == 0 {
return ErrEmpty
}
idx := make(map[string]struct{}, len(addrs))
for _, a := range addrs {
if _, err := sdk.AccAddressFromBech32(a); err != nil {
return sdkerrors.Wrapf(err, "address: %s", a)
}
if _, exists := idx[a]; exists {
return ErrDuplicate.Wrapf("address: %s", a)
}
idx[a] = struct{}{}
}
return nil
}
// Allowed returns if permission includes the actor.
// Actor address must be valid and not nil
func (a AccessConfig) Allowed(actor sdk.AccAddress) bool {
switch a.Permission {
case AccessTypeNobody:
@@ -171,6 +214,13 @@ func (a AccessConfig) Allowed(actor sdk.AccAddress) bool {
return true
case AccessTypeOnlyAddress:
return a.Address == actor.String()
case AccessTypeAnyOfAddresses:
for _, v := range a.Addresses {
if v == actor.String() {
return true
}
}
return false
default:
panic("unknown type")
}

View File

@@ -1,6 +1,7 @@
package types
import (
"bytes"
"encoding/json"
"testing"
@@ -14,6 +15,7 @@ import (
func TestValidateParams(t *testing.T) {
var (
anyAddress sdk.AccAddress = make([]byte, ContractAddrLen)
otherAddress sdk.AccAddress = bytes.Repeat([]byte{1}, ContractAddrLen)
invalidAddress = "invalid address"
)
@@ -42,6 +44,18 @@ func TestValidateParams(t *testing.T) {
InstantiateDefaultPermission: AccessTypeOnlyAddress,
},
},
"all good with anyOf address": {
src: Params{
CodeUploadAccess: AccessTypeAnyOfAddresses.With(anyAddress),
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
},
"all good with anyOf addresses": {
src: Params{
CodeUploadAccess: AccessTypeAnyOfAddresses.With(anyAddress, otherAddress),
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
},
"reject empty type in instantiate permission": {
src: Params{
CodeUploadAccess: AllowNobody,
@@ -62,6 +76,13 @@ func TestValidateParams(t *testing.T) {
},
expErr: true,
},
"reject wrong field addresses in only address": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeOnlyAddress, Address: anyAddress.String(), Addresses: []string{anyAddress.String()}},
InstantiateDefaultPermission: AccessTypeOnlyAddress,
},
expErr: true,
},
"reject CodeUploadAccess Everybody with obsolete address": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeEverybody, Address: anyAddress.String()},
@@ -89,6 +110,41 @@ func TestValidateParams(t *testing.T) {
},
expErr: true,
},
"reject empty addresses in any of addresses": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{}},
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
expErr: true,
},
"reject addresses not set in any of addresses": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeAnyOfAddresses},
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
expErr: true,
},
"reject invalid address in any of addresses": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{invalidAddress}},
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
expErr: true,
},
"reject duplicate address in any of addresses": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{anyAddress.String(), anyAddress.String()}},
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
expErr: true,
},
"reject wrong field address in any of addresses": {
src: Params{
CodeUploadAccess: AccessConfig{Permission: AccessTypeAnyOfAddresses, Address: anyAddress.String(), Addresses: []string{anyAddress.String()}},
InstantiateDefaultPermission: AccessTypeAnyOfAddresses,
},
expErr: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
@@ -107,11 +163,12 @@ func TestAccessTypeMarshalJson(t *testing.T) {
src AccessType
exp string
}{
"Unspecified": {src: AccessTypeUnspecified, exp: `"Unspecified"`},
"Nobody": {src: AccessTypeNobody, exp: `"Nobody"`},
"OnlyAddress": {src: AccessTypeOnlyAddress, exp: `"OnlyAddress"`},
"Everybody": {src: AccessTypeEverybody, exp: `"Everybody"`},
"unknown": {src: 999, exp: `"Unspecified"`},
"Unspecified": {src: AccessTypeUnspecified, exp: `"Unspecified"`},
"Nobody": {src: AccessTypeNobody, exp: `"Nobody"`},
"OnlyAddress": {src: AccessTypeOnlyAddress, exp: `"OnlyAddress"`},
"AccessTypeAnyOfAddresses": {src: AccessTypeAnyOfAddresses, exp: `"AnyOfAddresses"`},
"Everybody": {src: AccessTypeEverybody, exp: `"Everybody"`},
"unknown": {src: 999, exp: `"Unspecified"`},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
@@ -127,11 +184,12 @@ func TestAccessTypeUnmarshalJson(t *testing.T) {
src string
exp AccessType
}{
"Unspecified": {src: `"Unspecified"`, exp: AccessTypeUnspecified},
"Nobody": {src: `"Nobody"`, exp: AccessTypeNobody},
"OnlyAddress": {src: `"OnlyAddress"`, exp: AccessTypeOnlyAddress},
"Everybody": {src: `"Everybody"`, exp: AccessTypeEverybody},
"unknown": {src: `""`, exp: AccessTypeUnspecified},
"Unspecified": {src: `"Unspecified"`, exp: AccessTypeUnspecified},
"Nobody": {src: `"Nobody"`, exp: AccessTypeNobody},
"OnlyAddress": {src: `"OnlyAddress"`, exp: AccessTypeOnlyAddress},
"AnyOfAddresses": {src: `"AnyOfAddresses"`, exp: AccessTypeAnyOfAddresses},
"Everybody": {src: `"Everybody"`, exp: AccessTypeEverybody},
"unknown": {src: `""`, exp: AccessTypeUnspecified},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
@@ -166,3 +224,83 @@ func TestParamsUnmarshalJson(t *testing.T) {
})
}
}
func TestAccessTypeWith(t *testing.T) {
myAddress := sdk.AccAddress(randBytes(SDKAddrLen))
myOtherAddress := sdk.AccAddress(randBytes(SDKAddrLen))
specs := map[string]struct {
src AccessType
addrs []sdk.AccAddress
exp AccessConfig
expPanic bool
}{
"nobody": {
src: AccessTypeNobody,
exp: AccessConfig{Permission: AccessTypeNobody},
},
"nobody with address": {
src: AccessTypeNobody,
addrs: []sdk.AccAddress{myAddress},
exp: AccessConfig{Permission: AccessTypeNobody},
},
"everybody": {
src: AccessTypeEverybody,
exp: AccessConfig{Permission: AccessTypeEverybody},
},
"everybody with address": {
src: AccessTypeEverybody,
addrs: []sdk.AccAddress{myAddress},
exp: AccessConfig{Permission: AccessTypeEverybody},
},
"only address without address": {
src: AccessTypeOnlyAddress,
expPanic: true,
},
"only address with address": {
src: AccessTypeOnlyAddress,
addrs: []sdk.AccAddress{myAddress},
exp: AccessConfig{Permission: AccessTypeOnlyAddress, Address: myAddress.String()},
},
"only address with invalid address": {
src: AccessTypeOnlyAddress,
addrs: []sdk.AccAddress{nil},
expPanic: true,
},
"any of address without address": {
src: AccessTypeAnyOfAddresses,
expPanic: true,
},
"any of address with single address": {
src: AccessTypeAnyOfAddresses,
addrs: []sdk.AccAddress{myAddress},
exp: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{myAddress.String()}},
},
"any of address with multiple addresses": {
src: AccessTypeAnyOfAddresses,
addrs: []sdk.AccAddress{myAddress, myOtherAddress},
exp: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{myAddress.String(), myOtherAddress.String()}},
},
"any of address with duplicate addresses": {
src: AccessTypeAnyOfAddresses,
addrs: []sdk.AccAddress{myAddress, myAddress},
expPanic: true,
},
"any of address with invalid address": {
src: AccessTypeAnyOfAddresses,
addrs: []sdk.AccAddress{nil},
expPanic: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
if !spec.expPanic {
got := spec.src.With(spec.addrs...)
assert.Equal(t, spec.exp, got)
return
}
assert.Panics(t, func() {
spec.src.With(spec.addrs...)
})
})
}
}

View File

@@ -342,9 +342,9 @@ func (a AccessType) IsSubset(superSet AccessType) bool {
case AccessTypeNobody:
// Only an exact match is a subset of this
return a == AccessTypeNobody
case AccessTypeOnlyAddress:
// An exact match or nobody
return a == AccessTypeNobody || a == AccessTypeOnlyAddress
case AccessTypeOnlyAddress, AccessTypeAnyOfAddresses:
// Nobody or address(es)
return a == AccessTypeNobody || a == AccessTypeOnlyAddress || a == AccessTypeAnyOfAddresses
default:
return false
}
@@ -356,8 +356,32 @@ func (a AccessConfig) IsSubset(superSet AccessConfig) bool {
switch superSet.Permission {
case AccessTypeOnlyAddress:
// An exact match or nobody
return a.Permission == AccessTypeNobody || (a.Permission == AccessTypeOnlyAddress && a.Address == superSet.Address)
return a.Permission == AccessTypeNobody || (a.Permission == AccessTypeOnlyAddress && a.Address == superSet.Address) ||
(a.Permission == AccessTypeAnyOfAddresses && isSubset([]string{superSet.Address}, a.Addresses))
case AccessTypeAnyOfAddresses:
// An exact match or nobody
return a.Permission == AccessTypeNobody || (a.Permission == AccessTypeOnlyAddress && isSubset(superSet.Addresses, []string{a.Address})) ||
a.Permission == AccessTypeAnyOfAddresses && isSubset(superSet.Addresses, a.Addresses)
case AccessTypeUnspecified:
return false
default:
return a.Permission.IsSubset(superSet.Permission)
}
}
// return true when all elements in sub are also part of super
func isSubset(super, sub []string) bool {
if len(sub) == 0 {
return true
}
var matches int
for _, o := range sub {
for _, s := range super {
if o == s {
matches++
break
}
}
}
return matches == len(sub)
}

View File

@@ -39,10 +39,13 @@ const (
AccessTypeUnspecified AccessType = 0
// AccessTypeNobody forbidden
AccessTypeNobody AccessType = 1
// AccessTypeOnlyAddress restricted to an address
// AccessTypeOnlyAddress restricted to a single address
// Deprecated: use AccessTypeAnyOfAddresses instead
AccessTypeOnlyAddress AccessType = 2
// AccessTypeEverybody unrestricted
AccessTypeEverybody AccessType = 3
// AccessTypeAnyOfAddresses allow any of the addresses
AccessTypeAnyOfAddresses AccessType = 4
)
var AccessType_name = map[int32]string{
@@ -50,13 +53,15 @@ var AccessType_name = map[int32]string{
1: "ACCESS_TYPE_NOBODY",
2: "ACCESS_TYPE_ONLY_ADDRESS",
3: "ACCESS_TYPE_EVERYBODY",
4: "ACCESS_TYPE_ANY_OF_ADDRESSES",
}
var AccessType_value = map[string]int32{
"ACCESS_TYPE_UNSPECIFIED": 0,
"ACCESS_TYPE_NOBODY": 1,
"ACCESS_TYPE_ONLY_ADDRESS": 2,
"ACCESS_TYPE_EVERYBODY": 3,
"ACCESS_TYPE_UNSPECIFIED": 0,
"ACCESS_TYPE_NOBODY": 1,
"ACCESS_TYPE_ONLY_ADDRESS": 2,
"ACCESS_TYPE_EVERYBODY": 3,
"ACCESS_TYPE_ANY_OF_ADDRESSES": 4,
}
func (AccessType) EnumDescriptor() ([]byte, []int) {
@@ -145,7 +150,10 @@ var xxx_messageInfo_AccessTypeParam proto.InternalMessageInfo
// AccessConfig access control type.
type AccessConfig struct {
Permission AccessType `protobuf:"varint,1,opt,name=permission,proto3,enum=cosmwasm.wasm.v1.AccessType" json:"permission,omitempty" yaml:"permission"`
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty" yaml:"address"`
// Address
// Deprecated: replaced by addresses
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty" yaml:"address"`
Addresses []string `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty" yaml:"addresses"`
}
func (m *AccessConfig) Reset() { *m = AccessConfig{} }
@@ -493,78 +501,81 @@ func init() {
func init() { proto.RegisterFile("cosmwasm/wasm/v1/types.proto", fileDescriptor_e6155d98fa173e02) }
var fileDescriptor_e6155d98fa173e02 = []byte{
// 1123 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcd, 0x8f, 0xdb, 0x44,
0x14, 0x8f, 0x93, 0xec, 0xd7, 0x34, 0x14, 0x77, 0xd8, 0xa5, 0x49, 0xa8, 0x9c, 0xd4, 0x14, 0xd8,
0x7e, 0x25, 0x74, 0x41, 0x80, 0x7a, 0xa8, 0x94, 0x0f, 0xd3, 0xb8, 0x62, 0x93, 0x68, 0x92, 0x52,
0x2d, 0x52, 0x65, 0x39, 0xf6, 0x6c, 0x62, 0xd5, 0xf1, 0x44, 0x9e, 0xc9, 0x36, 0xfe, 0x0f, 0x50,
0x24, 0x04, 0x37, 0xb8, 0x44, 0x42, 0x80, 0x50, 0xff, 0x00, 0xae, 0xdc, 0x2b, 0x4e, 0x3d, 0x72,
0x8a, 0x20, 0xbd, 0xc0, 0x75, 0x8f, 0xe5, 0x82, 0x3c, 0x93, 0x10, 0xab, 0xdd, 0x76, 0xc3, 0xc5,
0xf2, 0xbc, 0xf7, 0x7e, 0xbf, 0xf7, 0xde, 0x6f, 0xde, 0xb3, 0x0c, 0x2e, 0x58, 0x84, 0xf6, 0x1f,
0x9a, 0xb4, 0x5f, 0xe4, 0x8f, 0xa3, 0x1b, 0x45, 0x16, 0x0c, 0x30, 0x2d, 0x0c, 0x7c, 0xc2, 0x08,
0x94, 0x17, 0xde, 0x02, 0x7f, 0x1c, 0xdd, 0xc8, 0x66, 0x42, 0x0b, 0xa1, 0x06, 0xf7, 0x17, 0xc5,
0x41, 0x04, 0x67, 0xb7, 0xbb, 0xa4, 0x4b, 0x84, 0x3d, 0x7c, 0x9b, 0x5b, 0x33, 0x5d, 0x42, 0xba,
0x2e, 0x2e, 0xf2, 0x53, 0x67, 0x78, 0x58, 0x34, 0xbd, 0x40, 0xb8, 0xd4, 0xfb, 0xe0, 0xf5, 0x92,
0x65, 0x61, 0x4a, 0xdb, 0xc1, 0x00, 0x37, 0x4d, 0xdf, 0xec, 0xc3, 0x2a, 0x58, 0x3b, 0x32, 0xdd,
0x21, 0x4e, 0x4b, 0x79, 0x69, 0xf7, 0xec, 0xde, 0x85, 0xc2, 0xf3, 0x05, 0x14, 0x96, 0x88, 0xb2,
0x7c, 0x3c, 0xcd, 0xa5, 0x02, 0xb3, 0xef, 0xde, 0x54, 0x39, 0x48, 0x45, 0x02, 0x7c, 0x33, 0xf9,
0xdd, 0xf7, 0x39, 0x49, 0xfd, 0x56, 0x02, 0x29, 0x11, 0x5d, 0x21, 0xde, 0xa1, 0xd3, 0x85, 0x2d,
0x00, 0x06, 0xd8, 0xef, 0x3b, 0x94, 0x3a, 0xc4, 0x5b, 0x29, 0xc3, 0xce, 0xf1, 0x34, 0x77, 0x4e,
0x64, 0x58, 0x22, 0x55, 0x14, 0xa1, 0x81, 0xd7, 0xc0, 0x86, 0x69, 0xdb, 0x3e, 0xa6, 0x34, 0x1d,
0xcf, 0x4b, 0xbb, 0x5b, 0x65, 0x78, 0x3c, 0xcd, 0x9d, 0x15, 0x98, 0xb9, 0x43, 0x45, 0x8b, 0x90,
0x79, 0x65, 0x5f, 0xc7, 0xc1, 0x3a, 0xef, 0x97, 0x42, 0x02, 0xa0, 0x45, 0x6c, 0x6c, 0x0c, 0x07,
0x2e, 0x31, 0x6d, 0xc3, 0xe4, 0xb9, 0x79, 0x6d, 0x67, 0xf6, 0x94, 0x97, 0xd5, 0x26, 0xfa, 0x29,
0x5f, 0x7c, 0x3c, 0xcd, 0xc5, 0x8e, 0xa7, 0xb9, 0x8c, 0xc8, 0xf6, 0x22, 0x8f, 0x8a, 0xe4, 0xd0,
0x78, 0x97, 0xdb, 0x04, 0x14, 0x7e, 0x25, 0x01, 0xc5, 0xf1, 0x28, 0x33, 0x3d, 0xe6, 0x98, 0x0c,
0x1b, 0x36, 0x3e, 0x34, 0x87, 0x2e, 0x33, 0x22, 0xca, 0xc4, 0x57, 0x50, 0xe6, 0xf2, 0xf1, 0x34,
0xf7, 0x8e, 0xc8, 0xfb, 0x6a, 0x36, 0x15, 0x5d, 0x88, 0x04, 0x54, 0x85, 0xbf, 0xf9, 0x9f, 0x9b,
0x2b, 0x12, 0x53, 0x7f, 0x90, 0xc0, 0x66, 0x85, 0xd8, 0x58, 0xf7, 0x0e, 0x09, 0x7c, 0x0b, 0x6c,
0xf1, 0x5e, 0x7a, 0x26, 0xed, 0x71, 0x29, 0x52, 0x68, 0x33, 0x34, 0xd4, 0x4c, 0xda, 0x83, 0x69,
0xb0, 0x61, 0xf9, 0xd8, 0x64, 0xc4, 0x17, 0x7a, 0xa3, 0xc5, 0x11, 0xb6, 0x00, 0x8c, 0x96, 0x62,
0x71, 0x91, 0xd2, 0x6b, 0x2b, 0x49, 0x99, 0x0c, 0xa5, 0x44, 0xe7, 0x22, 0x78, 0xe1, 0xb8, 0x93,
0xdc, 0x4c, 0xc8, 0xc9, 0x3b, 0xc9, 0xcd, 0xa4, 0xbc, 0xa6, 0xfe, 0x1a, 0x07, 0xa9, 0x0a, 0xf1,
0x98, 0x6f, 0x5a, 0x8c, 0x17, 0xfa, 0x36, 0xd8, 0xe0, 0x85, 0x3a, 0x36, 0x2f, 0x33, 0x59, 0x06,
0xb3, 0x69, 0x6e, 0x9d, 0xf7, 0x51, 0x45, 0xeb, 0xa1, 0x4b, 0xb7, 0x5f, 0x51, 0xf0, 0x36, 0x58,
0x33, 0xed, 0xbe, 0xe3, 0xa5, 0x13, 0xdc, 0x2e, 0x0e, 0xa1, 0xd5, 0x35, 0x3b, 0xd8, 0x4d, 0x27,
0x85, 0x95, 0x1f, 0xe0, 0xad, 0x39, 0x0b, 0xb6, 0xe7, 0x1d, 0x5d, 0x3a, 0xa1, 0xa3, 0x0e, 0x25,
0xee, 0x90, 0xe1, 0xf6, 0xa8, 0x49, 0xa8, 0xc3, 0x1c, 0xe2, 0xa1, 0x05, 0x08, 0x5e, 0x07, 0x67,
0x9c, 0x8e, 0x65, 0x0c, 0x88, 0xcf, 0xc2, 0x72, 0xd7, 0xf9, 0xa8, 0xbe, 0x36, 0x9b, 0xe6, 0xb6,
0xf4, 0x72, 0xa5, 0x49, 0x7c, 0xa6, 0x57, 0xd1, 0x96, 0xd3, 0xb1, 0xf8, 0xab, 0x0d, 0xf7, 0xc1,
0x16, 0x1e, 0x31, 0xec, 0xf1, 0x79, 0xd8, 0xe0, 0x09, 0xb7, 0x0b, 0x62, 0x93, 0x0b, 0x8b, 0x4d,
0x2e, 0x94, 0xbc, 0xa0, 0x9c, 0xf9, 0xed, 0x97, 0xeb, 0x3b, 0x51, 0x51, 0xb4, 0x05, 0x0c, 0x2d,
0x19, 0x6e, 0x26, 0xff, 0x0a, 0xc7, 0xfe, 0x1f, 0x09, 0xa4, 0x17, 0xa1, 0xa1, 0x48, 0x35, 0x87,
0x32, 0xe2, 0x07, 0x9a, 0xc7, 0xfc, 0x00, 0x36, 0xc1, 0x16, 0x19, 0x60, 0xdf, 0x64, 0xcb, 0xdd,
0xdc, 0x7b, 0xb1, 0xc5, 0x13, 0xe0, 0x8d, 0x05, 0x2a, 0x9c, 0x4b, 0xb4, 0x24, 0x89, 0xde, 0x4e,
0xfc, 0xa5, 0xb7, 0x73, 0x0b, 0x6c, 0x0c, 0x07, 0x36, 0xd7, 0x35, 0xf1, 0x7f, 0x74, 0x9d, 0x83,
0xe0, 0x2e, 0x48, 0xf4, 0x69, 0x97, 0xdf, 0x55, 0xaa, 0xfc, 0xe6, 0xb3, 0x69, 0x0e, 0x22, 0xf3,
0xe1, 0xa2, 0xca, 0x7d, 0x4c, 0xa9, 0xd9, 0xc5, 0x28, 0x0c, 0x51, 0x11, 0x80, 0x2f, 0x12, 0xc1,
0x8b, 0x20, 0xd5, 0x71, 0x89, 0xf5, 0xc0, 0xe8, 0x61, 0xa7, 0xdb, 0x63, 0x62, 0x8e, 0xd0, 0x19,
0x6e, 0xab, 0x71, 0x13, 0xcc, 0x80, 0x4d, 0x36, 0x32, 0x1c, 0xcf, 0xc6, 0x23, 0xd1, 0x08, 0xda,
0x60, 0x23, 0x3d, 0x3c, 0xaa, 0x0e, 0x58, 0xdb, 0x27, 0x36, 0x76, 0xe1, 0x1d, 0x90, 0x78, 0x80,
0x03, 0xb1, 0x2c, 0xe5, 0x4f, 0x9e, 0x4d, 0x73, 0x1f, 0x76, 0x1d, 0xd6, 0x1b, 0x76, 0x0a, 0x16,
0xe9, 0x17, 0x19, 0xf6, 0xec, 0x70, 0xe1, 0x3c, 0x16, 0x7d, 0x75, 0x9d, 0x0e, 0x2d, 0x76, 0x02,
0x86, 0x69, 0xa1, 0x86, 0x47, 0xe5, 0xf0, 0x05, 0x85, 0x24, 0xe1, 0x00, 0x8a, 0x6f, 0x70, 0x9c,
0xaf, 0x9e, 0x38, 0x5c, 0xf9, 0x5b, 0x02, 0x60, 0xb9, 0xff, 0xf0, 0x23, 0x70, 0xbe, 0x54, 0xa9,
0x68, 0xad, 0x96, 0xd1, 0x3e, 0x68, 0x6a, 0xc6, 0xdd, 0x7a, 0xab, 0xa9, 0x55, 0xf4, 0x4f, 0x75,
0xad, 0x2a, 0xc7, 0xb2, 0x99, 0xf1, 0x24, 0xbf, 0xb3, 0x0c, 0xbe, 0xeb, 0xd1, 0x01, 0xb6, 0x9c,
0x43, 0x07, 0xdb, 0xf0, 0x1a, 0x80, 0x51, 0x5c, 0xbd, 0x51, 0x6e, 0x54, 0x0f, 0x64, 0x29, 0xbb,
0x3d, 0x9e, 0xe4, 0xe5, 0x25, 0xa4, 0x4e, 0x3a, 0xc4, 0x0e, 0xe0, 0xc7, 0x20, 0x1d, 0x8d, 0x6e,
0xd4, 0x3f, 0x3b, 0x30, 0x4a, 0xd5, 0x2a, 0xd2, 0x5a, 0x2d, 0x39, 0xfe, 0x7c, 0x9a, 0x86, 0xe7,
0x06, 0x25, 0xf1, 0x9d, 0x85, 0x7b, 0x60, 0x27, 0x0a, 0xd4, 0x3e, 0xd7, 0xd0, 0x01, 0xcf, 0x94,
0xc8, 0x9e, 0x1f, 0x4f, 0xf2, 0x6f, 0x2c, 0x51, 0xda, 0x11, 0xf6, 0x83, 0x30, 0x59, 0x76, 0xf3,
0xcb, 0x1f, 0x95, 0xd8, 0xa3, 0x9f, 0x94, 0xd8, 0x95, 0x9f, 0x13, 0x20, 0x7f, 0xda, 0xa4, 0x41,
0x0c, 0xde, 0xaf, 0x34, 0xea, 0x6d, 0x54, 0xaa, 0xb4, 0x8d, 0x4a, 0xa3, 0xaa, 0x19, 0x35, 0xbd,
0xd5, 0x6e, 0xa0, 0x03, 0xa3, 0xd1, 0xd4, 0x50, 0xa9, 0xad, 0x37, 0xea, 0x27, 0x49, 0x53, 0x1c,
0x4f, 0xf2, 0x57, 0x4f, 0xe3, 0x8e, 0x0a, 0x76, 0x0f, 0x5c, 0x5e, 0x29, 0x8d, 0x5e, 0xd7, 0xdb,
0xb2, 0x94, 0xdd, 0x1d, 0x4f, 0xf2, 0x97, 0x4e, 0xe3, 0xd7, 0x3d, 0x87, 0xc1, 0xfb, 0xe0, 0xda,
0x4a, 0xc4, 0xfb, 0xfa, 0x6d, 0x54, 0x6a, 0x6b, 0x72, 0x3c, 0x7b, 0x75, 0x3c, 0xc9, 0xbf, 0x77,
0x1a, 0xf7, 0xbe, 0xd3, 0xf5, 0x4d, 0x86, 0x57, 0xa6, 0xbf, 0xad, 0xd5, 0xb5, 0x96, 0xde, 0x92,
0x13, 0xab, 0xd1, 0xdf, 0xc6, 0x1e, 0xa6, 0x0e, 0xcd, 0x26, 0xc3, 0xcb, 0x2a, 0xd7, 0x1e, 0xff,
0xa9, 0xc4, 0x1e, 0xcd, 0x14, 0xe9, 0xf1, 0x4c, 0x91, 0x9e, 0xcc, 0x14, 0xe9, 0x8f, 0x99, 0x22,
0x7d, 0xf3, 0x54, 0x89, 0x3d, 0x79, 0xaa, 0xc4, 0x7e, 0x7f, 0xaa, 0xc4, 0xbe, 0x78, 0x37, 0xb2,
0x07, 0x15, 0x42, 0xfb, 0xf7, 0x16, 0xbf, 0x3a, 0x76, 0x71, 0x24, 0x7e, 0x79, 0xf8, 0xff, 0x4e,
0x67, 0x9d, 0x7f, 0xd5, 0x3e, 0xf8, 0x37, 0x00, 0x00, 0xff, 0xff, 0x21, 0x8c, 0xa0, 0x70, 0x10,
0x09, 0x00, 0x00,
// 1178 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcf, 0x8f, 0xdb, 0xc4,
0x17, 0x8f, 0x93, 0xec, 0x8f, 0x4c, 0xf7, 0xdb, 0xaf, 0x3b, 0xec, 0xd2, 0x6c, 0x58, 0x25, 0xa9,
0x29, 0xb0, 0xfd, 0x95, 0xd0, 0x05, 0x01, 0xea, 0xa1, 0x52, 0x7e, 0xb8, 0x5d, 0x57, 0x6c, 0x1c,
0x4d, 0x52, 0xaa, 0x45, 0xaa, 0x2c, 0xc7, 0x9e, 0xcd, 0x5a, 0x75, 0x3c, 0x91, 0x67, 0xb2, 0x8d,
0xff, 0x03, 0x14, 0x09, 0xc1, 0x91, 0x4b, 0x24, 0x04, 0x08, 0x95, 0x3b, 0x57, 0xee, 0x15, 0x5c,
0x7a, 0xe4, 0x14, 0xc1, 0xf6, 0xc2, 0x39, 0xc7, 0x72, 0x41, 0x9e, 0x89, 0x1b, 0xd3, 0x6e, 0xbb,
0xe1, 0x62, 0xcd, 0xbc, 0xf7, 0x3e, 0x9f, 0xf7, 0xde, 0x67, 0xe6, 0x8d, 0x0c, 0xb6, 0x2c, 0x42,
0x7b, 0x0f, 0x4d, 0xda, 0x2b, 0xf3, 0xcf, 0xd1, 0xf5, 0x32, 0x0b, 0xfa, 0x98, 0x96, 0xfa, 0x3e,
0x61, 0x04, 0xca, 0x91, 0xb7, 0xc4, 0x3f, 0x47, 0xd7, 0x73, 0x9b, 0xa1, 0x85, 0x50, 0x83, 0xfb,
0xcb, 0x62, 0x23, 0x82, 0x73, 0xeb, 0x5d, 0xd2, 0x25, 0xc2, 0x1e, 0xae, 0x66, 0xd6, 0xcd, 0x2e,
0x21, 0x5d, 0x17, 0x97, 0xf9, 0xae, 0x33, 0x38, 0x28, 0x9b, 0x5e, 0x20, 0x5c, 0xca, 0x7d, 0xf0,
0xff, 0x8a, 0x65, 0x61, 0x4a, 0xdb, 0x41, 0x1f, 0x37, 0x4d, 0xdf, 0xec, 0xc1, 0x3a, 0x58, 0x3a,
0x32, 0xdd, 0x01, 0xce, 0x4a, 0x45, 0x69, 0xfb, 0xec, 0xce, 0x56, 0xe9, 0xc5, 0x02, 0x4a, 0x73,
0x44, 0x55, 0x9e, 0x4e, 0x0a, 0x6b, 0x81, 0xd9, 0x73, 0x6f, 0x28, 0x1c, 0xa4, 0x20, 0x01, 0xbe,
0x91, 0xfe, 0xe6, 0xdb, 0x82, 0xa4, 0xfc, 0x26, 0x81, 0x35, 0x11, 0x5d, 0x23, 0xde, 0x81, 0xd3,
0x85, 0x2d, 0x00, 0xfa, 0xd8, 0xef, 0x39, 0x94, 0x3a, 0xc4, 0x5b, 0x28, 0xc3, 0xc6, 0x74, 0x52,
0x38, 0x27, 0x32, 0xcc, 0x91, 0x0a, 0x8a, 0xd1, 0xc0, 0xab, 0x60, 0xc5, 0xb4, 0x6d, 0x1f, 0x53,
0x9a, 0x4d, 0x16, 0xa5, 0xed, 0x4c, 0x15, 0x4e, 0x27, 0x85, 0xb3, 0x02, 0x33, 0x73, 0x28, 0x28,
0x0a, 0x81, 0x3b, 0x20, 0x33, 0x5b, 0x62, 0x9a, 0x4d, 0x15, 0x53, 0xdb, 0x99, 0xea, 0xfa, 0x74,
0x52, 0x90, 0xff, 0x15, 0x8f, 0xa9, 0x82, 0xe6, 0x61, 0xb3, 0x6e, 0xbe, 0x4a, 0x82, 0x65, 0xae,
0x11, 0x85, 0x04, 0x40, 0x8b, 0xd8, 0xd8, 0x18, 0xf4, 0x5d, 0x62, 0xda, 0x86, 0xc9, 0xeb, 0xe5,
0xfd, 0x9c, 0xd9, 0xc9, 0xbf, 0xaa, 0x1f, 0xa1, 0x41, 0xf5, 0xc2, 0xe3, 0x49, 0x21, 0x31, 0x9d,
0x14, 0x36, 0x45, 0xc6, 0x97, 0x79, 0x14, 0x24, 0x87, 0xc6, 0xbb, 0xdc, 0x26, 0xa0, 0xf0, 0x4b,
0x09, 0xe4, 0x1d, 0x8f, 0x32, 0xd3, 0x63, 0x8e, 0xc9, 0xb0, 0x61, 0xe3, 0x03, 0x73, 0xe0, 0x32,
0x23, 0xa6, 0x66, 0x72, 0x01, 0x35, 0x2f, 0x4d, 0x27, 0x85, 0x77, 0x44, 0xde, 0xd7, 0xb3, 0x29,
0x68, 0x2b, 0x16, 0x50, 0x17, 0xfe, 0xe6, 0x73, 0x37, 0x57, 0x24, 0xa1, 0x7c, 0x27, 0x81, 0xd5,
0x1a, 0xb1, 0xb1, 0xe6, 0x1d, 0x10, 0xf8, 0x16, 0xc8, 0xf0, 0x5e, 0x0e, 0x4d, 0x7a, 0xc8, 0xa5,
0x58, 0x43, 0xab, 0xa1, 0x61, 0xd7, 0xa4, 0x87, 0x30, 0x0b, 0x56, 0x2c, 0x1f, 0x9b, 0x8c, 0xf8,
0xe2, 0x8c, 0x50, 0xb4, 0x85, 0x2d, 0x00, 0xe3, 0xa5, 0x58, 0x5c, 0xa4, 0xec, 0xd2, 0x42, 0x52,
0xa6, 0x43, 0x29, 0xd1, 0xb9, 0x18, 0x5e, 0x38, 0xee, 0xa4, 0x57, 0x53, 0x72, 0xfa, 0x4e, 0x7a,
0x35, 0x2d, 0x2f, 0x29, 0xbf, 0x24, 0xc1, 0x5a, 0x8d, 0x78, 0xcc, 0x37, 0x2d, 0xc6, 0x0b, 0x7d,
0x1b, 0xac, 0xf0, 0x42, 0x1d, 0x9b, 0x97, 0x99, 0xae, 0x82, 0xe3, 0x49, 0x61, 0x99, 0xf7, 0x51,
0x47, 0xcb, 0xa1, 0x4b, 0xb3, 0x5f, 0x53, 0xf0, 0x3a, 0x58, 0x32, 0xed, 0x9e, 0xe3, 0x65, 0x53,
0xdc, 0x2e, 0x36, 0xa1, 0xd5, 0x35, 0x3b, 0xd8, 0xcd, 0xa6, 0x85, 0x95, 0x6f, 0xe0, 0xcd, 0x19,
0x0b, 0xb6, 0x67, 0x1d, 0x5d, 0x3c, 0xa1, 0xa3, 0x0e, 0x25, 0xee, 0x80, 0xe1, 0xf6, 0xb0, 0x49,
0xa8, 0xc3, 0x1c, 0xe2, 0xa1, 0x08, 0x04, 0xaf, 0x81, 0x33, 0x4e, 0xc7, 0x32, 0xfa, 0xc4, 0x67,
0x61, 0xb9, 0xcb, 0xfc, 0x7a, 0xff, 0xef, 0x78, 0x52, 0xc8, 0x68, 0xd5, 0x5a, 0x93, 0xf8, 0x4c,
0xab, 0xa3, 0x8c, 0xd3, 0xb1, 0xf8, 0xd2, 0x86, 0x7b, 0x20, 0x83, 0x87, 0x0c, 0x7b, 0xfc, 0x3e,
0xac, 0xf0, 0x84, 0xeb, 0x25, 0x31, 0xfd, 0xa5, 0x68, 0xfa, 0x4b, 0x15, 0x2f, 0xa8, 0x6e, 0xfe,
0xfa, 0xf3, 0xb5, 0x8d, 0xb8, 0x28, 0x6a, 0x04, 0x43, 0x73, 0x86, 0x1b, 0xe9, 0xbf, 0xc2, 0x6b,
0xff, 0xb7, 0x04, 0xb2, 0x51, 0x68, 0x28, 0xd2, 0xae, 0x43, 0x19, 0xf1, 0x03, 0xd5, 0x63, 0x7e,
0x00, 0x9b, 0x20, 0x43, 0xfa, 0xd8, 0x37, 0xd9, 0x7c, 0x9e, 0x77, 0x5e, 0x6e, 0xf1, 0x04, 0xb8,
0x1e, 0xa1, 0xc2, 0x7b, 0x89, 0xe6, 0x24, 0xf1, 0xd3, 0x49, 0xbe, 0xf2, 0x74, 0x6e, 0x82, 0x95,
0x41, 0xdf, 0xe6, 0xba, 0xa6, 0xfe, 0x8b, 0xae, 0x33, 0x10, 0xdc, 0x06, 0xa9, 0x1e, 0xed, 0xf2,
0xb3, 0x5a, 0xab, 0xbe, 0xf9, 0x6c, 0x52, 0x80, 0xc8, 0x7c, 0x18, 0x55, 0xb9, 0x87, 0x29, 0x35,
0xbb, 0x18, 0x85, 0x21, 0x0a, 0x02, 0xf0, 0x65, 0x22, 0x78, 0x01, 0xac, 0x75, 0x5c, 0x62, 0x3d,
0x30, 0x0e, 0xb1, 0xd3, 0x3d, 0x64, 0xe2, 0x1e, 0xa1, 0x33, 0xdc, 0xb6, 0xcb, 0x4d, 0x70, 0x13,
0xac, 0xb2, 0xa1, 0xe1, 0x78, 0x36, 0x1e, 0x8a, 0x46, 0xd0, 0x0a, 0x1b, 0x6a, 0xe1, 0x56, 0x71,
0xc0, 0xd2, 0x1e, 0xb1, 0xb1, 0x0b, 0xef, 0x80, 0xd4, 0x03, 0x1c, 0x88, 0x61, 0xa9, 0x7e, 0xf2,
0x6c, 0x52, 0xf8, 0xb0, 0xeb, 0xb0, 0xc3, 0x41, 0xa7, 0x64, 0x91, 0x5e, 0x99, 0x61, 0xcf, 0x0e,
0x07, 0xce, 0x63, 0xf1, 0xa5, 0xeb, 0x74, 0x68, 0xb9, 0x13, 0x30, 0x4c, 0x4b, 0xbb, 0x78, 0x58,
0x0d, 0x17, 0x28, 0x24, 0x09, 0x2f, 0xa0, 0x78, 0xb7, 0x93, 0x7c, 0xf4, 0xc4, 0xe6, 0xf2, 0x4f,
0x49, 0x00, 0xe6, 0xf3, 0x0f, 0x3f, 0x02, 0xe7, 0x2b, 0xb5, 0x9a, 0xda, 0x6a, 0x19, 0xed, 0xfd,
0xa6, 0x6a, 0xdc, 0x6d, 0xb4, 0x9a, 0x6a, 0x4d, 0xbb, 0xa5, 0xa9, 0x75, 0x39, 0x91, 0xdb, 0x1c,
0x8d, 0x8b, 0x1b, 0xf3, 0xe0, 0xbb, 0x1e, 0xed, 0x63, 0xcb, 0x39, 0x70, 0xb0, 0x0d, 0xaf, 0x02,
0x18, 0xc7, 0x35, 0xf4, 0xaa, 0x5e, 0xdf, 0x97, 0xa5, 0xdc, 0xfa, 0x68, 0x5c, 0x94, 0xe7, 0x90,
0x06, 0xe9, 0x10, 0x3b, 0x80, 0x1f, 0x83, 0x6c, 0x3c, 0x5a, 0x6f, 0x7c, 0xba, 0x6f, 0x54, 0xea,
0x75, 0xa4, 0xb6, 0x5a, 0x72, 0xf2, 0xc5, 0x34, 0xba, 0xe7, 0x06, 0x95, 0xe7, 0x6f, 0xf3, 0x46,
0x1c, 0xa8, 0x7e, 0xa6, 0xa2, 0x7d, 0x9e, 0x29, 0x95, 0x3b, 0x3f, 0x1a, 0x17, 0xdf, 0x98, 0xa3,
0xd4, 0x23, 0xec, 0x07, 0x3c, 0xd9, 0x4d, 0xb0, 0x15, 0xc7, 0x54, 0x1a, 0xfb, 0x86, 0x7e, 0x2b,
0x4a, 0xa7, 0xb6, 0xe4, 0x74, 0x6e, 0x6b, 0x34, 0x2e, 0x66, 0xe7, 0xd0, 0x8a, 0x17, 0xe8, 0x07,
0x95, 0xe8, 0x6d, 0xcf, 0xad, 0x7e, 0xf1, 0x7d, 0x3e, 0xf1, 0xe8, 0x87, 0x7c, 0xe2, 0xf2, 0x8f,
0x29, 0x50, 0x3c, 0xed, 0xa6, 0x42, 0x0c, 0xde, 0xaf, 0xe9, 0x8d, 0x36, 0xaa, 0xd4, 0xda, 0x46,
0x4d, 0xaf, 0xab, 0xc6, 0xae, 0xd6, 0x6a, 0xeb, 0x68, 0xdf, 0xd0, 0x9b, 0x2a, 0xaa, 0xb4, 0x35,
0xbd, 0x71, 0x92, 0xb4, 0xe5, 0xd1, 0xb8, 0x78, 0xe5, 0x34, 0xee, 0xb8, 0xe0, 0xf7, 0xc0, 0xa5,
0x85, 0xd2, 0x68, 0x0d, 0xad, 0x2d, 0x4b, 0xb9, 0xed, 0xd1, 0xb8, 0x78, 0xf1, 0x34, 0x7e, 0xcd,
0x73, 0x18, 0xbc, 0x0f, 0xae, 0x2e, 0x44, 0xbc, 0xa7, 0xdd, 0x46, 0x95, 0xb6, 0x2a, 0x27, 0x73,
0x57, 0x46, 0xe3, 0xe2, 0x7b, 0xa7, 0x71, 0xef, 0x39, 0x5d, 0xdf, 0x64, 0x78, 0x61, 0xfa, 0xdb,
0x6a, 0x43, 0x6d, 0x69, 0x2d, 0x39, 0xb5, 0x18, 0xfd, 0x6d, 0xec, 0x61, 0xea, 0xd0, 0x5c, 0x3a,
0x3c, 0xac, 0xea, 0xee, 0xe3, 0x3f, 0xf3, 0x89, 0x47, 0xc7, 0x79, 0xe9, 0xf1, 0x71, 0x5e, 0x7a,
0x72, 0x9c, 0x97, 0xfe, 0x38, 0xce, 0x4b, 0x5f, 0x3f, 0xcd, 0x27, 0x9e, 0x3c, 0xcd, 0x27, 0x7e,
0x7f, 0x9a, 0x4f, 0x7c, 0xfe, 0x6e, 0x6c, 0x8e, 0x6a, 0x84, 0xf6, 0xee, 0x45, 0xbf, 0x57, 0x76,
0x79, 0x28, 0x7e, 0xb3, 0xf8, 0x3f, 0x56, 0x67, 0x99, 0xbf, 0x8a, 0x1f, 0xfc, 0x13, 0x00, 0x00,
0xff, 0xff, 0x7a, 0x16, 0x8c, 0xd9, 0x84, 0x09, 0x00, 0x00,
}
func (this *AccessTypeParam) Equal(that interface{}) bool {
@@ -617,6 +628,14 @@ func (this *AccessConfig) Equal(that interface{}) bool {
if this.Address != that1.Address {
return false
}
if len(this.Addresses) != len(that1.Addresses) {
return false
}
for i := range this.Addresses {
if this.Addresses[i] != that1.Addresses[i] {
return false
}
}
return true
}
@@ -860,6 +879,15 @@ func (m *AccessConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Addresses) > 0 {
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Addresses[iNdEx])
copy(dAtA[i:], m.Addresses[iNdEx])
i = encodeVarintTypes(dAtA, i, uint64(len(m.Addresses[iNdEx])))
i--
dAtA[i] = 0x1a
}
}
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
@@ -1199,6 +1227,12 @@ func (m *AccessConfig) Size() (n int) {
if l > 0 {
n += 1 + l + sovTypes(uint64(l))
}
if len(m.Addresses) > 0 {
for _, s := range m.Addresses {
l = len(s)
n += 1 + l + sovTypes(uint64(l))
}
}
return n
}
@@ -1484,6 +1518,38 @@ func (m *AccessConfig) Unmarshal(dAtA []byte) error {
}
m.Address = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthTypes
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthTypes
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTypes(dAtA[iNdEx:])

View File

@@ -374,52 +374,42 @@ func TestVerifyAddressLen(t *testing.T) {
}
func TestAccessConfigSubset(t *testing.T) {
// read
// <, <= is subset of
// !< is not subset of
specs := map[string]struct {
check AccessConfig
superSet AccessConfig
isSubSet bool
}{
// nobody
"nobody <= nobody": {
superSet: AccessConfig{Permission: AccessTypeNobody},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: true,
},
"only > nobody": {
"only !< nobody": {
superSet: AccessConfig{Permission: AccessTypeNobody},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "foobar"},
isSubSet: false,
},
"everybody > nobody": {
"anyOf !< nobody": {
superSet: AccessConfig{Permission: AccessTypeNobody},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"foobar"}},
isSubSet: false,
},
"everybody !< nobody ": {
superSet: AccessConfig{Permission: AccessTypeNobody},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: false,
},
"unspecified > nobody": {
"unspecified !< nobody": {
superSet: AccessConfig{Permission: AccessTypeNobody},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
"nobody <= everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: true,
},
"only <= everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "foobar"},
isSubSet: true,
},
"everybody <= everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: true,
},
"unspecified > everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
"nobody <= only": {
// only
"nobody < only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: true,
@@ -429,23 +419,141 @@ func TestAccessConfigSubset(t *testing.T) {
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
isSubSet: true,
},
"only > only(other)": {
"only !< only(other)": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "other"},
isSubSet: false,
},
"everybody > only": {
"anyOf(same) <= only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
isSubSet: true,
},
"anyOf(other) !< only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"foobar"}},
isSubSet: false,
},
"anyOf(same, other) !< only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "foobar"}},
isSubSet: false,
},
"everybody !< only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: false,
},
"nobody > unspecified": {
"unspecified !<= only": {
superSet: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
// any of
"nobody < anyOf": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: true,
},
"only(same) < anyOf(same)": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
isSubSet: true,
},
"only(same) < anyOf(same, other)": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other"}},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "owner"},
isSubSet: true,
},
"only(other) !< anyOf": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "other"},
isSubSet: false,
},
"anyOf < anyOf": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
isSubSet: true,
},
"anyOf(multiple) < anyOf(multiple)": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other"}},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other"}},
isSubSet: true,
},
"anyOf(multiple, other) !< anyOf(multiple)": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other", "foo"}},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other", "bar"}},
isSubSet: false,
},
"anyOf(multiple) !< anyOf": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner", "other"}},
isSubSet: false,
},
"everybody !< anyOf": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: false,
},
"unspecified !< anyOf ": {
superSet: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"owner"}},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
// everybody
"nobody < everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: true,
},
"only < everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "foobar"},
isSubSet: true,
},
"anyOf < everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"foobar"}},
isSubSet: true,
},
"everybody <= everybody": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: true,
},
"unspecified !< everybody ": {
superSet: AccessConfig{Permission: AccessTypeEverybody},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
// unspecified
"nobody !< unspecified": {
superSet: AccessConfig{Permission: AccessTypeUnspecified},
check: AccessConfig{Permission: AccessTypeNobody},
isSubSet: false,
},
"only !< unspecified": {
superSet: AccessConfig{Permission: AccessTypeUnspecified},
check: AccessConfig{Permission: AccessTypeOnlyAddress, Address: "foobar"},
isSubSet: false,
},
"anyOf !< unspecified": {
superSet: AccessConfig{Permission: AccessTypeUnspecified},
check: AccessConfig{Permission: AccessTypeAnyOfAddresses, Addresses: []string{"foobar"}},
isSubSet: false,
},
"everybody !< unspecified": {
superSet: AccessConfig{Permission: AccessTypeUnspecified},
check: AccessConfig{Permission: AccessTypeEverybody},
isSubSet: false,
},
"unspecified !< unspecified ": {
superSet: AccessConfig{Permission: AccessTypeUnspecified},
check: AccessConfig{Permission: AccessTypeUnspecified},
isSubSet: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
subset := spec.check.IsSubset(spec.superSet)
@@ -460,64 +568,134 @@ func TestAccessTypeSubset(t *testing.T) {
superSet AccessType
isSubSet bool
}{
// nobody
"nobody <= nobody": {
superSet: AccessTypeNobody,
check: AccessTypeNobody,
isSubSet: true,
},
"only > nobody": {
"only !< nobody": {
superSet: AccessTypeNobody,
check: AccessTypeOnlyAddress,
isSubSet: false,
},
"everybody > nobody": {
"any !< nobody": {
superSet: AccessTypeNobody,
check: AccessTypeAnyOfAddresses,
isSubSet: false,
},
"everybody !< nobody": {
superSet: AccessTypeNobody,
check: AccessTypeEverybody,
isSubSet: false,
},
"unspecified > nobody": {
"unspecified !< nobody": {
superSet: AccessTypeNobody,
check: AccessTypeUnspecified,
isSubSet: false,
},
"nobody <= everybody": {
// only
"nobody < only": {
superSet: AccessTypeOnlyAddress,
check: AccessTypeNobody,
isSubSet: true,
},
"only <= only": {
superSet: AccessTypeOnlyAddress,
check: AccessTypeOnlyAddress,
isSubSet: true,
},
"anyOf !< only": {
superSet: AccessTypeOnlyAddress,
check: AccessTypeAnyOfAddresses,
isSubSet: true,
},
"everybody !< only": {
superSet: AccessTypeOnlyAddress,
check: AccessTypeEverybody,
isSubSet: false,
},
"unspecified !< only": {
superSet: AccessTypeOnlyAddress,
check: AccessTypeUnspecified,
isSubSet: false,
},
// any of
"nobody < anyOf": {
superSet: AccessTypeAnyOfAddresses,
check: AccessTypeNobody,
isSubSet: true,
},
"only <= anyOf": {
superSet: AccessTypeAnyOfAddresses,
check: AccessTypeOnlyAddress,
isSubSet: true,
},
"anyOf <= anyOf": {
superSet: AccessTypeAnyOfAddresses,
check: AccessTypeAnyOfAddresses,
isSubSet: true,
},
"everybody !< anyOf": {
superSet: AccessTypeAnyOfAddresses,
check: AccessTypeEverybody,
isSubSet: false,
},
"unspecified !< anyOf": {
superSet: AccessTypeAnyOfAddresses,
check: AccessTypeUnspecified,
isSubSet: false,
},
// everybody
"nobody < everybody": {
superSet: AccessTypeEverybody,
check: AccessTypeNobody,
isSubSet: true,
},
"only <= everybody": {
"only < everybody": {
superSet: AccessTypeEverybody,
check: AccessTypeOnlyAddress,
isSubSet: true,
},
"anyOf < everybody": {
superSet: AccessTypeEverybody,
check: AccessTypeAnyOfAddresses,
isSubSet: true,
},
"everybody <= everybody": {
superSet: AccessTypeEverybody,
check: AccessTypeEverybody,
isSubSet: true,
},
"unspecified > everybody": {
"unspecified !< everybody": {
superSet: AccessTypeEverybody,
check: AccessTypeUnspecified,
isSubSet: false,
},
"nobody <= only": {
superSet: AccessTypeOnlyAddress,
// unspecified
"nobody !< unspecified": {
superSet: AccessTypeUnspecified,
check: AccessTypeNobody,
isSubSet: true,
isSubSet: false,
},
"only <= only(same)": {
superSet: AccessTypeOnlyAddress,
"only !< unspecified": {
superSet: AccessTypeUnspecified,
check: AccessTypeOnlyAddress,
isSubSet: true,
isSubSet: false,
},
"everybody > only": {
superSet: AccessTypeOnlyAddress,
"anyOf !< unspecified": {
superSet: AccessTypeUnspecified,
check: AccessTypeAnyOfAddresses,
isSubSet: false,
},
"everybody !< unspecified": {
superSet: AccessTypeUnspecified,
check: AccessTypeEverybody,
isSubSet: false,
},
"nobody > unspecified": {
"unspecified !< unspecified": {
superSet: AccessTypeUnspecified,
check: AccessTypeNobody,
check: AccessTypeUnspecified,
isSubSet: false,
},
}