diff --git a/changelog/fragments/1735137195-remove-deprecated-list-in-favor-of-items.yaml b/changelog/fragments/1735137195-remove-deprecated-list-in-favor-of-items.yaml new file mode 100644 index 0000000000..015675d0e8 --- /dev/null +++ b/changelog/fragments/1735137195-remove-deprecated-list-in-favor-of-items.yaml @@ -0,0 +1,31 @@ +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: feature + +# Change summary; a 80ish characters long description of the change. +summary: removes `list` from kibanaFetchToken in favor of `items` as the former is deprecated and will be removed from the api response + +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. +#description: + +# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc. +component: "elastic-agent" + +# PR URL; optional; the PR number that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +pr: https://github.com/elastic/elastic-agent/pull/6437 +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +issue: https://github.com/elastic/elastic-agent/issues/6023 diff --git a/internal/pkg/agent/cmd/container.go b/internal/pkg/agent/cmd/container.go index b807c8ec16..a983f4df3e 100644 --- a/internal/pkg/agent/cmd/container.go +++ b/internal/pkg/agent/cmd/container.go @@ -51,11 +51,9 @@ const ( logsPathPerms = 0775 ) -var ( - // Used to strip the appended ({uuid}) from the name of an enrollment token. This makes much easier for - // a container to reference a token by name, without having to know what the generated UUID is for that name. - tokenNameStrip = regexp.MustCompile(`\s\([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)$`) -) +// Used to strip the appended ({uuid}) from the name of an enrollment token. This makes much easier for +// a container to reference a token by name, without having to know what the generated UUID is for that name. +var tokenNameStrip = regexp.MustCompile(`\s\([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)$`) func newContainerCommand(_ []string, streams *cli.IOStreams) *cobra.Command { cmd := cobra.Command{ @@ -293,6 +291,7 @@ func runContainerCmd(streams *cli.IOStreams, cfg setupConfig) error { return err } } + if cfg.Fleet.Enroll { var policy *kibanaPolicy token := cfg.Fleet.EnrollmentToken @@ -547,7 +546,7 @@ func kibanaFetchToken(cfg setupConfig, client *kibana.Client, policy *kibanaPoli if err != nil { return "", err } - key, err := findKey(keys.List, policy, tokenName) + key, err := findKey(keys.Items, policy, tokenName) if err != nil { return "", err } @@ -951,7 +950,7 @@ type kibanaAPIKey struct { } type kibanaAPIKeys struct { - List []kibanaAPIKey `json:"list"` + Items []kibanaAPIKey `json:"items"` } type kibanaAPIKeyDetail struct { diff --git a/internal/pkg/agent/cmd/container_test.go b/internal/pkg/agent/cmd/container_test.go index 3ada160fee..1136985a4e 100644 --- a/internal/pkg/agent/cmd/container_test.go +++ b/internal/pkg/agent/cmd/container_test.go @@ -5,11 +5,17 @@ package cmd import ( + "encoding/json" + "net/http" + "net/http/httptest" + "strings" "testing" "time" "github.com/stretchr/testify/require" + "github.com/elastic/elastic-agent-libs/kibana" + "github.com/elastic/elastic-agent/internal/pkg/cli" "github.com/elastic/elastic-agent/internal/pkg/config" ) @@ -173,3 +179,65 @@ func TestBuildEnrollArgs(t *testing.T) { }) } } + +func TestKibanaFetchToken(t *testing.T) { + t.Run("should fetch details from items in the api response", func(t *testing.T) { + mux := http.NewServeMux() + mux.HandleFunc("/api/fleet/enrollment_api_keys/", func(w http.ResponseWriter, r *http.Request) { + basePath := "/api/fleet/enrollment_api_keys/" + + apiKey := kibanaAPIKey{ + ID: "id", + PolicyID: "policyID", + Name: "tokenName", + APIKey: "apiKey", + } + + trimmed := strings.TrimPrefix(r.URL.String(), basePath) + if trimmed == "" { + apiKeys := kibanaAPIKeys{ + Items: []kibanaAPIKey{ + apiKey, + }, + } + b, err := json.Marshal(apiKeys) + require.NoError(t, err) + + _, err = w.Write(b) + require.NoError(t, err) + + return + } + + keyDetail := kibanaAPIKeyDetail{ + Item: apiKey, + } + b, err := json.Marshal(keyDetail) + require.NoError(t, err) + + _, err = w.Write(b) + require.NoError(t, err) + }) + + policy := kibanaPolicy{ + ID: "policyID", + } + + server := httptest.NewServer(mux) + defer server.Close() + + client := &kibana.Client{ + Connection: kibana.Connection{ + URL: server.URL, + Username: "", + Password: "", + APIKey: "", + ServiceToken: "", + HTTP: &http.Client{}, + }, + } + ak, err := kibanaFetchToken(setupConfig{Kibana: kibanaConfig{RetryMaxCount: 1}}, client, &policy, cli.NewIOStreams(), "tokenName") + require.NoError(t, err) + require.Equal(t, "apiKey", ak) + }) +} diff --git a/testing/integration/validate_items_deprecated_list_test.go b/testing/integration/validate_items_deprecated_list_test.go new file mode 100644 index 0000000000..ce7828bf48 --- /dev/null +++ b/testing/integration/validate_items_deprecated_list_test.go @@ -0,0 +1,66 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License 2.0; +// you may not use this file except in compliance with the Elastic License 2.0. + +//go:build integration + +package integration + +import ( + "encoding/json" + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/elastic/elastic-agent/pkg/testing/define" +) + +type testKibanaApiKey struct { + ID string `json:"id"` + Name string `json:"name"` + Active bool `json:"active"` + PolicyID string `json:"policy_id"` + APIKey string `json:"api_key"` +} + +type deprecatedBody struct { + List []testKibanaApiKey `json:"list"` +} + +type newBody struct { + Items []testKibanaApiKey `json:"items"` +} + +// TODO: Remove test after list deprecation is complete +// Added by https://github.com/elastic/elastic-agent/pull/6437 +func TestItemsMatchDeprecatedList(t *testing.T) { + info := define.Require(t, define.Requirements{ + Group: Default, + Stack: &define.Stack{}, + Local: true, + Sudo: false, + }) + + res, err := info.KibanaClient.Connection.Send(http.MethodGet, "/api/fleet/enrollment_api_keys", nil, nil, nil) + require.NoError(t, err) + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + require.NoError(t, err) + + dpb := deprecatedBody{} + nb := newBody{} + + err = json.Unmarshal(body, &dpb) + require.NoError(t, err) + + err = json.Unmarshal(body, &nb) + require.NoError(t, err) + + require.Equal(t, len(dpb.List), len(nb.Items)) + for i := 0; i < len(dpb.List); i++ { + require.Equal(t, dpb.List[i], nb.Items[i]) + } +}