// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. package role import ( "sort" "strings" ) // Role represents Talos user role. // Its string value is used everywhere: as the the Organization value of Talos client certificate, // as the value of talosctl flag, etc. type Role string const ( // Prefix for all built-in roles. Prefix = string("os:") // Admin defines Talos role for admins. Admin = Role(Prefix + "admin") // Reader defines Talos role for readers who can access read-only APIs that do not expose secrets. Reader = Role(Prefix + "reader") // EtcdBackup defines Talos role that allows making etcd backups. EtcdBackup = Role(Prefix + "etcd:backup") // Impersonator defines Talos role for impersonating another user (and their role). // Used internally, but may also be granted to the user. Impersonator = Role(Prefix + "impersonator") ) // Set represents a set of roles. type Set struct { roles map[Role]struct{} } var ( // All roles that can be granted to users. All = MakeSet(Admin, Reader, EtcdBackup, Impersonator) // Zero is an empty set of roles. Zero = MakeSet() ) // MakeSet makes a set of roles from constants. // Use Parse in other cases. func MakeSet(roles ...Role) Set { res := Set{ roles: make(map[Role]struct{}, len(roles)), } for _, r := range roles { res.roles[r] = struct{}{} } return res } // Parse parses a set of roles. // The returned set is always non-nil and contains all roles, including unknown (for compatibility with future versions). // The returned slice contains roles unknown to the current version. func Parse(str []string) (Set, []string) { res := MakeSet() var unknownRoles []string for _, r := range str { r = strings.TrimSpace(r) // Client certificates generated by previous Talos versions contained one empty organization. if r == "" { continue } role := Role(r) if _, ok := All.roles[role]; !ok { unknownRoles = append(unknownRoles, r) } res.roles[role] = struct{}{} } return res, unknownRoles } // Strings returns a set as a slice of strings. func (s Set) Strings() []string { res := make([]string, 0, len(s.roles)) for r := range s.roles { res = append(res, string(r)) } sort.Strings(res) return res } // IncludesAny returns true if there is a non-empty intersection between sets. // // Returns false if any set is empty. func (s Set) IncludesAny(other Set) bool { for r := range other.roles { if _, ok := s.roles[r]; ok { return true } } return false } // Includes returns true if given role is present in the set. func (s Set) Includes(role Role) bool { _, ok := s.roles[role] return ok }