Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/design/IamUserInlinePolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,10 @@ Check the ability of the user to perform S3 operations according to the IAM poli

### Notes:
The IAM policy (like bucket policy) is read from the account info, which is saved in the endpoint cache. Currently, the cache does not invalidate those changes immediately. For local testing, you may temporarily reduce the cache expiry in `src/sdk/object_sdk.js` by setting `expiry_ms: 1`, but this should never be committed to the repository.

We enforce the policy document to have an array in the field of `Statement` even though there are cases of a single item in the array (same behavior as bucket policy document in NooBaa).
Although this IAM policy is legal in AWS:
`{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"*","Resource":"*"}}`.
In NooBaa system it should be used with:
`{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}`.
(notice the array in `Statement` field).
104 changes: 103 additions & 1 deletion src/test/integration_tests/api/iam/test_iam_basic_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const { TMP_PATH, generate_nsfs_account, get_new_buckets_path_by_test_env, gener
const { ListUsersCommand, CreateUserCommand, GetUserCommand, UpdateUserCommand, DeleteUserCommand,
ListAccessKeysCommand, CreateAccessKeyCommand, GetAccessKeyLastUsedCommand,
UpdateAccessKeyCommand, DeleteAccessKeyCommand,
ListUserPoliciesCommand, PutUserPolicyCommand, DeleteUserPolicyCommand, GetUserPolicyCommand,
ListGroupsForUserCommand, ListAccountAliasesCommand, ListAttachedGroupPoliciesCommand,
ListAttachedRolePoliciesCommand, ListAttachedUserPoliciesCommand, ListEntitiesForPolicyCommand,
ListGroupPoliciesCommand, ListGroupsCommand, ListInstanceProfilesCommand,
Expand All @@ -22,7 +23,7 @@ const { ListUsersCommand, CreateUserCommand, GetUserCommand, UpdateUserCommand,
ListPoliciesCommand, ListPolicyTagsCommand, ListPolicyVersionsCommand, ListRolesCommand,
ListRoleTagsCommand, ListSAMLProvidersCommand, ListServerCertificatesCommand,
ListServerCertificateTagsCommand, ListServiceSpecificCredentialsCommand,
ListSigningCertificatesCommand, ListSSHPublicKeysCommand, ListUserPoliciesCommand,
ListSigningCertificatesCommand, ListSSHPublicKeysCommand,
ListUserTagsCommand, ListVirtualMFADevicesCommand } = require('@aws-sdk/client-iam');
const { ACCESS_KEY_STATUS_ENUM } = require('../../../../endpoint/iam/iam_constants');
const IamError = require('../../../../endpoint/iam/iam_errors').IamError;
Expand Down Expand Up @@ -257,6 +258,107 @@ mocha.describe('IAM basic integration tests - happy path', async function() {
});
});

mocha.describe('IAM User Policy API', async function() {
if (is_nc_coretest) this.skip(); // eslint-disable-line no-invalid-this
const username3 = 'Kai';
const policy_name = 'AllAccessPolicy';
const iam_user_inline_policy_document = '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}';

mocha.before(async () => {
// create a user
const input = {
UserName: username3
};
const command = new CreateUserCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);
});

mocha.after(async () => {
// delete a user
const input = {
UserName: username3
};
const command = new DeleteUserCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);
// note: if somehow the delete user policy would fail, then deleting the user would also fail
// (as we can delete a user only after its user policies were deleted)
});

mocha.it('list user policies for non existing user - should throw an error', async function() {
try {
const input = {
UserName: 'non-existing-user'
};
const command = new ListUserPoliciesCommand(input);
await iam_account.send(command);
assert.fail('list user policies for non existing user - should throw an error');
} catch (err) {
const err_code = err.Error.Code;
assert.equal(err_code, IamError.NoSuchEntity.code);
}
});

mocha.it('list user policies for user - should be empty', async function() {
const input = {
UserName: username3
};
const command = new ListUserPoliciesCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);
assert.equal(response.PolicyNames.length, 0);
});

mocha.it('put user policy', async function() {
const input = {
UserName: username3,
PolicyName: policy_name,
PolicyDocument: iam_user_inline_policy_document
};
const command = new PutUserPolicyCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);

// verify it using list user policies
const input2 = {
UserName: username3
};
const command2 = new ListUserPoliciesCommand(input2);
const response2 = await iam_account.send(command2);
_check_status_code_ok(response2);
assert.equal(response2.PolicyNames.length, 1);
assert.equal(response2.PolicyNames[0], policy_name);
});

mocha.it('get user policy', async function() {
const input = {
UserName: username3,
PolicyName: policy_name
};
const command = new GetUserPolicyCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);
assert.equal(response.UserName, username3);
assert.equal(response.PolicyName, policy_name);
assert(response.PolicyDocument !== undefined);
const response_policy_document_json = JSON.parse(response.PolicyDocument);
assert.equal(response_policy_document_json.Version, '2012-10-17');
assert(Array.isArray(response_policy_document_json.Statement));
assert.deepEqual(response_policy_document_json.Statement[0], {"Effect": "Allow", "Action": "*", "Resource": "*"});
});

mocha.it('delete user policy', async function() {
const input = {
UserName: username3,
PolicyName: policy_name
};
const command = new DeleteUserPolicyCommand(input);
const response = await iam_account.send(command);
_check_status_code_ok(response);
});
});

mocha.describe('IAM other APIs (currently returns empty value)', async function() {
const username3 = 'Emi';
const group_name = 'my_group';
Expand Down