-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathauth.go
104 lines (83 loc) · 2.65 KB
/
auth.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
// Package replidentity provides verification utilities for Repl Identity tokens.
package replidentity
import (
"encoding/base64"
"fmt"
"github.com/o1egl/paseto"
"golang.org/x/crypto/ed25519"
"google.golang.org/protobuf/proto"
"github.com/replit/go-replidentity/protos/external/goval/api"
)
// PubKeySource provides an interface for looking up an [ed25519.PublicKey] from some external source.
type PubKeySource func(keyid, issuer string) (ed25519.PublicKey, error)
// MessageClaims is a collection of indexable claims that are made by a certificate.
type MessageClaims struct {
Repls map[string]struct{}
Users map[string]struct{}
UserIDs map[int64]struct{}
Orgs map[OrgKey]struct{}
Clusters map[string]struct{}
Subclusters map[string]struct{}
Flags map[api.FlagClaim]struct{}
}
type OrgKey struct {
Id string
Typ api.Org_OrgType
}
func parseClaims(cert *api.GovalCert) *MessageClaims {
if cert == nil {
return nil
}
claims := MessageClaims{
Repls: map[string]struct{}{},
Users: map[string]struct{}{},
UserIDs: map[int64]struct{}{},
Orgs: map[OrgKey]struct{}{},
Clusters: map[string]struct{}{},
Subclusters: map[string]struct{}{},
Flags: map[api.FlagClaim]struct{}{},
}
for _, claim := range cert.Claims {
switch typedClaim := claim.Claim.(type) {
case *api.CertificateClaim_Replid:
claims.Repls[typedClaim.Replid] = struct{}{}
case *api.CertificateClaim_User:
claims.Users[typedClaim.User] = struct{}{}
case *api.CertificateClaim_UserId:
claims.UserIDs[typedClaim.UserId] = struct{}{}
case *api.CertificateClaim_Org:
orgKey := OrgKey{
Id: typedClaim.Org.Id,
Typ: typedClaim.Org.Type,
}
claims.Orgs[orgKey] = struct{}{}
case *api.CertificateClaim_Cluster:
claims.Clusters[typedClaim.Cluster] = struct{}{}
case *api.CertificateClaim_Subcluster:
claims.Subclusters[typedClaim.Subcluster] = struct{}{}
case *api.CertificateClaim_Flag:
claims.Flags[typedClaim.Flag] = struct{}{}
}
}
return &claims
}
func getSigningAuthority(message string) (*api.GovalSigningAuthority, error) {
var encodedFooter string
err := paseto.ParseFooter(message, &encodedFooter)
if err != nil {
return nil, err
}
if len(encodedFooter) == 0 {
return nil, fmt.Errorf("footer is empty")
}
footerBytes, err := base64.StdEncoding.DecodeString(encodedFooter)
if err != nil {
return nil, fmt.Errorf("failed to decode footer: %w", err)
}
var signingAuthority api.GovalSigningAuthority
err = proto.Unmarshal(footerBytes, &signingAuthority)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal footer: %w", err)
}
return &signingAuthority, nil
}