Skip to content

Commit 08a0d9a

Browse files
authored
Return meta information from DoUpdate and Enroll (#23)
1 parent f2cf939 commit 08a0d9a

4 files changed

Lines changed: 255 additions & 72 deletions

File tree

client.go

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,33 @@ func (e *APIError) Unwrap() error {
8282
var ErrInvalidCredentials = fmt.Errorf("invalid credentials")
8383
var ErrInvalidCode = fmt.Errorf("invalid enrollment code")
8484

85-
type EnrollMeta struct {
86-
OrganizationID string
87-
OrganizationName string
85+
type ConfigMeta struct {
86+
Org ConfigOrg
87+
Network ConfigNetwork
88+
Host ConfigHost
89+
}
90+
91+
type ConfigOrg struct {
92+
ID string
93+
Name string
94+
}
95+
96+
type ConfigNetwork struct {
97+
ID string
98+
Name string
99+
}
100+
101+
type ConfigHost struct {
102+
ID string
103+
Name string
104+
IPAddress string
88105
}
89106

90107
// Enroll issues an enrollment request against the REST API using the given enrollment code, passing along a locally
91108
// generated DH X25519 public key to be signed by the CA, and an Ed 25519 public key for future API call authentication.
92109
// On success it returns the Nebula config generated by the server, a Nebula private key PEM to be inserted into the
93-
// config (see api.InsertConfigPrivateKey), credentials to be used in DNClient API requests, and a meta object
94-
// containing organization info.
95-
func (c *Client) Enroll(ctx context.Context, logger logrus.FieldLogger, code string) ([]byte, []byte, *keys.Credentials, *EnrollMeta, error) {
110+
// config (see api.InsertConfigPrivateKey), credentials to be used in DNClient API requests, and a meta object.
111+
func (c *Client) Enroll(ctx context.Context, logger logrus.FieldLogger, code string) ([]byte, []byte, *keys.Credentials, *ConfigMeta, error) {
96112
logger.WithFields(logrus.Fields{"server": c.dnServer}).Debug("Making enrollment request to API")
97113

98114
// Generate newKeys for the enrollment request
@@ -172,9 +188,20 @@ func (c *Client) Enroll(ctx context.Context, logger logrus.FieldLogger, code str
172188
return nil, nil, nil, nil, &APIError{e: fmt.Errorf("unexpected error during enrollment: %v", err), ReqID: reqID}
173189
}
174190

175-
meta := &EnrollMeta{
176-
OrganizationID: r.Data.Organization.ID,
177-
OrganizationName: r.Data.Organization.Name,
191+
meta := &ConfigMeta{
192+
Org: ConfigOrg{
193+
ID: r.Data.Organization.ID,
194+
Name: r.Data.Organization.Name,
195+
},
196+
Network: ConfigNetwork{
197+
ID: r.Data.Network.ID,
198+
Name: r.Data.Network.Name,
199+
},
200+
Host: ConfigHost{
201+
ID: r.Data.HostID,
202+
Name: r.Data.Host.Name,
203+
IPAddress: r.Data.Host.IPAddress,
204+
},
178205
}
179206

180207
// Determine the private keys to save based on the network curve type
@@ -243,17 +270,17 @@ func (c *Client) LongPollWait(ctx context.Context, creds keys.Credentials, suppo
243270

244271
// DoUpdate sends a signed message to the DNClient API to fetch the new configuration update. During this call new keys
245272
// are generated both for Nebula and DNClient API communication. If the API response is successful, the new configuration
246-
// is returned along with the new Nebula private key PEM and new DNClient API credentials.
273+
// is returned along with the new Nebula private key PEM, new DNClient API credentials, and a meta object.
247274
//
248275
// See dnapi.InsertConfigPrivateKey for how to insert the new Nebula private key into the configuration.
249-
func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte, []byte, *keys.Credentials, error) {
276+
func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte, []byte, *keys.Credentials, *ConfigMeta, error) {
250277
// Rotate keys
251278
var nebulaPrivkeyPEM []byte // ECDH
252279
var hostPrivkey keys.PrivateKey // ECDSA
253280

254281
newKeys, err := keys.New()
255282
if err != nil {
256-
return nil, nil, nil, fmt.Errorf("failed to generate new keys: %s", err)
283+
return nil, nil, nil, nil, fmt.Errorf("failed to generate new keys: %s", err)
257284
}
258285

259286
msg := message.DoUpdateRequest{
@@ -265,7 +292,7 @@ func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte,
265292
case ed25519.PrivateKey:
266293
hostPubkeyPEM, err := newKeys.HostEd25519PublicKey.MarshalPEM()
267294
if err != nil {
268-
return nil, nil, nil, fmt.Errorf("failed to marshal Ed25519 public key: %s", err)
295+
return nil, nil, nil, nil, fmt.Errorf("failed to marshal Ed25519 public key: %s", err)
269296
}
270297
hostPrivkey = newKeys.HostEd25519PrivateKey
271298
nebulaPrivkeyPEM = newKeys.NebulaX25519PrivateKeyPEM
@@ -274,7 +301,7 @@ func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte,
274301
case *ecdsa.PrivateKey:
275302
hostPubkeyPEM, err := newKeys.HostP256PublicKey.MarshalPEM()
276303
if err != nil {
277-
return nil, nil, nil, fmt.Errorf("failed to marshal P256 public key: %s", err)
304+
return nil, nil, nil, nil, fmt.Errorf("failed to marshal P256 public key: %s", err)
278305
}
279306
hostPrivkey = newKeys.HostP256PrivateKey
280307
nebulaPrivkeyPEM = newKeys.NebulaP256PrivateKeyPEM
@@ -284,18 +311,18 @@ func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte,
284311

285312
blob, err := json.Marshal(msg)
286313
if err != nil {
287-
return nil, nil, nil, fmt.Errorf("failed to marshal DNClient message: %s", err)
314+
return nil, nil, nil, nil, fmt.Errorf("failed to marshal DNClient message: %s", err)
288315
}
289316

290317
// Make API call
291318
resp, err := c.postDNClient(ctx, message.DoUpdate, blob, creds.HostID, creds.Counter, creds.PrivateKey)
292319
if err != nil {
293-
return nil, nil, nil, fmt.Errorf("failed to make API call to Defined Networking: %w", err)
320+
return nil, nil, nil, nil, fmt.Errorf("failed to make API call to Defined Networking: %w", err)
294321
}
295322
resultWrapper := message.SignedResponseWrapper{}
296323
err = json.Unmarshal(resp, &resultWrapper)
297324
if err != nil {
298-
return nil, nil, nil, fmt.Errorf("failed to unmarshal signed response wrapper: %s", err)
325+
return nil, nil, nil, nil, fmt.Errorf("failed to unmarshal signed response wrapper: %s", err)
299326
}
300327

301328
// Verify the signature
@@ -307,29 +334,29 @@ func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte,
307334
}
308335
}
309336
if !valid {
310-
return nil, nil, nil, fmt.Errorf("failed to verify signed API result")
337+
return nil, nil, nil, nil, fmt.Errorf("failed to verify signed API result")
311338
}
312339

313340
// Consume the verified message
314341
result := message.DoUpdateResponse{}
315342
err = json.Unmarshal(resultWrapper.Data.Message, &result)
316343
if err != nil {
317-
return nil, nil, nil, fmt.Errorf("failed to unmarshal response (%s): %s", resultWrapper.Data.Message, err)
344+
return nil, nil, nil, nil, fmt.Errorf("failed to unmarshal response (%s): %s", resultWrapper.Data.Message, err)
318345
}
319346

320347
// Verify the nonce
321348
if !bytes.Equal(result.Nonce, msg.Nonce) {
322-
return nil, nil, nil, fmt.Errorf("nonce mismatch between request (%s) and response (%s)", msg.Nonce, result.Nonce)
349+
return nil, nil, nil, nil, fmt.Errorf("nonce mismatch between request (%s) and response (%s)", msg.Nonce, result.Nonce)
323350
}
324351

325352
// Verify the counter
326353
if result.Counter <= creds.Counter {
327-
return nil, nil, nil, fmt.Errorf("counter in request (%d) should be less than counter in response (%d)", creds.Counter, result.Counter)
354+
return nil, nil, nil, nil, fmt.Errorf("counter in request (%d) should be less than counter in response (%d)", creds.Counter, result.Counter)
328355
}
329356

330357
trustedKeys, err := keys.TrustedKeysFromPEM(result.TrustedKeys)
331358
if err != nil {
332-
return nil, nil, nil, fmt.Errorf("failed to load trusted keys from bundle: %s", err)
359+
return nil, nil, nil, nil, fmt.Errorf("failed to load trusted keys from bundle: %s", err)
333360
}
334361

335362
newCreds := &keys.Credentials{
@@ -339,7 +366,23 @@ func (c *Client) DoUpdate(ctx context.Context, creds keys.Credentials) ([]byte,
339366
TrustedKeys: trustedKeys,
340367
}
341368

342-
return result.Config, nebulaPrivkeyPEM, newCreds, nil
369+
meta := &ConfigMeta{
370+
Org: ConfigOrg{
371+
ID: result.Organization.ID,
372+
Name: result.Organization.Name,
373+
},
374+
Network: ConfigNetwork{
375+
ID: result.Network.ID,
376+
Name: result.Network.Name,
377+
},
378+
Host: ConfigHost{
379+
ID: result.Host.ID,
380+
Name: result.Host.Name,
381+
IPAddress: result.Host.IPAddress,
382+
},
383+
}
384+
385+
return result.Config, nebulaPrivkeyPEM, newCreds, meta, nil
343386
}
344387

345388
func (c *Client) CommandResponse(ctx context.Context, creds keys.Credentials, responseToken string, response any) error {

0 commit comments

Comments
 (0)