Skip to content

Add fallbacks for import crypt#2156

Open
norakoiralamsft wants to merge 4 commits intomasterfrom
norakoirala/vmaccess-crypt
Open

Add fallbacks for import crypt#2156
norakoiralamsft wants to merge 4 commits intomasterfrom
norakoirala/vmaccess-crypt

Conversation

@norakoiralamsft
Copy link
Copy Markdown
Contributor

@norakoiralamsft norakoiralamsft commented Mar 30, 2026

This PR is aimed to add fallbacks for importing the cypt library with was deprecated in python 3.11, takes a similar approach as to Linux Agent, first trying to import crypt (which includes crypt + crypt_r), legacycrypt, and finally passlib.

This was chosen over the crypt_fallback that was introduced in this PR because we want to continue supporting older distros that may not have cyptes available, and Canocial raised concerns about the crypt_r lib as well, and have ensured that passlib will be available on Ubuntu.

@norakoiralamsft norakoiralamsft requested review from a team, D1v38om83r and nkuchta as code owners March 30, 2026 18:49
jscalev
jscalev previously approved these changes Mar 30, 2026
@norakoiralamsft norakoiralamsft changed the title Import crypt fallback Add fallbacks for import crypt Apr 1, 2026
Comment thread Utils/distroutils.py
Comment thread Utils/distroutils.py
Copy link
Copy Markdown

@malhotrarohit malhotrarohit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test comment

Comment thread Utils/distroutils.py
pass

if cryptImported == False:
if sys.version_info[0] == 3 and sys.version_info[1] >= 13 or sys.version_info[0] > 3:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be good to explain what these numbers mean or rather what this expression means

Comment thread Utils/distroutils.py

if cryptImported:
return crypt(password, salt)
elif passLibImported:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't ignore crypt_id and salt. This could result in a bug depending on n distro configuration?

Copy link
Copy Markdown
Contributor

@dylanbun dylanbun Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, I think it would be a good idea to get the hashes for all scenarios/libraries first and confirming they all match prior to merging. (i.e. assuming they are using sha512_crypt and passing in salt).

Copy link
Copy Markdown
Member

@narrieta narrieta Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The crypt_id defines the hashing algorithm to use and is included as part of the salt parameter in the call to crypt.crypt (notice that it is prepended to the salt). For some reason, the WALinuxAgent allowed users to set the crypt_id in waagent.conf; I am assuming that VmAccess is using legacy code that reads this value from waagent.conf.

@norakoiralamsft - For WALinuxAgent, we decided to make this change (see the README in the develop branch, marked with ******* below):

Provisioning.PasswordCryptId
Type: String
Default: 6

Algorithm used by crypt when generating password hash. 

******This parameter, as well as PasswordCryptSaltLength, is used only on Python versions previous to 3.13, and SHA-512 is the default for most distros. From Python 3.13 onwards, SHA-512 is always used, regardless of the value of this parameter.*******

1 - MD5
2a - Blowfish
5 - SHA-256
6 - SHA-512

I think that would be appropriate for VmAccess as well, but pointing it out in case you want to follow a different approach.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call to passlib.hash() is not given a salt. One will be generated automatically and that is the recommended usage.

Comment thread Utils/distroutils.py
pass

if cryptImported == False:
if sys.version_info[0] == 3 and sys.version_info[1] >= 13 or sys.version_info[0] > 3:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add braces for sys.version_info[0] == 3 and sys.version_info[1] >= 13 ? (for easier readability)

Comment thread Utils/distroutils.py
from passlib.hash import sha512_crypt
passLibImported = True
except ImportError:
pass
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all 3 imports fail, do we need to throw an error here + log ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition (all 3 imports failing) needs to be handled, but raising an exception here would require all modules depending on this module, directly or indirectly, to handle that exception, or the extension would crash.

@norakoiralamsft - in the original PR, an exception is raised on usage of these functions if no module was imported. I see that you are handling this at line 192 by returning None. Do verify that this error handling is appropriate for your usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants