acl: sso auth methods RPC/API/CLI should return created or updated objects (#15410)
Currently CRUD code that operates on SSO auth methods does not return created or updated object upon creation/update. This is bad UX and inconsistent behavior compared to other ACL objects like roles, policies or tokens. This PR fixes it. Relates to #13120
This commit is contained in:
parent
a65fbeb3b3
commit
0eccd3286c
22
api/acl.go
22
api/acl.go
|
@ -319,27 +319,29 @@ func (a *ACLAuthMethods) List(q *QueryOptions) ([]*ACLAuthMethodListStub, *Query
|
|||
}
|
||||
|
||||
// Create is used to create an ACL auth-method.
|
||||
func (a *ACLAuthMethods) Create(authMethod *ACLAuthMethod, w *WriteOptions) (*WriteMeta, error) {
|
||||
func (a *ACLAuthMethods) Create(authMethod *ACLAuthMethod, w *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
|
||||
if authMethod.Name == "" {
|
||||
return nil, errMissingACLAuthMethodName
|
||||
return nil, nil, errMissingACLAuthMethodName
|
||||
}
|
||||
wm, err := a.client.write("/v1/acl/auth-method", authMethod, nil, w)
|
||||
var resp ACLAuthMethod
|
||||
wm, err := a.client.write("/v1/acl/auth-method", authMethod, &resp, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return wm, nil
|
||||
return &resp, wm, nil
|
||||
}
|
||||
|
||||
// Update is used to update an existing ACL auth-method.
|
||||
func (a *ACLAuthMethods) Update(authMethod *ACLAuthMethod, w *WriteOptions) (*WriteMeta, error) {
|
||||
func (a *ACLAuthMethods) Update(authMethod *ACLAuthMethod, w *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
|
||||
if authMethod.Name == "" {
|
||||
return nil, errMissingACLAuthMethodName
|
||||
return nil, nil, errMissingACLAuthMethodName
|
||||
}
|
||||
wm, err := a.client.write("/v1/acl/auth-method/"+authMethod.Name, authMethod, nil, w)
|
||||
var resp ACLAuthMethod
|
||||
wm, err := a.client.write("/v1/acl/auth-method/"+authMethod.Name, authMethod, &resp, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return wm, nil
|
||||
return &resp, wm, nil
|
||||
}
|
||||
|
||||
// Delete is used to delete an ACL auth-method.
|
||||
|
|
|
@ -209,7 +209,7 @@ func TestACLTokens_CreateUpdate(t *testing.T) {
|
|||
out2.Roles = []*ACLTokenRoleLink{{Name: aclRoleCreateResp.Name}}
|
||||
out2.ExpirationTTL = 0
|
||||
|
||||
out3, writeMeta, err = at.Update(out2, nil)
|
||||
out3, _, err = at.Update(out2, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, out3)
|
||||
require.Len(t, out3.Policies, 1)
|
||||
|
@ -608,7 +608,7 @@ func TestACLAuthMethods(t *testing.T) {
|
|||
MaxTokenTTL: 15 * time.Minute,
|
||||
Default: true,
|
||||
}
|
||||
writeMeta, err := testClient.ACLAuthMethods().Create(&authMethod, nil)
|
||||
_, writeMeta, err := testClient.ACLAuthMethods().Create(&authMethod, nil)
|
||||
must.NoError(t, err)
|
||||
assertWriteMeta(t, writeMeta)
|
||||
|
||||
|
@ -632,7 +632,7 @@ func TestACLAuthMethods(t *testing.T) {
|
|||
|
||||
// Update the auth-method token locality.
|
||||
authMethod.TokenLocality = ACLAuthMethodTokenLocalityGlobal
|
||||
writeMeta, err = testClient.ACLAuthMethods().Update(&authMethod, nil)
|
||||
_, writeMeta, err = testClient.ACLAuthMethods().Update(&authMethod, nil)
|
||||
must.NoError(t, err)
|
||||
assertWriteMeta(t, writeMeta)
|
||||
|
||||
|
|
|
@ -168,12 +168,12 @@ func (a *ACLAuthMethodCreateCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create the auth method via the API.
|
||||
_, err = client.ACLAuthMethods().Create(&authMethod, nil)
|
||||
method, _, err := client.ACLAuthMethods().Create(&authMethod, nil)
|
||||
if err != nil {
|
||||
a.Ui.Error(fmt.Sprintf("Error creating ACL auth method: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
a.Ui.Output(fmt.Sprintf("Created ACL auth method %s", a.name))
|
||||
a.Ui.Output(fmt.Sprintf("Created ACL auth method:\n%s", formatAuthMethod(method)))
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -185,13 +185,13 @@ func (a *ACLAuthMethodUpdateCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Update the auth method via the API.
|
||||
_, err = client.ACLAuthMethods().Update(&updatedMethod, nil)
|
||||
method, _, err := client.ACLAuthMethods().Update(&updatedMethod, nil)
|
||||
if err != nil {
|
||||
a.Ui.Error(fmt.Sprintf("Error updating ACL auth method: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
a.Ui.Output(fmt.Sprintf("Updated ACL auth method %s", originalMethodName))
|
||||
a.Ui.Output(fmt.Sprintf("Updated ACL auth method:\n%s", formatAuthMethod(method)))
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -670,5 +670,9 @@ func (s *HTTPServer) aclAuthMethodUpsertRequest(
|
|||
return nil, err
|
||||
}
|
||||
setIndex(resp, out.Index)
|
||||
|
||||
if len(out.AuthMethods) > 0 {
|
||||
return out.AuthMethods[0], nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -1104,14 +1104,14 @@ func TestHTTPServer_ACLAuthMethodRequest(t *testing.T) {
|
|||
|
||||
// Build the HTTP request.
|
||||
req, err := http.NewRequest(http.MethodPut, "/v1/acl/auth-method", encodeReq(mockACLRole))
|
||||
require.NoError(t, err)
|
||||
must.NoError(t, err)
|
||||
respW := httptest.NewRecorder()
|
||||
|
||||
// Send the HTTP request.
|
||||
obj, err := srv.Server.ACLAuthMethodRequest(respW, req)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "Permission denied")
|
||||
require.Nil(t, obj)
|
||||
must.Error(t, err)
|
||||
must.StrContains(t, err.Error(), "Permission denied")
|
||||
must.Nil(t, obj)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1120,7 +1120,7 @@ func TestHTTPServer_ACLAuthMethodRequest(t *testing.T) {
|
|||
|
||||
// Build the HTTP request.
|
||||
req, err := http.NewRequest(http.MethodConnect, "/v1/acl/auth-method", nil)
|
||||
require.NoError(t, err)
|
||||
must.NoError(t, err)
|
||||
respW := httptest.NewRecorder()
|
||||
|
||||
// Ensure we have a token set.
|
||||
|
@ -1128,9 +1128,9 @@ func TestHTTPServer_ACLAuthMethodRequest(t *testing.T) {
|
|||
|
||||
// Send the HTTP request.
|
||||
obj, err := srv.Server.ACLAuthMethodRequest(respW, req)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "Invalid method")
|
||||
require.Nil(t, obj)
|
||||
must.Error(t, err)
|
||||
must.StrContains(t, err.Error(), "Invalid method")
|
||||
must.Nil(t, obj)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1142,7 +1142,7 @@ func TestHTTPServer_ACLAuthMethodRequest(t *testing.T) {
|
|||
|
||||
// Build the HTTP request.
|
||||
req, err := http.NewRequest(http.MethodPut, "/v1/acl/auth-method", encodeReq(mockACLAuthMethod))
|
||||
require.NoError(t, err)
|
||||
must.NoError(t, err)
|
||||
respW := httptest.NewRecorder()
|
||||
|
||||
// Ensure we have a token set.
|
||||
|
@ -1150,8 +1150,10 @@ func TestHTTPServer_ACLAuthMethodRequest(t *testing.T) {
|
|||
|
||||
// Send the HTTP request.
|
||||
obj, err := srv.Server.ACLAuthMethodRequest(respW, req)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, obj)
|
||||
must.NoError(t, err)
|
||||
|
||||
result := obj.(*structs.ACLAuthMethod)
|
||||
must.Eq(t, result, mockACLAuthMethod)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1724,6 +1724,22 @@ func (a *ACL) UpsertAuthMethods(
|
|||
return err
|
||||
}
|
||||
|
||||
// Populate the response. We do a lookup against the state to pick up the
|
||||
// proper create / modify times.
|
||||
stateSnapshot, err := a.srv.State().Snapshot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, method := range args.AuthMethods {
|
||||
lookupAuthMethod, err := stateSnapshot.GetACLAuthMethodByName(nil, method.Name)
|
||||
if err != nil {
|
||||
return structs.NewErrRPCCodedf(400, "ACL auth method lookup failed: %v", err)
|
||||
}
|
||||
if lookupAuthMethod != nil {
|
||||
reply.AuthMethods = append(reply.AuthMethods, lookupAuthMethod)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the index
|
||||
reply.Index = index
|
||||
return nil
|
||||
|
|
|
@ -3041,4 +3041,5 @@ func TestACLEndpoint_UpsertACLAuthMethods(t *testing.T) {
|
|||
out, err := s1.fsm.State().GetACLAuthMethodByName(nil, am1.Name)
|
||||
must.Nil(t, err)
|
||||
must.NotNil(t, out)
|
||||
must.True(t, am1.Equal(resp.AuthMethods[0]))
|
||||
}
|
||||
|
|
|
@ -825,6 +825,7 @@ type ACLAuthMethodUpsertRequest struct {
|
|||
// ACLAuthMethodUpsertResponse is a response of the upsert ACL auth methods
|
||||
// operation
|
||||
type ACLAuthMethodUpsertResponse struct {
|
||||
AuthMethods []*ACLAuthMethod
|
||||
WriteMeta
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue