Skip to content

Commit 1ca13a0

Browse files
Merge remote-tracking branch 'remotes/from/ce/release/1.21.x' into release/1.21.x
2 parents c85e01b + 363655e commit 1ca13a0

File tree

7 files changed

+146
-2
lines changed

7 files changed

+146
-2
lines changed

builtin/logical/nomad/backend_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ import (
1616
nomadapi "github.com/hashicorp/nomad/api"
1717
"github.com/hashicorp/vault/helper/testhelpers"
1818
"github.com/hashicorp/vault/sdk/helper/docker"
19+
"github.com/hashicorp/vault/sdk/helper/testhelpers/observations"
1920
"github.com/hashicorp/vault/sdk/logical"
2021
"github.com/mitchellh/mapstructure"
22+
"github.com/stretchr/testify/require"
2123
)
2224

2325
type Config struct {
@@ -159,6 +161,8 @@ func preprePolicies(nomadClient *nomadapi.Client) error {
159161
func TestBackend_config_Bootstrap(t *testing.T) {
160162
config := logical.TestBackendConfig()
161163
config.StorageView = &logical.InmemStorage{}
164+
or := observations.NewTestObservationRecorder()
165+
config.ObservationRecorder = or
162166
b, err := Factory(context.Background(), config)
163167
if err != nil {
164168
t.Fatal(err)
@@ -184,12 +188,16 @@ func TestBackend_config_Bootstrap(t *testing.T) {
184188
t.Fatalf("failed to write configuration: resp:%#v err:%s", resp, err)
185189
}
186190

191+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadConfigAccessWrite))
192+
187193
confReq.Operation = logical.ReadOperation
188194
resp, err = b.HandleRequest(context.Background(), confReq)
189195
if err != nil || (resp != nil && resp.IsError()) {
190196
t.Fatalf("failed to write configuration: resp:%#v err:%s", resp, err)
191197
}
192198

199+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadConfigAccessRead))
200+
193201
expected := map[string]interface{}{
194202
"address": connData["address"].(string),
195203
"max_token_name_length": 0,
@@ -318,6 +326,8 @@ func TestBackend_config_access_with_certs(t *testing.T) {
318326
func TestBackend_renew_revoke(t *testing.T) {
319327
config := logical.TestBackendConfig()
320328
config.StorageView = &logical.InmemStorage{}
329+
or := observations.NewTestObservationRecorder()
330+
config.ObservationRecorder = or
321331
b, err := Factory(context.Background(), config)
322332
if err != nil {
323333
t.Fatal(err)
@@ -341,6 +351,7 @@ func TestBackend_renew_revoke(t *testing.T) {
341351
if err != nil {
342352
t.Fatal(err)
343353
}
354+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadConfigAccessWrite))
344355

345356
req.Path = "role/test"
346357
req.Data = map[string]interface{}{
@@ -351,6 +362,12 @@ func TestBackend_renew_revoke(t *testing.T) {
351362
if err != nil {
352363
t.Fatal(err)
353364
}
365+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadRoleWrite))
366+
roleObs := or.ObservationsByType(ObservationTypeNomadRoleWrite)
367+
require.Len(t, roleObs, 1)
368+
require.Equal(t, "test", roleObs[0].Data["role_name"])
369+
require.Equal(t, "client", roleObs[0].Data["token_type"])
370+
require.Equal(t, false, roleObs[0].Data["global"])
354371

355372
req.Operation = logical.ReadOperation
356373
req.Path = "creds/test"
@@ -364,6 +381,15 @@ func TestBackend_renew_revoke(t *testing.T) {
364381
if resp.IsError() {
365382
t.Fatalf("resp is error: %v", resp.Error())
366383
}
384+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadCredentialCreateSuccess))
385+
credObs := or.ObservationsByType(ObservationTypeNomadCredentialCreateSuccess)
386+
require.Len(t, credObs, 1)
387+
require.Equal(t, "test", credObs[0].Data["role_name"])
388+
require.Equal(t, "client", credObs[0].Data["token_type"])
389+
require.Equal(t, false, credObs[0].Data["global"])
390+
require.Equal(t, "0s", credObs[0].Data["ttl"])
391+
require.Equal(t, "0s", credObs[0].Data["max_ttl"])
392+
require.NotEmpty(t, credObs[0].Data["accessor_id"])
367393

368394
generatedSecret := resp.Secret
369395
generatedSecret.TTL = 6 * time.Hour
@@ -402,12 +428,24 @@ func TestBackend_renew_revoke(t *testing.T) {
402428
t.Fatal("got nil response from renew")
403429
}
404430

431+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadCredentialRenew))
432+
renewObs := or.ObservationsByType(ObservationTypeNomadCredentialRenew)
433+
require.Len(t, renewObs, 1)
434+
require.Equal(t, d.Accessor, renewObs[0].Data["accessor_id"])
435+
require.Equal(t, "0s", renewObs[0].Data["ttl"])
436+
require.Equal(t, "0s", renewObs[0].Data["max_ttl"])
437+
405438
req.Operation = logical.RevokeOperation
406439
resp, err = b.HandleRequest(context.Background(), req)
407440
if err != nil {
408441
t.Fatal(err)
409442
}
410443

444+
require.Equal(t, 1, or.NumObservationsByType(ObservationTypeNomadCredentialRevoke))
445+
revokeObs := or.ObservationsByType(ObservationTypeNomadCredentialRevoke)
446+
require.Len(t, revokeObs, 1)
447+
require.Equal(t, d.Accessor, revokeObs[0].Data["accessor_id"])
448+
411449
// Build a management client and verify that the token does not exist anymore
412450
nomadmgmtConfig := nomadapi.DefaultConfig()
413451
nomadmgmtConfig.Address = connData["address"].(string)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright IBM Corp. 2016, 2025
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package nomad
5+
6+
const (
7+
// Role observation types
8+
// These contain role_name, token_type, global as metadata
9+
10+
ObservationTypeNomadRoleWrite = "nomad/role/write"
11+
ObservationTypeNomadRoleRead = "nomad/role/read"
12+
13+
// Role delete observation type
14+
// This contains role_name as metadata
15+
16+
ObservationTypeNomadRoleDelete = "nomad/role/delete"
17+
18+
// Config observation types
19+
// These contain no metadata
20+
21+
ObservationTypeNomadConfigAccessRead = "nomad/config/access/read"
22+
ObservationTypeNomadConfigAccessWrite = "nomad/config/access/write"
23+
ObservationTypeNomadConfigAccessDelete = "nomad/config/access/delete"
24+
25+
// Lease config observation types
26+
// These contain ttl and max_ttl as metadata
27+
28+
ObservationTypeNomadConfigLeaseRead = "nomad/config/lease/read"
29+
ObservationTypeNomadConfigLeaseWrite = "nomad/config/lease/write"
30+
ObservationTypeNomadConfigLeaseDelete = "nomad/config/lease/delete"
31+
32+
// Credential success observation type
33+
// This contains role_name, token_type, global, ttl, max_ttl, accessor_id as metadata
34+
35+
ObservationTypeNomadCredentialCreateSuccess = "nomad/credential/create/success"
36+
37+
// Credential fail observation type
38+
// This contains role_name, token_type, global, ttl, max_ttl as metadata
39+
40+
ObservationTypeNomadCredentialCreateFail = "nomad/credential/create/fail"
41+
42+
// Credential revoke observation type
43+
// This contains accessor_id as metadata
44+
45+
ObservationTypeNomadCredentialRevoke = "nomad/credential/revoke"
46+
47+
// Credential renew observation type
48+
// This contains ttl, max_ttl, accessor_id as metadata
49+
50+
ObservationTypeNomadCredentialRenew = "nomad/credential/renew"
51+
)

builtin/logical/nomad/path_config_access.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ func (b *backend) pathConfigAccessRead(ctx context.Context, req *logical.Request
123123
return nil, nil
124124
}
125125

126+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigAccessRead, nil)
126127
return &logical.Response{
127128
Data: map[string]interface{}{
128129
"address": conf.Address,
@@ -177,6 +178,7 @@ func (b *backend) pathConfigAccessWrite(ctx context.Context, req *logical.Reques
177178

178179
conf.MaxTokenNameLength = data.Get("max_token_name_length").(int)
179180

181+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigAccessWrite, nil)
180182
entry, err := logical.StorageEntryJSON("config/access", conf)
181183
if err != nil {
182184
return nil, err
@@ -192,6 +194,7 @@ func (b *backend) pathConfigAccessDelete(ctx context.Context, req *logical.Reque
192194
if err := req.Storage.Delete(ctx, configAccessKey); err != nil {
193195
return nil, err
194196
}
197+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigAccessDelete, nil)
195198
return nil, nil
196199
}
197200

builtin/logical/nomad/path_config_lease.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,22 @@ func pathConfigLease(b *backend) *framework.Path {
6363

6464
// Sets the lease configuration parameters
6565
func (b *backend) pathLeaseUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
66+
ttl := time.Second * time.Duration(d.Get("ttl").(int))
67+
maxTTL := time.Second * time.Duration(d.Get("max_ttl").(int))
6668
entry, err := logical.StorageEntryJSON("config/lease", &configLease{
67-
TTL: time.Second * time.Duration(d.Get("ttl").(int)),
68-
MaxTTL: time.Second * time.Duration(d.Get("max_ttl").(int)),
69+
TTL: ttl,
70+
MaxTTL: maxTTL,
6971
})
7072
if err != nil {
7173
return nil, err
7274
}
7375
if err := req.Storage.Put(ctx, entry); err != nil {
7476
return nil, err
7577
}
78+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigLeaseWrite, map[string]interface{}{
79+
"ttl": ttl.String(),
80+
"max_ttl": maxTTL.String(),
81+
})
7682

7783
return nil, nil
7884
}
@@ -82,6 +88,7 @@ func (b *backend) pathLeaseDelete(ctx context.Context, req *logical.Request, d *
8288
return nil, err
8389
}
8490

91+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigLeaseDelete, nil)
8592
return nil, nil
8693
}
8794

@@ -95,6 +102,10 @@ func (b *backend) pathLeaseRead(ctx context.Context, req *logical.Request, data
95102
return nil, nil
96103
}
97104

105+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadConfigLeaseRead, map[string]interface{}{
106+
"ttl": lease.TTL.String(),
107+
"max_ttl": lease.MaxTTL.String(),
108+
})
98109
return &logical.Response{
99110
Data: map[string]interface{}{
100111
"ttl": int64(lease.TTL.Seconds()),

builtin/logical/nomad/path_creds_create.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ func (b *backend) pathTokenRead(ctx context.Context, req *logical.Request, d *fr
8282
tokenName = tokenName[:tokenNameLength]
8383
}
8484

85+
metadata := map[string]interface{}{
86+
"role_name": name,
87+
"token_type": role.TokenType,
88+
"global": role.Global,
89+
"ttl": leaseConfig.TTL.String(),
90+
"max_ttl": leaseConfig.MaxTTL.String(),
91+
}
92+
8593
// Create it
8694
token, _, err := c.ACLTokens().Create(&api.ACLToken{
8795
Name: tokenName,
@@ -90,6 +98,7 @@ func (b *backend) pathTokenRead(ctx context.Context, req *logical.Request, d *fr
9098
Global: role.Global,
9199
}, nil)
92100
if err != nil {
101+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadCredentialCreateFail, metadata)
93102
return nil, err
94103
}
95104

@@ -103,5 +112,7 @@ func (b *backend) pathTokenRead(ctx context.Context, req *logical.Request, d *fr
103112
resp.Secret.TTL = leaseConfig.TTL
104113
resp.Secret.MaxTTL = leaseConfig.MaxTTL
105114

115+
metadata["accessor_id"] = token.AccessorID
116+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadCredentialCreateSuccess, metadata)
106117
return resp, nil
107118
}

builtin/logical/nomad/path_roles.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ func (b *backend) pathRolesRead(ctx context.Context, req *logical.Request, d *fr
132132
"policies": role.Policies,
133133
},
134134
}
135+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadRoleRead, map[string]interface{}{
136+
"role_name": name,
137+
"token_type": role.TokenType,
138+
"global": role.Global,
139+
})
135140
return resp, nil
136141
}
137142

@@ -182,6 +187,12 @@ func (b *backend) pathRolesWrite(ctx context.Context, req *logical.Request, d *f
182187
return nil, err
183188
}
184189

190+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadRoleWrite, map[string]interface{}{
191+
"role_name": name,
192+
"token_type": role.TokenType,
193+
"global": role.Global,
194+
})
195+
185196
return nil, nil
186197
}
187198

@@ -190,6 +201,9 @@ func (b *backend) pathRolesDelete(ctx context.Context, req *logical.Request, d *
190201
if err := req.Storage.Delete(ctx, "role/"+name); err != nil {
191202
return nil, err
192203
}
204+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadRoleDelete, map[string]interface{}{
205+
"role_name": name,
206+
})
193207
return nil, nil
194208
}
195209

builtin/logical/nomad/secret_token.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ func (b *backend) secretTokenRenew(ctx context.Context, req *logical.Request, d
4242
resp := &logical.Response{Secret: req.Secret}
4343
resp.Secret.TTL = lease.TTL
4444
resp.Secret.MaxTTL = lease.MaxTTL
45+
accessorID := ""
46+
if req.Secret.InternalData != nil {
47+
accessorIDRaw, ok := req.Secret.InternalData["accessor_id"]
48+
if ok {
49+
accessorID, _ = accessorIDRaw.(string)
50+
}
51+
}
52+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadCredentialRenew, map[string]interface{}{
53+
"ttl": lease.TTL.String(),
54+
"max_ttl": lease.MaxTTL.String(),
55+
"accessor_id": accessorID,
56+
})
4557
return resp, nil
4658
}
4759

@@ -68,5 +80,9 @@ func (b *backend) secretTokenRevoke(ctx context.Context, req *logical.Request, d
6880
return nil, err
6981
}
7082

83+
b.TryRecordObservationWithRequest(ctx, req, ObservationTypeNomadCredentialRevoke, map[string]interface{}{
84+
"accessor_id": accessorID,
85+
})
86+
7187
return nil, nil
7288
}

0 commit comments

Comments
 (0)