Skip to content

Commit

Permalink
Add API key invalidation on unenroll ACK. (#124) (#125)
Browse files Browse the repository at this point in the history
* Add API key invalidation on unenroll ACK.

* Fix import location.

* Fix test.

(cherry picked from commit dc762b5)
  • Loading branch information
blakerouse committed Mar 5, 2021
1 parent 0322984 commit f2841a5
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 3 deletions.
19 changes: 19 additions & 0 deletions cmd/fleet/handleAck.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"time"

"github.com/elastic/fleet-server/v7/internal/pkg/apikey"
"github.com/elastic/fleet-server/v7/internal/pkg/bulk"
"github.com/elastic/fleet-server/v7/internal/pkg/cache"
"github.com/elastic/fleet-server/v7/internal/pkg/dl"
Expand Down Expand Up @@ -191,6 +192,13 @@ func _handlePolicyChange(ctx context.Context, bulker bulk.Bulk, agent *model.Age
}

func _handleUnenroll(ctx context.Context, bulker bulk.Bulk, agent *model.Agent) error {
apiKeys := _getAPIKeyIDs(agent)
if len(apiKeys) > 0 {
if err := apikey.Invalidate(ctx, bulker.Client(), apiKeys...); err != nil {
return err
}
}

updates := make([]bulk.BulkOp, 0, 1)
now := time.Now().UTC().Format(time.RFC3339)
fields := map[string]interface{}{
Expand All @@ -214,3 +222,14 @@ func _handleUnenroll(ctx context.Context, bulker bulk.Bulk, agent *model.Agent)

return bulker.MUpdate(ctx, updates, bulk.WithRefresh())
}

func _getAPIKeyIDs(agent *model.Agent) []string {
keys := make([]string, 0, 1)
if agent.AccessApiKeyId != "" {
keys = append(keys, agent.AccessApiKeyId)
}
if agent.DefaultApiKeyId != "" {
keys = append(keys, agent.DefaultApiKeyId)
}
return keys
}
2 changes: 1 addition & 1 deletion cmd/fleet/server_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func TestServerUnauthorized(t *testing.T) {

// Unauthorized, expecting error from /_security/_authenticate
t.Run("unauthorized", func(t *testing.T) {
const expectedErrResponsePrefix = `Fail Auth: [401 Unauthorized]`
const expectedErrResponsePrefix = `fail Auth: [401 Unauthorized]`
for _, u := range agenturls {
req, err := http.NewRequest("POST", u, bytes.NewBuffer([]byte("{}")))
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/apikey/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (k ApiKey) Authenticate(ctx context.Context, es *elasticsearch.Client) (*Se
}

if res.IsError() {
return nil, fmt.Errorf("Fail Auth: %s", res.String())
return nil, fmt.Errorf("fail Auth: %s", res.String())
}

var info SecurityInfo
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/apikey/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func Create(ctx context.Context, client *elasticsearch.Client, name, ttl string,
defer res.Body.Close()

if res.IsError() {
return nil, fmt.Errorf("Fail CreateAPIKey: %s", res.String())
return nil, fmt.Errorf("fail CreateAPIKey: %s", res.String())
}

type APIKeyResponse struct {
Expand Down
50 changes: 50 additions & 0 deletions internal/pkg/apikey/invalidate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package apikey

import (
"bytes"
"context"
"encoding/json"
"fmt"

"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)

// Invalidate invalidates the provides API keys by ID.
func Invalidate(ctx context.Context, client *elasticsearch.Client, ids ...string) error {

payload := struct {
IDs []string `json:"ids,omitempty"`
}{
ids,
}

body, err := json.Marshal(&payload)
if err != nil {
return err
}

opts := []func(*esapi.SecurityInvalidateAPIKeyRequest){
client.Security.InvalidateAPIKey.WithContext(ctx),
}

res, err := client.Security.InvalidateAPIKey(
bytes.NewReader(body),
opts...,
)

if err != nil {
return err
}

defer res.Body.Close()

if res.IsError() {
return fmt.Errorf("fail InvalidateAPIKey: %s", res.String())
}
return nil
}

0 comments on commit f2841a5

Please sign in to comment.