2021-06-23 21:14:28 +00:00
|
|
|
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.
|
2021-12-01 19:32:34 +00:00
|
|
|
func (b autoConfigBackend) DatacenterJoinAddresses(partition, segment string) ([]string, error) {
|
2021-10-26 20:08:55 +00:00
|
|
|
members, err := b.Server.LANMembers(LANMemberFilter{
|
|
|
|
Segment: segment,
|
2021-12-01 19:32:34 +00:00
|
|
|
Partition: partition,
|
2021-10-26 20:08:55 +00:00
|
|
|
})
|
2021-06-23 21:14:28 +00:00
|
|
|
if err != nil {
|
2021-12-01 19:32:34 +00:00
|
|
|
if segment != "" {
|
|
|
|
return nil, fmt.Errorf("Failed to retrieve members for segment %s: %w", segment, err)
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("Failed to retrieve members for partition %s: %w", structs.PartitionOrDefault(partition), err)
|
2021-06-23 21:14:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|