github.com/crowdsecurity/crowdsec@v1.6.1/pkg/apiclient/client.go (about) 1 package apiclient 2 3 import ( 4 "context" 5 "crypto/tls" 6 "crypto/x509" 7 "fmt" 8 "net" 9 "net/http" 10 "net/url" 11 "strings" 12 13 "github.com/golang-jwt/jwt/v4" 14 15 "github.com/crowdsecurity/crowdsec/pkg/models" 16 ) 17 18 var ( 19 InsecureSkipVerify = false 20 Cert *tls.Certificate 21 CaCertPool *x509.CertPool 22 ) 23 24 type ApiClient struct { 25 /*The http client used to make requests*/ 26 client *http.Client 27 /*Reuse a single struct instead of allocating one for each service on the heap.*/ 28 common service 29 /*config stuff*/ 30 BaseURL *url.URL 31 PapiURL *url.URL 32 URLPrefix string 33 UserAgent string 34 /*exposed Services*/ 35 Decisions *DecisionsService 36 DecisionDelete *DecisionDeleteService 37 Alerts *AlertsService 38 Auth *AuthService 39 Metrics *MetricsService 40 Signal *SignalService 41 HeartBeat *HeartBeatService 42 } 43 44 func (a *ApiClient) GetClient() *http.Client { 45 return a.client 46 } 47 48 func (a *ApiClient) IsEnrolled() bool { 49 jwtTransport := a.client.Transport.(*JWTTransport) 50 tokenStr := jwtTransport.Token 51 52 token, _ := jwt.Parse(tokenStr, nil) 53 if token == nil { 54 return false 55 } 56 57 claims := token.Claims.(jwt.MapClaims) 58 _, ok := claims["organization_id"] 59 60 return ok 61 } 62 63 type service struct { 64 client *ApiClient 65 } 66 67 func NewClient(config *Config) (*ApiClient, error) { 68 t := &JWTTransport{ 69 MachineID: &config.MachineID, 70 Password: &config.Password, 71 Scenarios: config.Scenarios, 72 UserAgent: config.UserAgent, 73 VersionPrefix: config.VersionPrefix, 74 UpdateScenario: config.UpdateScenario, 75 } 76 77 transport, baseURL := createTransport(config.URL) 78 if transport != nil { 79 t.Transport = transport 80 } 81 82 t.URL = baseURL 83 84 tlsconfig := tls.Config{InsecureSkipVerify: InsecureSkipVerify} 85 tlsconfig.RootCAs = CaCertPool 86 87 if Cert != nil { 88 tlsconfig.Certificates = []tls.Certificate{*Cert} 89 } 90 91 if ht, ok := http.DefaultTransport.(*http.Transport); ok { 92 ht.TLSClientConfig = &tlsconfig 93 } 94 95 c := &ApiClient{client: t.Client(), BaseURL: baseURL, UserAgent: config.UserAgent, URLPrefix: config.VersionPrefix, PapiURL: config.PapiURL} 96 c.common.client = c 97 c.Decisions = (*DecisionsService)(&c.common) 98 c.Alerts = (*AlertsService)(&c.common) 99 c.Auth = (*AuthService)(&c.common) 100 c.Metrics = (*MetricsService)(&c.common) 101 c.Signal = (*SignalService)(&c.common) 102 c.DecisionDelete = (*DecisionDeleteService)(&c.common) 103 c.HeartBeat = (*HeartBeatService)(&c.common) 104 105 return c, nil 106 } 107 108 func NewDefaultClient(URL *url.URL, prefix string, userAgent string, client *http.Client) (*ApiClient, error) { 109 transport, baseURL := createTransport(URL) 110 111 if client == nil { 112 client = &http.Client{} 113 114 if transport != nil { 115 client.Transport = transport 116 } else { 117 if ht, ok := http.DefaultTransport.(*http.Transport); ok { 118 tlsconfig := tls.Config{InsecureSkipVerify: InsecureSkipVerify} 119 tlsconfig.RootCAs = CaCertPool 120 121 if Cert != nil { 122 tlsconfig.Certificates = []tls.Certificate{*Cert} 123 } 124 125 ht.TLSClientConfig = &tlsconfig 126 client.Transport = ht 127 } 128 } 129 } 130 131 c := &ApiClient{client: client, BaseURL: baseURL, UserAgent: userAgent, URLPrefix: prefix} 132 c.common.client = c 133 c.Decisions = (*DecisionsService)(&c.common) 134 c.Alerts = (*AlertsService)(&c.common) 135 c.Auth = (*AuthService)(&c.common) 136 c.Metrics = (*MetricsService)(&c.common) 137 c.Signal = (*SignalService)(&c.common) 138 c.DecisionDelete = (*DecisionDeleteService)(&c.common) 139 c.HeartBeat = (*HeartBeatService)(&c.common) 140 141 return c, nil 142 } 143 144 func RegisterClient(config *Config, client *http.Client) (*ApiClient, error) { 145 transport, baseURL := createTransport(config.URL) 146 147 if client == nil { 148 client = &http.Client{} 149 if transport != nil { 150 client.Transport = transport 151 } else { 152 tlsconfig := tls.Config{InsecureSkipVerify: InsecureSkipVerify} 153 if Cert != nil { 154 tlsconfig.RootCAs = CaCertPool 155 tlsconfig.Certificates = []tls.Certificate{*Cert} 156 } 157 158 http.DefaultTransport.(*http.Transport).TLSClientConfig = &tlsconfig 159 } 160 } else if client.Transport == nil && transport != nil { 161 client.Transport = transport 162 } 163 164 c := &ApiClient{client: client, BaseURL: baseURL, UserAgent: config.UserAgent, URLPrefix: config.VersionPrefix} 165 c.common.client = c 166 c.Decisions = (*DecisionsService)(&c.common) 167 c.Alerts = (*AlertsService)(&c.common) 168 c.Auth = (*AuthService)(&c.common) 169 170 resp, err := c.Auth.RegisterWatcher(context.Background(), models.WatcherRegistrationRequest{MachineID: &config.MachineID, Password: &config.Password}) 171 /*if we have http status, return it*/ 172 if err != nil { 173 if resp != nil && resp.Response != nil { 174 return nil, fmt.Errorf("api register (%s) http %s: %w", c.BaseURL, resp.Response.Status, err) 175 } 176 177 return nil, fmt.Errorf("api register (%s): %w", c.BaseURL, err) 178 } 179 180 return c, nil 181 } 182 183 func createTransport(url *url.URL) (*http.Transport, *url.URL) { 184 urlString := url.String() 185 186 // TCP transport 187 if !strings.HasPrefix(urlString, "/") { 188 return nil, url 189 } 190 191 // Unix transport 192 url.Path = "/" 193 url.Host = "unix" 194 url.Scheme = "http" 195 196 return &http.Transport{ 197 DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { 198 return net.Dial("unix", strings.TrimSuffix(urlString, "/")) 199 }, 200 }, url 201 } 202 203 type Response struct { 204 Response *http.Response 205 // add our pagination stuff 206 // NextPage int 207 // ... 208 } 209 210 func newResponse(r *http.Response) *Response { 211 return &Response{Response: r} 212 } 213 214 type ListOpts struct { 215 // Page int 216 // PerPage int 217 } 218 219 type DeleteOpts struct { 220 // ?? 221 } 222 223 type AddOpts struct { 224 // ?? 225 }