-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
auto-config: move autoConfigBackend impl off of Server
Most of these methods are used exclusively for the AutoConfig RPC endpoint. This PR uses a pattern that we've used in other places as an incremental step to reducing the scope of Server.
- Loading branch information
1 parent
2c5eac0
commit 3b90b99
Showing
8 changed files
with
213 additions
and
186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package consul | ||
|
||
import ( | ||
"crypto/x509" | ||
"fmt" | ||
"net" | ||
"time" | ||
|
||
"github.com/hashicorp/consul/agent/connect" | ||
"github.com/hashicorp/consul/agent/metadata" | ||
"github.com/hashicorp/consul/agent/structs" | ||
"github.com/hashicorp/consul/lib" | ||
) | ||
|
||
type autoConfigBackend struct { | ||
Server *Server | ||
} | ||
|
||
func (b autoConfigBackend) ForwardRPC(method string, info structs.RPCInfo, reply interface{}) (bool, error) { | ||
return b.Server.ForwardRPC(method, info, reply) | ||
} | ||
|
||
func (b autoConfigBackend) SignCertificate(csr *x509.CertificateRequest, id connect.CertURI) (*structs.IssuedCert, error) { | ||
return b.Server.caManager.SignCertificate(csr, id) | ||
} | ||
|
||
// GetCARoots returns the CA roots. | ||
func (b autoConfigBackend) GetCARoots() (*structs.IndexedCARoots, error) { | ||
return b.Server.getCARoots(nil, b.Server.fsm.State()) | ||
} | ||
|
||
// DatacenterJoinAddresses will return all the strings suitable for usage in | ||
// retry join operations to connect to the the LAN or LAN segment gossip pool. | ||
func (b autoConfigBackend) DatacenterJoinAddresses(segment string) ([]string, error) { | ||
members, err := b.Server.LANSegmentMembers(segment) | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to retrieve members for segment %s - %w", segment, err) | ||
} | ||
|
||
var joinAddrs []string | ||
for _, m := range members { | ||
if ok, _ := metadata.IsConsulServer(m); ok { | ||
serfAddr := net.TCPAddr{IP: m.Addr, Port: int(m.Port)} | ||
joinAddrs = append(joinAddrs, serfAddr.String()) | ||
} | ||
} | ||
|
||
return joinAddrs, nil | ||
} | ||
|
||
// CreateACLToken will create an ACL token from the given template | ||
func (b autoConfigBackend) CreateACLToken(template *structs.ACLToken) (*structs.ACLToken, error) { | ||
// we have to require local tokens or else it would require having these servers use a token with acl:write to make a | ||
// token create RPC to the servers in the primary DC. | ||
if !b.Server.LocalTokensEnabled() { | ||
return nil, fmt.Errorf("Agent Auto Configuration requires local token usage to be enabled in this datacenter: %s", b.Server.config.Datacenter) | ||
} | ||
|
||
newToken := *template | ||
|
||
// generate the accessor id | ||
if newToken.AccessorID == "" { | ||
accessor, err := lib.GenerateUUID(b.Server.checkTokenUUID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
newToken.AccessorID = accessor | ||
} | ||
|
||
// generate the secret id | ||
if newToken.SecretID == "" { | ||
secret, err := lib.GenerateUUID(b.Server.checkTokenUUID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
newToken.SecretID = secret | ||
} | ||
|
||
newToken.CreateTime = time.Now() | ||
|
||
req := structs.ACLTokenBatchSetRequest{ | ||
Tokens: structs.ACLTokens{&newToken}, | ||
CAS: false, | ||
} | ||
|
||
// perform the request to mint the new token | ||
if _, err := b.Server.raftApplyMsgpack(structs.ACLTokenSetRequestType, &req); err != nil { | ||
return nil, err | ||
} | ||
|
||
// return the full token definition from the FSM | ||
_, token, err := b.Server.fsm.State().ACLTokenGetByAccessor(nil, newToken.AccessorID, &newToken.EnterpriseMeta) | ||
return token, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package consul | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/hashicorp/consul/agent/structs" | ||
) | ||
|
||
func TestAutoConfigBackend_DatacenterJoinAddresses(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("too slow for testing.Short") | ||
} | ||
|
||
conf := testClusterConfig{ | ||
Datacenter: "primary", | ||
Servers: 3, | ||
} | ||
|
||
nodes := newTestCluster(t, &conf) | ||
|
||
var expected []string | ||
for _, srv := range nodes.Servers { | ||
expected = append(expected, fmt.Sprintf("127.0.0.1:%d", srv.config.SerfLANConfig.MemberlistConfig.BindPort)) | ||
} | ||
|
||
backend := autoConfigBackend{Server: nodes.Servers[0]} | ||
actual, err := backend.DatacenterJoinAddresses("") | ||
require.NoError(t, err) | ||
require.ElementsMatch(t, expected, actual) | ||
} | ||
|
||
func TestAutoConfigBackend_CreateACLToken(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("too slow for testing.Short") | ||
} | ||
|
||
_, srv, codec := testACLServerWithConfig(t, nil, false) | ||
|
||
waitForLeaderEstablishment(t, srv) | ||
|
||
r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1") | ||
require.NoError(t, err) | ||
|
||
t.Run("predefined-ids", func(t *testing.T) { | ||
accessor := "554cd3ab-5d4e-4d6e-952e-4e8b6c77bfb3" | ||
secret := "ef453f31-ad58-4ec8-8bf8-342e99763026" | ||
in := &structs.ACLToken{ | ||
AccessorID: accessor, | ||
SecretID: secret, | ||
Description: "test", | ||
Policies: []structs.ACLTokenPolicyLink{ | ||
{ | ||
ID: structs.ACLPolicyGlobalManagementID, | ||
}, | ||
}, | ||
NodeIdentities: []*structs.ACLNodeIdentity{ | ||
{ | ||
NodeName: "foo", | ||
Datacenter: "bar", | ||
}, | ||
}, | ||
ServiceIdentities: []*structs.ACLServiceIdentity{ | ||
{ | ||
ServiceName: "web", | ||
}, | ||
}, | ||
Roles: []structs.ACLTokenRoleLink{ | ||
{ | ||
ID: r1.ID, | ||
}, | ||
}, | ||
} | ||
|
||
b := autoConfigBackend{Server: srv} | ||
out, err := b.CreateACLToken(in) | ||
require.NoError(t, err) | ||
require.Equal(t, accessor, out.AccessorID) | ||
require.Equal(t, secret, out.SecretID) | ||
require.Equal(t, "test", out.Description) | ||
require.NotZero(t, out.CreateTime) | ||
require.Len(t, out.Policies, 1) | ||
require.Len(t, out.Roles, 1) | ||
require.Len(t, out.NodeIdentities, 1) | ||
require.Len(t, out.ServiceIdentities, 1) | ||
require.Equal(t, structs.ACLPolicyGlobalManagementID, out.Policies[0].ID) | ||
require.Equal(t, "foo", out.NodeIdentities[0].NodeName) | ||
require.Equal(t, "web", out.ServiceIdentities[0].ServiceName) | ||
require.Equal(t, r1.ID, out.Roles[0].ID) | ||
}) | ||
|
||
t.Run("autogen-ids", func(t *testing.T) { | ||
in := &structs.ACLToken{ | ||
Description: "test", | ||
NodeIdentities: []*structs.ACLNodeIdentity{ | ||
{ | ||
NodeName: "foo", | ||
Datacenter: "bar", | ||
}, | ||
}, | ||
} | ||
|
||
b := autoConfigBackend{Server: srv} | ||
out, err := b.CreateACLToken(in) | ||
require.NoError(t, err) | ||
require.NotEmpty(t, out.AccessorID) | ||
require.NotEmpty(t, out.SecretID) | ||
require.Equal(t, "test", out.Description) | ||
require.NotZero(t, out.CreateTime) | ||
require.Len(t, out.NodeIdentities, 1) | ||
require.Equal(t, "foo", out.NodeIdentities[0].NodeName) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.