| OLD | NEW |
| 1 # Copyright 2014 The LUCI Authors. All rights reserved. | 1 # Copyright 2014 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 """Defines access groups.""" | 5 """Defines access groups. |
| 6 |
| 7 +------+ |
| 8 |admins| |
| 9 +------+ |
| 10 ^ |
| 11 | |
| 12 +------------------------+ |
| 13 | | |
| 14 +----------------+ +-------------+ |
| 15 |privileged_users| |bot_bootstrap| |
| 16 +----------------+ +-------------+ |
| 17 ^ |
| 18 | |
| 19 +-----+ |
| 20 |users| |
| 21 +-----+ |
| 22 |
| 23 |
| 24 +-------------+ +--------------+ |
| 25 |view_all_bots| |view_all_tasks| |
| 26 +-------------+ +--------------+ |
| 27 |
| 28 |
| 29 +-------------------------+ |
| 30 |is_ip_whitelisted_machine| |
| 31 +-------------------------+ |
| 32 |
| 33 |
| 34 Keep this file synchronized with the documentation at ../proto/config.proto. |
| 35 """ |
| 6 | 36 |
| 7 from components import auth | 37 from components import auth |
| 8 from components import utils | 38 from components import utils |
| 9 from server import config | 39 from server import config |
| 10 | 40 |
| 11 | 41 |
| 12 def is_admin(): | 42 def _is_admin(): |
| 13 admins = config.settings().auth.admins_group | 43 """Full administrative access.""" |
| 14 return auth.is_group_member(admins) or auth.is_admin() | 44 group = config.settings().auth.admins_group |
| 45 return auth.is_group_member(group) or auth.is_admin() |
| 15 | 46 |
| 16 | 47 |
| 17 def is_privileged_user(): | 48 def _is_privileged_user(): |
| 18 priv_users = config.settings().auth.privileged_users_group | 49 """Can edit all bots and tasks.""" |
| 19 return auth.is_group_member(priv_users) or is_admin() | 50 group = config.settings().auth.privileged_users_group |
| 51 return auth.is_group_member(group) or _is_admin() |
| 20 | 52 |
| 21 | 53 |
| 22 def is_user(): | 54 def _is_user(): |
| 23 users = config.settings().auth.users_group | 55 group = config.settings().auth.users_group |
| 24 return auth.is_group_member(users) or is_privileged_user() | 56 return auth.is_group_member(group) or _is_privileged_user() |
| 25 | 57 |
| 26 | 58 |
| 27 def is_bootstrapper(): | 59 def _is_view_all_bots(): |
| 60 group = config.settings().auth.view_all_bots_group |
| 61 return auth.is_group_member(group) or _is_privileged_user() |
| 62 |
| 63 |
| 64 def _is_view_all_tasks(): |
| 65 group = config.settings().auth.view_all_tasks_group |
| 66 return auth.is_group_member(group) or _is_privileged_user() |
| 67 |
| 68 |
| 69 def _is_bootstrapper(): |
| 28 """Returns True if current user have access to bot code (for bootstrap).""" | 70 """Returns True if current user have access to bot code (for bootstrap).""" |
| 29 bot_group = config.settings().auth.bot_bootstrap_group | 71 bot_group = config.settings().auth.bot_bootstrap_group |
| 30 return is_admin() or auth.is_group_member(bot_group) | 72 return auth.is_group_member(bot_group) or _is_admin() |
| 73 |
| 74 |
| 75 ### Capabilities |
| 31 | 76 |
| 32 | 77 |
| 33 def is_ip_whitelisted_machine(): | 78 def is_ip_whitelisted_machine(): |
| 34 """Returns True if the call is made from IP whitelisted machine.""" | 79 """Returns True if the call is made from IP whitelisted machine.""" |
| 35 # TODO(vadimsh): Get rid of this. It's blocked on fixing /bot_code calls in | 80 # TODO(vadimsh): Get rid of this. It's blocked on fixing /bot_code calls in |
| 36 # bootstrap code everywhere to use service accounts and switching all Swarming | 81 # bootstrap code everywhere to use service accounts and switching all Swarming |
| 37 # Tasks API calls made from bots to use proper authentication. | 82 # Tasks API calls made from bots to use proper authentication. |
| 38 return auth.is_in_ip_whitelist( | 83 return auth.is_in_ip_whitelist( |
| 39 auth.bots_ip_whitelist(), auth.get_peer_ip(), False) | 84 auth.bots_ip_whitelist(), auth.get_peer_ip(), False) |
| 40 | 85 |
| 41 | 86 |
| 42 def is_bot(): | 87 def can_access(): |
| 43 # TODO(vadimsh): Get rid of this. Swarming jobs will use service accounts | 88 """Minimally authenticated user.""" |
| 44 # associated with the job when calling Swarming, not the machine IP. | 89 return ( |
| 45 return is_ip_whitelisted_machine() or is_admin() | 90 is_ip_whitelisted_machine() or _is_user() or |
| 91 _is_view_all_bots() or _is_view_all_tasks()) |
| 46 | 92 |
| 47 | 93 |
| 48 def is_bot_or_user(): | 94 #### Config |
| 49 # TODO(vadimsh): Get rid of this. Swarming jobs will use service accounts | |
| 50 # associated with the job when calling Swarming, not the machine ID itself. | |
| 51 return is_bot() or is_user() | |
| 52 | 95 |
| 53 | 96 |
| 54 def is_bot_or_privileged_user(): | 97 def can_view_config(): |
| 55 # TODO(vadimsh): Get rid of this. Swarming jobs will use service accounts | 98 """Can view the configuration data.""" |
| 56 # associated with the job when calling Swarming, not the machine ID itself. | 99 return _is_admin() |
| 57 return is_bot() or is_privileged_user() | |
| 58 | 100 |
| 59 | 101 |
| 60 def is_bot_or_admin(): | 102 def can_edit_config(): |
| 61 """Returns True if current user can execute user-side and bot-side calls.""" | 103 """Can edit the configuration data. |
| 62 # TODO(vadimsh): Get rid of this. Swarming jobs will use service accounts | 104 |
| 63 # associated with the job when calling Swarming, not the machine ID itself. | 105 Only super users can edit the configuration data. |
| 64 return is_bot() or is_admin() | 106 """ |
| 107 return _is_admin() |
| 108 |
| 109 |
| 110 #### Bot |
| 111 |
| 112 |
| 113 def can_create_bot(): |
| 114 """Can create (bootstrap) a bot.""" |
| 115 return _is_bootstrapper() |
| 116 |
| 117 |
| 118 def can_edit_bot(): |
| 119 """Can terminate a bot. |
| 120 |
| 121 Bots can terminate other bots. This may change in the future. |
| 122 """ |
| 123 return is_ip_whitelisted_machine() or _is_privileged_user() |
| 124 |
| 125 |
| 126 def can_delete_bot(): |
| 127 """Can delete the existence of a bot. |
| 128 |
| 129 Bots can delete other bots. This may change in the future. |
| 130 """ |
| 131 return is_ip_whitelisted_machine() or _is_admin() |
| 132 |
| 133 |
| 134 def can_view_bot(): |
| 135 """Can view bot. |
| 136 |
| 137 Bots can view other bots. This may change in the future. |
| 138 """ |
| 139 return is_ip_whitelisted_machine() or _is_view_all_bots() |
| 140 |
| 141 |
| 142 #### Task |
| 143 |
| 144 |
| 145 def can_create_task(): |
| 146 """Can create a task. |
| 147 |
| 148 Swarming is reentrant, a bot can create a new task as part of a task. This may |
| 149 change in the future. |
| 150 """ |
| 151 return is_ip_whitelisted_machine() or _is_user() |
| 65 | 152 |
| 66 | 153 |
| 67 def can_schedule_high_priority_tasks(): | 154 def can_schedule_high_priority_tasks(): |
| 68 """Returns True if the current user can schedule high priority tasks.""" | 155 """Returns True if the current user can schedule high priority tasks.""" |
| 69 return is_bot() or is_privileged_user() | 156 # TODO(maruel): Deny priority < 100 task creation instead of silently |
| 157 # downgrading the priority. |
| 158 return is_ip_whitelisted_machine() or _is_privileged_user() |
| 70 | 159 |
| 71 | 160 |
| 72 def get_user_type(): | 161 def can_edit_task(task): |
| 73 """Returns a string describing the current access control for the user.""" | 162 """Can 'edit' tasks, like cancelling. |
| 74 if is_admin(): | 163 |
| 75 return 'admin' | 164 Since bots can create tasks, they can also cancel them. This may change in the |
| 76 if is_privileged_user(): | 165 future. |
| 77 return 'privileged user' | 166 """ |
| 78 if is_user(): | 167 return ( |
| 79 return 'user' | 168 is_ip_whitelisted_machine() or _is_privileged_user() or |
| 169 auth.get_current_identity() == task.authenticated) |
| 170 |
| 171 |
| 172 def can_edit_all_tasks(): |
| 173 """Can 'edit' a batch of tasks, like cancelling.""" |
| 174 return _is_admin() |
| 175 |
| 176 |
| 177 def can_view_task(task): |
| 178 """Can view a single task.""" |
| 179 return ( |
| 180 is_ip_whitelisted_machine() or _is_view_all_tasks() or |
| 181 auth.get_current_identity() == task.authenticated) |
| 182 |
| 183 |
| 184 def can_view_all_tasks(): |
| 185 """Can view all tasks.""" |
| 186 return _is_view_all_tasks() |
| 187 |
| 188 |
| 189 ### Other |
| 80 | 190 |
| 81 | 191 |
| 82 def bootstrap_dev_server_acls(): | 192 def bootstrap_dev_server_acls(): |
| 83 """Adds localhost to IP whitelist and Swarming groups.""" | 193 """Adds localhost to IP whitelist and Swarming groups.""" |
| 84 assert utils.is_local_dev_server() | 194 assert utils.is_local_dev_server() |
| 85 if auth.is_replica(): | 195 if auth.is_replica(): |
| 86 return | 196 return |
| 87 | 197 |
| 88 bots = auth.bootstrap_loopback_ips() | 198 bots = auth.bootstrap_loopback_ips() |
| 89 | 199 |
| 90 auth_settings = config.settings().auth | 200 auth_settings = config.settings().auth |
| 91 admins_group = auth_settings.admins_group | 201 admins_group = auth_settings.admins_group |
| 92 users_group = auth_settings.users_group | 202 users_group = auth_settings.users_group |
| 93 bot_bootstrap_group = auth_settings.bot_bootstrap_group | 203 bot_bootstrap_group = auth_settings.bot_bootstrap_group |
| 94 | 204 |
| 95 auth.bootstrap_group(users_group, bots, 'Swarming users') | 205 auth.bootstrap_group(users_group, bots, 'Swarming users') |
| 96 auth.bootstrap_group(bot_bootstrap_group, bots, 'Bot bootstrap') | 206 auth.bootstrap_group(bot_bootstrap_group, bots, 'Bot bootstrap') |
| 97 | 207 |
| 98 # Add a swarming admin. smoke-test@example.com is used in | 208 # Add a swarming admin. smoke-test@example.com is used in |
| 99 # server_smoke_test.py | 209 # server_smoke_test.py |
| 100 admin = auth.Identity(auth.IDENTITY_USER, 'smoke-test@example.com') | 210 admin = auth.Identity(auth.IDENTITY_USER, 'smoke-test@example.com') |
| 101 auth.bootstrap_group(admins_group, [admin], 'Swarming administrators') | 211 auth.bootstrap_group(admins_group, [admin], 'Swarming administrators') |
| 102 | 212 |
| 103 # Add an instance admin (for easier manual testing when running dev server). | 213 # Add an instance admin (for easier manual testing when running dev server). |
| 104 auth.bootstrap_group( | 214 auth.bootstrap_group( |
| 105 auth.ADMIN_GROUP, | 215 auth.ADMIN_GROUP, |
| 106 [auth.Identity(auth.IDENTITY_USER, 'test@example.com')], | 216 [auth.Identity(auth.IDENTITY_USER, 'test@example.com')], |
| 107 'Users that can manage groups') | 217 'Users that can manage groups') |
| OLD | NEW |