-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
session_revival_token.go
73 lines (66 loc) · 2.74 KB
/
session_revival_token.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
// Copyright 2022 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package sql
import (
"github.com/cockroachdb/cockroach/pkg/security"
"github.com/cockroachdb/cockroach/pkg/security/sessionrevival"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
)
// CreateSessionRevivalToken is a wrapper for createSessionRevivalToken, and
// uses the planner.
func (p *planner) CreateSessionRevivalToken() (*tree.DBytes, error) {
cm, err := p.ExecCfg().RPCContext.SecurityContext.GetCertificateManager()
if err != nil {
return nil, err
}
return createSessionRevivalToken(p.ExecCfg().AllowSessionRevival, p.SessionData(), cm)
}
// createSessionRevivalToken creates a session revival token for the current
// user.
//
// NOTE: This is used within an observer statement directly, and should not rely
// on the planner because those statements do not get planned.
func createSessionRevivalToken(
allowSessionRevival bool, sd *sessiondata.SessionData, cm *security.CertificateManager,
) (*tree.DBytes, error) {
if !allowSessionRevival {
return nil, pgerror.New(pgcode.FeatureNotSupported, "session revival tokens are not supported on this cluster")
}
// Note that we use SessionUser here and not CurrentUser, since when the
// token is used to create a new session, it should be for the user who was
// originally authenticated. (Whereas CurrentUser could be a different user
// if SET ROLE had been used.)
user := sd.SessionUser()
if user.IsRootUser() {
return nil, pgerror.New(pgcode.InsufficientPrivilege, "cannot create token for root user")
}
tokenBytes, err := sessionrevival.CreateSessionRevivalToken(cm, user)
if err != nil {
return nil, err
}
return tree.NewDBytes(tree.DBytes(tokenBytes)), nil
}
// ValidateSessionRevivalToken validates a session revival token.
func (p *planner) ValidateSessionRevivalToken(token *tree.DBytes) (*tree.DBool, error) {
if !p.ExecCfg().AllowSessionRevival {
return nil, pgerror.New(pgcode.FeatureNotSupported, "session revival tokens are not supported on this cluster")
}
cm, err := p.ExecCfg().RPCContext.SecurityContext.GetCertificateManager()
if err != nil {
return nil, err
}
if err := sessionrevival.ValidateSessionRevivalToken(cm, p.SessionData().SessionUser(), []byte(*token)); err != nil {
return nil, err
}
return tree.DBoolTrue, nil
}