From 4a6bfc9eecd72184bd034122354ee87aadb6be80 Mon Sep 17 00:00:00 2001 From: Anton Averchenkov <84287187+averche@users.noreply.github.com> Date: Tue, 24 Jan 2023 13:12:41 -0500 Subject: [PATCH] Add approle's remaining response schema definitions (#18772) --- builtin/credential/approle/path_login.go | 22 ++++++++++++ builtin/credential/approle/path_login_test.go | 34 +++++++++++++++++++ .../credential/approle/path_tidy_user_id.go | 11 ++++-- .../approle/path_tidy_user_id_test.go | 28 +++++++++++++-- changelog/18772.txt | 3 ++ .../testhelpers/schema/response_validation.go | 5 +-- 6 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 changelog/18772.txt diff --git a/builtin/credential/approle/path_login.go b/builtin/credential/approle/path_login.go index 2ad3924ba9e5..489ff638e2e4 100644 --- a/builtin/credential/approle/path_login.go +++ b/builtin/credential/approle/path_login.go @@ -3,6 +3,7 @@ package approle import ( "context" "fmt" + "net/http" "strings" "time" @@ -29,12 +30,33 @@ func pathLogin(b *backend) *framework.Path { Operations: map[logical.Operation]framework.OperationHandler{ logical.UpdateOperation: &framework.PathOperation{ Callback: b.pathLoginUpdate, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: http.StatusText(http.StatusOK), + }}, + }, }, logical.AliasLookaheadOperation: &framework.PathOperation{ Callback: b.pathLoginUpdateAliasLookahead, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: http.StatusText(http.StatusOK), + }}, + }, }, logical.ResolveRoleOperation: &framework.PathOperation{ Callback: b.pathLoginResolveRole, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: http.StatusText(http.StatusOK), + Fields: map[string]*framework.FieldSchema{ + "role": { + Type: framework.TypeString, + Required: true, + }, + }, + }}, + }, }, }, HelpSynopsis: pathLoginHelpSys, diff --git a/builtin/credential/approle/path_login_test.go b/builtin/credential/approle/path_login_test.go index 542bf665b6e9..9a7f57af4d85 100644 --- a/builtin/credential/approle/path_login_test.go +++ b/builtin/credential/approle/path_login_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/hashicorp/vault/sdk/framework" + "github.com/hashicorp/vault/sdk/helper/testhelpers/schema" "github.com/hashicorp/vault/sdk/logical" ) @@ -14,6 +16,8 @@ func TestAppRole_BoundCIDRLogin(t *testing.T) { var err error b, s := createBackendWithStorage(t) + paths := []*framework.Path{pathLogin(b)} + // Create a role with secret ID binding disabled and only bound cidr list // enabled resp, err = b.HandleRequest(context.Background(), &logical.Request{ @@ -64,6 +68,12 @@ func TestAppRole_BoundCIDRLogin(t *testing.T) { if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/8" { t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), + resp, + true, + ) // Override with a secret-id value, verify it doesn't pass resp, err = b.HandleRequest(context.Background(), &logical.Request{ @@ -120,6 +130,12 @@ func TestAppRole_BoundCIDRLogin(t *testing.T) { if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/24" { t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), + resp, + true, + ) } func TestAppRole_RoleLogin(t *testing.T) { @@ -127,6 +143,8 @@ func TestAppRole_RoleLogin(t *testing.T) { var err error b, storage := createBackendWithStorage(t) + paths := []*framework.Path{pathLogin(b)} + createRole(t, b, storage, "role1", "a,b,c") roleRoleIDReq := &logical.Request{ Operation: logical.ReadOperation, @@ -188,6 +206,13 @@ func TestAppRole_RoleLogin(t *testing.T) { t.Fatalf("expected metadata.alias.role_name to equal 'role1', got: %v", val) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, loginReq.Operation), + resp, + true, + ) + // Test renewal renewReq := generateRenewRequest(storage, loginResp.Auth) @@ -307,6 +332,8 @@ func TestAppRole_RoleResolve(t *testing.T) { var err error b, storage := createBackendWithStorage(t) + paths := []*framework.Path{pathLogin(b)} + role := "role1" createRole(t, b, storage, role, "a,b,c") roleRoleIDReq := &logical.Request{ @@ -353,6 +380,13 @@ func TestAppRole_RoleResolve(t *testing.T) { if resp.Data["role"] != role { t.Fatalf("Role was not as expected. Expected %s, received %s", role, resp.Data["role"]) } + + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, loginReq.Operation), + resp, + true, + ) } func TestAppRole_RoleDoesNotExist(t *testing.T) { diff --git a/builtin/credential/approle/path_tidy_user_id.go b/builtin/credential/approle/path_tidy_user_id.go index b7c6fcc6b1ec..3f031267928c 100644 --- a/builtin/credential/approle/path_tidy_user_id.go +++ b/builtin/credential/approle/path_tidy_user_id.go @@ -17,8 +17,15 @@ func pathTidySecretID(b *backend) *framework.Path { return &framework.Path{ Pattern: "tidy/secret-id$", - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.UpdateOperation: b.pathTidySecretIDUpdate, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.UpdateOperation: &framework.PathOperation{ + Callback: b.pathTidySecretIDUpdate, + Responses: map[int][]framework.Response{ + http.StatusAccepted: {{ + Description: http.StatusText(http.StatusAccepted), + }}, + }, + }, }, HelpSynopsis: pathTidySecretIDSyn, diff --git a/builtin/credential/approle/path_tidy_user_id_test.go b/builtin/credential/approle/path_tidy_user_id_test.go index dd7dfdfd7d65..c0590e1edec6 100644 --- a/builtin/credential/approle/path_tidy_user_id_test.go +++ b/builtin/credential/approle/path_tidy_user_id_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/hashicorp/vault/sdk/framework" + "github.com/hashicorp/vault/sdk/helper/testhelpers/schema" "github.com/hashicorp/vault/sdk/logical" ) @@ -16,6 +18,8 @@ func TestAppRole_TidyDanglingAccessors_Normal(t *testing.T) { var err error b, storage := createBackendWithStorage(t) + paths := []*framework.Path{pathTidySecretID(b)} + // Create a role createRole(t, b, storage, "role1", "a,b,c") @@ -73,12 +77,18 @@ func TestAppRole_TidyDanglingAccessors_Normal(t *testing.T) { t.Fatalf("bad: len(accessorHashes); expect 3, got %d", len(accessorHashes)) } - _, err = b.tidySecretID(context.Background(), &logical.Request{ + secret, err := b.tidySecretID(context.Background(), &logical.Request{ Storage: storage, }) if err != nil { t.Fatal(err) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), + secret, + true, + ) // It runs async so we give it a bit of time to run time.Sleep(10 * time.Second) @@ -97,6 +107,8 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) { var err error b, storage := createBackendWithStorage(t) + paths := []*framework.Path{pathTidySecretID(b)} + // Create a role createRole(t, b, storage, "role1", "a,b,c") @@ -116,12 +128,18 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) { start := time.Now() for time.Now().Sub(start) < 10*time.Second { if time.Now().Sub(start) > 100*time.Millisecond && atomic.LoadUint32(b.tidySecretIDCASGuard) == 0 { - _, err = b.tidySecretID(context.Background(), &logical.Request{ + secret, err := b.tidySecretID(context.Background(), &logical.Request{ Storage: storage, }) if err != nil { t.Fatal(err) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), + secret, + true, + ) } wg.Add(1) go func() { @@ -173,6 +191,12 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) { if err != nil || len(secret.Warnings) > 0 { t.Fatal(err, secret.Warnings) } + schema.ValidateResponse( + t, + schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), + secret, + true, + ) // Wait for tidy to start for atomic.LoadUint32(b.tidySecretIDCASGuard) == 0 { diff --git a/changelog/18772.txt b/changelog/18772.txt new file mode 100644 index 000000000000..55c0696de1ba --- /dev/null +++ b/changelog/18772.txt @@ -0,0 +1,3 @@ +```release-note:improvement +openapi: Add openapi response definitions to approle/path_login.go & approle/path_tidy_user_id.go +``` diff --git a/sdk/helper/testhelpers/schema/response_validation.go b/sdk/helper/testhelpers/schema/response_validation.go index 3b7f2a48a340..8e46fac47976 100644 --- a/sdk/helper/testhelpers/schema/response_validation.go +++ b/sdk/helper/testhelpers/schema/response_validation.go @@ -100,8 +100,9 @@ func FindResponseSchema(t *testing.T, paths []*framework.Path, pathIdx int, oper var schemaResponses []framework.Response for _, status := range []int{ - http.StatusOK, - http.StatusNoContent, + http.StatusOK, // 200 + http.StatusAccepted, // 202 + http.StatusNoContent, // 204 } { schemaResponses, ok = schemaOperation.Properties().Responses[status] if ok {