Add approle's remaining response schema definitions (#18772)

This commit is contained in:
Anton Averchenkov 2023-01-24 13:12:41 -05:00 committed by GitHub
parent 08413df3fc
commit 5a6092f8ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 6 deletions

View file

@ -3,6 +3,7 @@ package approle
import ( import (
"context" "context"
"fmt" "fmt"
"net/http"
"strings" "strings"
"time" "time"
@ -29,12 +30,33 @@ func pathLogin(b *backend) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{ Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{ logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathLoginUpdate, Callback: b.pathLoginUpdate,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: http.StatusText(http.StatusOK),
}},
},
}, },
logical.AliasLookaheadOperation: &framework.PathOperation{ logical.AliasLookaheadOperation: &framework.PathOperation{
Callback: b.pathLoginUpdateAliasLookahead, Callback: b.pathLoginUpdateAliasLookahead,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: http.StatusText(http.StatusOK),
}},
},
}, },
logical.ResolveRoleOperation: &framework.PathOperation{ logical.ResolveRoleOperation: &framework.PathOperation{
Callback: b.pathLoginResolveRole, 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, HelpSynopsis: pathLoginHelpSys,

View file

@ -6,6 +6,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )
@ -14,6 +16,8 @@ func TestAppRole_BoundCIDRLogin(t *testing.T) {
var err error var err error
b, s := createBackendWithStorage(t) b, s := createBackendWithStorage(t)
paths := []*framework.Path{pathLogin(b)}
// Create a role with secret ID binding disabled and only bound cidr list // Create a role with secret ID binding disabled and only bound cidr list
// enabled // enabled
resp, err = b.HandleRequest(context.Background(), &logical.Request{ 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" { if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/8" {
t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) 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 // Override with a secret-id value, verify it doesn't pass
resp, err = b.HandleRequest(context.Background(), &logical.Request{ 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" { if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/24" {
t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) 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) { func TestAppRole_RoleLogin(t *testing.T) {
@ -127,6 +143,8 @@ func TestAppRole_RoleLogin(t *testing.T) {
var err error var err error
b, storage := createBackendWithStorage(t) b, storage := createBackendWithStorage(t)
paths := []*framework.Path{pathLogin(b)}
createRole(t, b, storage, "role1", "a,b,c") createRole(t, b, storage, "role1", "a,b,c")
roleRoleIDReq := &logical.Request{ roleRoleIDReq := &logical.Request{
Operation: logical.ReadOperation, 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) 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 // Test renewal
renewReq := generateRenewRequest(storage, loginResp.Auth) renewReq := generateRenewRequest(storage, loginResp.Auth)
@ -307,6 +332,8 @@ func TestAppRole_RoleResolve(t *testing.T) {
var err error var err error
b, storage := createBackendWithStorage(t) b, storage := createBackendWithStorage(t)
paths := []*framework.Path{pathLogin(b)}
role := "role1" role := "role1"
createRole(t, b, storage, role, "a,b,c") createRole(t, b, storage, role, "a,b,c")
roleRoleIDReq := &logical.Request{ roleRoleIDReq := &logical.Request{
@ -353,6 +380,13 @@ func TestAppRole_RoleResolve(t *testing.T) {
if resp.Data["role"] != role { if resp.Data["role"] != role {
t.Fatalf("Role was not as expected. Expected %s, received %s", role, resp.Data["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) { func TestAppRole_RoleDoesNotExist(t *testing.T) {

View file

@ -17,8 +17,15 @@ func pathTidySecretID(b *backend) *framework.Path {
return &framework.Path{ return &framework.Path{
Pattern: "tidy/secret-id$", Pattern: "tidy/secret-id$",
Callbacks: map[logical.Operation]framework.OperationFunc{ Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: b.pathTidySecretIDUpdate, logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathTidySecretIDUpdate,
Responses: map[int][]framework.Response{
http.StatusAccepted: {{
Description: http.StatusText(http.StatusAccepted),
}},
},
},
}, },
HelpSynopsis: pathTidySecretIDSyn, HelpSynopsis: pathTidySecretIDSyn,

View file

@ -8,6 +8,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )
@ -16,6 +18,8 @@ func TestAppRole_TidyDanglingAccessors_Normal(t *testing.T) {
var err error var err error
b, storage := createBackendWithStorage(t) b, storage := createBackendWithStorage(t)
paths := []*framework.Path{pathTidySecretID(b)}
// Create a role // Create a role
createRole(t, b, storage, "role1", "a,b,c") 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)) 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, Storage: storage,
}) })
if err != nil { if err != nil {
t.Fatal(err) 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 // It runs async so we give it a bit of time to run
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
@ -97,6 +107,8 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) {
var err error var err error
b, storage := createBackendWithStorage(t) b, storage := createBackendWithStorage(t)
paths := []*framework.Path{pathTidySecretID(b)}
// Create a role // Create a role
createRole(t, b, storage, "role1", "a,b,c") createRole(t, b, storage, "role1", "a,b,c")
@ -116,12 +128,18 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) {
start := time.Now() start := time.Now()
for time.Now().Sub(start) < 10*time.Second { for time.Now().Sub(start) < 10*time.Second {
if time.Now().Sub(start) > 100*time.Millisecond && atomic.LoadUint32(b.tidySecretIDCASGuard) == 0 { 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, Storage: storage,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
schema.ValidateResponse(
t,
schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation),
secret,
true,
)
} }
wg.Add(1) wg.Add(1)
go func() { go func() {
@ -173,6 +191,12 @@ func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) {
if err != nil || len(secret.Warnings) > 0 { if err != nil || len(secret.Warnings) > 0 {
t.Fatal(err, secret.Warnings) t.Fatal(err, secret.Warnings)
} }
schema.ValidateResponse(
t,
schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation),
secret,
true,
)
// Wait for tidy to start // Wait for tidy to start
for atomic.LoadUint32(b.tidySecretIDCASGuard) == 0 { for atomic.LoadUint32(b.tidySecretIDCASGuard) == 0 {

3
changelog/18772.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:improvement
openapi: Add openapi response definitions to approle/path_login.go & approle/path_tidy_user_id.go
```

View file

@ -100,8 +100,9 @@ func FindResponseSchema(t *testing.T, paths []*framework.Path, pathIdx int, oper
var schemaResponses []framework.Response var schemaResponses []framework.Response
for _, status := range []int{ for _, status := range []int{
http.StatusOK, http.StatusOK, // 200
http.StatusNoContent, http.StatusAccepted, // 202
http.StatusNoContent, // 204
} { } {
schemaResponses, ok = schemaOperation.Properties().Responses[status] schemaResponses, ok = schemaOperation.Properties().Responses[status]
if ok { if ok {