mirror of
https://github.com/status-im/consul.git
synced 2025-02-08 20:05:09 +00:00
Add keyring http endpoints
This commit is contained in:
parent
4ed6770cfa
commit
dd3368c19e
@ -43,6 +43,26 @@ type RaftConfiguration struct {
|
|||||||
Index uint64
|
Index uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyringOpts is used for performing Keyring operations
|
||||||
|
type KeyringOpts struct {
|
||||||
|
Key string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringResponse is returned when listing the gossip encryption keys
|
||||||
|
type KeyringResponse struct {
|
||||||
|
// Whether this response is for a WAN ring
|
||||||
|
WAN bool
|
||||||
|
|
||||||
|
// The datacenter name this request corresponds to
|
||||||
|
Datacenter string
|
||||||
|
|
||||||
|
// A map of the encryption keys to the number of nodes they're installed on
|
||||||
|
Keys map[string]int
|
||||||
|
|
||||||
|
// The total number of nodes in this ring
|
||||||
|
NumNodes int
|
||||||
|
}
|
||||||
|
|
||||||
// RaftGetConfiguration is used to query the current Raft peer set.
|
// RaftGetConfiguration is used to query the current Raft peer set.
|
||||||
func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) {
|
func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) {
|
||||||
r := op.c.newRequest("GET", "/v1/operator/raft/configuration")
|
r := op.c.newRequest("GET", "/v1/operator/raft/configuration")
|
||||||
@ -79,3 +99,61 @@ func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) err
|
|||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyringInstall is used to install a new gossip encryption key into the cluster
|
||||||
|
func (op *Operator) KeyringInstall(key string) error {
|
||||||
|
r := op.c.newRequest("PUT", "/v1/operator/keyring/install")
|
||||||
|
r.obj = KeyringOpts{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
_, resp, err := requireOK(op.c.doRequest(r))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringList is used to list the gossip keys installed in the cluster
|
||||||
|
func (op *Operator) KeyringList() ([]*KeyringResponse, error) {
|
||||||
|
r := op.c.newRequest("GET", "/v1/operator/keyring/list")
|
||||||
|
_, resp, err := requireOK(op.c.doRequest(r))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var out []*KeyringResponse
|
||||||
|
if err := decodeBody(resp, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringRemove is used to remove a gossip encryption key from the cluster
|
||||||
|
func (op *Operator) KeyringRemove(key string) error {
|
||||||
|
r := op.c.newRequest("DELETE", "/v1/operator/keyring/remove")
|
||||||
|
r.obj = KeyringOpts{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
_, resp, err := requireOK(op.c.doRequest(r))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyringUse is used to change the active gossip encryption key
|
||||||
|
func (op *Operator) KeyringUse(key string) error {
|
||||||
|
r := op.c.newRequest("PUT", "/v1/operator/keyring/use")
|
||||||
|
r.obj = KeyringOpts{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
_, resp, err := requireOK(op.c.doRequest(r))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -3,6 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOperator_RaftGetConfiguration(t *testing.T) {
|
func TestOperator_RaftGetConfiguration(t *testing.T) {
|
||||||
@ -36,3 +38,69 @@ func TestOperator_RaftRemovePeerByAddress(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOperator_KeyringInstallListPutRemove(t *testing.T) {
|
||||||
|
oldKey := "d8wu8CSUrqgtjVsvcBPmhQ=="
|
||||||
|
newKey := "qxycTi/SsePj/TZzCBmNXw=="
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) {
|
||||||
|
c.Encrypt = oldKey
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
operator := c.Operator()
|
||||||
|
if err := operator.KeyringInstall(newKey); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
listResponses, err := operator.KeyringList()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the new key is installed
|
||||||
|
if len(listResponses) != 2 {
|
||||||
|
t.Fatalf("bad: %v", len(listResponses))
|
||||||
|
}
|
||||||
|
for _, response := range listResponses {
|
||||||
|
if len(response.Keys) != 2 {
|
||||||
|
t.Fatalf("bad: %v", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[oldKey]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[newKey]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch the primary to the new key
|
||||||
|
if err := operator.KeyringUse(newKey); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := operator.KeyringRemove(oldKey); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
listResponses, err = operator.KeyringList()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the old key is removed
|
||||||
|
if len(listResponses) != 2 {
|
||||||
|
t.Fatalf("bad: %v", len(listResponses))
|
||||||
|
}
|
||||||
|
for _, response := range listResponses {
|
||||||
|
if len(response.Keys) != 1 {
|
||||||
|
t.Fatalf("bad: %v", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[oldKey]; ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[newKey]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -291,6 +291,10 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) {
|
|||||||
s.handleFuncMetrics("/v1/kv/", s.wrap(s.KVSEndpoint))
|
s.handleFuncMetrics("/v1/kv/", s.wrap(s.KVSEndpoint))
|
||||||
s.handleFuncMetrics("/v1/operator/raft/configuration", s.wrap(s.OperatorRaftConfiguration))
|
s.handleFuncMetrics("/v1/operator/raft/configuration", s.wrap(s.OperatorRaftConfiguration))
|
||||||
s.handleFuncMetrics("/v1/operator/raft/peer", s.wrap(s.OperatorRaftPeer))
|
s.handleFuncMetrics("/v1/operator/raft/peer", s.wrap(s.OperatorRaftPeer))
|
||||||
|
s.handleFuncMetrics("/v1/operator/keyring/install", s.wrap(s.OperatorKeyringInstall))
|
||||||
|
s.handleFuncMetrics("/v1/operator/keyring/list", s.wrap(s.OperatorKeyringList))
|
||||||
|
s.handleFuncMetrics("/v1/operator/keyring/remove", s.wrap(s.OperatorKeyringRemove))
|
||||||
|
s.handleFuncMetrics("/v1/operator/keyring/use", s.wrap(s.OperatorKeyringUse))
|
||||||
s.handleFuncMetrics("/v1/query", s.wrap(s.PreparedQueryGeneral))
|
s.handleFuncMetrics("/v1/query", s.wrap(s.PreparedQueryGeneral))
|
||||||
s.handleFuncMetrics("/v1/query/", s.wrap(s.PreparedQuerySpecific))
|
s.handleFuncMetrics("/v1/query/", s.wrap(s.PreparedQuerySpecific))
|
||||||
s.handleFuncMetrics("/v1/session/create", s.wrap(s.SessionCreate))
|
s.handleFuncMetrics("/v1/session/create", s.wrap(s.SessionCreate))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/consul/structs"
|
"github.com/hashicorp/consul/consul/structs"
|
||||||
@ -55,3 +56,110 @@ func (s *HTTPServer) OperatorRaftPeer(resp http.ResponseWriter, req *http.Reques
|
|||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OperatorKeyringInstall is used to install a new gossip encryption key into the cluster
|
||||||
|
func (s *HTTPServer) OperatorKeyringInstall(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var args structs.KeyringRequest
|
||||||
|
if err := decodeBody(req, &args, nil); err != nil {
|
||||||
|
resp.WriteHeader(400)
|
||||||
|
resp.Write([]byte(fmt.Sprintf("Request decode failed: %v", err)))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
s.parseToken(req, &args.Token)
|
||||||
|
|
||||||
|
responses, err := s.agent.InstallKey(args.Key, args.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, response := range responses.Responses {
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorKeyringList is used to list the keys installed in the cluster
|
||||||
|
func (s *HTTPServer) OperatorKeyringList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var token string
|
||||||
|
s.parseToken(req, &token)
|
||||||
|
|
||||||
|
responses, err := s.agent.ListKeys(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, response := range responses.Responses {
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return responses.Responses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorKeyringRemove is used to list the keys installed in the cluster
|
||||||
|
func (s *HTTPServer) OperatorKeyringRemove(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "DELETE" {
|
||||||
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var args structs.KeyringRequest
|
||||||
|
if err := decodeBody(req, &args, nil); err != nil {
|
||||||
|
resp.WriteHeader(400)
|
||||||
|
resp.Write([]byte(fmt.Sprintf("Request decode failed: %v", err)))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
s.parseToken(req, &args.Token)
|
||||||
|
|
||||||
|
responses, err := s.agent.RemoveKey(args.Key, args.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, response := range responses.Responses {
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorKeyringUse is used to change the primary gossip encryption key
|
||||||
|
func (s *HTTPServer) OperatorKeyringUse(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var args structs.KeyringRequest
|
||||||
|
if err := decodeBody(req, &args, nil); err != nil {
|
||||||
|
resp.WriteHeader(400)
|
||||||
|
resp.Write([]byte(fmt.Sprintf("Request decode failed: %v", err)))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
s.parseToken(req, &args.Token)
|
||||||
|
|
||||||
|
responses, err := s.agent.UseKey(args.Key, args.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, response := range responses.Responses {
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package agent
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
@ -56,3 +57,185 @@ func TestOperator_OperatorRaftPeer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOperator_KeyringInstall(t *testing.T) {
|
||||||
|
oldKey := "H3/9gBxcKKRf45CaI2DlRg=="
|
||||||
|
newKey := "z90lFx3sZZLtTOkutXcwYg=="
|
||||||
|
configFunc := func(c *Config) {
|
||||||
|
c.EncryptKey = oldKey
|
||||||
|
}
|
||||||
|
httpTestWithConfig(t, func(srv *HTTPServer) {
|
||||||
|
body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", newKey))
|
||||||
|
req, err := http.NewRequest("PUT", "/v1/operator/keyring/install", body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
_, err = srv.OperatorKeyringInstall(resp, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
listResponse, err := srv.agent.ListKeys("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, response := range listResponse.Responses {
|
||||||
|
count, ok := response.Keys[newKey]
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad: %v", response.Keys)
|
||||||
|
}
|
||||||
|
if count != response.NumNodes {
|
||||||
|
t.Fatalf("bad: %d, %d", count, response.NumNodes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, configFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOperator_KeyringList(t *testing.T) {
|
||||||
|
key := "H3/9gBxcKKRf45CaI2DlRg=="
|
||||||
|
configFunc := func(c *Config) {
|
||||||
|
c.EncryptKey = key
|
||||||
|
}
|
||||||
|
httpTestWithConfig(t, func(srv *HTTPServer) {
|
||||||
|
req, err := http.NewRequest("GET", "/v1/operator/keyring/list", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
r, err := srv.OperatorKeyringList(resp, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
responses, ok := r.([]*structs.KeyringResponse)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("err: %v", !ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we get both a LAN and WAN response, and that they both only
|
||||||
|
// contain the original key
|
||||||
|
if len(responses) != 2 {
|
||||||
|
t.Fatalf("bad: %d", len(responses))
|
||||||
|
}
|
||||||
|
for _, response := range responses {
|
||||||
|
if len(response.Keys) != 1 {
|
||||||
|
t.Fatalf("bad: %d", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[key]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, configFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOperator_KeyringRemove(t *testing.T) {
|
||||||
|
key := "H3/9gBxcKKRf45CaI2DlRg=="
|
||||||
|
tempKey := "z90lFx3sZZLtTOkutXcwYg=="
|
||||||
|
configFunc := func(c *Config) {
|
||||||
|
c.EncryptKey = key
|
||||||
|
}
|
||||||
|
httpTestWithConfig(t, func(srv *HTTPServer) {
|
||||||
|
_, err := srv.agent.InstallKey(tempKey, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the temp key is installed
|
||||||
|
list, err := srv.agent.ListKeys("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
responses := list.Responses
|
||||||
|
if len(responses) != 2 {
|
||||||
|
t.Fatalf("bad: %d", len(responses))
|
||||||
|
}
|
||||||
|
for _, response := range responses {
|
||||||
|
if len(response.Keys) != 2 {
|
||||||
|
t.Fatalf("bad: %d", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[tempKey]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", tempKey))
|
||||||
|
req, err := http.NewRequest("DELETE", "/v1/operator/keyring/remove", body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
_, err = srv.OperatorKeyringRemove(resp, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the temp key has been removed
|
||||||
|
list, err = srv.agent.ListKeys("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
responses = list.Responses
|
||||||
|
if len(responses) != 2 {
|
||||||
|
t.Fatalf("bad: %d", len(responses))
|
||||||
|
}
|
||||||
|
for _, response := range responses {
|
||||||
|
if len(response.Keys) != 1 {
|
||||||
|
t.Fatalf("bad: %d", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[tempKey]; ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, configFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOperator_KeyringUse(t *testing.T) {
|
||||||
|
oldKey := "H3/9gBxcKKRf45CaI2DlRg=="
|
||||||
|
newKey := "z90lFx3sZZLtTOkutXcwYg=="
|
||||||
|
configFunc := func(c *Config) {
|
||||||
|
c.EncryptKey = oldKey
|
||||||
|
}
|
||||||
|
httpTestWithConfig(t, func(srv *HTTPServer) {
|
||||||
|
if _, err := srv.agent.InstallKey(newKey, ""); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", newKey))
|
||||||
|
req, err := http.NewRequest("PUT", "/v1/operator/keyring/use", body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
_, err = srv.OperatorKeyringUse(resp, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := srv.agent.RemoveKey(oldKey, ""); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure only the new key remains
|
||||||
|
list, err := srv.agent.ListKeys("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
responses := list.Responses
|
||||||
|
if len(responses) != 2 {
|
||||||
|
t.Fatalf("bad: %d", len(responses))
|
||||||
|
}
|
||||||
|
for _, response := range responses {
|
||||||
|
if len(response.Keys) != 1 {
|
||||||
|
t.Fatalf("bad: %d", len(response.Keys))
|
||||||
|
}
|
||||||
|
if _, ok := response.Keys[newKey]; !ok {
|
||||||
|
t.Fatalf("bad: %v", ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, configFunc)
|
||||||
|
}
|
||||||
|
@ -4,8 +4,9 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeygenCommand is a Command implementation that generates an encryption
|
// KeygenCommand is a Command implementation that generates an encryption
|
||||||
|
@ -906,10 +906,10 @@ func (r *KeyringRequest) RequestDatacenter() string {
|
|||||||
type KeyringResponse struct {
|
type KeyringResponse struct {
|
||||||
WAN bool
|
WAN bool
|
||||||
Datacenter string
|
Datacenter string
|
||||||
Messages map[string]string
|
Messages map[string]string `json:",omitempty"`
|
||||||
Keys map[string]int
|
Keys map[string]int
|
||||||
NumNodes int
|
NumNodes int
|
||||||
Error string
|
Error string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyringResponses holds multiple responses to keyring queries. Each
|
// KeyringResponses holds multiple responses to keyring queries. Each
|
||||||
|
@ -70,6 +70,7 @@ type TestServerConfig struct {
|
|||||||
ACLMasterToken string `json:"acl_master_token,omitempty"`
|
ACLMasterToken string `json:"acl_master_token,omitempty"`
|
||||||
ACLDatacenter string `json:"acl_datacenter,omitempty"`
|
ACLDatacenter string `json:"acl_datacenter,omitempty"`
|
||||||
ACLDefaultPolicy string `json:"acl_default_policy,omitempty"`
|
ACLDefaultPolicy string `json:"acl_default_policy,omitempty"`
|
||||||
|
Encrypt string `json:"encrypt,omitempty"`
|
||||||
Stdout, Stderr io.Writer `json:"-"`
|
Stdout, Stderr io.Writer `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user