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

kibana: add CreateFleetServerHosts and CreateFleetProxy #246

Merged
merged 6 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ...
rdner marked this conversation as resolved.
Show resolved Hide resolved
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")
rdner marked this conversation as resolved.
Show resolved Hide resolved
}

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 {
rdner marked this conversation as resolved.
Show resolved Hide resolved
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 {
rdner marked this conversation as resolved.
Show resolved Hide resolved
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")
rdner marked this conversation as resolved.
Show resolved Hide resolved
}

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")
rdner marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading