github.com/hernad/nomad@v1.6.112/e2e/acl/acl_role_test.go (about)

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