Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into extend-upgrade-command
Browse files Browse the repository at this point in the history
  • Loading branch information
dsurnin committed Aug 1, 2018
2 parents 977d296 + ab947de commit f4b6095
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 41 deletions.
36 changes: 36 additions & 0 deletions indy_client/test/cli/test_send_claim_def_permission_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json
import pytest

from indy_common.auth import Authoriser
from plenum.test.helper import sdk_sign_request_from_dict, sdk_send_and_check

from indy_node.test.anon_creds.conftest import claim_def


@pytest.fixture(scope="module")
def tconf(tconf):
# We need to reset authorization map to set new authorization rules
Authoriser.auth_map = None
OLD_WRITES_REQUIRE_TRUST_ANCHOR = tconf.WRITES_REQUIRE_TRUST_ANCHOR
tconf.WRITES_REQUIRE_TRUST_ANCHOR = False

yield tconf

tconf.WRITES_REQUIRE_TRUST_ANCHOR = OLD_WRITES_REQUIRE_TRUST_ANCHOR
Authoriser.auth_map = None


def test_client_can_send_claim_def(looper,
txnPoolNodeSet,
sdk_wallet_client,
sdk_wallet_trust_anchor,
sdk_pool_handle,
claim_def,
tconf):
# Trust anchor can create claim_def in any case
req = sdk_sign_request_from_dict(looper, sdk_wallet_trust_anchor, claim_def)
sdk_send_and_check([json.dumps(req)], looper, txnPoolNodeSet, sdk_pool_handle)

# Client can create claim_def if WRITES_REQUIRE_TRUST_ANCHOR flag set to False
req = sdk_sign_request_from_dict(looper, sdk_wallet_client, claim_def)
sdk_send_and_check([json.dumps(req)], looper, txnPoolNodeSet, sdk_pool_handle)
39 changes: 39 additions & 0 deletions indy_client/test/cli/test_send_claim_def_permission_no_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json
import pytest

from indy_common.auth import Authoriser
from plenum.common.exceptions import RequestRejectedException
from plenum.test.helper import sdk_sign_request_from_dict, sdk_send_and_check, sdk_send_signed_requests, \
sdk_get_bad_response

from indy_node.test.anon_creds.conftest import claim_def


@pytest.fixture(scope="module")
def tconf(tconf):
# We need to reset authorization map to set new authorization rules
Authoriser.auth_map = None
OLD_WRITES_REQUIRE_TRUST_ANCHOR = tconf.WRITES_REQUIRE_TRUST_ANCHOR
tconf.WRITES_REQUIRE_TRUST_ANCHOR = True

yield tconf

tconf.WRITES_REQUIRE_TRUST_ANCHOR = OLD_WRITES_REQUIRE_TRUST_ANCHOR
Authoriser.auth_map = None


def test_client_cant_send_claim_def(looper,
txnPoolNodeSet,
sdk_wallet_client,
sdk_wallet_trust_anchor,
sdk_pool_handle,
claim_def,
tconf):
# Trust anchor can create claim_def in any case
req = sdk_sign_request_from_dict(looper, sdk_wallet_trust_anchor, claim_def)
sdk_send_and_check([json.dumps(req)], looper, txnPoolNodeSet, sdk_pool_handle)

# Client cant send create if WRITES_REQUIRE_TRUST_ANCHOR flag set to True
req = sdk_sign_request_from_dict(looper, sdk_wallet_client, claim_def)
req = sdk_send_signed_requests(sdk_pool_handle, [json.dumps(req)])
sdk_get_bad_response(looper, req, RequestRejectedException, 'None role cannot add claim def')
42 changes: 42 additions & 0 deletions indy_client/test/cli/test_send_schema_permission_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import json

import pytest
from indy.anoncreds import issuer_create_schema
from indy.ledger import build_schema_request

from indy_common.auth import Authoriser
from plenum.test.helper import sdk_get_and_check_replies, sdk_sign_and_submit_req


@pytest.fixture(scope="module")
def tconf(tconf):
# We need to reset authorization map to set new authorization rules
Authoriser.auth_map = None
OLD_WRITES_REQUIRE_TRUST_ANCHOR = tconf.WRITES_REQUIRE_TRUST_ANCHOR
tconf.WRITES_REQUIRE_TRUST_ANCHOR = False

yield tconf

tconf.WRITES_REQUIRE_TRUST_ANCHOR = OLD_WRITES_REQUIRE_TRUST_ANCHOR
Authoriser.auth_map = None


def test_client_can_send_schema(looper,
txnPoolNodeSet,
sdk_wallet_client,
sdk_wallet_trust_anchor,
sdk_pool_handle,
tconf):
# Trust anchor can create schema in any case
_, identifier = sdk_wallet_trust_anchor
_, schema_json = looper.loop.run_until_complete(
issuer_create_schema(identifier, "name", "1.0", json.dumps(["first", "last"])))
request = looper.loop.run_until_complete(build_schema_request(identifier, schema_json))
sdk_get_and_check_replies(looper, [sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_trust_anchor, request)])

# Client can create schema if WRITES_REQUIRE_TRUST_ANCHOR flag set to False
_, identifier = sdk_wallet_client
_, schema_json = looper.loop.run_until_complete(
issuer_create_schema(identifier, "name", "1.0", json.dumps(["first", "last"])))
request = looper.loop.run_until_complete(build_schema_request(identifier, schema_json))
sdk_get_and_check_replies(looper, [sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_client, request)])
45 changes: 45 additions & 0 deletions indy_client/test/cli/test_send_schema_permission_no_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import json

import pytest
from indy.anoncreds import issuer_create_schema
from indy.ledger import build_schema_request

from indy_common.auth import Authoriser
from plenum.common.exceptions import RequestRejectedException

from plenum.test.helper import sdk_get_bad_response, sdk_sign_and_submit_req, sdk_get_and_check_replies


@pytest.fixture(scope="module")
def tconf(tconf):
# We need to reset authorization map to set new authorization rules
Authoriser.auth_map = None
OLD_WRITES_REQUIRE_TRUST_ANCHOR = tconf.WRITES_REQUIRE_TRUST_ANCHOR
tconf.WRITES_REQUIRE_TRUST_ANCHOR = True

yield tconf

tconf.WRITES_REQUIRE_TRUST_ANCHOR = OLD_WRITES_REQUIRE_TRUST_ANCHOR
Authoriser.auth_map = None


def test_client_cant_send_schema(looper,
txnPoolNodeSet,
sdk_wallet_client,
sdk_wallet_trust_anchor,
sdk_pool_handle,
tconf):
# Trust anchor can create schema in any case
_, identifier = sdk_wallet_trust_anchor
_, schema_json = looper.loop.run_until_complete(
issuer_create_schema(identifier, "another_name", "2.0", json.dumps(["first", "last"])))
request = looper.loop.run_until_complete(build_schema_request(identifier, schema_json))
sdk_get_and_check_replies(looper, [sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_trust_anchor, request)])

# Client cant create schema if WRITES_REQUIRE_TRUST_ANCHOR flag set to True
_, identifier = sdk_wallet_client
_, schema_json = looper.loop.run_until_complete(
issuer_create_schema(identifier, "another_name", "2.0", json.dumps(["first", "last"])))
request = looper.loop.run_until_complete(build_schema_request(identifier, schema_json))
sdk_get_bad_response(looper, [sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_client, request)],
RequestRejectedException, 'None role cannot add schema')
31 changes: 21 additions & 10 deletions indy_common/auth.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from indy_common.config_util import getConfig
from plenum.common.constants import TRUSTEE, STEWARD, NODE
from stp_core.common.log import getlogger

Expand All @@ -12,10 +13,8 @@
# TODO: make this class the only point of authorization and checking permissions!
# There are some duplicates of this logic in *_req_handler classes

class Authoriser:
ValidRoles = (TRUSTEE, TGB, STEWARD, TRUST_ANCHOR, None)

AuthMap = {
def generate_auth_map(valid_roles, need_permission=None):
auth_map = {
'{}_role__{}'.format(NYM, TRUSTEE):
{TRUSTEE: []},
'{}_role__{}'.format(NYM, TGB):
Expand All @@ -39,7 +38,7 @@ class Authoriser:
'{}_<any>_<any>_<any>'.format(CLAIM_DEF):
{TRUSTEE: [OWNER, ], STEWARD: [OWNER, ], TRUST_ANCHOR: [OWNER, ]},
'{}_verkey_<any>_<any>'.format(NYM):
{r: [OWNER] for r in ValidRoles},
{r: [OWNER] for r in valid_roles},
'{}_services__[VALIDATOR]'.format(NODE):
{STEWARD: [OWNER, ]},
# INDY-410 - steward allowed to demote/promote its validator
Expand Down Expand Up @@ -68,6 +67,16 @@ class Authoriser:
'{}_<any>_<any>_<any>'.format(VALIDATOR_INFO):
{TRUSTEE: [], STEWARD: []},
}
if need_permission is False or (need_permission is None and not getConfig().WRITES_REQUIRE_TRUST_ANCHOR):
auth_map['{}_<any>_<any>_<any>'.format(SCHEMA)][None] = []
auth_map['{}_<any>_<any>_<any>'.format(CLAIM_DEF)][None] = [OWNER]
return auth_map


class Authoriser:
ValidRoles = (TRUSTEE, TGB, STEWARD, TRUST_ANCHOR, None)

auth_map = None

@staticmethod
def isValidRole(role) -> bool:
Expand All @@ -94,28 +103,30 @@ def isValidRoleName(roleName) -> bool:
@staticmethod
def authorised(typ, actorRole, field=None, oldVal=None, newVal=None,
isActorOwnerOfSubject=None) -> (bool, str):
if not Authoriser.auth_map:
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles)
field = field if field is not None else ""
oldVal = '' if oldVal is None else \
str(oldVal).replace('"', '').replace("'", '')
newVal = '' if newVal is None else \
str(newVal).replace('"', '').replace("'", '')
key = '_'.join([typ, field, oldVal, newVal])
if key not in Authoriser.AuthMap:
if key not in Authoriser.auth_map:
any_value = '_'.join([typ, field, '<any>', '<any>'])
if any_value not in Authoriser.AuthMap:
if any_value not in Authoriser.auth_map:
any_field = '_'.join([typ, "<any>", '<any>', '<any>'])
if any_field not in Authoriser.AuthMap:
if any_field not in Authoriser.auth_map:
msg = "key '{}' not found in authorized map".format(key)
logger.debug(msg)
return False, msg
else:
key = any_field
else:
key = any_value
roles = Authoriser.AuthMap[key]
roles = Authoriser.auth_map[key]
if actorRole not in roles:
roles_as_str = [Roles.nameFromValue(role) for role in roles.keys()]
return False, '{} not in allowed roles {}'.\
return False, '{} not in allowed roles {}'. \
format(Roles.nameFromValue(actorRole), roles_as_str)
roleDetails = roles[actorRole]
if len(roleDetails) == 0:
Expand Down
2 changes: 2 additions & 0 deletions indy_common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,5 @@

# Top level packet to be updated via pool upgrade command
UPGRADE_ENTRY = 'indy-node'

WRITES_REQUIRE_TRUST_ANCHOR = True
7 changes: 7 additions & 0 deletions indy_common/test/auth/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import pytest

from indy_common.auth import Authoriser, generate_auth_map
from plenum.common.constants import STEWARD, TRUSTEE

from indy_common.constants import TRUST_ANCHOR, TGB
Expand All @@ -17,3 +19,8 @@ def is_owner(request):
@pytest.fixture(scope='function', params=[None, "value1"])
def old_values(request):
return request.param


@pytest.fixture(scope='module')
def initialized_auth_map():
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, True)
30 changes: 25 additions & 5 deletions indy_common/test/auth/test_auth_claim_def.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,58 @@
from plenum.common.constants import TRUSTEE, STEWARD

from indy_common.auth import Authoriser
from indy_common.auth import Authoriser, generate_auth_map
from indy_common.constants import REF, TGB, TRUST_ANCHOR, CLAIM_DEF


def test_claim_def_adding():
def test_claim_def_adding(initialized_auth_map):
roles = {TRUSTEE, STEWARD, TRUST_ANCHOR}
for role in roles:
r, msg = _authorised_for_claim_def(role, True)
assert r and not msg


def test_claim_def_adding_without_permission():
def test_claim_def_adding_without_permission(initialized_auth_map):
roles = {TGB, None}
for role in roles:
r, msg = _authorised_for_claim_def(role, True)
assert not r and msg


def test_claim_def_adding_not_owner():
def test_claim_def_adding_not_owner(initialized_auth_map):
roles = {TRUSTEE, STEWARD, TRUST_ANCHOR}
for role in roles:
r, msg = _authorised_for_claim_def(role, False)
assert not r and msg == "Only owner is allowed"


def test_claim_def_adding_with_some_field():
def test_claim_def_adding_with_some_field(initialized_auth_map):
r, msg = Authoriser.authorised(typ=CLAIM_DEF,
actorRole=TRUSTEE,
field="name",
isActorOwnerOfSubject=True)
assert r and not msg


def test_client_can_send_claim_def():
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, False)

r, msg = Authoriser.authorised(typ=CLAIM_DEF,
actorRole=None,
field="name",
isActorOwnerOfSubject=True)
assert r and not msg


def test_client_cant_send_claim_def():
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, True)

r, msg = Authoriser.authorised(typ=CLAIM_DEF,
actorRole=None,
field="name",
isActorOwnerOfSubject=True)
assert not r and "None role not in allowed roles" in msg


def _authorised_for_claim_def(role, is_owner):
return Authoriser.authorised(typ=CLAIM_DEF,
actorRole=role,
Expand Down
20 changes: 17 additions & 3 deletions indy_common/test/auth/test_auth_schema.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
from plenum.common.constants import TRUSTEE, STEWARD

from indy_common.auth import Authoriser
from indy_common.auth import Authoriser, generate_auth_map
from indy_common.constants import NAME, TGB, TRUST_ANCHOR, SCHEMA


def test_schema_adding():
def test_schema_adding(initialized_auth_map):
roles = {TRUSTEE, STEWARD, TRUST_ANCHOR}
for role in roles:
r, msg = _authorised_for_schemas(role)
assert r and not msg


def test_schema_adding_without_permission():
def test_schema_adding_without_permission(initialized_auth_map):
roles = {TGB, None}
for role in roles:
r, msg = _authorised_for_schemas(role)
assert not r and msg


def test_client_can_send_claim_def():
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, False)

r, msg = _authorised_for_schemas(None)
assert r and not msg


def test_client_cant_send_claim_def():
Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, True)

r, msg = _authorised_for_schemas(None)
assert not r and "None role not in allowed roles" in msg


def _authorised_for_schemas(role):
return Authoriser.authorised(typ=SCHEMA,
actorRole=role)
Loading

0 comments on commit f4b6095

Please sign in to comment.