Skip to content

Commit

Permalink
Rotate logged in host api key (#143)
Browse files Browse the repository at this point in the history
* Disable VCS stamping for dev build

* Add test case for rotating logged-in host api key

* Implement own api key rotation for host

* Update CHANGELOG.md
  • Loading branch information
doodlesbykumbi authored Aug 25, 2023
1 parent 32e25a1 commit 3a3202b
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 20 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Nothing should go in this section, please add to the latest unreleased version
(and update the corresponding date), or add a new version.

## [8.0.11] - 2023-07-27
## [8.0.11] - 2023-08-25

### Fixed
- Handle trailing slash on appliance URL
[cyberark/conjur-cli-go#142](https://github.com/cyberark/conjur-cli-go/pull/142)
- Allow API key rotation for logged-in host
[cyberark/conjur-cli-go#143](https://github.com/cyberark/conjur-cli-go/pull/143)

## [8.0.10] - 2023-06-29

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
build:
go build -tags=dev -o ./dev/tmp/ ./cmd/conjur
go build -tags=dev -buildvcs=false -o ./dev/tmp/ ./cmd/conjur

test:
go test -tags=dev -count=1 -v ./...
Expand Down
20 changes: 19 additions & 1 deletion cmd/integration/host_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,33 @@ package main
import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
)

func TestHostIntegration(t *testing.T) {
cli := newConjurTestCLI(t)
cli.InitAndLoginAsAdmin(t)

t.Run("rotate own api key", func(t *testing.T) {
cli.LoginAsHost(t, "bob")

stdOut, stdErr, err := cli.Run("whoami")
assert.Contains(t, stdOut, `"username": "host/bob"`)

priorApiKey := ""
stdOut, stdErr, err = cli.Run("host", "rotate-api-key")
assertAPIKeyRotationCmd(t, err, stdOut, stdErr, priorApiKey)
})

t.Run("rotate host api key", func(t *testing.T) {
cli.LoginAsAdmin(t)

stdOut, stdErr, err := cli.Run("whoami")
assert.Contains(t, stdOut, `"username": "admin"`)

priorAPIKey := ""
stdOut, stdErr, err := cli.Run("host", "rotate-api-key", "-i", fmt.Sprintf("%s:host:bob", cli.account))
stdOut, stdErr, err = cli.Run("host", "rotate-api-key", "-i", fmt.Sprintf("%s:host:bob", cli.account))
assertAPIKeyRotationCmd(t, err, stdOut, stdErr, priorAPIKey)

priorAPIKey = stdOut
Expand Down
5 changes: 5 additions & 0 deletions cmd/integration/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ func (cli *testConjurCLI) LoginAsAdmin(t *testing.T) {
assertLoginCmd(t, err, stdOut, stdErr)
}

func (cli *testConjurCLI) LoginAsHost(t *testing.T, host string) {
stdOut, stdErr, err := cli.Run("login", "-i", "host/"+host, "-p", makeDevRequest("retrieve_api_key", map[string]string{"role_id": cli.account + ":host:" + host}))
assertLoginCmd(t, err, stdOut, stdErr)
}

func (cli *testConjurCLI) LoadPolicy(t *testing.T, policyText string) {
stdOut, stdErr, err := cli.RunWithStdin(
bytes.NewReader([]byte(policyText)),
Expand Down
12 changes: 10 additions & 2 deletions pkg/cmd/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

type hostClient interface {
RotateHostAPIKey(hostID string) ([]byte, error)
RotateCurrentUserAPIKey() ([]byte, error)
}

type hostClientFactoryFunc func(*cobra.Command) (hostClient, error)
Expand Down Expand Up @@ -35,9 +36,10 @@ func newHostRotateAPIKeyCmd(clientFactory hostClientFactoryFunc) *cobra.Command
cmd := &cobra.Command{
Use: "rotate-api-key",
Short: "Rotate a host's API key",
Long: `Rotate the API key of the host specified by the [id] parameter.
Long: `Rotate the API key of the host specified by the [id] parameter or for the currently logged-in host if no [id] is provided.
Examples:
- conjur host rotate-api-key
- conjur host rotate-api-key --id ci-staging
- conjur host rotate-api-key --id host:ci-staging
- conjur host rotate-api-key --id dev:host:ci-staging`,
Expand All @@ -54,7 +56,13 @@ Examples:
return err
}

newAPIKey, err := client.RotateHostAPIKey(hostID)
var newAPIKey []byte
if hostID == "" {
newAPIKey, err = client.RotateCurrentUserAPIKey()
} else {
newAPIKey, err = client.RotateHostAPIKey(hostID)
}

if err != nil {
return err
}
Expand Down
46 changes: 31 additions & 15 deletions pkg/cmd/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@ import (
)

type mockHostClient struct {
t *testing.T
hostRotateAPIKey func(*testing.T, string) ([]byte, error)
t *testing.T
rotateCurrentUserAPIKey func() ([]byte, error)
rotateHostAPIKey func(*testing.T, string) ([]byte, error)
}

func (m mockHostClient) RotateCurrentUserAPIKey() ([]byte, error) {
return m.rotateCurrentUserAPIKey()
}

func (m mockHostClient) RotateHostAPIKey(hostID string) ([]byte, error) {
return m.hostRotateAPIKey(m.t, hostID)
return m.rotateHostAPIKey(m.t, hostID)
}

var hostRotateAPIKeyCmdTestCases = []struct {
name string
args []string
hostRotateAPIKey func(t *testing.T, hostID string) ([]byte, error)
clientFactoryError error
assert func(t *testing.T, stdout, stderr string, err error)
var rotateHostAPIKeyCmdTestCases = []struct {
name string
args []string
rotateCurrentUserAPIKey func() ([]byte, error)
rotateHostAPIKey func(t *testing.T, hostID string) ([]byte, error)
clientFactoryError error
assert func(t *testing.T, stdout, stderr string, err error)
}{
{
name: "without subcommand",
Expand All @@ -39,9 +45,19 @@ var hostRotateAPIKeyCmdTestCases = []struct {
},
},
{
name: "successful rotation",
name: "rotate API key for logged in host",
args: []string{"host", "rotate-api-key"},
rotateCurrentUserAPIKey: func() ([]byte, error) {
return []byte("test-api-key"), nil
},
assert: func(t *testing.T, stdout, stderr string, err error) {
assert.Contains(t, stdout, "test-api-key")
},
},
{
name: "rotate API key for specified host",
args: []string{"host", "rotate-api-key", "--id=dev-host"},
hostRotateAPIKey: func(t *testing.T, hostID string) ([]byte, error) {
rotateHostAPIKey: func(t *testing.T, hostID string) ([]byte, error) {
// Assert on arguments
assert.Equal(t, "dev-host", hostID)

Expand All @@ -54,7 +70,7 @@ var hostRotateAPIKeyCmdTestCases = []struct {
{
name: "client error",
args: []string{"host", "rotate-api-key", "--id=dev-host"},
hostRotateAPIKey: func(t *testing.T, hostID string) ([]byte, error) {
rotateHostAPIKey: func(t *testing.T, hostID string) ([]byte, error) {
return nil, fmt.Errorf("%s", "an error")
},
assert: func(t *testing.T, stdout, stderr string, err error) {
Expand All @@ -71,10 +87,10 @@ var hostRotateAPIKeyCmdTestCases = []struct {
},
}

func TestHostRotateAPIKeyCmd(t *testing.T) {
for _, tc := range hostRotateAPIKeyCmdTestCases {
func TestRotateHostAPIKeyCmd(t *testing.T) {
for _, tc := range rotateHostAPIKeyCmdTestCases {
t.Run(tc.name, func(t *testing.T) {
mockClient := mockHostClient{t: t, hostRotateAPIKey: tc.hostRotateAPIKey}
mockClient := mockHostClient{t: t, rotateHostAPIKey: tc.rotateHostAPIKey, rotateCurrentUserAPIKey: tc.rotateCurrentUserAPIKey}

cmd := newHostCmd(
func(cmd *cobra.Command) (hostClient, error) {
Expand Down

0 comments on commit 3a3202b

Please sign in to comment.