Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add http headers #202

Merged
merged 10 commits into from
Oct 6, 2022
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export PM_API_URL="https://xxxx.com:8006/api2/json"
export PM_USER=user@pam
export PM_PASS=password
export PM_OTP=otpcode (only if required)
export HTTP_HEADERS=Key,Value,Key1,Value1 (only if required)

./proxmox-api-go installQemu proxmox-node-name < qemu1.json

Expand Down
13 changes: 8 additions & 5 deletions cli/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ func Execute() (err error) {
}

func NewClient() (c *proxmox.Client) {
c, err := Client("", "", "", "")
c, err := Client("", "", "", "", "")
LogFatalError(err)
return
}

func Client(apiUlr, userID, password, otp string) (c *proxmox.Client, err error) {
func Client(apiUrl, userID, password, otp string, http_headers string) (c *proxmox.Client, err error) {
insecure, _ := RootCmd.Flags().GetBool("insecure")
timeout, _ := RootCmd.Flags().GetInt("timeout")
proxyUrl, _ := RootCmd.Flags().GetString("proxyurl")
Expand All @@ -47,8 +47,8 @@ func Client(apiUlr, userID, password, otp string) (c *proxmox.Client, err error)
if !insecure {
tlsconf = nil
}
if apiUlr == "" {
apiUlr = os.Getenv("PM_API_URL")
if apiUrl == "" {
apiUrl = os.Getenv("PM_API_URL")
}
if userID == "" {
userID = os.Getenv("PM_USER")
Expand All @@ -59,7 +59,10 @@ func Client(apiUlr, userID, password, otp string) (c *proxmox.Client, err error)
if otp == "" {
otp = os.Getenv("PM_OTP")
}
c, err = proxmox.NewClient(apiUlr, nil, tlsconf, proxyUrl, timeout)
if http_headers == "" {
http_headers = os.Getenv("HTTP_HEADERS")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use PM_HTTP_HEADERS for coherence with other envs, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works out for me.

}
c, err = proxmox.NewClient(apiUrl, nil, http_headers, tlsconf, proxyUrl, timeout)
LogFatalError(err)
if userRequiresAPIToken(userID) {
c.SetAPIToken(userID, password)
Expand Down
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func main() {
if !*insecure {
tlsconf = nil
}
c, err := proxmox.NewClient(os.Getenv("PM_API_URL"), nil, tlsconf, *proxyURL, *taskTimeout)
c, err := proxmox.NewClient(os.Getenv("PM_API_URL"), nil, os.Getenv("HTTP_HEADERS"), tlsconf, *proxyURL, *taskTimeout)
failError(err)
if userRequiresAPIToken(os.Getenv("PM_USER")) {
c.SetAPIToken(os.Getenv("PM_USER"), os.Getenv("PM_PASS"))
Expand Down
15 changes: 10 additions & 5 deletions proxmox/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,18 @@ func NewVmRef(vmId int) (vmr *VmRef) {
return
}

func NewClient(apiUrl string, hclient *http.Client, tls *tls.Config, proxyString string, taskTimeout int) (client *Client, err error) {
func NewClient(apiUrl string, hclient *http.Client, http_headers string, tls *tls.Config, proxyString string, taskTimeout int) (client *Client, err error) {
var sess *Session
sess, err = NewSession(apiUrl, hclient, proxyString, tls)
if err == nil {
sess, err_s := NewSession(apiUrl, hclient, proxyString, tls)
sess, err = createHeaderList(http_headers, sess)
if err != nil {
return nil, err
}
if err_s == nil {
client = &Client{session: sess, ApiUrl: apiUrl, TaskTimeout: taskTimeout}
}
return client, err

return client, err_s
}

// SetAPIToken specifies a pair of user identifier and token UUID to use
Expand Down Expand Up @@ -1320,7 +1325,7 @@ func (c *Client) Upload(node string, storage string, contentType string, filenam
}

url := fmt.Sprintf("%s/nodes/%s/storage/%s/upload", c.session.ApiUrl, node, storage)
req, err := c.session.NewRequest(http.MethodPost, url, nil, body)
req, err := c.session.NewRequest(http.MethodPost, url, &c.session.Headers, body)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion proxmox/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestClient_Login(t *testing.T) {
client, err := NewClient(os.Getenv("PM_API_URL"), nil, &tls.Config{InsecureSkipVerify: true}, "", 300)
client, err := NewClient(os.Getenv("PM_API_URL"), nil, os.Getenv("HTTP_HEADERS"), &tls.Config{InsecureSkipVerify: true}, "", 300)
assert.Nil(t, err)

err = client.Login(os.Getenv("PM_USER"), os.Getenv("PM_PASS"), "")
Expand Down
12 changes: 6 additions & 6 deletions proxmox/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (s *Session) Login(username string, password string, otp string) (err error
reqbody := ParamsToBody(reqUser)
olddebug := *Debug
*Debug = false // don't share passwords in debug log
resp, err := s.Post("/access/ticket", nil, nil, &reqbody)
resp, err := s.Post("/access/ticket", nil, &s.Headers, &reqbody)
*Debug = olddebug
if err != nil {
return err
Expand Down Expand Up @@ -202,18 +202,18 @@ func (s *Session) NewRequest(method, url string, headers *http.Header, body io.R
req.Header = *headers
}
if s.AuthToken != "" {
req.Header.Add("Authorization", "PVEAPIToken="+s.AuthToken)
req.Header["Authorization"] = []string{"PVEAPIToken=" + s.AuthToken}
} else if s.AuthTicket != "" {
req.Header.Add("Cookie", "PVEAuthCookie="+s.AuthTicket)
req.Header.Add("CSRFPreventionToken", s.CsrfToken)
req.Header["Authorization"] = []string{"PVEAuthCookie=" + s.AuthTicket}
req.Header["CSRFPreventionToken"] = []string{s.CsrfToken}
}
return
}

func (s *Session) Do(req *http.Request) (*http.Response, error) {
// Add session headers
for k := range s.Headers {
req.Header.Set(k, s.Headers.Get(k))
for k, v := range s.Headers {
req.Header[k] = v
}

if *Debug {
Expand Down
13 changes: 13 additions & 0 deletions proxmox/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,16 @@ func failError(err error) {
log.Fatal(err)
}
}

// Create list of http.Header out of string, separator is ","
func createHeaderList(header_string string, sess *Session) (*Session, error) {
header_string_split := strings.Split(header_string, ",")
err := ValidateArrayEven(header_string_split, "Header key(s) and value(s) not even. Check your HTTP_HEADERS.")
if err != nil {
return nil, err
}
for i := 0; i < len(header_string_split); i += 2 {
sess.Headers[header_string_split[i]] = []string{header_string_split[i+1]}
}
return sess, nil
}
7 changes: 7 additions & 0 deletions proxmox/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ func ValidateArrayNotEmpty(array interface{}, text string) error {
return ErrorKeyEmpty(text)
}

func ValidateArrayEven(array interface{}, text string) error {
if len(array.([]string))%2 == 0 {
return nil
}
return ErrorKeyEmpty(text)
}

func ErrorKeyEmpty(text string) error {
return fmt.Errorf("error the value of key (%s) may not be empty", text)
}
Expand Down
13 changes: 7 additions & 6 deletions test/cli/shared_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,16 @@ func (test *Test) StandardTest(t *testing.T) {
}

type LoginTest struct {
APIurl string
UserID string
Password string
OTP string
ReqErr bool //if an error is expected as output
APIurl string
UserID string
Password string
OTP string
HttpHeaders string
ReqErr bool //if an error is expected as output
}

func (test *LoginTest) Login(t *testing.T) {
_, err := cli.Client(test.APIurl, test.UserID, test.Password, test.OTP)
_, err := cli.Client(test.APIurl, test.UserID, test.Password, test.OTP, test.HttpHeaders)
if test.ReqErr {
require.Error(t, err)
} else {
Expand Down