-
Notifications
You must be signed in to change notification settings - Fork 1
/
key.go
139 lines (124 loc) · 4.42 KB
/
key.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
package model
import (
"context"
"time"
"github.com/google/go-cmp/cmp"
"github.com/jinzhu/gorm"
"github.com/ofte-auth/dogpark/internal/db"
"github.com/ofte-auth/dogpark/internal/util"
"github.com/pkg/errors"
)
// FIDOKey represents a FIDO key generated by an authenticator.
type FIDOKey struct {
ID string `json:"id"`
AAGUID string `json:"aaguid" gorm:"index"`
State string `json:"state" gorm:"index"`
CertCommonName string `json:"certCommonName" gorm:"index"`
CertOrganization string `json:"certOrganization" gorm:"index"`
CertSerial int64 `json:"certSerial" gorm:"index"`
PrincipalID string `gorm:"index" json:"principalId"`
PrincipalUsername string `gorm:"index" json:"username"`
PublicKey []byte `json:"publicKey"`
AttestationType string `json:"attestationType"`
NotValidBefore time.Time `gorm:"index" json:"notValidBefore"`
NotValidAfter time.Time `gorm:"index" json:"notValidAfter"`
Nonce uint32 `json:"-"`
CAKey *CAKey `json:"caKey,omitempty"`
LastUsed time.Time `gorm:"index" json:"lastUsed"`
CreatedAt time.Time `gorm:"index" json:"createdAt"`
ModifiedAt time.Time `gorm:"index" json:"modifiedAt"`
}
var _fidoKeyAPIToDBFields = map[string]string{
"aaguid": "aa_guid",
"certCommonName": "cert_common_name",
"certOrganization": "cert_organization",
"certSerial": "cert_serial",
"principalID": "principal_id",
"principalUsername": "principal_username",
"attestationType": "attestation_type",
"notValidBefore": "not_valid_before",
"notValidAfter": "not_valid_after",
"lastUsed": "last_used",
"createdAt": "created_at",
"modifiedAt": "modified_at",
}
// TableName overrides the naming of this table in the DB.
func (FIDOKey) TableName() string {
return "fido_keys"
}
// FIDOKeyByID returns a stored FIDO key by ID.
func FIDOKeyByID(ctx context.Context, db db.DB, id string) (*FIDOKey, error) {
k := new(FIDOKey)
err := db.Set("gorm:auto_preload", true).Where("id = ?", id).First(k).Error
if err == gorm.ErrRecordNotFound {
k = nil
err = ErrRecordNotFound
}
return k, err
}
// Update ...
func (fk *FIDOKey) Update(ctx context.Context, db db.DB, values map[string]string) (string, error) {
changes, err := fk.ApplyChanges(values)
if err != nil {
return "", errors.Wrap(err, "updating record")
}
return changes, db.Save(fk).Error
}
// AllowedUpdateFields returns the fields that are mutable.
func (fk *FIDOKey) AllowedUpdateFields() map[string]bool {
return map[string]bool{"state": true}
}
// ApplyChanges updates the object with values found in the map and returns the "delta"
// of the changes.
func (fk *FIDOKey) ApplyChanges(values map[string]string) (string, error) {
orig := new(FIDOKey)
*orig = *fk
allowed := fk.AllowedUpdateFields()
for k, v := range values {
if _, ok := allowed[k]; !ok {
return "", errors.Errorf("update field not allowed %s", k)
}
switch k {
case "state":
_, err := NewState(v)
if err != nil {
return "", err
}
fk.State = v
}
}
return cmp.Diff(orig, fk), nil
}
// TouchLastUsed updates the last used field with the current time.
func (fk *FIDOKey) TouchLastUsed(ctx context.Context, db db.DB) error {
fk.LastUsed = time.Now()
return db.Save(fk).Error
}
// FIDOKeys returns a list of managed FIDOKeys.
func FIDOKeys(ctx context.Context, dbConn db.DB, params *util.APIParams) ([]*FIDOKey, int64, error) {
var count int64
entries := make([]*FIDOKey, 0)
dbConn, countDB, _ := db.QueryStatement(dbConn, "fido_keys", params, _fidoKeyAPIToDBFields)
err := dbConn.Find(&entries).Error
if err != nil {
return entries, 0, err
}
// get total record count
err = countDB.Select("count(*)").Row().Scan(&count)
return entries, count, err
}
// CAKey represents an Ofte-specific key generated by an Ofte key device that implements
// continuous authentication. Only used when Ofte CA is integrated, see https://ofte.io.
type CAKey struct {
// Ofte key handle
ID string `json:"id"`
FIDOKeyID string `gorm:"column:fidokey_id" json:"fidoKeyId"`
PrincipalID string `gorm:"index" json:"principalId"`
Raw []byte `json:"raw"`
CreatedAt time.Time `gorm:"index" json:"createdAt"`
ModifiedAt time.Time `gorm:"index" json:"modifiedAt"`
}
// TableName overrides the naming of this table in the DB.
func (CAKey) TableName() string {
return "ofte_keys"
}