@@ -3,35 +3,28 @@ package infa_auth
3
3
import (
4
4
"context"
5
5
"crypto/tls"
6
- "errors"
7
- "io/ioutil"
8
- "net/http"
9
-
10
6
"crypto/x509"
7
+ "errors"
11
8
"github.com/gofiber/fiber/v2/log"
9
+ "github.com/lwithers/minijks/jks"
12
10
"go.opentelemetry.io/collector/client"
13
11
"go.opentelemetry.io/collector/component"
14
12
"go.opentelemetry.io/collector/extension/auth"
15
13
"go.uber.org/zap"
14
+ "net/http"
16
15
"os"
16
+ "strings"
17
17
"time"
18
18
)
19
19
20
20
type infaAuthExtension struct {
21
- cfg * Config
22
- logger * zap.Logger
21
+ cfg * Config
22
+ logger * zap.Logger
23
+ sessionServiceClient * http.Client
23
24
}
24
25
25
26
func newExtension (ctx context.Context , cfg * Config , logger * zap.Logger ) (auth.Server , error ) {
26
- /*
27
- if cfg.ValidationURL == "" {
28
- return nil, errors.New("validation url is empty")
29
- }
30
27
31
- if cfg.Headerkey == "" {
32
- return nil, errors.New("header key is empty")
33
- }
34
- */
35
28
oe := & infaAuthExtension {
36
29
cfg : cfg ,
37
30
logger : logger ,
@@ -45,71 +38,76 @@ func (e *infaAuthExtension) start(context.Context, component.Host) error {
45
38
log .Debug ("begin executing extension.start" )
46
39
47
40
//validation url and header key must NOT be empty
48
- if e .cfg .ValidationURL == "" {
41
+ if strings . TrimSpace ( e .cfg .ValidationURL ) == "" {
49
42
return errors .New ("ValidationURL is empty" )
50
43
}
51
44
52
- if e .cfg .Headerkey == "" {
45
+ if strings . TrimSpace ( e .cfg .Headerkey ) == "" {
53
46
return errors .New ("Headerkey is empty" )
54
47
}
55
48
56
- /*
57
- if e.cfg.CACertPath == "" {
58
- log.Debug("CACertPath is empty")
59
- return errors.New("CACertPath is empty")
60
- }
49
+ sessionServiceClient , err := getClient (e .cfg )
50
+ e .sessionServiceClient = sessionServiceClient
51
+ if err != nil {
52
+ log .Debug ("error while creating client in extension.start" )
53
+ return err
54
+ }
61
55
62
- log.Debugf("CACertPath is : %s ", e.cfg.CACertPath)
63
- _, error := os.Stat(e.cfg.CACertPath)
64
- if error != nil {
65
- log.Debugf("error reading CACertPath")
66
- return errors.New("error reading CACertPath")
67
- }
68
- */
56
+ log .Debugf ("finished executing extension.start , sessionServiceClient : %A" , sessionServiceClient )
57
+ return nil
58
+ }
69
59
70
- //validate client cert
71
- log .Debugf ("ClientSideSsl is : %s " , e .cfg .ClientSideSsl )
72
- if e .cfg .ClientSideSsl {
73
- log .Debugf ("ClientCertPath is : %s " , e .cfg .ClientCertPath )
74
- if e .cfg .ClientCertPath == "" {
75
- log .Debug ("ClientCertPath is empty" )
76
- return errors .New ("ClientCertPath is empty" )
77
-
78
- } else {
79
- _ , error := os .Stat (e .cfg .ClientCertPath )
80
- if error != nil {
81
- log .Debugf ("error reading ClientCert" )
82
- return errors .New ("error reading ClientCert" )
83
- }
84
- }
60
+ func getJksKeystore (filename string , password string ) (* jks.Keystore , error ) {
85
61
86
- log .Debugf ("ClientKeyPath is : %s " , e .cfg .ClientKeyPath )
87
- if e .cfg .ClientKeyPath == "" {
88
- log .Debug ("ClientKeyPath is empty" )
89
- return errors .New ("ClientKeyPath is empty" )
62
+ jksContent , err := os .ReadFile (filename )
63
+ if err != nil {
64
+ return nil , err
65
+ }
66
+ log .Debug ("read keystorefile : " + filename )
90
67
91
- } else {
92
- _ , error := os . Stat ( e . cfg . ClientKeyPath )
93
- if error != nil {
94
- log . Debugf ( "error reading ClientKeyPath" )
95
- return errors . New ( "error reading ClientKeyPath" )
96
- }
68
+ var opts * jks. Options
69
+ if strings . TrimSpace ( password ) == "" {
70
+ log . Debug ( "password is empty , will use nil options" )
71
+ } else {
72
+ opts = & jks. Options {
73
+ Password : password ,
97
74
}
75
+ }
98
76
77
+ keyStore , err := jks .Parse (jksContent , opts )
78
+ if err != nil {
79
+ return nil , err
99
80
}
81
+ log .Debug ("success read keystorefile : " + filename )
82
+ return keyStore , nil
83
+ }
100
84
101
- log .Debug ("finished executing extension.start" )
102
- return nil
85
+ func getClientCert (ks jks.Keystore ) (* tls.Certificate , error ) {
86
+ cert , err := tls .X509KeyPair (ks .Keypairs [0 ].CertChain [0 ].Cert .Raw , ks .Keypairs [0 ].RawKey )
87
+ if err != nil {
88
+ log .Debugf ("getClientCert ERR %A" , err )
89
+ }
90
+ return & cert , nil
91
+ }
92
+
93
+ func getCACertPool (ks jks.Keystore ) (* x509.CertPool , error ) {
94
+ pool := x509 .NewCertPool ()
95
+ for i := 0 ; i < len (ks .Certs ); i ++ {
96
+ log .Debugf ("adding CA cert to pool : " + string (ks .Certs [i ].Alias ))
97
+ pool .AddCert (ks .Certs [i ].Cert )
98
+ }
99
+ return pool , nil
103
100
}
104
101
105
102
// authenticate checks whether the given context contains valid auth data. Successfully authenticated calls will always return a nil error and a context with the auth data.
106
103
// this associated to the Authenticate() method
107
104
func (e * infaAuthExtension ) authenticate (ctx context.Context , headers map [string ][]string ) (context.Context , error ) {
108
105
log .Debug ("executing extensions.authenticate() " )
109
- log .Debugf ("headers :: %A" , headers )
110
- log .Debugf ("ctx :: %A" , ctx )
111
- log .Debugf ("e.cfg :: %A" , * e .cfg )
112
-
106
+ /*
107
+ log.Debugf("headers :: %A", headers)
108
+ log.Debugf("ctx :: %A", ctx)
109
+ log.Debugf("e.cfg :: %A", *e.cfg)
110
+ */
113
111
var h []string
114
112
115
113
h = headers ["Ids-Agent-Session-Id" ]
@@ -134,81 +132,89 @@ func (e *infaAuthExtension) authenticate(ctx context.Context, headers map[string
134
132
}
135
133
136
134
cl := client .FromContext (ctx )
137
- status , err := validateToken (e . cfg , token )
138
- if err != nil || status == false {
135
+ status , err := validateToken (e , token )
136
+ if err != nil || ! status {
139
137
return ctx , err
140
138
}
141
139
142
140
//success
143
141
return client .NewContext (ctx , cl ), nil
144
142
}
145
143
146
- // this method creates a HTTP client and makes HTTP/S request to session service, if http status is 200 , it returns
147
- // true with nil error , otherwise non-nil error is returned
148
- func validateToken (cfg * Config , sessionToken string ) (bool , error ) {
149
- // Create an HTTP client
150
- log .Debug ("calling extension.validateToken() " )
151
-
144
+ func getClient (cfg * Config ) (* http.Client , error ) {
145
+ var pool * x509.CertPool
146
+ var clientCert * tls.Certificate
147
+ client := & http.Client {
148
+ Timeout : func () time.Duration {
149
+ if cfg .TimeOut > 0 {
150
+ return time .Duration (cfg .TimeOut ) * time .Second
151
+ }
152
+ return 2 * time .Second
153
+ }(),
154
+ }
152
155
tr := & http.Transport {}
156
+ client .Transport = tr
153
157
154
- //read ca-cert file
155
- pool := x509 .NewCertPool ()
156
- if cfg .CACertPath != "" {
157
- cert , err := ioutil .ReadFile (cfg .CACertPath )
158
- if err != nil {
159
- log .Debugf ("Error reading CA certificate: %A" , err )
160
- return false , err
161
- } else {
162
- pool .AppendCertsFromPEM (cert )
163
- tr = & http.Transport {
164
- TLSClientConfig : & tls.Config {InsecureSkipVerify : cfg .InsecureSkipVerify , RootCAs : pool },
165
- }
166
- }
158
+ //create client with no TLS
159
+ if cfg .InsecureSkipVerify {
160
+ tr .TLSClientConfig = & tls.Config {InsecureSkipVerify : true }
161
+ log .Info ("returning client block1 " )
162
+ return client , nil
167
163
} else {
168
- tr = & http.Transport {
169
- TLSClientConfig : & tls.Config {InsecureSkipVerify : cfg .InsecureSkipVerify },
170
- }
171
- }
164
+ //create client with TLS , CACert is mandatory clientCert is optional
165
+ caKs , err := getJksKeystore (cfg .CAJksPath , cfg .CAJksPassword )
172
166
173
- // Load client certificate and private key
174
- if cfg .ClientSideSsl {
175
- cert , err := tls .LoadX509KeyPair (cfg .ClientCertPath , cfg .ClientKeyPath )
176
167
if err != nil {
177
- log .Debugf ( "Error loading client certificate:" , err )
178
- return false , err
168
+ log .Info ( "error while reading CA jksKeystore : " + cfg . CAJksPath )
169
+ return nil , err
179
170
}
180
- config := & tls.Config {
181
- Certificates : []tls.Certificate {cert },
182
- RootCAs : pool ,
183
- InsecureSkipVerify : cfg .InsecureSkipVerify ,
171
+
172
+ pool , err = getCACertPool (* caKs )
173
+ if err != nil {
174
+ log .Info ("error while generating CACertPool : " + cfg .CAJksPath )
175
+ return nil , err
184
176
}
185
- tr = & http.Transport {
186
- TLSClientConfig : config ,
177
+
178
+ tr .TLSClientConfig = & tls.Config {InsecureSkipVerify : false , RootCAs : pool }
179
+
180
+ if cfg .ClientSideSsl {
181
+ clientKs , err := getJksKeystore (cfg .ClientJksPath , cfg .ClientJksPassword )
182
+ if err != nil {
183
+ log .Info ("error while reading Client jksKeystore : " + cfg .ClientJksPath )
184
+ return nil , err
185
+ }
186
+
187
+ clientCert , err = getClientCert (* clientKs )
188
+ if err != nil {
189
+ log .Info ("error while creating Client cert : " + cfg .ClientJksPath )
190
+ return nil , err
191
+ }
192
+
193
+ tr .TLSClientConfig .Certificates = []tls.Certificate {* clientCert }
187
194
}
188
- }
189
195
190
- client := & http.Client {}
191
- if cfg .TimeOut > 0 {
192
- client = & http.Client {
193
- Timeout : time .Duration (cfg .TimeOut ) * time .Second ,
194
- Transport : tr }
195
- } else {
196
- client = & http.Client {
197
- Timeout : 2 * time .Second ,
198
- Transport : tr }
196
+ log .Info ("returning client block2 " )
197
+ client .Transport = tr
198
+ return client , nil
199
199
}
200
+ }
200
201
201
- req , err := http .NewRequest ("GET" , cfg .ValidationURL , nil )
202
+ // this method creates a HTTP client and makes HTTP/S request to session service, if http status is 200 , it returns
203
+ // true with nil error , otherwise non-nil error is returned
204
+ func validateToken (e * infaAuthExtension , sessionToken string ) (bool , error ) {
205
+ // Create an HTTP client
206
+ log .Debug ("calling extension.validateToken() " )
207
+ req , err := http .NewRequest ("GET" , e .cfg .ValidationURL , nil )
202
208
if err != nil {
203
209
log .Debugf ("Error creating request:" , err )
204
210
return false , err
205
211
}
206
212
207
- req .Header .Add (cfg .Headerkey , sessionToken )
213
+ req .Header .Add (e . cfg .Headerkey , sessionToken )
208
214
209
215
// Make the request
210
216
log .Debugf ("invoking http request : %A" , req )
211
- resp , err := client .Do (req )
217
+ resp , err := e . sessionServiceClient .Do (req )
212
218
log .Debugf ("got response %A" , resp )
213
219
214
220
if err != nil {
@@ -218,20 +224,15 @@ func validateToken(cfg *Config, sessionToken string) (bool, error) {
218
224
219
225
if resp .StatusCode != 200 {
220
226
log .Debug ("http status is not 200 in response" )
221
- return false , errors .New ("http status is not 200 in response" )
227
+ body := make ([]byte , 1024 )
228
+ _ , err := resp .Body .Read (body )
229
+ if err != nil {
230
+ log .Debugf ("Error reading response body:" , err )
231
+ return false , err
232
+ }
233
+ return false , errors .New ("http status is not 200 in response response body is " + string (body ))
222
234
}
223
235
224
236
defer resp .Body .Close ()
225
-
226
- // Read the response body
227
- body , err := ioutil .ReadAll (resp .Body )
228
- if err != nil {
229
- log .Debugf ("Error reading response body:" , err )
230
- return false , err
231
- }
232
-
233
- // Print the response
234
- log .Debugf ("response body is %A" , string (body ))
235
237
return true , nil
236
-
237
238
}
0 commit comments