Use crypt to generate salt

Let's use the crypt to generate the salt, the crypt.crypt
can handle the generation of the salt if we don't pass.

Change-Id: I63fca663940e44924a201b166bdd79d8f7710bee
Story: 2007443
Task: 39103
This commit is contained in:
Iury Gregory Melo Ferreira 2020-03-18 17:14:29 +01:00
parent 6f1f9c7f6e
commit 7f8afac092
3 changed files with 14 additions and 36 deletions

View File

@ -11,8 +11,6 @@
# limitations under the License. # limitations under the License.
import crypt import crypt
import random
import string
from oslo_log import log from oslo_log import log
@ -25,16 +23,6 @@ PASSWORD_FILE = '/etc/ipa-rescue-config/ipa-rescue-password'
class RescueExtension(base.BaseAgentExtension): class RescueExtension(base.BaseAgentExtension):
def make_salt(self):
"""Generate a random salt for hashing the rescue password.
Salt should be a two-character string from the set [a-zA-Z0-9].
:returns: a valid salt for use with crypt.crypt
"""
allowed_chars = string.ascii_letters + string.digits
return random.choice(allowed_chars) + random.choice(allowed_chars)
def write_rescue_password(self, rescue_password="", hashed=False): def write_rescue_password(self, rescue_password="", hashed=False):
"""Write rescue password to a file for use after IPA exits. """Write rescue password to a file for use after IPA exits.
@ -55,8 +43,7 @@ class RescueExtension(base.BaseAgentExtension):
if hashed: if hashed:
hashed_password = password hashed_password = password
else: else:
salt = self.make_salt() hashed_password = crypt.crypt(rescue_password)
hashed_password = crypt.crypt(rescue_password, salt)
try: try:
with open(PASSWORD_FILE, 'w') as f: with open(PASSWORD_FILE, 'w') as f:
f.write(hashed_password) f.write(hashed_password)

View File

@ -10,8 +10,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import string
import mock import mock
from oslotest import base as test_base from oslotest import base as test_base
@ -26,25 +24,16 @@ class TestRescueExtension(test_base.BaseTestCase):
self.agent_extension = rescue.RescueExtension() self.agent_extension = rescue.RescueExtension()
self.agent_extension.agent = FakeAgent() self.agent_extension.agent = FakeAgent()
def test_make_salt(self):
salt = self.agent_extension.make_salt()
self.assertEqual(2, len(salt))
for char in salt:
self.assertIn(char, string.ascii_letters + string.digits)
@mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt', @mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt',
autospec=True) autospec=True)
@mock.patch('ironic_python_agent.extensions.rescue.RescueExtension.' def test_write_rescue_password(self, mock_crypt):
'make_salt', autospec=True)
def test_write_rescue_password(self, mock_salt, mock_crypt):
mock_salt.return_value = '12'
mock_crypt.return_value = '12deadbeef' mock_crypt.return_value = '12deadbeef'
mock_open = mock.mock_open() mock_open = mock.mock_open()
with mock.patch('ironic_python_agent.extensions.rescue.open', with mock.patch('ironic_python_agent.extensions.rescue.open',
mock_open): mock_open):
self.agent_extension.write_rescue_password('password') self.agent_extension.write_rescue_password('password')
mock_crypt.assert_called_once_with('password', '12') mock_crypt.assert_called_once_with('password')
mock_open.assert_called_once_with( mock_open.assert_called_once_with(
'/etc/ipa-rescue-config/ipa-rescue-password', 'w') '/etc/ipa-rescue-config/ipa-rescue-password', 'w')
file_handle = mock_open() file_handle = mock_open()
@ -52,10 +41,7 @@ class TestRescueExtension(test_base.BaseTestCase):
@mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt', @mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt',
autospec=True) autospec=True)
@mock.patch('ironic_python_agent.extensions.rescue.RescueExtension.' def test_write_rescue_password_ioerror(self, mock_crypt):
'make_salt', autospec=True)
def test_write_rescue_password_ioerror(self, mock_salt, mock_crypt):
mock_salt.return_value = '12'
mock_crypt.return_value = '12deadbeef' mock_crypt.return_value = '12deadbeef'
mock_open = mock.mock_open() mock_open = mock.mock_open()
with mock.patch('ironic_python_agent.extensions.rescue.open', with mock.patch('ironic_python_agent.extensions.rescue.open',
@ -68,16 +54,12 @@ class TestRescueExtension(test_base.BaseTestCase):
@mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt', @mock.patch('ironic_python_agent.extensions.rescue.crypt.crypt',
autospec=True) autospec=True)
@mock.patch('ironic_python_agent.extensions.rescue.RescueExtension.' def _write_password_hashed_test(self, password, mock_crypt):
'make_salt', autospec=True)
def _write_password_hashed_test(self, password, mock_salt,
mock_crypt):
mock_open = mock.mock_open() mock_open = mock.mock_open()
with mock.patch('ironic_python_agent.extensions.rescue.open', with mock.patch('ironic_python_agent.extensions.rescue.open',
mock_open): mock_open):
self.agent_extension.write_rescue_password(password, self.agent_extension.write_rescue_password(password,
hashed=True) hashed=True)
self.assertFalse(mock_salt.called)
self.assertFalse(mock_crypt.called) self.assertFalse(mock_crypt.called)
mock_open.assert_called_once_with( mock_open.assert_called_once_with(
'/etc/ipa-rescue-config/ipa-rescue-password', 'w') '/etc/ipa-rescue-config/ipa-rescue-password', 'w')

View File

@ -0,0 +1,9 @@
---
security:
- |
The salt was generated using random and the module it's not in compliance
with FIPS 140-2. Now we let the salt be automatically generated by the
crypt function (it will use the strongest method available).
fixes:
- |
The salt now will be automatically generated by the crypt function.