go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/starlark/stdlib/internal/luci/rules/realm.star (about) 1 # Copyright 2020 The LUCI Authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """Defines luci.realm(...) rule.""" 16 17 load("@stdlib//internal/luci/lib/realms.star", "realms") 18 load("@stdlib//internal/lucicfg.star", "lucicfg") 19 load("@stdlib//internal/validate.star", "validate") 20 21 def _realm( 22 ctx, # @unused 23 *, 24 name, 25 extends = None, 26 bindings = None, 27 enforce_in = None): 28 """Defines a realm. 29 30 Realm is a named collection of `(<principal>, <permission>)` pairs. 31 32 A LUCI resource can point to exactly one realm by referring to its full 33 name (`<project>:<realm>`). We say that such resource "belongs to the realm" 34 or "lives in the realm" or is just "in the realm". We also say that such 35 resource belongs to the project `<project>`. The corresponding 36 luci.realm(...) definition then describes who can do what to the resource. 37 38 The logic of how resources get assigned to realms is a part of the public 39 API of the service that owns resources. Some services may use a static realm 40 assignment via project configuration files, others may do it dynamically by 41 accepting a realm when a resource is created via an RPC. 42 43 A realm can "extend" one or more other realms. If a realm `A` extends `B`, 44 then all permissions defined in `B` are also in `A`. Remembering that a 45 realm is just a set of `(<principal>, <permission>)` pairs, the "extends" 46 relation is just a set inclusion. 47 48 There are two special realms that a project can have: "@root" and "@legacy". 49 50 The root realm is implicitly included into all other realms (including 51 "@legacy"), and it is also used as a fallback when a resource points to a 52 realm that no longer exists. Without the root realm, such resources become 53 effectively inaccessible and this may be undesirable. Permissions in the 54 root realm apply to all realms in the project (current, past and future), 55 and thus the root realm should contain only administrative-level bindings. 56 If you are not sure whether you should use the root realm or not, err on 57 the side of not using it. 58 59 The legacy realm is used for existing resources created before the realms 60 mechanism was introduced. Such resources usually are not associated with any 61 realm at all. They are implicitly placed into the legacy realm to allow 62 reusing realms' machinery for them. 63 64 Note that the details of how resources are placed in the legacy realm are up 65 to a particular service implementation. Some services may be able to figure 66 out an appropriate realm for a legacy resource based on resource's existing 67 attributes. Some services may not have legacy resources at all. The legacy 68 realm is not used in these case. Refer to the service documentation. 69 70 The primary way of populating the permission set of a realm is via bindings. 71 Each binding assigns a role to a set of principals (individuals, groups or 72 LUCI projects). A role is just a set of permissions. A binding grants these 73 permissions to all principals listed in it. 74 75 Binding can be specific either right here: 76 77 luci.realm( 78 name = 'try', 79 bindings = [ 80 luci.binding( 81 roles = 'role/a', 82 groups = ['group-a'], 83 ), 84 luci.binding( 85 roles = 'role/b', 86 groups = ['group-b'], 87 ), 88 ], 89 ) 90 91 Or separately one by one via luci.binding(...) declarations: 92 93 luci.binding( 94 realm = 'try', 95 roles = 'role/a', 96 groups = ['group-a'], 97 ) 98 luci.binding( 99 realm = 'try', 100 roles = 'role/b', 101 groups = ['group-b'], 102 ) 103 104 Args: 105 ctx: the implicit rule context, see lucicfg.rule(...). 106 name: name of the realm. Must match `[a-z0-9_\\.\\-/]{1,400}` or be 107 `@root` or `@legacy`. Required. 108 extends: a reference or a list of references to realms to inherit 109 permission from. Optional. Default (and implicit) is `@root`. 110 bindings: a list of luci.binding(...) to add to the realm. 111 enforce_in: a list of LUCI service IDs that should enforce this realm's 112 permissions. Children realms inherit and extend this list. Used only 113 during Realms migration to gradually roll out the enforcement realm by 114 realm, service by service. 115 """ 116 return realms.realm( 117 impl = realms.default_impl, 118 name = name, 119 extends = extends, 120 bindings = bindings, 121 enforce_in_service = validate.str_list("enforce_in", enforce_in), 122 ) 123 124 realm = lucicfg.rule(impl = _realm)