THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

This is Gitea test Portainer repository mirror from Github
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

139 lines
3.4 KiB

  1. package client
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "net/http"
  9. "net/url"
  10. "strings"
  11. "time"
  12. "github.com/portainer/portainer/api"
  13. )
  14. const (
  15. errInvalidResponseStatus = portainer.Error("Invalid response status (expecting 200)")
  16. defaultHTTPTimeout = 5
  17. )
  18. // HTTPClient represents a client to send HTTP requests.
  19. type HTTPClient struct {
  20. *http.Client
  21. }
  22. // NewHTTPClient is used to build a new HTTPClient.
  23. func NewHTTPClient() *HTTPClient {
  24. return &HTTPClient{
  25. &http.Client{
  26. Timeout: time.Second * time.Duration(defaultHTTPTimeout),
  27. },
  28. }
  29. }
  30. // AzureAuthenticationResponse represents an Azure API authentication response.
  31. type AzureAuthenticationResponse struct {
  32. AccessToken string `json:"access_token"`
  33. ExpiresOn string `json:"expires_on"`
  34. }
  35. // ExecuteAzureAuthenticationRequest is used to execute an authentication request
  36. // against the Azure API. It re-uses the same http.Client.
  37. func (client *HTTPClient) ExecuteAzureAuthenticationRequest(credentials *portainer.AzureCredentials) (*AzureAuthenticationResponse, error) {
  38. loginURL := fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/token", credentials.TenantID)
  39. params := url.Values{
  40. "grant_type": {"client_credentials"},
  41. "client_id": {credentials.ApplicationID},
  42. "client_secret": {credentials.AuthenticationKey},
  43. "resource": {"https://management.azure.com/"},
  44. }
  45. response, err := client.PostForm(loginURL, params)
  46. if err != nil {
  47. return nil, err
  48. }
  49. if response.StatusCode != http.StatusOK {
  50. return nil, portainer.ErrAzureInvalidCredentials
  51. }
  52. var token AzureAuthenticationResponse
  53. err = json.NewDecoder(response.Body).Decode(&token)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return &token, nil
  58. }
  59. // Get executes a simple HTTP GET to the specified URL and returns
  60. // the content of the response body. Timeout can be specified via the timeout parameter,
  61. // will default to defaultHTTPTimeout if set to 0.
  62. func Get(url string, timeout int) ([]byte, error) {
  63. if timeout == 0 {
  64. timeout = defaultHTTPTimeout
  65. }
  66. client := &http.Client{
  67. Timeout: time.Second * time.Duration(timeout),
  68. }
  69. response, err := client.Get(url)
  70. if err != nil {
  71. return nil, err
  72. }
  73. defer response.Body.Close()
  74. if response.StatusCode != http.StatusOK {
  75. log.Printf("[ERROR] [http,client] [message: unexpected status code] [status_code: %d]", response.StatusCode)
  76. return nil, errInvalidResponseStatus
  77. }
  78. body, err := ioutil.ReadAll(response.Body)
  79. if err != nil {
  80. return nil, err
  81. }
  82. return body, nil
  83. }
  84. // ExecutePingOperation will send a SystemPing operation HTTP request to a Docker environment
  85. // using the specified host and optional TLS configuration.
  86. // It uses a new Http.Client for each operation.
  87. func ExecutePingOperation(host string, tlsConfig *tls.Config) (bool, error) {
  88. transport := &http.Transport{}
  89. scheme := "http"
  90. if tlsConfig != nil {
  91. transport.TLSClientConfig = tlsConfig
  92. scheme = "https"
  93. }
  94. client := &http.Client{
  95. Timeout: time.Second * 3,
  96. Transport: transport,
  97. }
  98. target := strings.Replace(host, "tcp://", scheme+"://", 1)
  99. return pingOperation(client, target)
  100. }
  101. func pingOperation(client *http.Client, target string) (bool, error) {
  102. pingOperationURL := target + "/_ping"
  103. response, err := client.Get(pingOperationURL)
  104. if err != nil {
  105. return false, err
  106. }
  107. agentOnDockerEnvironment := false
  108. if response.Header.Get(portainer.PortainerAgentHeader) != "" {
  109. agentOnDockerEnvironment = true
  110. }
  111. return agentOnDockerEnvironment, nil
  112. }