-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathutil.go
100 lines (82 loc) · 2.9 KB
/
util.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
package replidentity
import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"golang.org/x/crypto/ed25519"
)
// ReadPublicKeyFromEnv provides a [PubKeySource] that reads public keys from the `REPL_PUBKEYS`
// environment variable that is present in all repls.
func ReadPublicKeyFromEnv(keyid, issuer string) (ed25519.PublicKey, error) {
var pubkeys map[string]json.RawMessage
err := json.Unmarshal([]byte(os.Getenv("REPL_PUBKEYS")), &pubkeys)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal REPL_PUBKEYS: %w", err)
}
pubkey, ok := pubkeys[keyid]
if !ok {
// no key
return nil, nil
}
var keyBase64 string
err = json.Unmarshal(pubkey, &keyBase64)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal pubkey value: %w", err)
}
keyBytes, err := base64.StdEncoding.DecodeString(keyBase64)
if err != nil {
return nil, fmt.Errorf("failed to parse public key as base64: %w", err)
}
return ed25519.PublicKey(keyBytes), nil
}
// CreateIdentityTokenSigningAuthority creates a signing authority with this repl's identity key.
func CreateIdentityTokenSigningAuthority() (*SigningAuthority, error) {
if os.Getenv("REPL_OWNER") == "five-nine" {
return nil, fmt.Errorf("not logged into Replit, no identity present")
}
identitySigningAuthorityToken, identitySigningAuthorityKey := readIdentity()
if identitySigningAuthorityToken == "" {
return nil, fmt.Errorf("could not read token from /tmp/replidentity or REPL_IDENTITY env var")
}
if identitySigningAuthorityKey == "" {
return nil, fmt.Errorf("could not read key from /tmp/replidentity.key or REPL_IDENTITY_KEY env var")
}
return NewSigningAuthority(
identitySigningAuthorityKey,
identitySigningAuthorityToken,
os.Getenv("REPL_ID"),
ReadPublicKeyFromEnv,
)
}
// CreateIdentityTokenAddressedTo returns a Replit identity token that proves this Repl's identity
// that includes an audience claim to restrict forwarding. It creates a new signing authority each
// time, which can be slow. If you plan on signing multiple tokens, use
// CreateIdentityTokenSigningAuthority() to create an authority to sign with.
func CreateIdentityTokenAddressedTo(audience string) (string, error) {
signingAuthority, err := CreateIdentityTokenSigningAuthority()
if err != nil {
return "", err
}
if signingAuthority == nil {
return "", fmt.Errorf("no signing authority could be created")
}
identityToken, err := signingAuthority.Sign(audience)
if err != nil {
return "", err
}
return identityToken, nil
}
// Try to read from /tmp/replidentity and /tmp/replidentity.key,
// falling back to the environment variables.
func readIdentity() (string, string) {
identity, err := os.ReadFile("/tmp/replidentity")
if err != nil {
identity = []byte(os.Getenv("REPL_IDENTITY"))
}
identityKey, err := os.ReadFile("/tmp/replidentity.key")
if err != nil {
identityKey = []byte(os.Getenv("REPL_IDENTITY_KEY"))
}
return string(identity), string(identityKey)
}