Skip to content

Commit

Permalink
kibana: add CreateFleetServerHosts CreateFleetProxy to client
Browse files Browse the repository at this point in the history
  • Loading branch information
AndersonQ committed Oct 31, 2024
1 parent 9d6c29d commit 6146d7f
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 9 deletions.
120 changes: 114 additions & 6 deletions kibana/fleet.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ const (
fleetAgentsAPI = "/api/fleet/agents"
fleetAgentsDeleteAPI = "/api/fleet/agent_policies/delete"
fleetEnrollmentAPIKeysAPI = "/api/fleet/enrollment_api_keys" //nolint:gosec // no API key being leaked here
fleetFleetServerHostAPI = "/api/fleet/fleet_server_hosts/%s"
fleetFleetServerHostsAPI = "/api/fleet/fleet_server_hosts"
fleetPackagePoliciesAPI = "/api/fleet/package_policies"
fleetUnEnrollAgentAPI = "/api/fleet/agents/%s/unenroll"
fleetUninstallTokensAPI = "/api/fleet/uninstall_tokens" //nolint:gosec // NOT the "Potential hardcoded credentials"
fleetUpgradeAgentAPI = "/api/fleet/agents/%s/upgrade"
fleetAgentDownloadSourcesAPI = "/api/fleet/agent_download_sources"
fleetProxiesAPI = "/api/fleet/proxies"
)

//
Expand Down Expand Up @@ -474,21 +474,43 @@ func (client *Client) UpgradeAgent(ctx context.Context, request UpgradeAgentRequ
type FleetServerHost struct {
ID string `json:"id"`
Name string `json:"name"`
IsDefault bool `json:"is_default"`
HostURLs []string `json:"host_urls"`
IsDefault bool `json:"is_default"`
IsInternal bool `json:"is_internal"`
IsPreconfigured bool `json:"is_preconfigured"`
ProxyID string `json:"proxy_id"`
}

// ListFleetServerHostsRequest is currently unused
// ListFleetServerHostsRequest ...
type ListFleetServerHostsRequest struct {
// For future use
HostURLs []string `json:"host_urls"`
ID string `json:"id"`
IsDefault bool `json:"is_default"`
IsInternal bool `json:"is_internal"`
IsPreconfigured bool `json:"is_preconfigured"`
Name string `json:"name"`
ProxyID string `json:"proxy_id"`
}

// ListFleetServerHostsResponse is the JSON response for ListFleetServerHosts
type ListFleetServerHostsResponse struct {
Items []FleetServerHost `json:"items"`
}

// FleetServerHostsResponse is the json representation of the response from POST
// to fleetFleetServerHostsAPI
type FleetServerHostsResponse struct {
Item struct {
ID string `json:"id"`
HostUrls []string `json:"host_urls"`
IsDefault bool `json:"is_default"`
IsInternal bool `json:"is_internal"`
IsPreconfigured bool `json:"is_preconfigured"`
Name string `json:"name"`
ProxyID string `json:"proxy_id"`
} `json:"item"`
}

// ListFleetServerHosts returns a list of fleet server hosts
func (client *Client) ListFleetServerHosts(ctx context.Context, _ ListFleetServerHostsRequest) (r ListFleetServerHostsResponse, err error) {
resp, err := client.Connection.SendWithContext(ctx, http.MethodGet, fleetFleetServerHostsAPI, nil, nil, nil)
Expand All @@ -502,6 +524,35 @@ func (client *Client) ListFleetServerHosts(ctx context.Context, _ ListFleetServe
return r, err
}

// CreateFleetServerHosts creates a new Fleet Server host
func (client *Client) CreateFleetServerHosts(ctx context.Context, req ListFleetServerHostsRequest) (FleetServerHostsResponse, error) {
bs, err := json.Marshal(req)
if err != nil {
return FleetServerHostsResponse{}, fmt.Errorf("could not marshal ListFleetServerHostsRequest")
}

resp, err := client.Connection.SendWithContext(ctx, http.MethodPost,
fleetFleetServerHostsAPI,
nil, nil, bytes.NewReader(bs))
if err != nil {
return FleetServerHostsResponse{}, fmt.Errorf("error calling new fleet server hosts API: %w", err)
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return FleetServerHostsResponse{}, fmt.Errorf("error reading fleet response: %w", err)
}

var fleetResp FleetServerHostsResponse
err = json.Unmarshal(body, &fleetResp)
if err != nil {
return FleetServerHostsResponse{}, fmt.Errorf("error parsing fleet response: %w", err)
}

return fleetResp, nil
}

//
// Get Fleet Server Host
//
Expand All @@ -516,7 +567,7 @@ type GetFleetServerHostResponse FleetServerHost

// GetFleetServerHost returns data on a fleet server
func (client *Client) GetFleetServerHost(ctx context.Context, request GetFleetServerHostRequest) (r GetFleetServerHostResponse, err error) {
apiURL := fmt.Sprintf(fleetFleetServerHostAPI, request.ID)
apiURL := fleetFleetServerHostsAPI + "/" + request.ID

resp, err := client.Connection.SendWithContext(ctx, http.MethodGet, apiURL, nil, nil, nil)
if err != nil {
Expand All @@ -536,6 +587,7 @@ func (client *Client) GetFleetServerHost(ctx context.Context, request GetFleetSe
// Fleet Package Policy
//

// PackagePolicyRequest
// https://www.elastic.co/guide/en/fleet/8.8/fleet-apis.html#createPackagePolicy
// request https://www.elastic.co/guide/en/fleet/8.8/fleet-apis.html#package_policy_request
type PackagePolicyRequest struct {
Expand All @@ -554,11 +606,13 @@ type PackagePolicyRequestPackage struct {
Version string `json:"version"`
}

// PackagePolicyResponse
// https://www.elastic.co/guide/en/fleet/8.8/fleet-apis.html#create_package_policy_200_response
type PackagePolicyResponse struct {
Item PackagePolicy `json:"item"`
}

// PackagePolicy
// https://www.elastic.co/guide/en/fleet/8.8/fleet-apis.html#package_policy
type PackagePolicy struct {
ID string `json:"id,omitempty"`
Expand All @@ -573,6 +627,7 @@ type PackagePolicy struct {
Description string `json:"description"`
}

// DeletePackagePolicyResponse
// https://www.elastic.co/guide/en/fleet/8.8/fleet-apis.html#delete_package_policy_200_response
type DeletePackagePolicyResponse struct {
ID string `json:"id"`
Expand Down Expand Up @@ -628,6 +683,59 @@ func (client *Client) DeleteFleetPackage(ctx context.Context, packagePolicyID st
return r, err
}

//
// Fleet Proxies
//

type ProxiesRequest struct {
Certificate string `json:"certificate"`
CertificateAuthorities string `json:"certificate_authorities"`
CertificateKey string `json:"certificate_key"`
ID string `json:"id"`
IsPreconfigured bool `json:"is_preconfigured"`
Name string `json:"name"`
ProxyHeaders map[string]string `json:"proxy_headers"`
URL string `json:"url"`
}

type ProxiesResponse struct {
Item struct {
Certificate string `json:"certificate"`
CertificateAuthorities string `json:"certificate_authorities"`
CertificateKey string `json:"certificate_key"`
ID string `json:"id"`
IsPreconfigured bool `json:"is_preconfigured"`
Name string `json:"name"`
ProxyHeaders map[string]string `json:"proxy_headers"`
URL string `json:"url"`
} `json:"item"`
}

// CreateFleetProxy creates a new proxy
func (client *Client) CreateFleetProxy(ctx context.Context, req ProxiesRequest) (ProxiesResponse, error) {
bs, err := json.Marshal(req)
if err != nil {
return ProxiesResponse{}, fmt.Errorf("could not marshal ListFleetServerHostsRequest")
}

r, err := client.Connection.SendWithContext(ctx, http.MethodPost,
fleetProxiesAPI, nil, nil,
bytes.NewReader(bs),
)
if err != nil {
return ProxiesResponse{}, err
}
defer r.Body.Close()

resp := ProxiesResponse{}
err = readJSONResponse(r, &resp)
if err != nil {
return ProxiesResponse{}, fmt.Errorf("failes parsing response")
}

return resp, nil
}

// UninstallTokenResponse uninstall tokens response with resolved token values
type UninstallTokenResponse struct {
Items []UninstallTokenItem `json:"items"`
Expand All @@ -647,7 +755,7 @@ type uninstallTokenValueResponse struct {
Item UninstallTokenItem `json:"item"`
}

// GetPolicyUninstallTokens Retrieves the the policy uninstall tokens
// GetPolicyUninstallTokens Retrieves the policy uninstall tokens
func (client *Client) GetPolicyUninstallTokens(ctx context.Context, policyID string) (r UninstallTokenResponse, err error) {
// Fetch uninstall token for the policy
// /api/fleet/uninstall_tokens?policyId={policyId}&page=1&perPage=1000
Expand Down
51 changes: 51 additions & 0 deletions kibana/fleet_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,57 @@ func TestListFleetServerHosts(t *testing.T) {
require.NotEmpty(t, resp.Items)
}

func TestCreateFleetServerHosts(t *testing.T) {
cfg := mustGetEnv(t)
ctx, cn := context.WithCancel(context.Background())
defer cn()

client, err := NewClientWithConfig(&cfg, "", "", "", "")
require.NoError(t, err)

id := uuid.Must(uuid.NewV4()).String()
req := ListFleetServerHostsRequest{
ID: "CreateFleetServerHosts" + id,
Name: "CreateFleetServerHosts" + id,
HostURLs: []string{"https://fleet.elastic.co"},
IsDefault: false,
}
got, err := client.CreateFleetServerHosts(ctx, req)
require.NoError(t, err, "error creating new fleet host")

require.Equal(t, req.ID, got.Item.ID)
require.Equal(t, req.HostURLs, got.Item.HostUrls)
}

func TestCreateFleetProxy(t *testing.T) {
cfg := mustGetEnv(t)
ctx, cn := context.WithCancel(context.Background())
defer cn()

client, err := NewClientWithConfig(&cfg, "", "", "", "")
require.NoError(t, err)

id := uuid.Must(uuid.NewV4()).String()
req := ProxiesRequest{
ID: "CreateFleetServerHosts" + id,
Name: "CreateFleetServerHosts" + id,
URL: "https://proxy.elastic.co",
CertificateAuthorities: "some CA",
Certificate: "some certificate",
CertificateKey: "some certificate key",
IsPreconfigured: true,
ProxyHeaders: map[string]string{
"h1": "v1",
"h2": "v2",
},
}
got, err := client.CreateFleetProxy(ctx, req)
require.NoError(t, err, "error creating new fleet host")

require.Equal(t, req.ID, got.Item.ID)
require.Equal(t, req, got.Item)
}

func TestGetFleetServerHost(t *testing.T) {
cfg := mustGetEnv(t)

Expand Down
6 changes: 3 additions & 3 deletions kibana/fleet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ func TestFleetUpdatePolicy(t *testing.T) {
require.Equal(t, id, resp.ID)
require.Equal(t, policyName, resp.Name)
require.Equal(t, "default", resp.Namespace)
//require.Equal(t, "active", resp.Status)
//require.Equal(t, false, resp.IsManaged)
// require.Equal(t, "active", resp.Status)
// require.Equal(t, false, resp.IsManaged)
require.Equal(t, []MonitoringEnabledOption{MonitoringEnabledLogs, MonitoringEnabledMetrics}, resp.MonitoringEnabled)
require.Equal(t, agentFeatures, resp.AgentFeatures)
}
Expand Down Expand Up @@ -361,7 +361,7 @@ func TestFleetGetFleetServerHost(t *testing.T) {

handler := func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case fmt.Sprintf(fleetFleetServerHostAPI, id):
case fleetFleetServerHostsAPI + "/" + id:
_, _ = w.Write(fleetGetFleetServerHostResponse)
}
}
Expand Down

0 comments on commit 6146d7f

Please sign in to comment.