-
Notifications
You must be signed in to change notification settings - Fork 34
/
user.go
164 lines (145 loc) · 3.83 KB
/
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (c) Edgeless Systems GmbH.
//
// 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 https://mozilla.org/MPL/2.0/.
package user
import (
"crypto/x509"
"encoding/json"
)
// Permissions available to users.
const (
PermissionWriteSecret = "writesecret"
PermissionReadSecret = "readsecret"
PermissionUpdatePackage = "updatesecurityversion"
PermissionUpdateManifest = "updatemanifest"
)
// User represents a privileged user of MarbleRun.
type User struct {
name string
// certificate is the users certificate, used for authentication
certificate *x509.Certificate
// permissions of the user
permissions map[string]Permission
}
// NewUser creates a new user.
func NewUser(name string, certificate *x509.Certificate) *User {
newUser := &User{
name: name,
certificate: certificate,
permissions: make(map[string]Permission),
}
return newUser
}
// Assign adds a new permission to the user.
func (u *User) Assign(p Permission) {
if _, ok := u.permissions[p.ID()]; !ok {
u.permissions[p.ID()] = p
} else {
for k, v := range p.ResourceID {
u.permissions[p.ID()].ResourceID[k] = u.permissions[p.ID()].ResourceID[k] || v
}
}
}
// IsGranted returns true if the user has the requested permission.
func (u *User) IsGranted(p Permission) bool {
q, ok := u.permissions[p.ID()]
if !ok {
return false
}
return q.match(p)
}
// Name returns the name of a user.
func (u *User) Name() string {
return u.name
}
// Permissions returns a users permissions.
func (u *User) Permissions() map[string]Permission {
return u.permissions
}
// Certificate returns a users certificate.
func (u *User) Certificate() *x509.Certificate {
return u.certificate
}
// MarshalJSON implements the json.Marshaler interface.
func (u *User) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Name string
Certificate []byte
Permissions map[string]Permission
}{
Name: u.name,
Certificate: u.certificate.Raw,
Permissions: u.permissions,
})
}
// UnmarshalJSON implements the json.Marshaler interface.
func (u *User) UnmarshalJSON(data []byte) error {
tmp := &struct {
Name string
Certificate []byte
Permissions map[string]Permission
}{}
if err := json.Unmarshal(data, tmp); err != nil {
return err
}
cert, err := x509.ParseCertificate(tmp.Certificate)
if err != nil {
return err
}
u.name = tmp.Name
u.permissions = tmp.Permissions
u.certificate = cert
return nil
}
// Equal returns true if both users are the same.
func (u *User) Equal(other *User) bool {
// Check if the other user is granted
// all permissions of the current user
for _, perm := range u.permissions {
if !other.IsGranted(perm) {
return false
}
}
// Check if the current user is granted
// all permissions of the other user
for _, perm := range other.permissions {
if !u.IsGranted(perm) {
return false
}
}
return u.name == other.name && u.certificate.Equal(other.certificate)
}
// Permission represents the permissions of a MarbleRun user.
type Permission struct {
PermissionID string
ResourceID map[string]bool
}
// NewPermission creates a new permission, granting access to resources grouped by permissionID.
func NewPermission(permissionID string, resourceIDs []string) Permission {
newPermission := Permission{
PermissionID: permissionID,
ResourceID: make(map[string]bool),
}
for _, v := range resourceIDs {
newPermission.ResourceID[v] = true
}
return newPermission
}
// ID returns the permissionID.
func (p Permission) ID() string {
return p.PermissionID
}
// Match returns true if a is a subgroup of p.
func (p Permission) match(q Permission) bool {
if p.PermissionID != q.ID() {
return false
}
for k := range q.ResourceID {
if !p.ResourceID[k] {
return false
}
}
return true
}