github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/asserts/account.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package asserts 21 22 import ( 23 "fmt" 24 "regexp" 25 "time" 26 ) 27 28 var ( 29 // account ids look like snap-ids or a nice identifier 30 validAccountID = regexp.MustCompile("^(?:[a-z0-9A-Z]{32}|[-a-z0-9]{2,28})$") 31 ) 32 33 // Account holds an account assertion, which ties a name for an account 34 // to its identifier and provides the authority's confidence in the name's validity. 35 type Account struct { 36 assertionBase 37 validation string 38 timestamp time.Time 39 } 40 41 func IsValidAccountID(accountID string) bool { 42 return validAccountID.MatchString(accountID) 43 } 44 45 // AccountID returns the account-id of the account. 46 func (acc *Account) AccountID() string { 47 return acc.HeaderString("account-id") 48 } 49 50 // Username returns the user name for the account. 51 func (acc *Account) Username() string { 52 return acc.HeaderString("username") 53 } 54 55 // DisplayName returns the human-friendly name for the account. 56 func (acc *Account) DisplayName() string { 57 return acc.HeaderString("display-name") 58 } 59 60 // Validation returns the level of confidence of the authority in the 61 // account's identity, expected to be "unproven" or "verified", and 62 // for forward compatibility any value != "unproven" can be considered 63 // at least "verified". 64 func (acc *Account) Validation() string { 65 return acc.validation 66 } 67 68 // Timestamp returns the time when the account was issued. 69 func (acc *Account) Timestamp() time.Time { 70 return acc.timestamp 71 } 72 73 // Implement further consistency checks. 74 func (acc *Account) checkConsistency(db RODatabase, acck *AccountKey) error { 75 if !db.IsTrustedAccount(acc.AuthorityID()) { 76 return fmt.Errorf("account assertion for %q is not signed by a directly trusted authority: %s", acc.AccountID(), acc.AuthorityID()) 77 } 78 return nil 79 } 80 81 // sanity 82 var _ consistencyChecker = (*Account)(nil) 83 84 func assembleAccount(assert assertionBase) (Assertion, error) { 85 _, err := checkNotEmptyString(assert.headers, "display-name") 86 if err != nil { 87 return nil, err 88 } 89 90 validation, err := checkNotEmptyString(assert.headers, "validation") 91 if err != nil { 92 return nil, err 93 } 94 // backward compatibility with the hard-coded trusted account 95 // assertions 96 // TODO: generate revision 1 of them with validation 97 // s/certified/verified/ 98 if validation == "certified" { 99 validation = "verified" 100 } 101 102 timestamp, err := checkRFC3339Date(assert.headers, "timestamp") 103 if err != nil { 104 return nil, err 105 } 106 107 _, err = checkOptionalString(assert.headers, "username") 108 if err != nil { 109 return nil, err 110 } 111 112 return &Account{ 113 assertionBase: assert, 114 validation: validation, 115 timestamp: timestamp, 116 }, nil 117 }