netboxgo/plugin_secrets_store.go
Kalle Carlbark 2bca52c094
Migrate to use secrets store plugin
Move secrets related code to plugin_secrets_store
While here, mute gosecs false positive for G101 on
secretsPath
2022-01-31 16:38:37 +01:00

139 lines
3.8 KiB
Go

package netboxgo
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
type SecretsService service
// Secrets contains secrets
type Secrets struct {
Next interface{} `json:"next"`
Previous interface{} `json:"previous"`
Results []struct {
CustomFields struct{} `json:"custom_fields"`
LastUpdated time.Time `json:"last_updated"`
Role struct {
URL string `json:"url"`
Display string `json:"display"`
Name string `json:"name"`
Slug string `json:"slug"`
ID int `json:"id"`
} `json:"role"`
AssignedObject struct {
URL string `json:"url"`
Display string `json:"display"`
Name string `json:"name"`
ID int `json:"id"`
} `json:"assigned_object"`
Name string `json:"name"`
Created string `json:"created"`
AssignedObjectType string `json:"assigned_object_type"`
Display string `json:"display"`
Plaintext string `json:"plaintext"`
Hash string `json:"hash"`
URL string `json:"url"`
Tags []interface{} `json:"tags"`
AssignedObjectID int `json:"assigned_object_id"`
ID int `json:"id"`
} `json:"results"`
Count int `json:"count"`
}
// SecretFilter is used to filter out secrets
type SecretFilter struct {
Offset int64 `schema:"offset,omitempty"`
Limit int64 `schema:"limit,omitempty"`
// User specific filters
Name string `schema:"name,omitempty"`
Role string `schema:"role,omitempty"`
RoleID string `schema:"role_id,omitempty"`
DeviceID string `schema:"device_id,omitempty"`
TypeID string `schema:"type_id,omitempty"`
Device string `schema:"device,omitempty"`
IDIn string `schema:"id__in,omitempty"`
Q string `schema:"q,omitempty"`
Tag string `schema:"tag,omitempty"`
}
// #nosec CWE-798 - gosec mute false positive
const secretsPath = "/plugins/netbox_secretstore"
// List secrets. SecretsFilter is used to list based on filter queries.
func (s *SecretsService) List(ctx context.Context, f *SecretFilter) (*Secrets, error) {
var secrets Secrets
var query string
var req *http.Request
var err error
if s.client.SessionKey == "" {
return &secrets, fmt.Errorf("session key needed when interacting with secrets. no session key found: you need to fetch a session key with FetchSessionKey()")
}
encoder := schema.NewEncoder()
form := url.Values{}
err = encoder.Encode(f, form)
if err != nil {
return &secrets, err
}
query = form.Encode()
req, err = s.client.newRequest(ctx, "GET", secretsPath+"/secrets", query, nil)
if err != nil {
return &secrets, err
}
_, err = s.client.do(req, &secrets)
if err != nil {
return &secrets, err
}
return &secrets, nil
}
// FetchSessionKey fetches sessionkey
func (s *SecretsService) FetchSessionKey(privatekey string) error {
form := url.Values{}
form.Add("private_key", privatekey)
query := form.Encode()
ctx := context.Background()
req, err := http.NewRequestWithContext(ctx, "POST", s.client.baseURL.String()+secretsPath+"/get-session-key/", strings.NewReader(query))
if err != nil {
return err
}
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
if s.client.FetchMode != "" {
req.Header.Add("js.fetch:mode", "no-cors")
}
req.Header.Add("Authorization", " Token "+s.client.Token)
var sessionkey NetBoxSessionKey
res, err := s.client.do(req, &sessionkey)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.Errorf("response was: %d should be %d\n%s\n", res.StatusCode, http.StatusOK, res.Header)
}
s.client.SessionKey = sessionkey.XSessionKey
return nil
}