@@ -3,11 +3,17 @@ package keystone
3
3
import (
4
4
"time"
5
5
6
+ "crypto/aes"
7
+ "crypto/cipher"
8
+ "crypto/rand"
9
+ "encoding/base64"
6
10
"errors"
7
11
"github.com/grafana/grafana/pkg/bus"
12
+ "github.com/grafana/grafana/pkg/log"
8
13
"github.com/grafana/grafana/pkg/middleware"
9
14
m "github.com/grafana/grafana/pkg/models"
10
15
"github.com/grafana/grafana/pkg/setting"
16
+ "io"
11
17
)
12
18
13
19
const (
@@ -19,7 +25,13 @@ const (
19
25
20
26
func getUserName (c * middleware.Context ) (string , error ) {
21
27
var keystoneUserIdObj interface {}
22
- if keystoneUserIdObj = c .Session .Get (middleware .SESS_KEY_USERID ); keystoneUserIdObj == nil {
28
+ if setting .KeystoneCookieCredentials {
29
+ if keystoneUserIdObj = c .GetCookie (setting .CookieUserName ); keystoneUserIdObj == nil {
30
+ return "" , errors .New ("Couldn't find cookie containing keystone userId" )
31
+ } else {
32
+ return keystoneUserIdObj .(string ), nil
33
+ }
34
+ } else if keystoneUserIdObj = c .Session .Get (middleware .SESS_KEY_USERID ); keystoneUserIdObj == nil {
23
35
return "" , errors .New ("Session timed out trying to get keystone userId" )
24
36
}
25
37
@@ -53,8 +65,28 @@ func getNewToken(c *middleware.Context) (string, error) {
53
65
}
54
66
55
67
var keystonePasswordObj interface {}
56
- if keystonePasswordObj = c .Session .Get (middleware .SESS_KEY_PASSWORD ); keystonePasswordObj == nil {
68
+ if setting .KeystoneCookieCredentials {
69
+ if setting .KeystoneCredentialAesKey != "" {
70
+ c .GetCookie (middleware .SESS_KEY_PASSWORD )
71
+ } else {
72
+ keystonePasswordObj = c .GetCookie (middleware .SESS_KEY_PASSWORD )
73
+ }
74
+ if keystonePasswordObj == nil {
75
+ return "" , errors .New ("Couldn't find cookie containing keystone password" )
76
+ } else {
77
+ log .Debug ("Got password from cookie" )
78
+ }
79
+ } else if keystonePasswordObj = c .Session .Get (middleware .SESS_KEY_PASSWORD ); keystonePasswordObj == nil {
57
80
return "" , errors .New ("Session timed out trying to get keystone password" )
81
+ } else if keystonePasswordObj != nil {
82
+ log .Debug ("Got password from session" )
83
+ }
84
+
85
+ if setting .KeystoneCredentialAesKey != "" {
86
+ keystonePasswordObj = decryptPassword (keystonePasswordObj .(string ))
87
+ log .Debug ("Decrypted password" )
88
+ } else {
89
+ log .Warn ("Password stored in cleartext!" )
58
90
}
59
91
60
92
auth := Auth_data {
@@ -65,6 +97,11 @@ func getNewToken(c *middleware.Context) (string, error) {
65
97
Server : setting .KeystoneURL ,
66
98
}
67
99
if err := AuthenticateScoped (& auth ); err != nil {
100
+ if setting .KeystoneCookieCredentials {
101
+ c .SetCookie (middleware .SESS_KEY_PASSWORD , "" , 0 )
102
+ } else {
103
+ c .Session .Set (middleware .SESS_KEY_PASSWORD , nil )
104
+ }
68
105
return "" , err
69
106
}
70
107
@@ -124,3 +161,34 @@ func GetToken(c *middleware.Context) (string, error) {
124
161
}
125
162
return token , nil
126
163
}
164
+
165
+ func EncryptPassword (password string ) string {
166
+ key := []byte (setting .KeystoneCredentialAesKey )
167
+ block , err := aes .NewCipher (key )
168
+ if err != nil {
169
+ log .Error (3 , "Error: NewCipher(%d bytes) = %s" , len (setting .KeystoneCredentialAesKey ), err )
170
+ }
171
+ ciphertext := make ([]byte , aes .BlockSize + len (password ))
172
+ iv := ciphertext [:aes .BlockSize ]
173
+ if _ , err := io .ReadFull (rand .Reader , iv ); err != nil {
174
+ log .Error (3 , "Error: %s" , err )
175
+ }
176
+ stream := cipher .NewOFB (block , iv )
177
+ stream .XORKeyStream (ciphertext [aes .BlockSize :], []byte (password ))
178
+
179
+ return base64 .StdEncoding .EncodeToString (ciphertext )
180
+ }
181
+
182
+ func decryptPassword (base64ciphertext string ) string {
183
+ key := []byte (setting .KeystoneCredentialAesKey )
184
+ block , err := aes .NewCipher (key )
185
+ if err != nil {
186
+ log .Error (3 , "Error: NewCipher(%d bytes) = %s" , len (setting .KeystoneCredentialAesKey ), err )
187
+ }
188
+ ciphertext , err := base64 .StdEncoding .DecodeString (base64ciphertext )
189
+ iv := ciphertext [:aes .BlockSize ]
190
+ password := make ([]byte , len (ciphertext )- aes .BlockSize )
191
+ stream := cipher .NewOFB (block , iv )
192
+ stream .XORKeyStream (password , ciphertext [aes .BlockSize :])
193
+ return string (password )
194
+ }
0 commit comments