-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mocking password_last_used date #5927
Comments
Hi @WesleyHindle, there is no way to mock this, no. You could reach directly in the internal API and change it there:
Just note that, as it is an internal API, this may change without notice. We use the same approach in our tests: moto/tests/test_iam/test_iam.py Line 1855 in 79a0b90
|
Thank you for the reply. I'm having trouble implementing this. def test_password_last_used(iam):
current_time = pytz.timezone("UTC").localize(datetime.utcnow())
password_last_used_date = current_time - timedelta(days=100)
username = "test.user"
iam[0].create_user(Path='/staff/', UserName=username)
iam[0].create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False)
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = password_last_used_date
x = iam[1].CurrentUser().user_name
print(x) So this returns Is there a way to change to current user from |
The proper way would be to create an AccessKey for that user, and then login as that user:
Would that work? Note that does not give you the password at the moment - Moto's implementation doesn't return that field yet. I'll raise a PR for that shortly to get that fixed. |
Okay, so that has solved the issue about being the However I'm still having trouble setting a date for def test_password_last_used(iam):
current_time = pytz.timezone("UTC").localize(datetime.utcnow())
password_last_used_date = current_time - timedelta(days=100)
username = "test.user"
iam[0].create_user(Path='/staff/', UserName=username)
iam[0].create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False)
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = password_last_used_date
access_key = iam[0].create_access_key(UserName=username)["AccessKey"]
as_new_user = boto3.resource(
"iam",
region_name="us-east-1",
aws_access_key_id=access_key["AccessKeyId"],
aws_secret_access_key=access_key["SecretAccessKey"],
)
print(as_new_user.CurrentUser().password_last_used) Which returns |
Can you try the latest version @WesleyHindle, moto >= 4.1.3.dev34? That should fix that |
Thanks for the reply, I'm still getting
|
Thank you for the reply, I'm still having issues though, even when replicating your code: pip show moto
Name: moto
Version: 4.1.3.dev34 from moto import mock_iam
from moto.backends import get_backend
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
@pytest.fixture
@mock_iam
def aws_credentials():
"""Mocked AWS Credentials for moto."""
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
os.environ["AWS_SECURITY_TOKEN"] = "testing"
os.environ["AWS_SESSION_TOKEN"] = "testing"
#Here for completeness
@pytest.fixture
def iam(aws_credentials):
with mock_iam():
#client will be [0], resource [1]
yield (boto3.client("iam"), boto3.resource("iam"))
mock = mock_iam()
mock.start()
client = boto3.client("iam", "us-east-1")
username = "test.user"
client.create_user(Path='/staff/', UserName=username)
client.create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False )
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = datetime.utcnow()
a_k = access_key = client.create_access_key(UserName=username)["AccessKey"]
print(a_k)
as_new_user = boto3.resource("iam", region_name="us-east-1", aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"] )
print("---")
print(as_new_user.CurrentUser().password_last_used)
mock.stop() Which still returns |
FYI, I've released Moto 4.1.3 just now. It contains the same functionality as |
I'be updated to 4.1.3 and ran this code in a new file import boto3
from datetime import datetime, timedelta
from moto import mock_iam
from moto.backends import get_backend
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
import os
import pytest
mock = mock_iam()
mock.start()
client = boto3.client("iam", "us-east-1")
username = "test.user"
client.create_user(Path='/staff/', UserName=username)
client.create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False )
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = datetime.utcnow()
a_k = access_key = client.create_access_key(UserName=username)["AccessKey"]
print(a_k)
as_new_user = boto3.resource("iam", region_name="us-east-1", aws_access_key_id=access_key["AccessKeyId"], aws_secret_access_key=access_key["SecretAccessKey"] )
print("---")
print(as_new_user.CurrentUser().password_last_used)
mock.stop() And I'm still getting |
Can you add some print-statements to Line 537 in d001f6a
Just curious to see what's going wrong, if it's the model or the view.
And maybe a |
Sorry, this is quickly becoming way out of my depth! So in def get_user(self):
user_name = self._get_param("UserName")
if not user_name:
access_key_id = self.get_access_key()
user = self.backend.get_user_from_access_key_id(access_key_id)
if user is None:
user = User(self.current_account, "default_user")
else:
user = self.backend.get_user(user_name)
tags = self.backend.tagger.list_tags_for_resource(user.arn).get("Tags", [])
template = self.response_template(USER_TEMPLATE)
print(user.__dict__)
print(user.password_last_used_iso_8601)
print(template.render(action="Get", user=user, tags=tags))
return template.render(action="Get", user=user, tags=tags) Which when I run the previous code doesn't output anything, additional. I was also unsure where to add |
If nothing is printed, then we're definitely looking at different Moto versions/installations. It is the right method, since that's where the I would suggest to start from scratch. Are you using virtual environments? If so, just create a new one, install moto in that env and execute the script again. Feel free to share the steps that you take if you're unsure about anything. |
Okay, so good news! You're right. Your update was working and it was an issue on my side. The only bad news is the horrible state of my pip, which was causing the issue. Thank you for your patience, help and new feature. |
Happy to hear this is now solved! |
Okay. I think I was slightly eager! I want to test this code: def password_last_used():
iam_resource = boto3.resource("iam")
iam_client = boto3.client("iam")
pass_last_used = iam_resource.CurrentUser().password_last_used
username = iam_resource.CurrentUser().user_name
if pass_last_used < cutoff_date:
print("not fine")
else:
print("fine") Using this test (I'll add the actual test once it's working): @pytest.fixture
@mock_iam
def aws_credentials():
"""Mocked AWS Credentials for moto."""
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
os.environ["AWS_SECURITY_TOKEN"] = "testing"
os.environ["AWS_SESSION_TOKEN"] = "testing"
@pytest.fixture
def iam(aws_credentials):
with mock_iam():
#client will be [0], resource [1]
yield (boto3.client("iam"), boto3.resource("iam"))
def test_password_last_used(iam):
current_time = pytz.timezone("UTC").localize(datetime.utcnow())
password_last_used_date = current_time - timedelta(days=100)
username = "test.user"
iam[0].create_user(Path='/staff/', UserName=username)
iam[0].create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False
)
access_key = iam[0].create_access_key(UserName=username)["AccessKey"]
as_new_user = boto3.resource(
"iam",
region_name="us-east-1",
aws_access_key_id=access_key["AccessKeyId"],
aws_secret_access_key=access_key["SecretAccessKey"],
)
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = password_last_used_date
print(password_last_used()) But when I run the test I get an error saying that there's None type, so can't comapre for dates. Makes sense, I'm comparing a different user to the test user who's However, I think that the test user only exists as a var within the test and not an env var as the actual current user, and because no param is passed into the test, there's no way for the test to know to use the test user if it isn't assigned as the Am I on the right track with this so and if so, is there a way for me to be able to configure the test so that I can use the test user's password last used object for testing the app code, even though the app doesn't take in a param. I think realistically though this app code would have to take in a param, else you're editiing your own AWS user |
Is the
A second theoretical option is to set environment variables just before calling
This should configure the |
Okay, so I had think about what I was trying to do and I was overcomplicating it. There was no need to use the This was my finished test / app code with a manipulated Thank you again. # App
import boto3
import pytz
from datetime import datetime, timedelta
# Password can only be 30 days old
# Convert current time date to be time zone aware needed for comparison with an AWS user date
current_time = pytz.timezone("UTC").localize(datetime.utcnow())
cutoff_date = current_time - timedelta(days=30)
def password_last_used(username):
iam_resource = boto3.resource("iam")
iam_client = boto3.client("iam")
aws_user = iam_resource.User(username)
if aws_user.password_last_used < cutoff_date:
print("not fine")
iam_client.delete_login_profile(UserName=username) from app_5 import password_last_used
import boto3
from datetime import datetime, timedelta
from moto import mock_iam
from moto.backends import get_backend
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
import os
import pytest
import pytz
@pytest.fixture
@mock_iam
def aws_credentials():
"""Mocked AWS Credentials for moto."""
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
os.environ["AWS_SECURITY_TOKEN"] = "testing"
os.environ["AWS_SESSION_TOKEN"] = "testing"
@pytest.fixture
def iam(aws_credentials):
with mock_iam():
#client will be [0], resource [1]
yield (boto3.client("iam"), boto3.resource("iam"))
def test_password_last_used(iam):
current_time = pytz.timezone("UTC").localize(datetime.utcnow())
password_last_used_date = current_time - timedelta(days=100)
username = "test.user"
iam[0].create_user(Path='/staff/', UserName=username)
iam[0].create_login_profile(
UserName = username,
Password = "Password1",
PasswordResetRequired = False
)
iam_backend = get_backend("iam")[ACCOUNT_ID]["global"]
iam_backend.users[username].password_last_used = password_last_used_date
assert iam[0].get_login_profile(UserName=username) is not None
password_last_used(username)
with pytest.raises(Exception):
iam[0].get_login_profile(UserName=username) |
As you mentioned changing the last used date requires you amending the backend, are there plans to implement functionality where you can manipulate the 'last used date' without amending the backend, or is this the only feasible way to do this? If this is the case are changes to the internal API listed on change notes? |
From what I can tell, this functionality isn't used by enough people to warrant a dedicated/public/fixed API. There are honestly too many internal API changes to list them all in the change notes. But for the |
Thank you |
Is there a way to mock a specific date that an IAM user last used their password?
I think the answer is no, because you actually have to log into the console to have used the password, but just wondered if I had missed anything.
Thanks.
The text was updated successfully, but these errors were encountered: