config.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package rest
  14. import (
  15. "context"
  16. "errors"
  17. "fmt"
  18. "net"
  19. "net/http"
  20. "net/url"
  21. "os"
  22. "path/filepath"
  23. gruntime "runtime"
  24. "strings"
  25. "time"
  26. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. "k8s.io/apimachinery/pkg/runtime"
  28. "k8s.io/apimachinery/pkg/runtime/schema"
  29. "k8s.io/client-go/pkg/version"
  30. clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
  31. "k8s.io/client-go/transport"
  32. certutil "k8s.io/client-go/util/cert"
  33. "k8s.io/client-go/util/flowcontrol"
  34. "k8s.io/klog/v2"
  35. )
  36. const (
  37. DefaultQPS float32 = 5.0
  38. DefaultBurst int = 10
  39. )
  40. var ErrNotInCluster = errors.New("unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined")
  41. // Config holds the common attributes that can be passed to a Kubernetes client on
  42. // initialization.
  43. type Config struct {
  44. // Host must be a host string, a host:port pair, or a URL to the base of the apiserver.
  45. // If a URL is given then the (optional) Path of that URL represents a prefix that must
  46. // be appended to all request URIs used to access the apiserver. This allows a frontend
  47. // proxy to easily relocate all of the apiserver endpoints.
  48. Host string
  49. // APIPath is a sub-path that points to an API root.
  50. APIPath string
  51. // ContentConfig contains settings that affect how objects are transformed when
  52. // sent to the server.
  53. ContentConfig
  54. // Server requires Basic authentication
  55. Username string
  56. Password string `datapolicy:"password"`
  57. // Server requires Bearer authentication. This client will not attempt to use
  58. // refresh tokens for an OAuth2 flow.
  59. // TODO: demonstrate an OAuth2 compatible client.
  60. BearerToken string `datapolicy:"token"`
  61. // Path to a file containing a BearerToken.
  62. // If set, the contents are periodically read.
  63. // The last successfully read value takes precedence over BearerToken.
  64. BearerTokenFile string
  65. // Impersonate is the configuration that RESTClient will use for impersonation.
  66. Impersonate ImpersonationConfig
  67. // Server requires plugin-specified authentication.
  68. AuthProvider *clientcmdapi.AuthProviderConfig
  69. // Callback to persist config for AuthProvider.
  70. AuthConfigPersister AuthProviderConfigPersister
  71. // Exec-based authentication provider.
  72. ExecProvider *clientcmdapi.ExecConfig
  73. // TLSClientConfig contains settings to enable transport layer security
  74. TLSClientConfig
  75. // UserAgent is an optional field that specifies the caller of this request.
  76. UserAgent string
  77. // DisableCompression bypasses automatic GZip compression requests to the
  78. // server.
  79. DisableCompression bool
  80. // Transport may be used for custom HTTP behavior. This attribute may not
  81. // be specified with the TLS client certificate options. Use WrapTransport
  82. // to provide additional per-server middleware behavior.
  83. Transport http.RoundTripper
  84. // WrapTransport will be invoked for custom HTTP behavior after the underlying
  85. // transport is initialized (either the transport created from TLSClientConfig,
  86. // Transport, or http.DefaultTransport). The config may layer other RoundTrippers
  87. // on top of the returned RoundTripper.
  88. //
  89. // A future release will change this field to an array. Use config.Wrap()
  90. // instead of setting this value directly.
  91. WrapTransport transport.WrapperFunc
  92. // QPS indicates the maximum QPS to the master from this client.
  93. // If it's zero, the created RESTClient will use DefaultQPS: 5
  94. QPS float32
  95. // Maximum burst for throttle.
  96. // If it's zero, the created RESTClient will use DefaultBurst: 10.
  97. Burst int
  98. // Rate limiter for limiting connections to the master from this client. If present overwrites QPS/Burst
  99. RateLimiter flowcontrol.RateLimiter
  100. // WarningHandler handles warnings in server responses.
  101. // If not set, the default warning handler is used.
  102. // See documentation for SetDefaultWarningHandler() for details.
  103. WarningHandler WarningHandler
  104. // The maximum length of time to wait before giving up on a server request. A value of zero means no timeout.
  105. Timeout time.Duration
  106. // Dial specifies the dial function for creating unencrypted TCP connections.
  107. Dial func(ctx context.Context, network, address string) (net.Conn, error)
  108. // Proxy is the proxy func to be used for all requests made by this
  109. // transport. If Proxy is nil, http.ProxyFromEnvironment is used. If Proxy
  110. // returns a nil *URL, no proxy is used.
  111. //
  112. // socks5 proxying does not currently support spdy streaming endpoints.
  113. Proxy func(*http.Request) (*url.URL, error)
  114. // Version forces a specific version to be used (if registered)
  115. // Do we need this?
  116. // Version string
  117. }
  118. var _ fmt.Stringer = new(Config)
  119. var _ fmt.GoStringer = new(Config)
  120. type sanitizedConfig *Config
  121. type sanitizedAuthConfigPersister struct{ AuthProviderConfigPersister }
  122. func (sanitizedAuthConfigPersister) GoString() string {
  123. return "rest.AuthProviderConfigPersister(--- REDACTED ---)"
  124. }
  125. func (sanitizedAuthConfigPersister) String() string {
  126. return "rest.AuthProviderConfigPersister(--- REDACTED ---)"
  127. }
  128. type sanitizedObject struct{ runtime.Object }
  129. func (sanitizedObject) GoString() string {
  130. return "runtime.Object(--- REDACTED ---)"
  131. }
  132. func (sanitizedObject) String() string {
  133. return "runtime.Object(--- REDACTED ---)"
  134. }
  135. // GoString implements fmt.GoStringer and sanitizes sensitive fields of Config
  136. // to prevent accidental leaking via logs.
  137. func (c *Config) GoString() string {
  138. return c.String()
  139. }
  140. // String implements fmt.Stringer and sanitizes sensitive fields of Config to
  141. // prevent accidental leaking via logs.
  142. func (c *Config) String() string {
  143. if c == nil {
  144. return "<nil>"
  145. }
  146. cc := sanitizedConfig(CopyConfig(c))
  147. // Explicitly mark non-empty credential fields as redacted.
  148. if cc.Password != "" {
  149. cc.Password = "--- REDACTED ---"
  150. }
  151. if cc.BearerToken != "" {
  152. cc.BearerToken = "--- REDACTED ---"
  153. }
  154. if cc.AuthConfigPersister != nil {
  155. cc.AuthConfigPersister = sanitizedAuthConfigPersister{cc.AuthConfigPersister}
  156. }
  157. if cc.ExecProvider != nil && cc.ExecProvider.Config != nil {
  158. cc.ExecProvider.Config = sanitizedObject{Object: cc.ExecProvider.Config}
  159. }
  160. return fmt.Sprintf("%#v", cc)
  161. }
  162. // ImpersonationConfig has all the available impersonation options
  163. type ImpersonationConfig struct {
  164. // UserName is the username to impersonate on each request.
  165. UserName string
  166. // UID is a unique value that identifies the user.
  167. UID string
  168. // Groups are the groups to impersonate on each request.
  169. Groups []string
  170. // Extra is a free-form field which can be used to link some authentication information
  171. // to authorization information. This field allows you to impersonate it.
  172. Extra map[string][]string
  173. }
  174. // +k8s:deepcopy-gen=true
  175. // TLSClientConfig contains settings to enable transport layer security
  176. type TLSClientConfig struct {
  177. // Server should be accessed without verifying the TLS certificate. For testing only.
  178. Insecure bool
  179. // ServerName is passed to the server for SNI and is used in the client to check server
  180. // certificates against. If ServerName is empty, the hostname used to contact the
  181. // server is used.
  182. ServerName string
  183. // Server requires TLS client certificate authentication
  184. CertFile string
  185. // Server requires TLS client certificate authentication
  186. KeyFile string
  187. // Trusted root certificates for server
  188. CAFile string
  189. // CertData holds PEM-encoded bytes (typically read from a client certificate file).
  190. // CertData takes precedence over CertFile
  191. CertData []byte
  192. // KeyData holds PEM-encoded bytes (typically read from a client certificate key file).
  193. // KeyData takes precedence over KeyFile
  194. KeyData []byte `datapolicy:"security-key"`
  195. // CAData holds PEM-encoded bytes (typically read from a root certificates bundle).
  196. // CAData takes precedence over CAFile
  197. CAData []byte
  198. // NextProtos is a list of supported application level protocols, in order of preference.
  199. // Used to populate tls.Config.NextProtos.
  200. // To indicate to the server http/1.1 is preferred over http/2, set to ["http/1.1", "h2"] (though the server is free to ignore that preference).
  201. // To use only http/1.1, set to ["http/1.1"].
  202. NextProtos []string
  203. }
  204. var _ fmt.Stringer = TLSClientConfig{}
  205. var _ fmt.GoStringer = TLSClientConfig{}
  206. type sanitizedTLSClientConfig TLSClientConfig
  207. // GoString implements fmt.GoStringer and sanitizes sensitive fields of
  208. // TLSClientConfig to prevent accidental leaking via logs.
  209. func (c TLSClientConfig) GoString() string {
  210. return c.String()
  211. }
  212. // String implements fmt.Stringer and sanitizes sensitive fields of
  213. // TLSClientConfig to prevent accidental leaking via logs.
  214. func (c TLSClientConfig) String() string {
  215. cc := sanitizedTLSClientConfig{
  216. Insecure: c.Insecure,
  217. ServerName: c.ServerName,
  218. CertFile: c.CertFile,
  219. KeyFile: c.KeyFile,
  220. CAFile: c.CAFile,
  221. CertData: c.CertData,
  222. KeyData: c.KeyData,
  223. CAData: c.CAData,
  224. NextProtos: c.NextProtos,
  225. }
  226. // Explicitly mark non-empty credential fields as redacted.
  227. if len(cc.CertData) != 0 {
  228. cc.CertData = []byte("--- TRUNCATED ---")
  229. }
  230. if len(cc.KeyData) != 0 {
  231. cc.KeyData = []byte("--- REDACTED ---")
  232. }
  233. return fmt.Sprintf("%#v", cc)
  234. }
  235. type ContentConfig struct {
  236. // AcceptContentTypes specifies the types the client will accept and is optional.
  237. // If not set, ContentType will be used to define the Accept header
  238. AcceptContentTypes string
  239. // ContentType specifies the wire format used to communicate with the server.
  240. // This value will be set as the Accept header on requests made to the server, and
  241. // as the default content type on any object sent to the server. If not set,
  242. // "application/json" is used.
  243. ContentType string
  244. // GroupVersion is the API version to talk to. Must be provided when initializing
  245. // a RESTClient directly. When initializing a Client, will be set with the default
  246. // code version.
  247. GroupVersion *schema.GroupVersion
  248. // NegotiatedSerializer is used for obtaining encoders and decoders for multiple
  249. // supported media types.
  250. //
  251. // TODO: NegotiatedSerializer will be phased out as internal clients are removed
  252. // from Kubernetes.
  253. NegotiatedSerializer runtime.NegotiatedSerializer
  254. }
  255. // RESTClientFor returns a RESTClient that satisfies the requested attributes on a client Config
  256. // object. Note that a RESTClient may require fields that are optional when initializing a Client.
  257. // A RESTClient created by this method is generic - it expects to operate on an API that follows
  258. // the Kubernetes conventions, but may not be the Kubernetes API.
  259. // RESTClientFor is equivalent to calling RESTClientForConfigAndClient(config, httpClient),
  260. // where httpClient was generated with HTTPClientFor(config).
  261. func RESTClientFor(config *Config) (*RESTClient, error) {
  262. if config.GroupVersion == nil {
  263. return nil, fmt.Errorf("GroupVersion is required when initializing a RESTClient")
  264. }
  265. if config.NegotiatedSerializer == nil {
  266. return nil, fmt.Errorf("NegotiatedSerializer is required when initializing a RESTClient")
  267. }
  268. // Validate config.Host before constructing the transport/client so we can fail fast.
  269. // ServerURL will be obtained later in RESTClientForConfigAndClient()
  270. _, _, err := DefaultServerUrlFor(config)
  271. if err != nil {
  272. return nil, err
  273. }
  274. httpClient, err := HTTPClientFor(config)
  275. if err != nil {
  276. return nil, err
  277. }
  278. return RESTClientForConfigAndClient(config, httpClient)
  279. }
  280. // RESTClientForConfigAndClient returns a RESTClient that satisfies the requested attributes on a
  281. // client Config object.
  282. // Unlike RESTClientFor, RESTClientForConfigAndClient allows to pass an http.Client that is shared
  283. // between all the API Groups and Versions.
  284. // Note that the http client takes precedence over the transport values configured.
  285. // The http client defaults to the `http.DefaultClient` if nil.
  286. func RESTClientForConfigAndClient(config *Config, httpClient *http.Client) (*RESTClient, error) {
  287. if config.GroupVersion == nil {
  288. return nil, fmt.Errorf("GroupVersion is required when initializing a RESTClient")
  289. }
  290. if config.NegotiatedSerializer == nil {
  291. return nil, fmt.Errorf("NegotiatedSerializer is required when initializing a RESTClient")
  292. }
  293. baseURL, versionedAPIPath, err := DefaultServerUrlFor(config)
  294. if err != nil {
  295. return nil, err
  296. }
  297. rateLimiter := config.RateLimiter
  298. if rateLimiter == nil {
  299. qps := config.QPS
  300. if config.QPS == 0.0 {
  301. qps = DefaultQPS
  302. }
  303. burst := config.Burst
  304. if config.Burst == 0 {
  305. burst = DefaultBurst
  306. }
  307. if qps > 0 {
  308. rateLimiter = flowcontrol.NewTokenBucketRateLimiter(qps, burst)
  309. }
  310. }
  311. var gv schema.GroupVersion
  312. if config.GroupVersion != nil {
  313. gv = *config.GroupVersion
  314. }
  315. clientContent := ClientContentConfig{
  316. AcceptContentTypes: config.AcceptContentTypes,
  317. ContentType: config.ContentType,
  318. GroupVersion: gv,
  319. Negotiator: runtime.NewClientNegotiator(config.NegotiatedSerializer, gv),
  320. }
  321. restClient, err := NewRESTClient(baseURL, versionedAPIPath, clientContent, rateLimiter, httpClient)
  322. if err == nil && config.WarningHandler != nil {
  323. restClient.warningHandler = config.WarningHandler
  324. }
  325. return restClient, err
  326. }
  327. // UnversionedRESTClientFor is the same as RESTClientFor, except that it allows
  328. // the config.Version to be empty.
  329. func UnversionedRESTClientFor(config *Config) (*RESTClient, error) {
  330. if config.NegotiatedSerializer == nil {
  331. return nil, fmt.Errorf("NegotiatedSerializer is required when initializing a RESTClient")
  332. }
  333. // Validate config.Host before constructing the transport/client so we can fail fast.
  334. // ServerURL will be obtained later in UnversionedRESTClientForConfigAndClient()
  335. _, _, err := DefaultServerUrlFor(config)
  336. if err != nil {
  337. return nil, err
  338. }
  339. httpClient, err := HTTPClientFor(config)
  340. if err != nil {
  341. return nil, err
  342. }
  343. return UnversionedRESTClientForConfigAndClient(config, httpClient)
  344. }
  345. // UnversionedRESTClientForConfigAndClient is the same as RESTClientForConfigAndClient,
  346. // except that it allows the config.Version to be empty.
  347. func UnversionedRESTClientForConfigAndClient(config *Config, httpClient *http.Client) (*RESTClient, error) {
  348. if config.NegotiatedSerializer == nil {
  349. return nil, fmt.Errorf("NegotiatedSerializer is required when initializing a RESTClient")
  350. }
  351. baseURL, versionedAPIPath, err := DefaultServerUrlFor(config)
  352. if err != nil {
  353. return nil, err
  354. }
  355. rateLimiter := config.RateLimiter
  356. if rateLimiter == nil {
  357. qps := config.QPS
  358. if config.QPS == 0.0 {
  359. qps = DefaultQPS
  360. }
  361. burst := config.Burst
  362. if config.Burst == 0 {
  363. burst = DefaultBurst
  364. }
  365. if qps > 0 {
  366. rateLimiter = flowcontrol.NewTokenBucketRateLimiter(qps, burst)
  367. }
  368. }
  369. gv := metav1.SchemeGroupVersion
  370. if config.GroupVersion != nil {
  371. gv = *config.GroupVersion
  372. }
  373. clientContent := ClientContentConfig{
  374. AcceptContentTypes: config.AcceptContentTypes,
  375. ContentType: config.ContentType,
  376. GroupVersion: gv,
  377. Negotiator: runtime.NewClientNegotiator(config.NegotiatedSerializer, gv),
  378. }
  379. restClient, err := NewRESTClient(baseURL, versionedAPIPath, clientContent, rateLimiter, httpClient)
  380. if err == nil && config.WarningHandler != nil {
  381. restClient.warningHandler = config.WarningHandler
  382. }
  383. return restClient, err
  384. }
  385. // SetKubernetesDefaults sets default values on the provided client config for accessing the
  386. // Kubernetes API or returns an error if any of the defaults are impossible or invalid.
  387. func SetKubernetesDefaults(config *Config) error {
  388. if len(config.UserAgent) == 0 {
  389. config.UserAgent = DefaultKubernetesUserAgent()
  390. }
  391. return nil
  392. }
  393. // adjustCommit returns sufficient significant figures of the commit's git hash.
  394. func adjustCommit(c string) string {
  395. if len(c) == 0 {
  396. return "unknown"
  397. }
  398. if len(c) > 7 {
  399. return c[:7]
  400. }
  401. return c
  402. }
  403. // adjustVersion strips "alpha", "beta", etc. from version in form
  404. // major.minor.patch-[alpha|beta|etc].
  405. func adjustVersion(v string) string {
  406. if len(v) == 0 {
  407. return "unknown"
  408. }
  409. seg := strings.SplitN(v, "-", 2)
  410. return seg[0]
  411. }
  412. // adjustCommand returns the last component of the
  413. // OS-specific command path for use in User-Agent.
  414. func adjustCommand(p string) string {
  415. // Unlikely, but better than returning "".
  416. if len(p) == 0 {
  417. return "unknown"
  418. }
  419. return filepath.Base(p)
  420. }
  421. // buildUserAgent builds a User-Agent string from given args.
  422. func buildUserAgent(command, version, os, arch, commit string) string {
  423. return fmt.Sprintf(
  424. "%s/%s (%s/%s) kubernetes/%s", command, version, os, arch, commit)
  425. }
  426. // DefaultKubernetesUserAgent returns a User-Agent string built from static global vars.
  427. func DefaultKubernetesUserAgent() string {
  428. return buildUserAgent(
  429. adjustCommand(os.Args[0]),
  430. adjustVersion(version.Get().GitVersion),
  431. gruntime.GOOS,
  432. gruntime.GOARCH,
  433. adjustCommit(version.Get().GitCommit))
  434. }
  435. // InClusterConfig returns a config object which uses the service account
  436. // kubernetes gives to pods. It's intended for clients that expect to be
  437. // running inside a pod running on kubernetes. It will return ErrNotInCluster
  438. // if called from a process not running in a kubernetes environment.
  439. func InClusterConfig() (*Config, error) {
  440. const (
  441. tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  442. rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
  443. )
  444. host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")
  445. if len(host) == 0 || len(port) == 0 {
  446. return nil, ErrNotInCluster
  447. }
  448. token, err := os.ReadFile(tokenFile)
  449. if err != nil {
  450. return nil, err
  451. }
  452. tlsClientConfig := TLSClientConfig{}
  453. if _, err := certutil.NewPool(rootCAFile); err != nil {
  454. klog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err)
  455. } else {
  456. tlsClientConfig.CAFile = rootCAFile
  457. }
  458. return &Config{
  459. // TODO: switch to using cluster DNS.
  460. Host: "https://" + net.JoinHostPort(host, port),
  461. TLSClientConfig: tlsClientConfig,
  462. BearerToken: string(token),
  463. BearerTokenFile: tokenFile,
  464. }, nil
  465. }
  466. // IsConfigTransportTLS returns true if and only if the provided
  467. // config will result in a protected connection to the server when it
  468. // is passed to restclient.RESTClientFor(). Use to determine when to
  469. // send credentials over the wire.
  470. //
  471. // Note: the Insecure flag is ignored when testing for this value, so MITM attacks are
  472. // still possible.
  473. func IsConfigTransportTLS(config Config) bool {
  474. baseURL, _, err := DefaultServerUrlFor(&config)
  475. if err != nil {
  476. return false
  477. }
  478. return baseURL.Scheme == "https"
  479. }
  480. // LoadTLSFiles copies the data from the CertFile, KeyFile, and CAFile fields into the CertData,
  481. // KeyData, and CAFile fields, or returns an error. If no error is returned, all three fields are
  482. // either populated or were empty to start.
  483. func LoadTLSFiles(c *Config) error {
  484. var err error
  485. c.CAData, err = dataFromSliceOrFile(c.CAData, c.CAFile)
  486. if err != nil {
  487. return err
  488. }
  489. c.CertData, err = dataFromSliceOrFile(c.CertData, c.CertFile)
  490. if err != nil {
  491. return err
  492. }
  493. c.KeyData, err = dataFromSliceOrFile(c.KeyData, c.KeyFile)
  494. return err
  495. }
  496. // dataFromSliceOrFile returns data from the slice (if non-empty), or from the file,
  497. // or an error if an error occurred reading the file
  498. func dataFromSliceOrFile(data []byte, file string) ([]byte, error) {
  499. if len(data) > 0 {
  500. return data, nil
  501. }
  502. if len(file) > 0 {
  503. fileData, err := os.ReadFile(file)
  504. if err != nil {
  505. return []byte{}, err
  506. }
  507. return fileData, nil
  508. }
  509. return nil, nil
  510. }
  511. func AddUserAgent(config *Config, userAgent string) *Config {
  512. fullUserAgent := DefaultKubernetesUserAgent() + "/" + userAgent
  513. config.UserAgent = fullUserAgent
  514. return config
  515. }
  516. // AnonymousClientConfig returns a copy of the given config with all user credentials (cert/key, bearer token, and username/password) and custom transports (WrapTransport, Transport) removed
  517. func AnonymousClientConfig(config *Config) *Config {
  518. // copy only known safe fields
  519. return &Config{
  520. Host: config.Host,
  521. APIPath: config.APIPath,
  522. ContentConfig: config.ContentConfig,
  523. TLSClientConfig: TLSClientConfig{
  524. Insecure: config.Insecure,
  525. ServerName: config.ServerName,
  526. CAFile: config.TLSClientConfig.CAFile,
  527. CAData: config.TLSClientConfig.CAData,
  528. NextProtos: config.TLSClientConfig.NextProtos,
  529. },
  530. RateLimiter: config.RateLimiter,
  531. WarningHandler: config.WarningHandler,
  532. UserAgent: config.UserAgent,
  533. DisableCompression: config.DisableCompression,
  534. QPS: config.QPS,
  535. Burst: config.Burst,
  536. Timeout: config.Timeout,
  537. Dial: config.Dial,
  538. Proxy: config.Proxy,
  539. }
  540. }
  541. // CopyConfig returns a copy of the given config
  542. func CopyConfig(config *Config) *Config {
  543. c := &Config{
  544. Host: config.Host,
  545. APIPath: config.APIPath,
  546. ContentConfig: config.ContentConfig,
  547. Username: config.Username,
  548. Password: config.Password,
  549. BearerToken: config.BearerToken,
  550. BearerTokenFile: config.BearerTokenFile,
  551. Impersonate: ImpersonationConfig{
  552. UserName: config.Impersonate.UserName,
  553. UID: config.Impersonate.UID,
  554. Groups: config.Impersonate.Groups,
  555. Extra: config.Impersonate.Extra,
  556. },
  557. AuthProvider: config.AuthProvider,
  558. AuthConfigPersister: config.AuthConfigPersister,
  559. ExecProvider: config.ExecProvider,
  560. TLSClientConfig: TLSClientConfig{
  561. Insecure: config.TLSClientConfig.Insecure,
  562. ServerName: config.TLSClientConfig.ServerName,
  563. CertFile: config.TLSClientConfig.CertFile,
  564. KeyFile: config.TLSClientConfig.KeyFile,
  565. CAFile: config.TLSClientConfig.CAFile,
  566. CertData: config.TLSClientConfig.CertData,
  567. KeyData: config.TLSClientConfig.KeyData,
  568. CAData: config.TLSClientConfig.CAData,
  569. NextProtos: config.TLSClientConfig.NextProtos,
  570. },
  571. UserAgent: config.UserAgent,
  572. DisableCompression: config.DisableCompression,
  573. Transport: config.Transport,
  574. WrapTransport: config.WrapTransport,
  575. QPS: config.QPS,
  576. Burst: config.Burst,
  577. RateLimiter: config.RateLimiter,
  578. WarningHandler: config.WarningHandler,
  579. Timeout: config.Timeout,
  580. Dial: config.Dial,
  581. Proxy: config.Proxy,
  582. }
  583. if config.ExecProvider != nil && config.ExecProvider.Config != nil {
  584. c.ExecProvider.Config = config.ExecProvider.Config.DeepCopyObject()
  585. }
  586. return c
  587. }