Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
b1ccec1
Initial commit for multi-tenant-configuration
mheyen Feb 19, 2021
a597f70
Nitpicking and minor corrections
mheyen Feb 25, 2021
0c803f6
Update README of multi-tenant-configuration script
mheyen Feb 25, 2021
f40ad0d
Added basic arguments parser for command options
mheyen Feb 25, 2021
74bc708
updated config file
mheyen Feb 25, 2021
cd8fc84
re-inserted API request for testing
mheyen Feb 25, 2021
9717219
added newline
mheyen Feb 25, 2021
4617bc6
minor restructuring of the script and improved options in available c…
mheyen Feb 27, 2021
597260b
Added error handling for user creation and option to add user to all …
mheyen Mar 25, 2021
f26f524
Update REAMDE
mheyen Mar 25, 2021
2a23c78
fixed minor error while creating users for all tenants
mheyen Mar 25, 2021
417986f
included group checks and restructured code
mheyen Apr 29, 2021
947ee77
restructured code and included verbose flag and logging
mheyen Apr 29, 2021
9c18544
added function to send a PUT request to request.py
mheyen May 17, 2021
1081112
Added member and role checks for group.
mheyen May 17, 2021
97d9224
Updated User Interaction
mheyen Jun 7, 2021
cd776b0
Integrated improved User interaction for group checks
mheyen Jun 7, 2021
f94d37b
Added function to perform checks for all tenants
mheyen Jun 9, 2021
7c57358
Refactoring code
mheyen Jun 9, 2021
3966713
Refactoring code
mheyen Jun 9, 2021
c7abf80
Fixed function call get_user with the new parameters
mheyen Jun 9, 2021
078bea0
Improved args parsing
mheyen Jun 9, 2021
af8ecbe
Added improved IO to User checks and restructured code
mheyen Jun 9, 2021
9f2e64c
Added header argument to get_request in request.py
mheyen Jun 21, 2021
ef2e9ec
Updated the way permissions are stored
mheyen Jun 21, 2021
f66ba67
Added checks to configure_users.py
mheyen Jun 21, 2021
19bddc6
minor code cleanup
mheyen Jun 23, 2021
3a8f52e
removed unused imports
mheyen Jul 12, 2021
d2bab49
removed more unused imports
mheyen Jul 12, 2021
ba009f5
updated README
mheyen Jul 12, 2021
69db473
code cleanup
mheyen Jul 12, 2021
cd17f0e
Improved config parsing and code cleanup
mheyen Jul 12, 2021
482917e
minor code cleanup
mheyen Jul 14, 2021
78dcbbe
get request now allows to also use BasicAuth
mheyen Jul 14, 2021
193f1c6
added API access check, changed user role checks, and general code cl…
mheyen Jul 14, 2021
c252098
Added new Checks and more documentation
mheyen Jul 17, 2021
2060de9
Added documentation
mheyen Jul 22, 2021
da377eb
minor code restructuring
mheyen Jul 22, 2021
7fbe1ee
added function parameter types
mheyen Jul 22, 2021
5670ab6
added code documentation and improved readability
mheyen Jul 22, 2021
5429368
fixed typo and added missing documentation
mheyen Jul 22, 2021
2712647
minor code restructuring
mheyen Jul 22, 2021
265c01a
fixed update_group function calls
mheyen Jul 22, 2021
0987a53
Removed comments and added documentation
mheyen Jul 28, 2021
fd83e52
Added check for Capture Agent Accounts
mheyen Aug 3, 2021
4512e5a
Changed ID of opencast organizaion 'dummy' to 'all'
mheyen Aug 3, 2021
9e1e6ce
Adapted the group description in the configuration file to allow pyth…
mheyen Aug 3, 2021
b49fbbb
finalized group check
mheyen Aug 3, 2021
1c337e2
minor changes: added capture check, removed ToDos, and improved code
mheyen Aug 3, 2021
85766ec
updated doc string in get_request()
mheyen Aug 29, 2021
9a8981f
Added BasicLogin Wraper for Basic Authentification
mheyen Aug 29, 2021
a851a27
Changed command argument from 'tenantid' to 'tenant-id'
mheyen Aug 29, 2021
e971f73
Updated README
mheyen Aug 29, 2021
f610d00
Updated config and README
mheyen Aug 29, 2021
3659eb8
Refactored variable: base_url -> server_url
mheyen Aug 29, 2021
96e7636
Updated README: Added explanation for optional tenant_urls dictionary
mheyen Aug 29, 2021
2446129
Added explanation in config
mheyen Aug 29, 2021
c32d026
Renamed config variables
mheyen Aug 29, 2021
646f6e7
Updated config: Added explanation
mheyen Aug 29, 2021
a3cf83d
fixed json
mheyen Aug 29, 2021
7f7f517
Removed group types
mheyen Aug 29, 2021
82f3308
changed uid to username in yaml file and script
mheyen Aug 29, 2021
b044742
Updated README: Added explanation group configplaceholder
mheyen Aug 29, 2021
c1bdb2c
removed blank line
mheyen Aug 29, 2021
f4ca5ff
Changed organization config file
mheyen Aug 29, 2021
0e11c1a
Added doc strings and moved private functions
mheyen Aug 30, 2021
cde69f7
moved generic functions to lib folder
mheyen Aug 30, 2021
0b00ec9
Removed condition for verbose flag to be set to True
mheyen Aug 30, 2021
c360adf
removed abort_script() function
mheyen Aug 30, 2021
f484f77
Restructured parsing_configuration.py and added Logger class
mheyen Aug 30, 2021
c314f95
renamed file to parse_arguments.py
mheyen Aug 30, 2021
009f96b
Added config option to exclude certain tenants from checks
mheyen Aug 30, 2021
0753bdc
renamed variable
mheyen Aug 30, 2021
ca6e2fd
changed Warning to Error
mheyen Aug 30, 2021
1bd47ef
merged two check functions into one
mheyen Aug 30, 2021
140b244
removed redundant docs
mheyen Aug 30, 2021
39b2a19
moved env folder into config folder
mheyen Aug 31, 2021
4cab954
Restructuring: Iterating over organizations is now done in main.py
mheyen Sep 1, 2021
ddc70ca
Addition to former commit - Iteration is done in main.py
mheyen Sep 1, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions multi-tenant-configuration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Multi-tenants User configuration scripts for Opencast
19 changes: 19 additions & 0 deletions multi-tenant-configuration/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Configuration

#Set this to your global admin node
url = "http://tenant1:8080"
#If you have multiple tenants use something like
#url_pattern = "https://{}.example.org"
#otherwise, url_pattern should be the same as the url variable above
url_pattern = "http://{}:8080"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say the url pattern could be blank if it's a single-tenant-system.

For the future it might be nice to have the alternative possibility to list all tenant urls here in case there's no pattern that matches all of them. So something like tenant_urls = ["http://tenant1.com", "http://tenant2.de"] But that's not really a high priority.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in the example where I have 'http://tenant1:8080' and 'http://tenant2:8080' as tenants, I would still keep the pattern_url ?

Or do you mean that the script would be more general and also applicable to single-tenant-systems if the pattern is {} ?
But in this case you would just use the global admin node url, right?
I thought the pattern was exactly for the case, where there are multiple tenants with similar URLs.

Copy link
Member

@KatrinIhler KatrinIhler Feb 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was talking about this comment:

otherwise, url_pattern should be the same as the url variable above

IMO, if you only have one tenant, url_pattern doesn't even need to be defined. You just use url for everything. The script should be able to deal with that.

If you have tenants URLs that match a pattern, define url_pattern. (Maybe rename to tenant_url_pattern to be clear?)
If they don't match a pattern, define something like tenant_urls instead. The script should use whatever's available. (And if a user defines both... idk, pick one or explode with errors. :D)

And in general, the script should treat 'config key undefined' and 'value is blank' the same.

I hope this is clear? If not, just ask. :D

PS: I just realized that tenant_urls might need to be a map, to know which url belongs to which tenant. But like I said, you could ignore this option for now and add it later. It's not really that important...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I got it :D
Just for clarification:

'config key undefined' -> the user commented out, i.e.
# tenant_url_pattern =

'value is blank' -> the user inserted an empty string, i.e.
tenant_url_pattern = ""


# digest user
digest_user = "opencast_system_account"
digest_pw = "CHANGE_ME"

# path to environment configuration file
env_path = "environment/staging/opencast-organizations.yml"

# workflow_definitions = ["import", "fast"]
# exclude_tenants = []
# export_dir = "."
113 changes: 113 additions & 0 deletions multi-tenant-configuration/configurations/group_configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"groups" : [
{
"name": "System Administrators",
"description": "System Administrators",
"tenants": "all",
"type": "closed",
"members": [
{
"name": "Guy 1",
"email": "[email protected]",
"reason": "Operations partner",
"uid": "guy-1",
"tenants": "all"
},
{
"name": "Guy 2",
"email": "[email protected]",
"reason": "Operations partner",
"uid": "guy-2",
"tenants": "tenant1"
}
],
"inactive_members": [ ],
"permissions": [
{
"tenants": "all",
"roles": ["ROLE_ADMIN", "ROLE_SUDO"]
}
]
},
{
"name": "Organization Administrators",
"description": "Organization administrators have full access to all content of ${name}",
"tenants": "all",
"type": "open",
"members": [],
"inactive_members": [],
"permissions": [
{
"tenants": "all",
"roles": [
"ROLE_ADMIN_UI",
"ROLE_ORG_ADMIN"
]
},
{
"tenants" : "tenant2",
"roles": {
"add": [
"ROLE_UI_EVENTS_DETAILS_ACL_VIEW",
"ROLE_UI_EVENTS_DETAILS_ACL_EDIT"
],
"remove": []
}
}
]
},
{
"name": "Producers",
"description": "Producers have limited access to content and functionality",
"tenants": "all",
"type": "open",
"members": [],
"inactive_members": [],
"permissions": [
{
"tenants": "all",
"roles": [
"ROLE_ADMIN_UI",
"ROLE_UI_EVENTS_CREATE"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't looked at the json file in a while :D

]
},
{
"tenants" : "tenant1",
"roles": {
"add": [
"ROLE_UI_EVENTS_COUNTERS_VIEW"
],
"remove": [
"ROLE_UI_EVENTS_CREATE"
]
}
},
{
"tenants" : "tenant2",
"roles": {
"add": [
"ROLE_ORG_ADMIN"
],
"remove": []
}
}
]
},
{
"name": "Tenant2 Producers",
"description": "Tenant2 Producers have limited access to content and functionality",
"tenants": "tenant2",
"type": "open",
"members": [],
"inactive_members": [],
"permissions": [
{
"tenants": "all",
"roles": [
"ROLE_ADMIN_UI"
]
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would still be cool if we could try to decrypt this with ansible-vault.


opencast_organizations:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is an example, maybe also put this in the configurations folder? (So config/env/.../org.yml) Path is configurable, so that should work. Nobody needs to know our weird folder structure, right? :D

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not exactly sure, what you wanted :D but I hope I did the right thing!
Moved environment folder into configurations folder.
See 39b2a19

- id: dummy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This structure is quite complex and if I remember correctly, not all of it is used by the user scripts. I might have to think about whether it makes sense to have a separate file for this, even if we then have some duplication...

name: Dummy Tenant
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this to something like All Tenants

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to "All Tenants"

aai_org: switch.ch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace this with something more abstract like aai.org

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see below.

stream_sec_key: 5387689
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually - strip everything out of here that isn't used by the script. No need to make it more complicated for people.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed aai_org and stream_sec_key from all organizations.

acl_default_template: organization
acl_default_download: False
acl_default_annotate: False

# Global External API user passwords
opencast_system_account:
username: opencast_system_account
password: CHANGE_ME
switchcast_system_accounts:
- username: player
name: Player System User
email: [email protected]
password: 34dchG6nbhmhnG
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case anyone is wondering - these are not real passwords, just me smashing on a keyboard. ;)

roles: [ROLE_ADMIN, ROLE_SUDO]
- username: annotate
name: Annotate System User
email: [email protected]
password: jhvhuJH7utghfgfgJH
roles: [ROLE_ADMIN, ROLE_SUDO]
- username: cast
name: Cast System User
email: [email protected]
password: jhvhuJH7utghfgfgJH
roles: [ROLE_ADMIN, ROLE_SUDO]
capture_agent_accounts: []

- id: tenant1
name: Tenant1
aai_org: tenant1.ch
stream_sec_key: tu7uzgjjhghjf
capture_agent_accounts:
- username: ca-tenant1-ch
password: jvblkajklvjhaklehr
external_api_accounts:
- username: moodle-tenant1-ch
password: hghghjghdghdjd76
name: Moodle System User
email: [email protected]
roles: [ROLE_EXTERNAL_APPLICATION]
- username: guy1
password: abc
name: Guy 1
email: [email protected]
roles: [ROLE_ADMIN]
- username: guy2
password: abc
name: Guy 2
email: [email protected]
roles: [ROLE_ADMIN, ROLE_SUDO]
- id: tenant2
name: Tenant2
aai_org: tenant2.ch
stream_sec_key: tu7uzgjjhghjf
capture_agent_accounts:
- username: ca-tenant2-ch
password: hjfkhfzuruzf76
external_api_accounts:
- username: moodle-tenant2-ch
password: 67rdghn
name: Moodle System User
email: [email protected]
roles: [ROLE_EXTERNAL_APPLICATION]
- username: guy-1
password: abc
name: Guy 1
email: [email protected]
roles: [ROLE_ADMIN, ROLE_SUDO]
82 changes: 82 additions & 0 deletions multi-tenant-configuration/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os
import sys
import yaml

sys.path.append(os.path.join(os.path.abspath('..'), "lib"))

# import datetime
import config
import io
# from collections import defaultdict
from rest_requests.request_error import RequestError
from args.digest_login import DigestLogin
from rest_requests.request import get_request, post_request
# from pathlib import Path


# ToDo
# add logger
# add interaction question
# add parameter to python command

def main():
"""
configure Groups and Users
"""

digest_login = DigestLogin(user=config.digest_user, password=config.digest_pw)
# read config file
opencast_organizations = read_configuration_file(config.env_path)['opencast_organizations']
tenants = [tenant['id'] for tenant in opencast_organizations]
external_api_accounts = opencast_organizations[1]['external_api_accounts']

# create users for tenant 1
for account in external_api_accounts:
tenant = tenants[1]
create_user(tenant, account, digest_login)


def read_configuration_file(path):
with open(path, 'r') as f:
conf = yaml.load(f, Loader=yaml.FullLoader)

return conf

# # example get request
# response = get_request("http://tenant1:8080/users/users.json", digest_login, "users/users.json")
# json_content = get_json_content(response)
# print(response)

def get_roles_as_Json_array(account):
roles = [{'name': role, 'type': 'INTERNAL'} for role in account['roles']]

return roles

def create_user(tenantid, account, digest_login):
""" sends a POST request to the admin UI to create a User

:param tenantid: str tenant id to form correct url (e.g. 'tenant1')
:param account: dict user account to be created (e.g. {'username': 'Peter', 'password': '123'}
:param digest_login: digest login
:return:
"""
url = '{}/admin-ng/users/'.format(config.url_pattern.format(tenantid))
data = {
'username': account['username'],
'password': account['password'],
'name': account['name'],
'email': account['email'],
'roles': str(get_roles_as_Json_array(account))
}
# ToDo error handling
response = post_request(url, digest_login, '/admin-ng/users/', data=data)

return response


if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("\nAborting process.")
sys.exit(0)
8 changes: 8 additions & 0 deletions multi-tenant-configuration/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
certifi==2020.11.8
chardet==3.0.4
idna==2.10
requests==2.25.0
requests-toolbelt==0.9.1
urllib3==1.26.2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that blank line generated by python or is that accidental?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed that line.

pyyaml