github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/e2e/acl/acl_role_test.go (about)

     1  package acl
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/nomad/api"
     8  	"github.com/hashicorp/nomad/e2e/e2eutil"
     9  	"github.com/hashicorp/nomad/helper/uuid"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  // testACLRole tests basic functionality of ACL roles when used for
    14  // authorization. It also performs some basic token and policy tests due to the
    15  // coupling between the ACL objects.
    16  func testACLRole(t *testing.T) {
    17  
    18  	nomadClient := e2eutil.NomadClient(t)
    19  
    20  	// Create and defer the cleanup process. This is used to remove all
    21  	// resources created by this test and covers situations where the test
    22  	// fails or during normal running.
    23  	cleanUpProcess := newCleanup()
    24  	defer cleanUpProcess.run(t, nomadClient)
    25  
    26  	// An ACL role must reference an ACL policy that is stored in state. Ensure
    27  	// this behaviour by attempting to create a role that links to a policy
    28  	// that does not exist.
    29  	invalidRole := api.ACLRole{
    30  		Name:        "e2e-acl-" + uuid.Short(),
    31  		Description: "E2E ACL Role Testing",
    32  		Policies:    []*api.ACLRolePolicyLink{{Name: "404-not-found"}},
    33  	}
    34  	aclRoleCreateResp, _, err := nomadClient.ACLRoles().Create(&invalidRole, nil)
    35  	require.ErrorContains(t, err, "cannot find policy 404-not-found")
    36  	require.Nil(t, aclRoleCreateResp)
    37  
    38  	// Create a custom namespace to test along with the default.
    39  	ns := api.Namespace{
    40  		Name:        "e2e-acl-" + uuid.Short(),
    41  		Description: "E2E ACL Role Testing",
    42  	}
    43  	_, err = nomadClient.Namespaces().Register(&ns, nil)
    44  	require.NoError(t, err)
    45  
    46  	cleanUpProcess.add(ns.Name, namespaceTestResourceType)
    47  
    48  	// Create an ACL policy which will be used to link from the role. This
    49  	// policy grants read access to our custom namespace.
    50  	customNamespacePolicy := api.ACLPolicy{
    51  		Name:        "e2e-acl-" + uuid.Short(),
    52  		Description: "E2E ACL Role Testing",
    53  		Rules:       fmt.Sprintf(`namespace %q {policy = "read"}`, ns.Name),
    54  	}
    55  	_, err = nomadClient.ACLPolicies().Upsert(&customNamespacePolicy, nil)
    56  	require.NoError(t, err)
    57  
    58  	cleanUpProcess.add(customNamespacePolicy.Name, aclPolicyTestResourceType)
    59  
    60  	// Create a valid role with a link to the previously created policy.
    61  	validRole := api.ACLRole{
    62  		Name:        "e2e-acl-" + uuid.Short(),
    63  		Description: "E2E ACL Role Testing",
    64  		Policies:    []*api.ACLRolePolicyLink{{Name: customNamespacePolicy.Name}},
    65  	}
    66  	aclRoleCreateResp, _, err = nomadClient.ACLRoles().Create(&validRole, nil)
    67  	require.NoError(t, err)
    68  	require.NotNil(t, aclRoleCreateResp)
    69  	require.NotEmpty(t, aclRoleCreateResp.ID)
    70  	require.Equal(t, validRole.Name, aclRoleCreateResp.Name)
    71  
    72  	cleanUpProcess.add(aclRoleCreateResp.ID, aclRoleTestResourceType)
    73  
    74  	// Perform a role listing and check we have the expected entries.
    75  	aclRoleListResp, _, err := nomadClient.ACLRoles().List(nil)
    76  	require.NoError(t, err)
    77  	require.Len(t, aclRoleListResp, 1)
    78  	require.Equal(t, aclRoleCreateResp.ID, aclRoleListResp[0].ID)
    79  
    80  	// Create our ACL token which is linked to the created ACL role.
    81  	token := api.ACLToken{
    82  		Name:  "e2e-acl-" + uuid.Short(),
    83  		Type:  "client",
    84  		Roles: []*api.ACLTokenRoleLink{{ID: aclRoleCreateResp.ID}},
    85  	}
    86  	aclTokenCreateResp, _, err := nomadClient.ACLTokens().Create(&token, nil)
    87  	require.NoError(t, err)
    88  	require.NotNil(t, aclTokenCreateResp)
    89  
    90  	cleanUpProcess.add(aclTokenCreateResp.AccessorID, aclTokenTestResourceType)
    91  
    92  	// Attempt two job listings against the two available namespaces. The token
    93  	// only has access to the custom namespace, so the default should return an
    94  	// error.
    95  	customNSQueryMeta := api.QueryOptions{Namespace: ns.Name, AuthToken: aclTokenCreateResp.SecretID}
    96  	defaultNSQueryMeta := api.QueryOptions{Namespace: "default", AuthToken: aclTokenCreateResp.SecretID}
    97  
    98  	jobListResp, _, err := nomadClient.Jobs().List(&customNSQueryMeta)
    99  	require.NoError(t, err)
   100  	require.Empty(t, jobListResp)
   101  
   102  	jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
   103  	require.ErrorContains(t, err, "Permission denied")
   104  
   105  	// Create an ACL policy which grants read access to the default namespace.
   106  	defaultNamespacePolicy := api.ACLPolicy{
   107  		Name:        "e2e-acl-" + uuid.Short(),
   108  		Description: "E2E ACL Role Testing",
   109  		Rules:       `namespace "default" {policy = "read"}`,
   110  	}
   111  	_, err = nomadClient.ACLPolicies().Upsert(&defaultNamespacePolicy, nil)
   112  	require.NoError(t, err)
   113  
   114  	cleanUpProcess.add(defaultNamespacePolicy.Name, aclPolicyTestResourceType)
   115  
   116  	// Update the ACL role to include the new ACL policy that allows read
   117  	// access to the default namespace.
   118  	aclRoleCreateResp.Policies = append(aclRoleCreateResp.Policies, &api.ACLRolePolicyLink{
   119  		Name: defaultNamespacePolicy.Name,
   120  	})
   121  	aclRoleUpdateResp, _, err := nomadClient.ACLRoles().Update(aclRoleCreateResp, nil)
   122  	require.NoError(t, err)
   123  	require.Equal(t, aclRoleCreateResp.ID, aclRoleUpdateResp.ID)
   124  	require.Len(t, aclRoleUpdateResp.Policies, 2)
   125  
   126  	// Try listing the jobs in the default namespace again to ensure we now
   127  	// have permission due to the updated role.
   128  	jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
   129  	require.NoError(t, err)
   130  	require.Empty(t, jobListResp)
   131  
   132  	// Delete a policy from under the role.
   133  	_, err = nomadClient.ACLPolicies().Delete(defaultNamespacePolicy.Name, nil)
   134  	require.NoError(t, err)
   135  
   136  	cleanUpProcess.remove(defaultNamespacePolicy.Name, aclPolicyTestResourceType)
   137  
   138  	// The permission to list the job in the default namespace should now be
   139  	// revoked.
   140  	jobListResp, _, err = nomadClient.Jobs().List(&defaultNSQueryMeta)
   141  	require.ErrorContains(t, err, "Permission denied")
   142  
   143  	// Delete the ACL role.
   144  	_, err = nomadClient.ACLRoles().Delete(aclRoleUpdateResp.ID, nil)
   145  	require.NoError(t, err)
   146  
   147  	cleanUpProcess.remove(aclRoleUpdateResp.ID, aclRoleTestResourceType)
   148  
   149  	// We should now not be able to list jobs in the custom namespace either as
   150  	// the token does not have any permissions.
   151  	jobListResp, _, err = nomadClient.Jobs().List(&customNSQueryMeta)
   152  	require.ErrorContains(t, err, "Permission denied")
   153  }