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
5 changes: 5 additions & 0 deletions .changes/next-release/bugfix-iam-84710.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "bugfix",
"category": "``iam``",
"description": "Tighten file permissions for virtual MFA bootstrap output"
}
6 changes: 5 additions & 1 deletion awscli/customizations/iamvirtmfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
"""

import base64
import os

from awscli.compat import compat_open
from awscli.customizations.arguments import (
StatefulArgument,
is_parsed_result_successful,
Expand Down Expand Up @@ -81,7 +83,9 @@ def _save_file(self, parsed, **kwargs):
outfile = self._outfile.value
if method in parsed['VirtualMFADevice']:
body = parsed['VirtualMFADevice'][method]
with open(outfile, 'wb') as fp:
with compat_open(outfile, 'wb', access_permissions=0o600) as fp:
if hasattr(os, 'fchmod'):
os.fchmod(fp.fileno(), 0o600)
fp.write(base64.b64decode(body))
for choice in CHOICES:
if choice in parsed['VirtualMFADevice']:
Expand Down
31 changes: 30 additions & 1 deletion tests/functional/iam/test_create_virtual_mfa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# language governing permissions and limitations under the License.
import os

from awscli.testutils import BaseAWSCommandParamsTest
from awscli.testutils import BaseAWSCommandParamsTest, skip_if_windows


class TestCreateVirtualMFADevice(BaseAWSCommandParamsTest):
Expand Down Expand Up @@ -161,3 +161,32 @@ def test_bad_response(self):
stderr_contains=self.parsed_response['Error']['Message'],
expected_rc=254,
)

@skip_if_windows("Permissions test not valid on Windows.")
def test_output_file_permissions(self):
outfile = self.getpath('fiebaz_perms.b32')
self.addCleanup(self.remove_file_if_exists, outfile)
cmdline = self.prefix
cmdline += ' --virtual-mfa-device-name fiebaz'
cmdline += (
' --outfile %s --bootstrap-method Base32StringSeed' % outfile
)
result = {"VirtualMFADeviceName": 'fiebaz'}
self.assert_params_for_cmd(cmdline, result)
self.assertEqual(os.stat(outfile).st_mode & 0xFFF, 0o600)

@skip_if_windows("Permissions test not valid on Windows.")
def test_output_file_permissions_existing_file(self):
outfile = self.getpath('fiebaz_perms_existing.b32')
self.addCleanup(self.remove_file_if_exists, outfile)
with open(outfile, 'wb') as f:
f.write(b'existing')
os.chmod(outfile, 0o644)
cmdline = self.prefix
cmdline += ' --virtual-mfa-device-name fiebaz'
cmdline += (
' --outfile %s --bootstrap-method Base32StringSeed' % outfile
)
result = {"VirtualMFADeviceName": 'fiebaz'}
self.assert_params_for_cmd(cmdline, result)
self.assertEqual(os.stat(outfile).st_mode & 0xFFF, 0o600)
Loading