|
72 | 72 | from apache_beam.transforms.core import FlatMapTuple |
73 | 73 | from apache_beam.transforms.trigger import AfterCount |
74 | 74 | from apache_beam.transforms.trigger import Repeatedly |
75 | | -from apache_beam.transforms.util import GcpHsmGeneratedSecret |
76 | 75 | from apache_beam.transforms.util import GcpSecret |
77 | 76 | from apache_beam.transforms.util import Secret |
78 | 77 | from apache_beam.transforms.window import FixedWindows |
@@ -434,124 +433,6 @@ def test_gbek_gcp_secret_manager_throws(self): |
434 | 433 | result, equal_to([('a', ([1, 2])), ('b', ([3])), ('c', ([4]))])) |
435 | 434 |
|
436 | 435 |
|
437 | | -@unittest.skipIf(secretmanager is None, 'GCP dependencies are not installed') |
438 | | -class GcpHsmGeneratedSecretTest(unittest.TestCase): |
439 | | - def setUp(self): |
440 | | - self.mock_secret_manager_client = mock.MagicMock() |
441 | | - self.mock_kms_client = mock.MagicMock() |
442 | | - |
443 | | - # Patch the clients |
444 | | - self.secretmanager_patcher = mock.patch( |
445 | | - 'google.cloud.secretmanager.SecretManagerServiceClient', |
446 | | - return_value=self.mock_secret_manager_client) |
447 | | - self.kms_patcher = mock.patch( |
448 | | - 'google.cloud.kms.KeyManagementServiceClient', |
449 | | - return_value=self.mock_kms_client) |
450 | | - self.os_urandom_patcher = mock.patch('os.urandom', return_value=b'0' * 32) |
451 | | - self.hkdf_patcher = mock.patch( |
452 | | - 'cryptography.hazmat.primitives.kdf.hkdf.HKDF.derive', |
453 | | - return_value=b'derived_key') |
454 | | - |
455 | | - self.secretmanager_patcher.start() |
456 | | - self.kms_patcher.start() |
457 | | - self.os_urandom_patcher.start() |
458 | | - self.hkdf_patcher.start() |
459 | | - |
460 | | - def tearDown(self): |
461 | | - self.secretmanager_patcher.stop() |
462 | | - self.kms_patcher.stop() |
463 | | - self.os_urandom_patcher.stop() |
464 | | - self.hkdf_patcher.stop() |
465 | | - |
466 | | - def test_happy_path_secret_creation(self): |
467 | | - from google.api_core import exceptions as api_exceptions |
468 | | - |
469 | | - project_id = 'test-project' |
470 | | - location_id = 'global' |
471 | | - key_ring_id = 'test-key-ring' |
472 | | - key_id = 'test-key' |
473 | | - job_name = 'test-job' |
474 | | - |
475 | | - secret = GcpHsmGeneratedSecret( |
476 | | - project_id, location_id, key_ring_id, key_id, job_name) |
477 | | - |
478 | | - # Mock responses for secret creation path |
479 | | - self.mock_secret_manager_client.access_secret_version.side_effect = [ |
480 | | - api_exceptions.NotFound('not found'), # first check |
481 | | - api_exceptions.NotFound('not found'), # second check |
482 | | - mock.MagicMock(payload=mock.MagicMock(data=b'derived_key')) |
483 | | - ] |
484 | | - self.mock_kms_client.encrypt.return_value = mock.MagicMock( |
485 | | - ciphertext=b'encrypted_nonce') |
486 | | - |
487 | | - secret_bytes = secret.get_secret_bytes() |
488 | | - self.assertEqual(secret_bytes, b'derived_key') |
489 | | - |
490 | | - # Assertions on mocks |
491 | | - secret_version_path = ( |
492 | | - f'projects/{project_id}/secrets/{secret._secret_version_name}' |
493 | | - '/versions/1') |
494 | | - self.mock_secret_manager_client.access_secret_version.assert_any_call( |
495 | | - request={'name': secret_version_path}) |
496 | | - self.assertEqual( |
497 | | - self.mock_secret_manager_client.access_secret_version.call_count, 3) |
498 | | - self.mock_secret_manager_client.create_secret.assert_called_once() |
499 | | - self.mock_kms_client.encrypt.assert_called_once() |
500 | | - self.mock_secret_manager_client.add_secret_version.assert_called_once() |
501 | | - |
502 | | - def test_secret_already_exists(self): |
503 | | - from google.api_core import exceptions as api_exceptions |
504 | | - |
505 | | - project_id = 'test-project' |
506 | | - location_id = 'global' |
507 | | - key_ring_id = 'test-key-ring' |
508 | | - key_id = 'test-key' |
509 | | - job_name = 'test-job' |
510 | | - |
511 | | - secret = GcpHsmGeneratedSecret( |
512 | | - project_id, location_id, key_ring_id, key_id, job_name) |
513 | | - |
514 | | - # Mock responses for secret creation path |
515 | | - self.mock_secret_manager_client.access_secret_version.side_effect = [ |
516 | | - api_exceptions.NotFound('not found'), |
517 | | - api_exceptions.NotFound('not found'), |
518 | | - mock.MagicMock(payload=mock.MagicMock(data=b'derived_key')) |
519 | | - ] |
520 | | - self.mock_secret_manager_client.create_secret.side_effect = ( |
521 | | - api_exceptions.AlreadyExists('exists')) |
522 | | - self.mock_kms_client.encrypt.return_value = mock.MagicMock( |
523 | | - ciphertext=b'encrypted_nonce') |
524 | | - |
525 | | - secret_bytes = secret.get_secret_bytes() |
526 | | - self.assertEqual(secret_bytes, b'derived_key') |
527 | | - |
528 | | - # Assertions on mocks |
529 | | - self.mock_secret_manager_client.create_secret.assert_called_once() |
530 | | - self.mock_secret_manager_client.add_secret_version.assert_called_once() |
531 | | - |
532 | | - def test_secret_version_already_exists(self): |
533 | | - project_id = 'test-project' |
534 | | - location_id = 'global' |
535 | | - key_ring_id = 'test-key-ring' |
536 | | - key_id = 'test-key' |
537 | | - job_name = 'test-job' |
538 | | - |
539 | | - secret = GcpHsmGeneratedSecret( |
540 | | - project_id, location_id, key_ring_id, key_id, job_name) |
541 | | - |
542 | | - self.mock_secret_manager_client.access_secret_version.return_value = ( |
543 | | - mock.MagicMock(payload=mock.MagicMock(data=b'existing_dek'))) |
544 | | - |
545 | | - secret_bytes = secret.get_secret_bytes() |
546 | | - self.assertEqual(secret_bytes, b'existing_dek') |
547 | | - |
548 | | - # Assertions |
549 | | - self.mock_secret_manager_client.access_secret_version.assert_called_once() |
550 | | - self.mock_secret_manager_client.create_secret.assert_not_called() |
551 | | - self.mock_secret_manager_client.add_secret_version.assert_not_called() |
552 | | - self.mock_kms_client.encrypt.assert_not_called() |
553 | | - |
554 | | - |
555 | 436 | class FakeClock(object): |
556 | 437 | def __init__(self, now=time.time()): |
557 | 438 | self._now = now |
|
0 commit comments