5f3665230b
This adds a new ACL test suite to the e2e framework which includes an initial test for ACL roles. The ACL test includes a helper to track and clean created Nomad resources which keeps the test cluster clean no matter if the test fails early or not.
154 lines
5.8 KiB
Go
154 lines
5.8 KiB
Go
package acl
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/nomad/api"
|
|
"github.com/hashicorp/nomad/e2e/e2eutil"
|
|
"github.com/hashicorp/nomad/helper/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// testACLRole tests basic functionality of ACL roles when used for
|
|
// authorization. It also performs some basic token and policy tests due to the
|
|
// coupling between the ACL objects.
|
|
func testACLRole(t *testing.T) {
|
|
|
|
nomadClient := e2eutil.NomadClient(t)
|
|
|
|
// Create and defer the cleanup process. This is used to remove all
|
|
// resources created by this test and covers situations where the test
|
|
// fails or during normal running.
|
|
cleanUpProcess := newCleanup()
|
|
defer cleanUpProcess.run(t, nomadClient)
|
|
|
|
// An ACL role must reference an ACL policy that is stored in state. Ensure
|
|
// this behaviour by attempting to create a role that links to a policy
|
|
// that does not exist.
|
|
invalidRole := api.ACLRole{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Description: "E2E ACL Role Testing",
|
|
Policies: []*api.ACLRolePolicyLink{{Name: "404-not-found"}},
|
|
}
|
|
aclRoleCreateResp, _, err := nomadClient.ACLRoles().Create(&invalidRole, nil)
|
|
require.ErrorContains(t, err, "cannot find policy 404-not-found")
|
|
require.Nil(t, aclRoleCreateResp)
|
|
|
|
// Create a custom namespace to test along with the default.
|
|
ns := api.Namespace{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Description: "E2E ACL Role Testing",
|
|
}
|
|
_, err = nomadClient.Namespaces().Register(&ns, nil)
|
|
require.NoError(t, err)
|
|
|
|
cleanUpProcess.add(ns.Name, namespaceTestResourceType)
|
|
|
|
// Create an ACL policy which will be used to link from the role. This
|
|
// policy grants read access to our custom namespace.
|
|
customNamespacePolicy := api.ACLPolicy{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Description: "E2E ACL Role Testing",
|
|
Rules: fmt.Sprintf(`namespace %q {policy = "read"}`, ns.Name),
|
|
}
|
|
_, err = nomadClient.ACLPolicies().Upsert(&customNamespacePolicy, nil)
|
|
require.NoError(t, err)
|
|
|
|
cleanUpProcess.add(customNamespacePolicy.Name, aclPolicyTestResourceType)
|
|
|
|
// Create a valid role with a link to the previously created policy.
|
|
validRole := api.ACLRole{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Description: "E2E ACL Role Testing",
|
|
Policies: []*api.ACLRolePolicyLink{{Name: customNamespacePolicy.Name}},
|
|
}
|
|
aclRoleCreateResp, _, err = nomadClient.ACLRoles().Create(&validRole, nil)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, aclRoleCreateResp)
|
|
require.NotEmpty(t, aclRoleCreateResp.ID)
|
|
require.Equal(t, validRole.Name, aclRoleCreateResp.Name)
|
|
|
|
cleanUpProcess.add(aclRoleCreateResp.ID, aclRoleTestResourceType)
|
|
|
|
// Perform a role listing and check we have the expected entries.
|
|
aclRoleListResp, _, err := nomadClient.ACLRoles().List(nil)
|
|
require.NoError(t, err)
|
|
require.Len(t, aclRoleListResp, 1)
|
|
require.Equal(t, aclRoleCreateResp.ID, aclRoleListResp[0].ID)
|
|
|
|
// Create our ACL token which is linked to the created ACL role.
|
|
token := api.ACLToken{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Type: "client",
|
|
Roles: []*api.ACLTokenRoleLink{{ID: aclRoleCreateResp.ID}},
|
|
}
|
|
aclTokenCreateResp, _, err := nomadClient.ACLTokens().Create(&token, nil)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, aclTokenCreateResp)
|
|
|
|
cleanUpProcess.add(aclTokenCreateResp.AccessorID, aclTokenTestResourceType)
|
|
|
|
// Attempt two job listings against the two available namespaces. The token
|
|
// only has access to the custom namespace, so the default should return an
|
|
// error.
|
|
customNSQueryMeta := api.QueryOptions{Namespace: ns.Name, AuthToken: aclTokenCreateResp.SecretID}
|
|
defaultNSQueryMeta := api.QueryOptions{Namespace: "default", AuthToken: aclTokenCreateResp.SecretID}
|
|
|
|
jobListResp, _, err := nomadClient.Jobs().List(&customNSQueryMeta)
|
|
require.NoError(t, err)
|
|
require.Empty(t, jobListResp)
|
|
|
|
jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
|
|
require.ErrorContains(t, err, "Permission denied")
|
|
|
|
// Create an ACL policy which grants read access to the default namespace.
|
|
defaultNamespacePolicy := api.ACLPolicy{
|
|
Name: "e2e-acl-" + uuid.Short(),
|
|
Description: "E2E ACL Role Testing",
|
|
Rules: `namespace "default" {policy = "read"}`,
|
|
}
|
|
_, err = nomadClient.ACLPolicies().Upsert(&defaultNamespacePolicy, nil)
|
|
require.NoError(t, err)
|
|
|
|
cleanUpProcess.add(defaultNamespacePolicy.Name, aclPolicyTestResourceType)
|
|
|
|
// Update the ACL role to include the new ACL policy that allows read
|
|
// access to the default namespace.
|
|
aclRoleCreateResp.Policies = append(aclRoleCreateResp.Policies, &api.ACLRolePolicyLink{
|
|
Name: defaultNamespacePolicy.Name,
|
|
})
|
|
aclRoleUpdateResp, _, err := nomadClient.ACLRoles().Update(aclRoleCreateResp, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, aclRoleCreateResp.ID, aclRoleUpdateResp.ID)
|
|
require.Len(t, aclRoleUpdateResp.Policies, 2)
|
|
|
|
// Try listing the jobs in the default namespace again to ensure we now
|
|
// have permission due to the updated role.
|
|
jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
|
|
require.NoError(t, err)
|
|
require.Empty(t, jobListResp)
|
|
|
|
// Delete a policy from under the role.
|
|
_, err = nomadClient.ACLPolicies().Delete(defaultNamespacePolicy.Name, nil)
|
|
require.NoError(t, err)
|
|
|
|
cleanUpProcess.remove(defaultNamespacePolicy.Name, aclPolicyTestResourceType)
|
|
|
|
// The permission to list the job in the default namespace should now be
|
|
// revoked.
|
|
jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
|
|
require.ErrorContains(t, err, "Permission denied")
|
|
|
|
// Delete the ACL role.
|
|
_, err = nomadClient.ACLRoles().Delete(aclRoleUpdateResp.ID, nil)
|
|
require.NoError(t, err)
|
|
|
|
cleanUpProcess.remove(aclRoleUpdateResp.ID, aclRoleTestResourceType)
|
|
|
|
// We should now not be able to list jobs in the custom namespace either as
|
|
// the token does not have any permissions.
|
|
jobListResp, _, err = nomadClient.Jobs().List(&customNSQueryMeta)
|
|
require.ErrorContains(t, err, "Permission denied")
|
|
}
|