@@ -15,6 +15,7 @@ import (
15
15
"testing"
16
16
"time"
17
17
18
+ "github.com/hashicorp/go-secure-stdlib/strutil"
18
19
"github.com/hashicorp/vault/api"
19
20
"github.com/hashicorp/vault/builtin/credential/userpass"
20
21
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
@@ -24,6 +25,7 @@ import (
24
25
"github.com/hashicorp/vault/sdk/logical"
25
26
"github.com/hashicorp/vault/vault"
26
27
"github.com/mitchellh/mapstructure"
28
+ "github.com/stretchr/testify/assert"
27
29
"github.com/stretchr/testify/require"
28
30
"golang.org/x/crypto/ssh"
29
31
)
@@ -212,6 +214,101 @@ func testSSH(user, host string, auth ssh.AuthMethod, command string) error {
212
214
return nil
213
215
}
214
216
217
+ // TestBackend_ReadRolesReturnsAllFields validates we did not forget to return a newly added
218
+ // field from the ssh role in the read API.
219
+ func TestBackend_ReadRolesReturnsAllFields (t * testing.T ) {
220
+ t .Parallel ()
221
+
222
+ config := logical .TestBackendConfig ()
223
+ config .StorageView = & logical.InmemStorage {}
224
+
225
+ b , err := Backend (config )
226
+ require .NoError (t , err , "failed creating backend" )
227
+ err = b .Setup (context .Background (), config )
228
+ require .NoError (t , err , "failed setting up backend" )
229
+
230
+ tests := []struct {
231
+ name string
232
+ data map [string ]interface {}
233
+ ignoredFields []string
234
+ }{
235
+ {
236
+ name : "otp" ,
237
+ data : map [string ]interface {}{
238
+ "key_type" : "otp" ,
239
+ "default_user" : "ubuntu" ,
240
+ },
241
+ ignoredFields : []string {
242
+ "allow_host_certificates" , "allow_subdomains" ,
243
+ "default_user_template" , "allowed_extensions" , "allowed_user_key_lengths" ,
244
+ "allow_empty_principals" , "ttl" , "allowed_domains_template" ,
245
+ "default_extensions_template" , "default_critical_options" ,
246
+ "allow_bare_domains" , "allowed_domains" , "allowed_critical_options" ,
247
+ "allow_user_certificates" , "allow_user_key_ids" , "algorithm_signer" ,
248
+ "not_before_duration" , "max_ttl" , "default_extensions" , "allowed_users_template" , "key_id_format" ,
249
+ },
250
+ },
251
+ {
252
+ name : "ca" ,
253
+ data : map [string ]interface {}{
254
+ "key_type" : "ca" ,
255
+ "algorithm_signer" : "rsa-sha2-256" ,
256
+ "allow_user_certificates" : true ,
257
+ },
258
+ ignoredFields : []string {"port" , "cidr_list" , "exclude_cidr_list" },
259
+ },
260
+ }
261
+
262
+ for _ , tc := range tests {
263
+ t .Run (tc .name , func (t * testing.T ) {
264
+ var fieldsToIgnore []string
265
+ fieldsToIgnore = append (fieldsToIgnore , tc .ignoredFields ... )
266
+ // These fields apply to all use cases, role_version is never returned and
267
+ // allowed_user_key_types_lengths is an internal value for the allowed_user_key_lengths field
268
+ fieldsToIgnore = append (fieldsToIgnore , "role_version" )
269
+ fieldsToIgnore = append (fieldsToIgnore , "allowed_user_key_types_lengths" )
270
+
271
+ roleName := fmt .Sprintf ("roles/role-%s" , tc .name )
272
+ req := & logical.Request {
273
+ Operation : logical .UpdateOperation ,
274
+ Path : roleName ,
275
+ Storage : config .StorageView ,
276
+ Data : tc .data ,
277
+ }
278
+ resp , err := b .HandleRequest (context .Background (), req )
279
+ if err != nil || (resp != nil && resp .IsError ()) || resp != nil {
280
+ t .Fatalf ("failed to create role %s: resp:%#v err:%s" , roleName , resp , err )
281
+ }
282
+
283
+ req = & logical.Request {
284
+ Operation : logical .ReadOperation ,
285
+ Path : roleName ,
286
+ Storage : config .StorageView ,
287
+ }
288
+ resp , err = b .HandleRequest (context .Background (), req )
289
+ if err != nil || (resp != nil && resp .IsError ()) || resp == nil {
290
+ t .Fatalf ("failed to read role %s: resp:%#v err:%s" , roleName , resp , err )
291
+ }
292
+
293
+ roleMap := map [string ]interface {}{}
294
+ err = mapstructure .Decode (sshRole {}, & roleMap )
295
+ require .NoError (t , err , "failed getting all fields in ssh role" )
296
+
297
+ // Identify missing fields from OTP response
298
+ var missingFields []string
299
+ for fieldName := range roleMap {
300
+ if _ , ok := resp .Data [fieldName ]; ! ok {
301
+ if strutil .StrListContains (fieldsToIgnore , fieldName ) {
302
+ continue
303
+ }
304
+ missingFields = append (missingFields , fieldName )
305
+ }
306
+ }
307
+ assert .Empty (t , missingFields , "response was missing fields: %s" , missingFields )
308
+ })
309
+ }
310
+ }
311
+
215
312
func TestBackend_AllowedUsers (t * testing.T ) {
216
313
config := logical .TestBackendConfig ()
217
314
config .StorageView = & logical.InmemStorage {}
0 commit comments