mirror of https://github.com/status-im/consul.git
Create HCP management token in HCP manager (#19830)
* Create HCP management token in HCP manager * Change InitializeManagementToken to ManagementTokenUpserter * Implement and use management token upsert function * Fix race condition in test * Add idea for improvement as comment * Return early in upsertManagementToken if token exists
This commit is contained in:
parent
98c9702ba3
commit
37a5fddffa
|
@ -586,6 +586,55 @@ func (s *Server) initializeManagementToken(name, secretID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) upsertManagementToken(name, secretID string) error {
|
||||
state := s.fsm.State()
|
||||
if _, err := uuid.ParseUUID(secretID); err != nil {
|
||||
s.logger.Warn("Configuring a non-UUID management token is deprecated")
|
||||
}
|
||||
|
||||
_, token, err := state.ACLTokenGetBySecret(nil, secretID, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s: %v", name, err)
|
||||
}
|
||||
|
||||
if token != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
accessor, err := lib.GenerateUUID(s.checkTokenUUID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate the accessor ID for %s: %v", name, err)
|
||||
}
|
||||
|
||||
newToken := structs.ACLToken{
|
||||
AccessorID: accessor,
|
||||
SecretID: secretID,
|
||||
Description: name,
|
||||
Policies: []structs.ACLTokenPolicyLink{
|
||||
{
|
||||
ID: structs.ACLPolicyGlobalManagementID,
|
||||
},
|
||||
},
|
||||
CreateTime: time.Now(),
|
||||
Local: false,
|
||||
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
|
||||
}
|
||||
|
||||
newToken.SetHash(true)
|
||||
|
||||
req := structs.ACLTokenBatchSetRequest{
|
||||
Tokens: structs.ACLTokens{&newToken},
|
||||
CAS: false,
|
||||
}
|
||||
if _, err := s.raftApply(structs.ACLTokenSetRequestType, &req); err != nil {
|
||||
return fmt.Errorf("failed to create %s: %v", name, err)
|
||||
}
|
||||
|
||||
s.logger.Info("Created ACL token", "description", name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) insertAnonymousToken() error {
|
||||
state := s.fsm.State()
|
||||
_, token, err := state.ACLTokenGetBySecret(nil, anonymousToken, nil)
|
||||
|
|
|
@ -588,6 +588,15 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server,
|
|||
Logger: logger.Named("hcp_manager"),
|
||||
SCADAProvider: flat.HCP.Provider,
|
||||
TelemetryProvider: flat.HCP.TelemetryProvider,
|
||||
ManagementTokenUpserterFn: func(name, secretId string) error {
|
||||
if s.IsLeader() {
|
||||
// Idea for improvement: Upsert a token with a well-known accessorId here instead
|
||||
// of a randomly generated one. This would prevent any possible insertion collision between
|
||||
// this and the insertion that happens during the ACL initialization process (initializeACLs function)
|
||||
return s.upsertManagementToken(name, secretId)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
var recorder *middleware.RequestRecorder
|
||||
|
|
|
@ -26,9 +26,12 @@ type ManagerConfig struct {
|
|||
SCADAProvider scada.Provider
|
||||
TelemetryProvider *hcpProviderImpl
|
||||
|
||||
StatusFn StatusCallback
|
||||
MinInterval time.Duration
|
||||
MaxInterval time.Duration
|
||||
StatusFn StatusCallback
|
||||
// Idempotent function to upsert the HCP management token. This will be called periodically in
|
||||
// the manager's main loop.
|
||||
ManagementTokenUpserterFn ManagementTokenUpserter
|
||||
MinInterval time.Duration
|
||||
MaxInterval time.Duration
|
||||
|
||||
Logger hclog.Logger
|
||||
}
|
||||
|
@ -54,6 +57,7 @@ func (cfg *ManagerConfig) nextHeartbeat() time.Duration {
|
|||
}
|
||||
|
||||
type StatusCallback func(context.Context) (hcpclient.ServerStatus, error)
|
||||
type ManagementTokenUpserter func(name, secretId string) error
|
||||
|
||||
type Manager struct {
|
||||
logger hclog.Logger
|
||||
|
@ -111,6 +115,14 @@ func (m *Manager) Run(ctx context.Context) error {
|
|||
|
||||
// main loop
|
||||
for {
|
||||
// Check for configured management token from HCP and upsert it if found
|
||||
if hcpManagement := m.cfg.CloudConfig.ManagementToken; len(hcpManagement) > 0 {
|
||||
upsertTokenErr := m.cfg.ManagementTokenUpserterFn("HCP Management Token", hcpManagement)
|
||||
if upsertTokenErr != nil {
|
||||
m.logger.Error("failed to upsert HCP management token", "err", upsertTokenErr)
|
||||
}
|
||||
}
|
||||
|
||||
m.cfgMu.RLock()
|
||||
cfg := m.cfg
|
||||
m.cfgMu.RUnlock()
|
||||
|
|
|
@ -22,12 +22,18 @@ func TestManager_Run(t *testing.T) {
|
|||
statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) {
|
||||
return hcpclient.ServerStatus{ID: t.Name()}, nil
|
||||
}
|
||||
upsertManagementTokenCalled := make(chan struct{}, 1)
|
||||
upsertManagementTokenF := func(name, secretID string) error {
|
||||
upsertManagementTokenCalled <- struct{}{}
|
||||
return nil
|
||||
}
|
||||
updateCh := make(chan struct{}, 1)
|
||||
client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once()
|
||||
|
||||
cloudCfg := config.CloudConfig{
|
||||
ResourceID: "organization/85702e73-8a3d-47dc-291c-379b783c5804/project/8c0547c0-10e8-1ea2-dffe-384bee8da634/hashicorp.consul.global-network-manager.cluster/test",
|
||||
NodeID: "node-1",
|
||||
ResourceID: "organization/85702e73-8a3d-47dc-291c-379b783c5804/project/8c0547c0-10e8-1ea2-dffe-384bee8da634/hashicorp.consul.global-network-manager.cluster/test",
|
||||
NodeID: "node-1",
|
||||
ManagementToken: "fake-token",
|
||||
}
|
||||
scadaM := scada.NewMockProvider(t)
|
||||
scadaM.EXPECT().UpdateHCPConfig(cloudCfg).Return(nil)
|
||||
|
@ -52,12 +58,13 @@ func TestManager_Run(t *testing.T) {
|
|||
mockTelemetryCfg, nil).Maybe()
|
||||
|
||||
mgr := NewManager(ManagerConfig{
|
||||
Client: client,
|
||||
Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}),
|
||||
StatusFn: statusF,
|
||||
CloudConfig: cloudCfg,
|
||||
SCADAProvider: scadaM,
|
||||
TelemetryProvider: telemetryProvider,
|
||||
Client: client,
|
||||
Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}),
|
||||
StatusFn: statusF,
|
||||
ManagementTokenUpserterFn: upsertManagementTokenF,
|
||||
CloudConfig: cloudCfg,
|
||||
SCADAProvider: scadaM,
|
||||
TelemetryProvider: telemetryProvider,
|
||||
})
|
||||
mgr.testUpdateSent = updateCh
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -76,6 +83,7 @@ func TestManager_Run(t *testing.T) {
|
|||
require.Equal(t, client, telemetryProvider.hcpClient)
|
||||
require.NotNil(t, telemetryProvider.GetHeader())
|
||||
require.NotNil(t, telemetryProvider.GetHTTPClient())
|
||||
require.NotEmpty(t, upsertManagementTokenCalled, "upsert management token function not called")
|
||||
}
|
||||
|
||||
func TestManager_SendUpdate(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue