/
settings.go
163 lines (142 loc) · 4.59 KB
/
settings.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package service
import (
"log"
"net/http"
"time"
"github.com/Sireax/gokrb5/v8/keytab"
"github.com/Sireax/gokrb5/v8/types"
)
// Settings defines service side configuration settings.
type Settings struct {
Keytab *keytab.Keytab
ktprinc *types.PrincipalName
sname string
requireHostAddr bool
disablePACDecoding bool
cAddr types.HostAddress
maxClockSkew time.Duration
logger *log.Logger
sessionMgr SessionMgr
}
// NewSettings creates a new service Settings.
func NewSettings(kt *keytab.Keytab, settings ...func(*Settings)) *Settings {
s := new(Settings)
s.Keytab = kt
for _, set := range settings {
set(s)
}
return s
}
// RequireHostAddr used to configure service side to required host addresses to be specified in Kerberos tickets.
//
// s := NewSettings(kt, RequireHostAddr(true))
func RequireHostAddr(b bool) func(*Settings) {
return func(s *Settings) {
s.requireHostAddr = b
}
}
// RequireHostAddr indicates if the service should require the host address to be included in the ticket.
func (s *Settings) RequireHostAddr() bool {
return s.requireHostAddr
}
// DecodePAC used to configure service side to enable/disable PAC decoding if the PAC is present.
// Defaults to enabled if not specified.
//
// s := NewSettings(kt, DecodePAC(false))
func DecodePAC(b bool) func(*Settings) {
return func(s *Settings) {
s.disablePACDecoding = !b
}
}
// DecodePAC indicates whether the service should decode any PAC information present in the ticket.
func (s *Settings) DecodePAC() bool {
return !s.disablePACDecoding
}
// ClientAddress used to configure service side with the clients host address to be used during validation.
//
// s := NewSettings(kt, ClientAddress(h))
func ClientAddress(h types.HostAddress) func(*Settings) {
return func(s *Settings) {
s.cAddr = h
}
}
// ClientAddress returns the client host address which has been provided to the service.
func (s *Settings) ClientAddress() types.HostAddress {
return s.cAddr
}
// Logger used to configure service side with a logger.
//
// s := NewSettings(kt, Logger(l))
func Logger(l *log.Logger) func(*Settings) {
return func(s *Settings) {
s.logger = l
}
}
// Logger returns the logger instances configured for the service. If none is configured nill will be returned.
func (s *Settings) Logger() *log.Logger {
return s.logger
}
// KeytabPrincipal used to override the principal name used to find the key in the keytab.
//
// s := NewSettings(kt, KeytabPrincipal("someaccount"))
func KeytabPrincipal(p string) func(*Settings) {
return func(s *Settings) {
pn, _ := types.ParseSPNString(p)
s.ktprinc = &pn
}
}
// KeytabPrincipal returns the principal name used to find the key in the keytab if it has been overridden.
func (s *Settings) KeytabPrincipal() *types.PrincipalName {
return s.ktprinc
}
// MaxClockSkew used to configure service side with the maximum acceptable clock skew
// between the service and the issue time of kerberos tickets
//
// s := NewSettings(kt, MaxClockSkew(d))
func MaxClockSkew(d time.Duration) func(*Settings) {
return func(s *Settings) {
s.maxClockSkew = d
}
}
// MaxClockSkew returns the maximum acceptable clock skew between the service and the issue time of kerberos tickets.
// If none is defined a duration of 5 minutes is returned.
func (s *Settings) MaxClockSkew() time.Duration {
if s.maxClockSkew.Nanoseconds() == 0 {
return time.Duration(5) * time.Minute
}
return s.maxClockSkew
}
// SName used provide a specific service name to the service settings.
//
// s := NewSettings(kt, SName("HTTP/some.service.com"))
func SName(sname string) func(*Settings) {
return func(s *Settings) {
s.sname = sname
}
}
// SName returns the specific service name to the service.
func (s *Settings) SName() string {
return s.sname
}
// SessionManager configures a session manager to establish sessions with clients to avoid excessive authentication challenges.
//
// s := NewSettings(kt, SessionManager(sm))
func SessionManager(sm SessionMgr) func(*Settings) {
return func(s *Settings) {
s.sessionMgr = sm
}
}
// SessionManager returns any configured session manager.
func (s *Settings) SessionManager() SessionMgr {
return s.sessionMgr
}
// SessionMgr must provide a ways to:
//
// - Create new sessions and in the process add a value to the session under the key provided.
//
// - Get an existing session returning the value in the session under the key provided.
// Return nil bytes and/or error if there is no session.
type SessionMgr interface {
New(w http.ResponseWriter, r *http.Request, k string, v []byte) error
Get(r *http.Request, k string) ([]byte, error)
}