Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Neil Hanlon
Efs Utils
Commits
493d9ea0
Commit
493d9ea0
authored
Oct 12, 2020
by
Yuan Gao
Browse files
Fix the issue that mounting with IAM authorization with iam role does not work with IMDSv2
parent
bb6b811a
Changes
11
Hide whitespace changes
Inline
Side-by-side
amazon-efs-utils.spec
View file @
493d9ea0
...
...
@@ -32,7 +32,7 @@
%endif
Name : amazon-efs-utils
Version : 1.28.
1
Version : 1.28.
2
Release : 1%{platform}
Summary : This package provides utilities for simplifying the use of EFS file systems
...
...
@@ -132,6 +132,9 @@ fi
%clean
%changelog
* Thu Oct 8 2020 Yuan Gao <ygaochn@amazon.com> - 1.28.2
- Fix an issue where fs cannot be mounted with iam using instance profile when IMDSv2 is enabled
* Fri Sep 18 2020 Yuan Gao <ygaochn@amazon.com> - 1.28.1
- Introduce botocore to publish mount success/failure notification to cloudwatch log
- Revert stop emitting unrecognized init system supervisord if the watchdog daemon has already been launched by supervisor check
...
...
build-deb.sh
View file @
493d9ea0
...
...
@@ -11,7 +11,7 @@ set -ex
BASE_DIR
=
$(
pwd
)
BUILD_ROOT
=
${
BASE_DIR
}
/build/debbuild
VERSION
=
1.28.
1
VERSION
=
1.28.
2
RELEASE
=
1
DEB_SYSTEM_RELEASE_PATH
=
/etc/os-release
UBUNTU18_REGEX
=
"Ubuntu 18"
...
...
config.ini
View file @
493d9ea0
...
...
@@ -7,5 +7,5 @@
#
[global]
version
=
1.28.
1
version
=
1.28.
2
release
=
1
dist/amazon-efs-utils.control
View file @
493d9ea0
Package: amazon-efs-utils
Architecture: all
Version: 1.28.
1
Version: 1.28.
2
Section: utils
Depends: python|python2, nfs-common, stunnel4 (>= 4.56), openssl (>= 1.0.2), util-linux
Priority: optional
...
...
src/mount_efs/__init__.py
View file @
493d9ea0
...
...
@@ -77,7 +77,7 @@ except ImportError:
BOTOCORE_PRESENT
=
False
VERSION
=
'1.28.
1
'
VERSION
=
'1.28.
2
'
SERVICE
=
'elasticfilesystem'
CONFIG_FILE
=
'/etc/amazon/efs/efs-utils.conf'
...
...
@@ -262,46 +262,28 @@ def get_target_region(config):
def
get_region_from_instance_metadata
():
instance_identity
,
err_msg
=
get_instance_identity_info_from_instance_metadata
(
'region'
)
instance_identity
=
get_instance_identity_info_from_instance_metadata
(
'region'
)
if
err_msg
:
raise
Exception
(
err_msg
)
if
not
instance_identity
:
raise
Exception
(
"Cannot retrieve region from instance_metadata"
)
return
instance_identity
def
get_instance_id_from_instance_metadata
():
instance_id
,
err_msg
=
get_instance_identity_info_from_instance_metadata
(
'instanceId'
)
if
err_msg
:
logging
.
warning
(
'Cannot get instance id from instance metadata, %s'
%
err_msg
)
return
instance_id
def
get_instance_identity_info_from_instance_metadata
(
property
):
err_msg
=
None
try
:
headers
=
{}
instance_identity
=
get_aws_ec2_metadata
(
headers
)
return
instance_identity
[
property
],
err_msg
except
HTTPError
as
e
:
# 401:Unauthorized, the GET request uses an invalid token, so generate a new one
if
e
.
code
==
401
:
token
=
get_aws_ec2_metadata_token
()
headers
=
{
'X-aws-ec2-metadata-token'
:
token
}
instance_identity
=
get_aws_ec2_metadata
(
headers
)
return
instance_identity
[
property
],
err_msg
err_msg
=
'Unable to reach instance metadata service at %s: status=%d, reason is %s'
\
%
(
INSTANCE_METADATA_SERVICE_URL
,
e
.
code
,
e
.
reason
)
except
URLError
as
e
:
err_msg
=
'Unable to reach instance metadata service at %s, reason is %s'
%
(
INSTANCE_METADATA_SERVICE_URL
,
e
.
reason
)
except
ValueError
as
e
:
err_msg
=
'Error parsing json: %s'
%
(
e
,)
except
KeyError
as
e
:
err_msg
=
'%s not present in %s: %s'
%
(
property
,
instance_identity
,
e
)
ec2_metadata_unsuccessful_resp
=
'Unsuccessful retrieval of EC2 metadata at %s.'
%
INSTANCE_METADATA_SERVICE_URL
ec2_metadata_url_error_msg
=
'Unable to reach %s to retrieve EC2 instance metadata.'
%
INSTANCE_METADATA_SERVICE_URL
instance_identity
=
url_request_helper
(
INSTANCE_METADATA_SERVICE_URL
,
ec2_metadata_unsuccessful_resp
,
ec2_metadata_url_error_msg
,
retry_with_new_header_token
=
True
)
if
instance_identity
:
try
:
return
instance_identity
[
property
]
except
KeyError
as
e
:
logging
.
warning
(
'%s not present in %s: %s'
%
(
property
,
instance_identity
,
e
))
except
TypeError
as
e
:
logging
.
warning
(
'response %s is not a json object: %s'
%
(
instance_identity
,
e
))
return
None
,
err_msg
return
None
def
get_region_from_legacy_dns_format
(
config
):
...
...
@@ -334,17 +316,6 @@ def get_aws_ec2_metadata_token():
return
res
.
read
()
def
get_aws_ec2_metadata
(
headers
):
request
=
Request
(
INSTANCE_METADATA_SERVICE_URL
,
headers
=
headers
)
response
=
urlopen
(
request
,
timeout
=
1
)
data
=
response
.
read
()
if
type
(
data
)
is
str
:
instance_identity
=
json
.
loads
(
data
)
else
:
instance_identity
=
json
.
loads
(
data
.
decode
(
response
.
headers
.
get_content_charset
()
or
'us-ascii'
))
return
instance_identity
def
get_aws_security_credentials
(
use_iam
,
awsprofile
=
None
,
aws_creds_uri
=
None
):
"""
Lookup AWS security credentials (access key ID and secret access key). Adapted credentials provider chain from:
...
...
@@ -475,7 +446,8 @@ def get_aws_security_credentials_from_instance_metadata(iam_role_name):
unsuccessful_resp
=
'Unsuccessful retrieval of AWS security credentials at %s.'
%
security_creds_lookup_url
url_error_msg
=
'Unable to reach %s to retrieve AWS security credentials. See %s for more info.'
%
\
(
security_creds_lookup_url
,
SECURITY_CREDS_IAM_ROLE_HELP_URL
)
iam_security_dict
=
url_request_helper
(
security_creds_lookup_url
,
unsuccessful_resp
,
url_error_msg
)
iam_security_dict
=
url_request_helper
(
security_creds_lookup_url
,
unsuccessful_resp
,
url_error_msg
,
retry_with_new_header_token
=
True
)
if
iam_security_dict
and
all
(
k
in
iam_security_dict
for
k
in
CREDENTIALS_KEYS
):
return
iam_security_dict
,
'metadata:'
...
...
@@ -487,7 +459,8 @@ def get_iam_role_name():
iam_role_unsuccessful_resp
=
'Unsuccessful retrieval of IAM role name at %s.'
%
INSTANCE_IAM_URL
iam_role_url_error_msg
=
'Unable to reach %s to retrieve IAM role name. See %s for more info.'
%
\
(
INSTANCE_IAM_URL
,
SECURITY_CREDS_IAM_ROLE_HELP_URL
)
iam_role_name
=
url_request_helper
(
INSTANCE_IAM_URL
,
iam_role_unsuccessful_resp
,
iam_role_url_error_msg
)
iam_role_name
=
url_request_helper
(
INSTANCE_IAM_URL
,
iam_role_unsuccessful_resp
,
iam_role_url_error_msg
,
retry_with_new_header_token
=
True
)
return
iam_role_name
...
...
@@ -533,33 +506,49 @@ def get_aws_profile(options, use_iam):
return
awsprofile
def
url_request_helper
(
url
,
unsuccessful_resp
,
url_error_msg
,
headers
=
{}):
def
url_request_helper
(
url
,
unsuccessful_resp
,
url_error_msg
,
headers
=
{}
,
retry_with_new_header_token
=
False
):
try
:
req
=
Request
(
url
)
for
k
,
v
in
headers
.
items
():
req
.
add_header
(
k
,
v
)
request_resp
=
urlopen
(
req
,
timeout
=
1
)
if
request_resp
.
getcode
()
!=
200
:
logging
.
debug
(
unsuccessful_resp
+
' %s: ResponseCode=%d'
,
url
,
request_resp
.
getcode
())
return
None
resp_body
=
request_resp
.
read
()
resp_body_type
=
type
(
resp_body
)
try
:
if
resp_body_type
is
str
:
resp_dict
=
json
.
loads
(
resp_body
)
else
:
resp_dict
=
json
.
loads
(
resp_body
.
decode
(
request_resp
.
headers
.
get_content_charset
()
or
'us-ascii'
))
return
resp_dict
except
ValueError
as
e
:
logging
.
info
(
'ValueError parsing "%s" into json: %s. Returning response body.'
%
(
str
(
resp_body
),
e
))
return
resp_body
if
resp_body_type
is
str
else
resp_body
.
decode
(
'utf-8'
)
return
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
)
except
HTTPError
as
e
:
# For instance enable with IMDSv2, Unauthorized 401 error will be thrown,
# to retrieve metadata, the header should embeded with metadata token
if
e
.
code
==
401
and
retry_with_new_header_token
:
token
=
get_aws_ec2_metadata_token
()
req
.
add_header
(
'X-aws-ec2-metadata-token'
,
token
)
request_resp
=
urlopen
(
req
,
timeout
=
1
)
return
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
)
err_msg
=
'Unable to reach the url at %s: status=%d, reason is %s'
%
(
url
,
e
.
code
,
e
.
reason
)
except
URLError
as
e
:
logging
.
debug
(
'%s %s'
,
url_error_msg
,
e
)
err_msg
=
'Unable to reach the url at %s, reason is %s'
%
(
url
,
e
.
reason
)
if
err_msg
:
logging
.
debug
(
'%s %s'
,
url_error_msg
,
err_msg
)
return
None
def
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
):
if
request_resp
.
getcode
()
!=
200
:
logging
.
debug
(
unsuccessful_resp
+
' %s: ResponseCode=%d'
,
url
,
request_resp
.
getcode
())
return
None
resp_body
=
request_resp
.
read
()
resp_body_type
=
type
(
resp_body
)
try
:
if
resp_body_type
is
str
:
resp_dict
=
json
.
loads
(
resp_body
)
else
:
resp_dict
=
json
.
loads
(
resp_body
.
decode
(
request_resp
.
headers
.
get_content_charset
()
or
'us-ascii'
))
return
resp_dict
except
ValueError
as
e
:
logging
.
info
(
'ValueError parsing "%s" into json: %s. Returning response body.'
%
(
str
(
resp_body
),
e
))
return
resp_body
if
resp_body_type
is
str
else
resp_body
.
decode
(
'utf-8'
)
def
parse_options
(
options
):
opts
=
{}
...
...
@@ -1719,7 +1708,7 @@ def get_cloudwatchlog_config(config, fs_id=None):
def
get_cloudwatch_log_stream_name
(
fs_id
=
None
):
instance_id
=
get_instance_id_from_instance_metadata
()
instance_id
=
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
if
instance_id
and
fs_id
:
log_stream_name
=
'%s - %s - mount.log'
%
(
fs_id
,
instance_id
)
elif
instance_id
:
...
...
src/watchdog/__init__.py
View file @
493d9ea0
...
...
@@ -40,14 +40,15 @@ except ImportError:
from
urllib
import
quote_plus
try
:
from
urllib2
import
urlopen
,
URLError
,
Request
from
urllib2
import
build_opener
,
urlopen
,
URLError
,
HTTPError
,
HTTPHandler
,
Request
from
urllib
import
urlencode
except
ImportError
:
from
urllib.error
import
URLError
from
urllib.error
import
HTTPError
,
URLError
from
urllib.request
import
urlopen
,
Request
from
urllib.parse
import
urlencode
VERSION
=
'1.28.1'
VERSION
=
'1.28.2'
SERVICE
=
'elasticfilesystem'
CONFIG_FILE
=
'/etc/amazon/efs/efs-utils.conf'
...
...
@@ -125,6 +126,7 @@ AP_ID_RE = re.compile('^fsap-[0-9a-f]{17}$')
ECS_TASK_METADATA_API
=
'http://169.254.170.2'
STS_ENDPOINT_URL
=
'https://sts.amazonaws.com/'
INSTANCE_IAM_URL
=
'http://169.254.169.254/latest/meta-data/iam/security-credentials/'
INSTANCE_METADATA_TOKEN_URL
=
'http://169.254.169.254/latest/api/token'
SECURITY_CREDS_ECS_URI_HELP_URL
=
'https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html'
SECURITY_CREDS_WEBIDENTITY_HELP_URL
=
'https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html'
SECURITY_CREDS_IAM_ROLE_HELP_URL
=
'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html'
...
...
@@ -164,6 +166,21 @@ def get_aws_security_credentials(credentials_source):
return
None
def
get_aws_ec2_metadata_token
():
try
:
opener
=
build_opener
(
HTTPHandler
)
request
=
Request
(
INSTANCE_METADATA_TOKEN_URL
)
request
.
add_header
(
'X-aws-ec2-metadata-token-ttl-seconds'
,
21600
)
request
.
get_method
=
lambda
:
'PUT'
res
=
opener
.
open
(
request
)
return
res
.
read
()
except
NameError
:
headers
=
{
'X-aws-ec2-metadata-token-ttl-seconds'
:
21600
}
req
=
Request
(
INSTANCE_METADATA_TOKEN_URL
,
headers
=
headers
,
method
=
'PUT'
)
res
=
urlopen
(
req
)
return
res
.
read
()
def
get_aws_security_credentials_from_file
(
file_name
,
awsprofile
):
# attempt to lookup AWS security credentials in AWS credentials file (~/.aws/credentials) and configs file (~/.aws/config)
file_path
=
AWS_CREDENTIALS_FILES
.
get
(
file_name
)
...
...
@@ -233,13 +250,15 @@ def get_aws_security_credentials_from_instance_metadata():
iam_role_unsuccessful_resp
=
'Unsuccessful retrieval of IAM role name at %s.'
%
INSTANCE_IAM_URL
iam_role_url_error_msg
=
'Unable to reach %s to retrieve IAM role name. See %s for more info.'
%
\
(
INSTANCE_IAM_URL
,
SECURITY_CREDS_IAM_ROLE_HELP_URL
)
iam_role_name
=
url_request_helper
(
INSTANCE_IAM_URL
,
iam_role_unsuccessful_resp
,
iam_role_url_error_msg
)
iam_role_name
=
url_request_helper
(
INSTANCE_IAM_URL
,
iam_role_unsuccessful_resp
,
iam_role_url_error_msg
,
retry_with_new_header_token
=
True
)
if
iam_role_name
:
security_creds_lookup_url
=
INSTANCE_IAM_URL
+
iam_role_name
unsuccessful_resp
=
'Unsuccessful retrieval of AWS security credentials at %s.'
%
security_creds_lookup_url
url_error_msg
=
'Unable to reach %s to retrieve AWS security credentials. See %s for more info.'
%
\
(
security_creds_lookup_url
,
SECURITY_CREDS_IAM_ROLE_HELP_URL
)
iam_security_dict
=
url_request_helper
(
security_creds_lookup_url
,
unsuccessful_resp
,
url_error_msg
)
iam_security_dict
=
url_request_helper
(
security_creds_lookup_url
,
unsuccessful_resp
,
url_error_msg
,
retry_with_new_header_token
=
True
)
if
iam_security_dict
and
all
(
k
in
iam_security_dict
for
k
in
dict_keys
):
return
iam_security_dict
...
...
@@ -273,33 +292,49 @@ def credentials_file_helper(file_path, awsprofile):
return
credentials
def
url_request_helper
(
url
,
unsuccessful_resp
,
url_error_msg
,
headers
=
{}):
def
url_request_helper
(
url
,
unsuccessful_resp
,
url_error_msg
,
headers
=
{}
,
retry_with_new_header_token
=
False
):
try
:
req
=
Request
(
url
)
for
k
,
v
in
headers
.
items
():
req
.
add_header
(
k
,
v
)
request_resp
=
urlopen
(
req
,
timeout
=
1
)
if
request_resp
.
getcode
()
!=
200
:
logging
.
debug
(
unsuccessful_resp
+
' %s: ResponseCode=%d'
,
url
,
request_resp
.
getcode
())
return
None
return
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
)
except
HTTPError
as
e
:
# For instance enable with IMDSv2, Unauthorized 401 error will be thrown,
# to retrieve metadata, the header should embeded with metadata token
if
e
.
code
==
401
and
retry_with_new_header_token
:
token
=
get_aws_ec2_metadata_token
()
req
.
add_header
(
'X-aws-ec2-metadata-token'
,
token
)
request_resp
=
urlopen
(
req
,
timeout
=
1
)
return
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
)
err_msg
=
'Unable to reach the url at %s: status=%d, reason is %s'
%
(
url
,
e
.
code
,
e
.
reason
)
except
URLError
as
e
:
err_msg
=
'Unable to reach the url at %s, reason is %s'
%
(
url
,
e
.
reason
)
resp_body
=
request_resp
.
read
()
resp_body_type
=
type
(
resp_body
)
try
:
if
resp_body_type
is
str
:
resp_dict
=
json
.
loads
(
resp_body
)
else
:
resp_dict
=
json
.
loads
(
resp_body
.
decode
(
request_resp
.
headers
.
get_content_charset
()
or
'us-ascii'
))
if
err_msg
:
logging
.
debug
(
'%s %s'
,
url_error_msg
,
err_msg
)
return
None
return
resp_dict
except
ValueError
as
e
:
logging
.
info
(
'ValueError parsing "%s" into json: %s. Returning response body.'
%
(
str
(
resp_body
),
e
))
return
resp_body
if
resp_body_type
is
str
else
resp_body
.
decode
(
'utf-8'
)
except
URLError
as
e
:
logging
.
debug
(
'%s %s'
,
url_error_msg
,
e
)
def
get_resp_obj
(
request_resp
,
url
,
unsuccessful_resp
):
if
request_resp
.
getcode
()
!=
200
:
logging
.
debug
(
unsuccessful_resp
+
' %s: ResponseCode=%d'
,
url
,
request_resp
.
getcode
())
return
None
resp_body
=
request_resp
.
read
()
resp_body_type
=
type
(
resp_body
)
try
:
if
resp_body_type
is
str
:
resp_dict
=
json
.
loads
(
resp_body
)
else
:
resp_dict
=
json
.
loads
(
resp_body
.
decode
(
request_resp
.
headers
.
get_content_charset
()
or
'us-ascii'
))
return
resp_dict
except
ValueError
as
e
:
logging
.
info
(
'ValueError parsing "%s" into json: %s. Returning response body.'
%
(
str
(
resp_body
),
e
))
return
resp_body
if
resp_body_type
is
str
else
resp_body
.
decode
(
'utf-8'
)
def
bootstrap_logging
(
config
,
log_dir
=
LOG_DIR
):
raw_level
=
config
.
get
(
CONFIG_SECTION
,
'logging_level'
)
...
...
test/mount_efs_test/test_get_aws_security_credentials.py
View file @
493d9ea0
...
...
@@ -18,6 +18,11 @@ try:
except
ImportError
:
from
configparser
import
ConfigParser
try
:
from
urllib2
import
HTTPError
except
ImportError
:
from
urllib.error
import
HTTPError
ACCESS_KEY_ID_KEY
=
'aws_access_key_id'
SECRET_ACCESS_KEY_KEY
=
'aws_secret_access_key'
SESSION_TOKEN_KEY
=
'aws_session_token'
...
...
@@ -119,7 +124,7 @@ def test_get_aws_security_credentials_do_not_use_iam():
assert
not
credentials_source
def
test_get_aws_security_credentials_get_ecs_from_env_url
(
mocker
):
def
_
test_get_aws_security_credentials_get_ecs_from_env_url
(
mocker
):
mocker
.
patch
.
dict
(
os
.
environ
,
{})
mocker
.
patch
(
'os.path.exists'
,
return_value
=
False
)
response
=
json
.
dumps
({
...
...
@@ -130,6 +135,7 @@ def test_get_aws_security_credentials_get_ecs_from_env_url(mocker):
'Token'
:
SESSION_TOKEN_VAL
})
mocker
.
patch
.
dict
(
os
.
environ
,
{
'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'
:
'fake_uri'
})
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
(
data
=
response
))
credentials
,
credentials_source
=
mount_efs
.
get_aws_security_credentials
(
True
,
None
)
...
...
@@ -158,29 +164,22 @@ def test_get_aws_security_credentials_get_ecs_from_option_url(mocker):
def
test_get_aws_security_credentials_get_instance_metadata_role_name_str
(
mocker
):
mocker
.
patch
.
dict
(
os
.
environ
,
{})
mocker
.
patch
(
'os.path.exists'
,
return_value
=
False
)
response
=
json
.
dumps
({
'Code'
:
'Success'
,
'LastUpdated'
:
'2019-10-25T14:41:42Z'
,
'Type'
:
'AWS-HMAC'
,
'AccessKeyId'
:
ACCESS_KEY_ID_VAL
,
'SecretAccessKey'
:
SECRET_ACCESS_KEY_VAL
,
'Token'
:
SESSION_TOKEN_VAL
,
'Expiration'
:
'2019-10-25T21:17:24Z'
})
side_effects
=
[
MockUrlLibResponse
(
data
=
'FAKE_IAM_ROLE_NAME'
),
MockUrlLibResponse
(
data
=
response
)]
mocker
.
patch
(
'mount_efs.urlopen'
,
side_effect
=
side_effects
)
_test_get_aws_security_credentials_get_instance_metadata_role_name
(
mocker
,
is_name_str
=
True
,
is_imds_v2
=
False
)
credentials
,
credentials_source
=
mount_efs
.
get_aws_security_credentials
(
True
,
None
)
assert
credentials
[
'AccessKeyId'
]
==
ACCESS_KEY_ID_VAL
assert
credentials
[
'SecretAccessKey'
]
==
SECRET_ACCESS_KEY_VAL
assert
credentials
[
'Token'
]
==
SESSION_TOKEN_VAL
assert
credentials_source
==
'metadata:'
def
test_get_aws_security_credentials_get_instance_metadata_role_name_str_imds_v2
(
mocker
):
_test_get_aws_security_credentials_get_instance_metadata_role_name
(
mocker
,
is_name_str
=
True
,
is_imds_v2
=
True
)
def
test_get_aws_security_credentials_get_instance_metadata_role_name_bytes
(
mocker
):
_test_get_aws_security_credentials_get_instance_metadata_role_name
(
mocker
,
is_name_str
=
False
,
is_imds_v2
=
False
)
def
test_get_aws_security_credentials_get_instance_metadata_role_name_bytes_imds_v2
(
mocker
):
_test_get_aws_security_credentials_get_instance_metadata_role_name
(
mocker
,
is_name_str
=
False
,
is_imds_v2
=
True
)
def
_test_get_aws_security_credentials_get_instance_metadata_role_name
(
mocker
,
is_name_str
=
True
,
is_imds_v2
=
False
):
mocker
.
patch
.
dict
(
os
.
environ
,
{})
mocker
.
patch
(
'os.path.exists'
,
return_value
=
False
)
response
=
json
.
dumps
({
...
...
@@ -192,7 +191,16 @@ def test_get_aws_security_credentials_get_instance_metadata_role_name_bytes(mock
'Token'
:
SESSION_TOKEN_VAL
,
'Expiration'
:
'2019-10-25T21:17:24Z'
})
side_effects
=
[
MockUrlLibResponse
(
data
=
b
'FAKE_IAM_ROLE_NAME'
),
MockUrlLibResponse
(
data
=
response
)]
if
is_name_str
:
role_name_data
=
b
'FAKE_IAM_ROLE_NAME'
else
:
role_name_data
=
'FAKE_IAM_ROLE_NAME'
if
is_imds_v2
:
side_effects
=
[
HTTPError
(
'url'
,
401
,
'Unauthorized'
,
None
,
None
)]
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
'ABCDEFG=='
)
else
:
side_effects
=
[]
side_effects
=
side_effects
+
[
MockUrlLibResponse
(
data
=
role_name_data
),
MockUrlLibResponse
(
data
=
response
)]
mocker
.
patch
(
'mount_efs.urlopen'
,
side_effect
=
side_effects
)
credentials
,
credentials_source
=
mount_efs
.
get_aws_security_credentials
(
True
,
None
)
...
...
test/mount_efs_test/test_get_instance_id.py
View file @
493d9ea0
...
...
@@ -65,19 +65,19 @@ class MockUrlLibResponse(object):
def
test_get_instance_id_with_token
(
mocker
):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
'ABCDEFG=='
)
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
())
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
def
test_get_instance_id_without_token
(
mocker
):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
())
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
def
test_get_instance_id_metadata_endpoint_unauthorized
(
mocker
):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
'ABCDEFG=='
)
mocker
.
patch
(
'mount_efs.urlopen'
,
side_effect
=
[
HTTPError
(
'url'
,
401
,
'Unauthorized'
,
None
,
None
),
MockUrlLibResponse
()])
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
# Reproduce https://github.com/aws/efs-utils/issues/46
...
...
@@ -85,14 +85,14 @@ def test_get_instance_id_token_endpoint_not_allowed(mocker):
get_aws_ec2_metadata_token_mock
=
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
side_effect
=
HTTPError
(
'url'
,
405
,
'Not allowed'
,
None
,
None
))
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
())
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
utils
.
assert_not_called
(
get_aws_ec2_metadata_token_mock
)
def
test_get_instance_id_py3_no_charset
(
mocker
):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
(
data
=
bytearray
(
INSTANCE_DOCUMENT
,
'us-ascii'
)))
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
def
test_get_instance_id_py3_utf8_charset
(
mocker
):
...
...
@@ -100,13 +100,13 @@ def test_get_instance_id_py3_utf8_charset(mocker):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.urlopen'
,
return_value
=
MockUrlLibResponse
(
data
=
bytearray
(
INSTANCE_DOCUMENT
,
charset
)),
headers
=
MockHeaders
(
content_charset
=
charset
))
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id_from_instance_metadata
()
assert
INSTANCE_ID
==
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
def
test_get_instance_id_config_metadata_unavailable
(
mocker
):
mocker
.
patch
(
'mount_efs.get_aws_ec2_metadata_token'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.urlopen'
,
side_effect
=
URLError
(
'test error'
))
instance_id
=
mount_efs
.
get_instance_id_from_instance_metadata
()
instance_id
=
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
assert
instance_id
==
None
...
...
@@ -119,7 +119,7 @@ def _test_get_instance_id_error(mocker, response=None, error=None):
elif
error
:
mocker
.
patch
(
'mount_efs.urlopen'
,
side_effect
=
error
)
instance_id
=
mount_efs
.
get_instance_id_from_instance_metadata
()
instance_id
=
mount_efs
.
get_instance_id
entity_info
_from_instance_metadata
(
'instanceId'
)
assert
instance_id
==
None
...
...
@@ -127,13 +127,13 @@ def test_get_instance_id_bad_response(mocker):
_test_get_instance_id_error
(
mocker
,
error
=
HTTPError
(
'url'
,
400
,
'Bad Request Error'
,
None
,
None
))
def
test_get_
target_region
_error_response
(
mocker
):
def
test_get_
instance_id
_error_response
(
mocker
):
_test_get_instance_id_error
(
mocker
,
error
=
URLError
(
'test error'
))
def
test_get_
target_region
_bad_json
(
mocker
):
def
test_get_
instance_id
_bad_json
(
mocker
):
_test_get_instance_id_error
(
mocker
,
response
=
MockUrlLibResponse
(
data
=
'not json'
))
def
test_get_target_region_missing_region
(
mocker
):
_test_get_instance_id_error
(
mocker
,
response
=
MockUrlLibResponse
(
data
=
json
.
dumps
({})))
\ No newline at end of file
def
test_get_instance_id_missing_instance_id
(
mocker
):
_test_get_instance_id_error
(
mocker
,
response
=
MockUrlLibResponse
(
data
=
json
.
dumps
({
'accountId'
:
'123412341234'
})))
\ No newline at end of file
test/mount_efs_test/test_get_target_region.py
View file @
493d9ea0
...
...
@@ -202,4 +202,4 @@ def test_get_target_region_from_legacy_dns_name_format(mocker):
def
test_get_target_region_from_suffixed_dns_name_format
(
mocker
):
config
=
get_config
(
'{fs_id}.efs.us-east-1.{dns_name_suffix}'
)
config
.
set
(
mount_efs
.
CONFIG_SECTION
,
'dns_name_suffix'
,
DNS_NAME_SUFFIX
)
_test_get_target_region_from_dns_format
(
mocker
,
config
)
_test_get_target_region_from_dns_format
(
mocker
,
config
)
\ No newline at end of file
test/mount_efs_test/test_publish_cloudwatch_log.py
View file @
493d9ea0
...
...
@@ -59,7 +59,7 @@ def test_get_cloudwatchlog_config_without_fsid_with_instance_id(mocker):
enabled
=
mount_efs
.
check_if_cloudwatch_log_enabled
(
config
)
assert
enabled
==
True
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
INSTANCE
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
INSTANCE
)
cloudwatchlog_agent
=
mount_efs
.
get_cloudwatchlog_config
(
config
)
assert
cloudwatchlog_agent
.
get
(
'log_group_name'
)
==
DEFAULT_CLOUDWATCH_LOG_GROUP
assert
cloudwatchlog_agent
.
get
(
'retention_days'
)
==
DEFAULT_RETENTION_DAYS
...
...
@@ -71,7 +71,7 @@ def test_get_cloudwatchlog_config_with_fsid_with_instance_id(mocker):
enabled
=
mount_efs
.
check_if_cloudwatch_log_enabled
(
config
)
assert
enabled
==
True
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
INSTANCE
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
INSTANCE
)
cloudwatchlog_agent
=
mount_efs
.
get_cloudwatchlog_config
(
config
,
FS_ID
)
assert
cloudwatchlog_agent
.
get
(
'log_group_name'
)
==
DEFAULT_CLOUDWATCH_LOG_GROUP
assert
cloudwatchlog_agent
.
get
(
'retention_days'
)
==
DEFAULT_RETENTION_DAYS
...
...
@@ -83,7 +83,7 @@ def test_get_cloudwatchlog_config_with_fsid_without_instance_id(mocker):
enabled
=
mount_efs
.
check_if_cloudwatch_log_enabled
(
config
)
assert
enabled
==
True
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
None
)
cloudwatchlog_agent
=
mount_efs
.
get_cloudwatchlog_config
(
config
,
FS_ID
)
assert
cloudwatchlog_agent
.
get
(
'log_group_name'
)
==
DEFAULT_CLOUDWATCH_LOG_GROUP
assert
cloudwatchlog_agent
.
get
(
'retention_days'
)
==
DEFAULT_RETENTION_DAYS
...
...
@@ -95,7 +95,7 @@ def test_get_cloudwatchlog_config_without_fsid_without_instance_id(mocker):
enabled
=
mount_efs
.
check_if_cloudwatch_log_enabled
(
config
)
assert
enabled
==
True
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
None
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
None
)
cloudwatchlog_agent
=
mount_efs
.
get_cloudwatchlog_config
(
config
)
assert
cloudwatchlog_agent
.
get
(
'log_group_name'
)
==
DEFAULT_CLOUDWATCH_LOG_GROUP
assert
cloudwatchlog_agent
.
get
(
'retention_days'
)
==
DEFAULT_RETENTION_DAYS
...
...
@@ -130,7 +130,7 @@ bootstrap cloud watch log unit tests
"""
def
test_bootstrap_cloudwatch_log
(
mocker
):
config
=
_get_mock_config
(
DEFAULT_CLOUDWATCH_ENABLED
,
DEFAULT_CLOUDWATCH_LOG_GROUP
,
DEFAULT_RETENTION_DAYS
)
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
INSTANCE
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
INSTANCE
)
get_botocore_client_mock
=
mocker
.
patch
(
'mount_efs.get_botocore_client'
,
return_value
=
'fake-agent'
)
create_log_group_mock
=
mocker
.
patch
(
'mount_efs.create_cloudwatch_log_group'
,
return_value
=
True
)
put_retention_policy_mock
=
mocker
.
patch
(
'mount_efs.put_cloudwatch_log_retention_policy'
,
return_value
=
True
)
...
...
@@ -147,7 +147,7 @@ def test_bootstrap_cloudwatch_log(mocker):
def
test_bootstrap_cloudwatch_log_create_log_group_failed
(
mocker
):
config
=
_get_mock_config
(
DEFAULT_CLOUDWATCH_ENABLED
,
DEFAULT_CLOUDWATCH_LOG_GROUP
,
DEFAULT_RETENTION_DAYS
)
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
INSTANCE
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
INSTANCE
)
get_botocore_client_mock
=
mocker
.
patch
(
'mount_efs.get_botocore_client'
,
return_value
=
'fake-agent'
)
create_log_group_mock
=
mocker
.
patch
(
'mount_efs.create_cloudwatch_log_group'
,
return_value
=
False
)
put_retention_policy_mock
=
mocker
.
patch
(
'mount_efs.put_cloudwatch_log_retention_policy'
)
...
...
@@ -164,7 +164,7 @@ def test_bootstrap_cloudwatch_log_create_log_group_failed(mocker):
def
test_bootstrap_cloudwatch_log_put_retention_days_failed
(
mocker
):
config
=
_get_mock_config
(
DEFAULT_CLOUDWATCH_ENABLED
,
DEFAULT_CLOUDWATCH_LOG_GROUP
,
DEFAULT_RETENTION_DAYS
)
mocker
.
patch
(
'mount_efs.get_instance_id_from_instance_metadata'
,
return_value
=
INSTANCE
)
mocker
.
patch
(
'mount_efs.get_instance_id
entity_info
_from_instance_metadata'
,
return_value
=
INSTANCE
)
get_botocore_client_mock
=
mocker
.
patch
(
'mount_efs.get_botocore_client'
,
return_value
=
'fake-agent'
)
create_log_group_mock
=
mocker
.
patch
(
'mount_efs.create_cloudwatch_log_group'
,
return_value
=
True
)
put_retention_policy_mock
=
mocker
.
patch
(
'mount_efs.put_cloudwatch_log_retention_policy'
,
return_value
=
False
)
...
...
@@ -181,7 +181,7 @@ def test_bootstrap_cloudwatch_log_put_retention_days_failed(mocker):