Skip to content

Commit

Permalink
change group fetch to max_int
Browse files Browse the repository at this point in the history
Add Auth documentaion
  • Loading branch information
datamel committed Jul 22, 2021
1 parent efe447a commit c0f1991
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 23 deletions.
11 changes: 6 additions & 5 deletions cylc/uiserver/authorise.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class Authorization:
# Beware of changing these permission groups. Users may be relying on #
# these settings. Changes should be widely publicised to users. #
# #
# If adding/removing operations, ensure both the Access Group and its #
# associated negation group is updated. #
# If adding/removing operations, ensure documentation is updated. #
# #
##########################################################################

READ_OPERATION = "read"
Expand Down Expand Up @@ -423,13 +423,14 @@ def get_groups(username: str) -> List[str]:
Returns:
list: system groups for username given
"""
group_ids = os.getgrouplist(username, 99999)
group_ids.remove(99999)
groupmax = (os.NGROUPS_MAX) # type: ignore
group_ids = os.getgrouplist(username, groupmax)
group_ids.remove(groupmax)
# turn list of group_ids into group names with group identifier prepended
return list(map(
lambda x: f'{Authorization.GRP_IDENTIFIER}{grp.getgrgid(x).gr_name}',
group_ids
)
)
)


Expand Down
3 changes: 0 additions & 3 deletions cylc/uiserver/config_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,3 @@
# Ensure env variable CYLC_SITE_CONF_PATH is passed to UI Server environment
c.Spawner.environment = {
'CYLC_SITE_CONF_PATH': f'{os.getenv("CYLC_SITE_CONF_PATH")}'}

# remove this before auth goes in...
c.Spawner.http_timeout = 3000
4 changes: 4 additions & 0 deletions cylc/uiserver/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class StaticHandler(BaseHandler, web.StaticFileHandler):

class MainHandler(BaseHandler):

# hub_users = ["kinow"]
# hub_groups = []
# allow_admin = True

def initialize(self, path):
self._static = path

Expand Down
86 changes: 83 additions & 3 deletions cylc/uiserver/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,97 @@ def validate(self, obj, value):

class CylcUIServer(Application):

# TODO: Add a link to the access group table mappings in cylc documentation
AUTH_DESCRIPTION = '''
Authorization can be granted at operation (mutation) level, i.e.
specifically grant user access to execute Cylc commands, e.g.
`play`, `pause`, `edit`, `trigger` etc. For your convenience,
these operations have been mapped to access groups `READ`,
`CONTROL` and `ALL`.
To remove permissions, prepend the access group or operation with
`!`.
Permissions are additive but negated permissions take precedence
above additions.
.. note::
Any authorization permissions granted to a user will be
applied to all workflows.
'''

site_authorization = Dict(
config=True,
help='''
Dictionary containing site limits and defaults for authorization.
''')
This configuration should be placed only in the site set
configuration file and not the user configuration file (use
``c.UIServer.user_authorization`` for user defined authorization).
If this configuration is empty, site authorization defaults to no
configuarble authorization and users will be unable to set any
authorization.
''' + AUTH_DESCRIPTION + '''
Example Configuration:
.. code-block:: python
c.UIServer.site_authorisation = {
"*": { # For all ui-server owners,
"*": { # Any authenticated user
"default": "READ", # Will have default read-only access
}
"user1": { # user1
"default": ["!ALL"], # No privileges for all ui-server
# owners.
}, # No limit set, so all ui-server owners
}, # limit is also "!ALL" for user1
"server_owner_1": { # For specific UI Server owner,
"group:group_a": { # Any user who is a member of group_a
"default": "READ", # Will have default read-only access
"limit": ["ALL", "!play"], # server_owner_1 is able to give away
}, # All privileges, except play.
},
"group:grp_of_svr_owners": { # Group of users who own UI Servers
"group:group_b": {
"limit": [ # can grant groupB users up to READ and
"READ", # CONTROL privileges, without stop and
"CONTROL", # kill
"!stop",
"!kill", # No default, so default is no access
],
},
},
}
''')

user_authorization = Dict(
config=True,
help='''
Dictionary containing authorised users and permission levels for
authorization.
Dictionary containing authorized users and permission levels for
authorization. Use this setting to share control of your workflows
with other users.
Note that you are only permitted to give away permissions up to
your limit for each user, as defined in the site_authorization
configuration.
''' + AUTH_DESCRIPTION + '''
Example configuaration, residing in `~/.cylc/hub/config.py`:
.. code-block:: python
c.UIServer.user_authorization = {
"*": ["READ"], # any authenticated user has READ access
"group:group2": ["ALL"], # Any user in system group2 has access to
# all operations
"userA": [
"ALL", "!stop"
], # userA has ALL operations, but not stop
}
'''
)

Expand Down
14 changes: 13 additions & 1 deletion cylc/uiserver/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,19 @@ class Arguments:
)
abort_if_any_task_fails = Boolean(
default_value=False,
description=sstrip('''result
description=sstrip('''
If set workflow will abort with status 1 if any task fails.
''')
)
debug = Boolean(
default_value=False,
description=sstrip('''
Output developer information and show exception tracebacks.
''')
)
no_timestamp = Boolean(
default_value=False,
description=sstrip('''
Don't timestamp logged messages.
''')
)
Expand Down
9 changes: 0 additions & 9 deletions cylc/uiserver/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,6 @@ def _read(obj, _):
yield _write


@pytest.fixture
def authorisation_true(monkeypatch):
"""Disabled request authorisation for test purposes."""
monkeypatch.setattr(
'cylc.uiserver.',
lambda x: True
)


@pytest.fixture
def mock_authentication(monkeypatch):

Expand Down
9 changes: 7 additions & 2 deletions cylc/uiserver/tests/test_authorise.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from getpass import getuser
from os import path
from graphql.execution.base import ResolveInfo
from subprocess import Popen, PIPE


import pytest
from tornado import web
Expand Down Expand Up @@ -160,22 +162,25 @@ def test_get_permitted_operations(mocked_get_groups,
id="Check user just in *"),
pytest.param({'!ping', 'pause', 'kill', '!stop', 'READ', 'CONTROL'},
{'access_username': 'access_user_1',
'access_user_groups': ['group:group1', 'group:group2'
]},
'access_user_groups': ['group:group1', 'group:group2']
},
{'*': ['READ', '!ping'],
'access_user_1': [
'READ', 'pause', 'kill', '!stop'],
'group:group1': ['CONTROL'],
}, id="Check group access permissions are added")
]
)
@patch('cylc.uiserver.authorise.get_groups')
def test_get_access_user_permissions_from_owner_conf(
mocked_get_groups,
expected_operations,
access_user_dict,
owner_auth_conf
):
"""Test the un-processed permissions of owner conf.
"""
mocked_get_groups.return_value = ['group:blah']
authobj = Authorization('some_user', owner_auth_conf, {'fake': 'config'})
permitted_operations = authobj.get_access_user_permissions_from_owner_conf(
access_user_dict)
Expand Down

0 comments on commit c0f1991

Please sign in to comment.