kiarina-lib-google-auth 1.6.1__tar.gz → 1.6.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. kiarina_lib_google_auth-1.6.3/.env.sample +2 -0
  2. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/.gitignore +1 -0
  3. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/CHANGELOG.md +17 -0
  4. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/PKG-INFO +43 -16
  5. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/README.md +41 -14
  6. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/pyproject.toml +2 -2
  7. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_helpers/get_credentials.py +1 -1
  8. kiarina_lib_google_auth-1.6.3/test_settings.sample.yaml +31 -0
  9. kiarina_lib_google_auth-1.6.3/tests/conftest.py +27 -0
  10. kiarina_lib_google_auth-1.6.3/tests/test_get_credentials.py +52 -0
  11. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/tests/test_get_default_credentials.py +7 -9
  12. kiarina_lib_google_auth-1.6.3/tests/test_get_self_signed_jwt.py +9 -0
  13. kiarina_lib_google_auth-1.6.3/tests/test_get_service_account_credentials.py +27 -0
  14. kiarina_lib_google_auth-1.6.3/tests/test_get_user_account_credentials.py +76 -0
  15. kiarina_lib_google_auth-1.6.1/tests/conftest.py +0 -0
  16. kiarina_lib_google_auth-1.6.1/tests/test_get_credentials.py +0 -83
  17. kiarina_lib_google_auth-1.6.1/tests/test_get_self_signed_jwt.py +0 -22
  18. kiarina_lib_google_auth-1.6.1/tests/test_get_service_account_credentials.py +0 -38
  19. kiarina_lib_google_auth-1.6.1/tests/test_get_user_account_credentials.py +0 -125
  20. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/.vscode/settings.json +0 -0
  21. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/__init__.py +0 -0
  22. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_helpers/__init__.py +0 -0
  23. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_helpers/get_self_signed_jwt.py +0 -0
  24. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_types/__init__.py +0 -0
  25. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_types/credentials.py +0 -0
  26. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_types/credentials_cache.py +0 -0
  27. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_utils/__init__.py +0 -0
  28. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_utils/get_default_credentials.py +0 -0
  29. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_utils/get_service_account_credentials.py +0 -0
  30. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/_utils/get_user_account_credentials.py +0 -0
  31. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/py.typed +0 -0
  32. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/src/kiarina/lib/google/auth/settings.py +28 -28
  33. {kiarina_lib_google_auth-1.6.1 → kiarina_lib_google_auth-1.6.3}/tests/__init__.py +0 -0
@@ -0,0 +1,2 @@
1
+ # Test settings file path
2
+ KIARINA_LIB_GOOGLE_AUTH_TEST_SETTINGS_FILE=packages/kiarina-lib-google-auth/test_settings.yaml
@@ -25,6 +25,7 @@ htmlcov/
25
25
  # Project specific
26
26
  *.log
27
27
  tmp/
28
+ packages/*/test_settings.yaml
28
29
 
29
30
  # Test data
30
31
  tests/data/large/
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.6.3] - 2025-10-13
11
+
12
+ ### Changed
13
+ - Updated `pydantic-settings-manager` dependency from `>=2.1.0` to `>=2.3.0`
14
+ - Improved test configuration approach using YAML-based settings file instead of individual environment variables
15
+ - Tests now use `pydantic-settings-manager` with multiple named configurations for different authentication scenarios
16
+ - Added `test_settings.sample.yaml` as a template for test configuration
17
+ - Added `.env.sample` to document required environment variables
18
+ - Reorganized `GoogleAuthSettings` field order for better readability (common fields first)
19
+ - Enhanced test coverage with more comprehensive authentication method tests
20
+ - Simplified test fixtures using session-scoped `load_settings` fixture
21
+
22
+ ## [1.6.2] - 2025-10-10
23
+
24
+ ### Changed
25
+ - No changes
26
+
10
27
  ## [1.6.1] - 2025-10-10
11
28
 
12
29
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiarina-lib-google-auth
3
- Version: 1.6.1
3
+ Version: 1.6.3
4
4
  Summary: Google Cloud client library for kiarina namespace
5
5
  Project-URL: Homepage, https://github.com/kiarina/kiarina-python
6
6
  Project-URL: Repository, https://github.com/kiarina/kiarina-python
@@ -21,7 +21,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Typing :: Typed
22
22
  Requires-Python: >=3.12
23
23
  Requires-Dist: google-api-python-client>=2.184.0
24
- Requires-Dist: pydantic-settings-manager>=2.1.0
24
+ Requires-Dist: pydantic-settings-manager>=2.3.0
25
25
  Requires-Dist: pydantic-settings>=2.10.1
26
26
  Description-Content-Type: text/markdown
27
27
 
@@ -461,26 +461,53 @@ mise run package:test kiarina-lib-google-auth --coverage
461
461
 
462
462
  ### Test Configuration
463
463
 
464
- Some tests require actual GCP credentials. Set the following environment variables:
464
+ Some tests require actual GCP credentials. Create a test settings file and set the environment variable to point to it:
465
465
 
466
466
  ```bash
467
- # Service account key file
468
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE="~/path/to/sa-key.json"
467
+ # Create test settings file from sample
468
+ cp packages/kiarina-lib-google-auth/test_settings.sample.yaml \
469
+ packages/kiarina-lib-google-auth/test_settings.yaml
469
470
 
470
- # Service account key data (JSON string)
471
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_DATA='{"type": "service_account", ...}'
472
-
473
- # Authorized user file
474
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE="~/.config/gcloud/application_default_credentials.json"
475
-
476
- # Authorized user data (JSON string)
477
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA='{"type": "authorized_user", ...}'
471
+ # Edit the file with your actual credentials
472
+ # Then set the environment variable
473
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_SETTINGS_FILE="packages/kiarina-lib-google-auth/test_settings.yaml"
474
+ ```
478
475
 
479
- # Target service account for impersonation tests
480
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_IMPERSONATE_SA="target-sa@project.iam.gserviceaccount.com"
476
+ The test settings file should contain multiple named configurations for different authentication scenarios:
477
+
478
+ ```yaml
479
+ kiarina.lib.google.auth:
480
+ default:
481
+ type: default
482
+ service_account_file:
483
+ type: service_account
484
+ project_id: your-project-id
485
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
486
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
487
+ service_account_data:
488
+ type: service_account
489
+ project_id: your-project-id
490
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
491
+ service_account_data: '{"type":"service_account","project_id":"...","private_key":"...","client_email":"..."}'
492
+ service_account_impersonate:
493
+ type: service_account
494
+ project_id: your-project-id
495
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
496
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
497
+ impersonate_service_account: impersonated-account@your-project.iam.gserviceaccount.com
498
+ user_account_file:
499
+ type: user_account
500
+ project_id: your-project-id
501
+ user_account_email: your-email@example.com
502
+ authorized_user_file: ~/.gcp/oauth2/your-project/authorized_user.json
503
+ user_account_data:
504
+ type: user_account
505
+ project_id: your-project-id
506
+ user_account_email: your-email@example.com
507
+ authorized_user_data: '{"type":"authorized_user","client_id":"...","client_secret":"...","refresh_token":"..."}'
481
508
  ```
482
509
 
483
- Tests will be skipped (xfail) if these environment variables are not set.
510
+ **Note**: The `test_settings.yaml` file is gitignored to prevent accidental credential exposure.
484
511
 
485
512
  ## Dependencies
486
513
 
@@ -434,26 +434,53 @@ mise run package:test kiarina-lib-google-auth --coverage
434
434
 
435
435
  ### Test Configuration
436
436
 
437
- Some tests require actual GCP credentials. Set the following environment variables:
437
+ Some tests require actual GCP credentials. Create a test settings file and set the environment variable to point to it:
438
438
 
439
439
  ```bash
440
- # Service account key file
441
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE="~/path/to/sa-key.json"
440
+ # Create test settings file from sample
441
+ cp packages/kiarina-lib-google-auth/test_settings.sample.yaml \
442
+ packages/kiarina-lib-google-auth/test_settings.yaml
442
443
 
443
- # Service account key data (JSON string)
444
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_DATA='{"type": "service_account", ...}'
445
-
446
- # Authorized user file
447
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE="~/.config/gcloud/application_default_credentials.json"
448
-
449
- # Authorized user data (JSON string)
450
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA='{"type": "authorized_user", ...}'
444
+ # Edit the file with your actual credentials
445
+ # Then set the environment variable
446
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_SETTINGS_FILE="packages/kiarina-lib-google-auth/test_settings.yaml"
447
+ ```
451
448
 
452
- # Target service account for impersonation tests
453
- export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_IMPERSONATE_SA="target-sa@project.iam.gserviceaccount.com"
449
+ The test settings file should contain multiple named configurations for different authentication scenarios:
450
+
451
+ ```yaml
452
+ kiarina.lib.google.auth:
453
+ default:
454
+ type: default
455
+ service_account_file:
456
+ type: service_account
457
+ project_id: your-project-id
458
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
459
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
460
+ service_account_data:
461
+ type: service_account
462
+ project_id: your-project-id
463
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
464
+ service_account_data: '{"type":"service_account","project_id":"...","private_key":"...","client_email":"..."}'
465
+ service_account_impersonate:
466
+ type: service_account
467
+ project_id: your-project-id
468
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
469
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
470
+ impersonate_service_account: impersonated-account@your-project.iam.gserviceaccount.com
471
+ user_account_file:
472
+ type: user_account
473
+ project_id: your-project-id
474
+ user_account_email: your-email@example.com
475
+ authorized_user_file: ~/.gcp/oauth2/your-project/authorized_user.json
476
+ user_account_data:
477
+ type: user_account
478
+ project_id: your-project-id
479
+ user_account_email: your-email@example.com
480
+ authorized_user_data: '{"type":"authorized_user","client_id":"...","client_secret":"...","refresh_token":"..."}'
454
481
  ```
455
482
 
456
- Tests will be skipped (xfail) if these environment variables are not set.
483
+ **Note**: The `test_settings.yaml` file is gitignored to prevent accidental credential exposure.
457
484
 
458
485
  ## Dependencies
459
486
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kiarina-lib-google-auth"
3
- version = "1.6.1"
3
+ version = "1.6.3"
4
4
  description = "Google Cloud client library for kiarina namespace"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -25,7 +25,7 @@ requires-python = ">=3.12"
25
25
  dependencies = [
26
26
  "google-api-python-client>=2.184.0",
27
27
  "pydantic-settings>=2.10.1",
28
- "pydantic-settings-manager>=2.1.0",
28
+ "pydantic-settings-manager>=2.3.0",
29
29
  ]
30
30
 
31
31
  [project.urls]
@@ -19,7 +19,7 @@ def get_credentials(
19
19
  cache: CredentialsCache | None = None,
20
20
  ) -> Credentials:
21
21
  if settings is None:
22
- settings = settings_manager.get_settings_by_key(config_key)
22
+ settings = settings_manager.get_settings(config_key)
23
23
 
24
24
  credentials: Credentials
25
25
 
@@ -0,0 +1,31 @@
1
+ kiarina.lib.google.auth:
2
+ default:
3
+ type: default
4
+ service_account_file:
5
+ type: service_account
6
+ project_id: your-project-id
7
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
8
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
9
+ service_account_data:
10
+ type: service_account
11
+ project_id: your-project-id
12
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
13
+ # cat $service_account_file | jq -c .
14
+ service_account_data: '{"type":"service_account","project_id":"your-project-id","private_key_id":"...","private_key":"...","client_email":"your-service-account@your-project.iam.gserviceaccount.com","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"..."}'
15
+ service_account_impersonate:
16
+ type: service_account
17
+ project_id: your-project-id
18
+ service_account_email: your-service-account@your-project.iam.gserviceaccount.com
19
+ service_account_file: ~/.gcp/service-account/your-project/your-service-account/key.json
20
+ impersonate_service_account: impersonated-account@your-project.iam.gserviceaccount.com
21
+ user_account_file:
22
+ type: user_account
23
+ project_id: your-project-id
24
+ user_account_email: your-email@example.com
25
+ authorized_user_file: ~/.gcp/oauth2/your-project/authorized_user.json
26
+ user_account_data:
27
+ type: user_account
28
+ project_id: your-project-id
29
+ user_account_email: your-email@example.com
30
+ # cat $authorized_user_file | jq -c .
31
+ authorized_user_data: '{"type":"authorized_user","client_id":"...","client_secret":"...","refresh_token":"..."}'
@@ -0,0 +1,27 @@
1
+ import os
2
+
3
+ import pytest
4
+ from pydantic_settings_manager import load_user_configs
5
+
6
+ import kiarina.utils.file as kf
7
+
8
+
9
+ @pytest.fixture(scope="session")
10
+ def load_settings():
11
+ env_var = "KIARINA_LIB_GOOGLE_AUTH_TEST_SETTINGS_FILE"
12
+
13
+ if env_var not in os.environ:
14
+ pytest.skip(f"Environment variable {env_var} not set, skipping tests.")
15
+
16
+ test_settings_file = os.environ[env_var]
17
+ test_settings_file = os.path.expanduser(test_settings_file)
18
+
19
+ if not os.path.exists(test_settings_file):
20
+ raise FileNotFoundError(f"Settings file not found: {test_settings_file}")
21
+
22
+ user_configs = kf.read_yaml_dict(test_settings_file)
23
+
24
+ if not user_configs:
25
+ raise ValueError(f"Settings file is empty or invalid: {test_settings_file}")
26
+
27
+ load_user_configs(user_configs)
@@ -0,0 +1,52 @@
1
+ import os
2
+
3
+ import google.auth.compute_engine.credentials
4
+ import google.oauth2.credentials
5
+ import google.oauth2.service_account
6
+ from google.auth import impersonated_credentials
7
+ import pytest
8
+
9
+ from kiarina.lib.google.auth import get_credentials
10
+
11
+
12
+ @pytest.mark.xfail(
13
+ not os.path.exists(
14
+ os.path.expanduser("~/.config/gcloud/application_default_credentials.json")
15
+ ),
16
+ reason="ADC file not set",
17
+ )
18
+ def test_default(load_settings):
19
+ credentials = get_credentials("default")
20
+ assert isinstance(
21
+ credentials,
22
+ (
23
+ google.auth.compute_engine.credentials.Credentials,
24
+ google.oauth2.service_account.Credentials,
25
+ google.oauth2.credentials.Credentials,
26
+ ),
27
+ )
28
+
29
+
30
+ def test_service_account_file(load_settings):
31
+ credentials = get_credentials("service_account_file")
32
+ assert isinstance(credentials, google.oauth2.service_account.Credentials)
33
+
34
+
35
+ def test_service_account_data(load_settings):
36
+ credentials = get_credentials("service_account_data")
37
+ assert isinstance(credentials, google.oauth2.service_account.Credentials)
38
+
39
+
40
+ def test_impersonate_service_account(load_settings):
41
+ credentials = get_credentials("service_account_impersonate")
42
+ assert isinstance(credentials, impersonated_credentials.Credentials)
43
+
44
+
45
+ def test_user_account_file(load_settings):
46
+ credentials = get_credentials("user_account_file")
47
+ assert isinstance(credentials, google.oauth2.credentials.Credentials)
48
+
49
+
50
+ def test_user_account_data(load_settings):
51
+ credentials = get_credentials("user_account_data")
52
+ assert isinstance(credentials, google.oauth2.credentials.Credentials)
@@ -4,6 +4,7 @@ import google.oauth2.credentials
4
4
  import google.oauth2.service_account
5
5
  import pytest
6
6
 
7
+ from kiarina.lib.google.auth import settings_manager
7
8
  from kiarina.lib.google.auth._utils.get_default_credentials import (
8
9
  get_default_credentials,
9
10
  )
@@ -21,15 +22,12 @@ def test_adc():
21
22
  assert isinstance(credentials, google.oauth2.credentials.Credentials)
22
23
 
23
24
 
24
- @pytest.mark.xfail(
25
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE" not in os.environ,
26
- reason="GCP SA key file not set",
27
- )
28
- def test_service_account():
29
- # Set the environment variable to point to a service account key file
30
- os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = os.path.expanduser(
31
- os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE"]
32
- )
25
+ def test_service_account(load_settings, monkeypatch):
26
+ if "GOOGLE_APPLICATION_CREDENTIALS" not in os.environ:
27
+ settings = settings_manager.get_settings("service_account_file")
28
+ monkeypatch.setenv(
29
+ "GOOGLE_APPLICATION_CREDENTIALS", settings.service_account_file
30
+ )
33
31
 
34
32
  credentials = get_default_credentials()
35
33
  print(f"Obtained service account credentials of type: {type(credentials)}")
@@ -0,0 +1,9 @@
1
+ from kiarina.lib.google.auth import get_self_signed_jwt
2
+
3
+
4
+ def test_get_self_signed_jwt(load_settings):
5
+ jwt = get_self_signed_jwt(
6
+ "service_account_file",
7
+ audience="https://blazeworks.jp/",
8
+ )
9
+ assert jwt.count(".") == 2
@@ -0,0 +1,27 @@
1
+ import google.oauth2.service_account
2
+ import pytest
3
+
4
+ from kiarina.lib.google.auth import settings_manager, get_service_account_credentials
5
+
6
+
7
+ def test_file(load_settings):
8
+ settings = settings_manager.get_settings("service_account_file")
9
+ credentials = get_service_account_credentials(
10
+ service_account_file=settings.service_account_file
11
+ )
12
+ assert isinstance(credentials, google.oauth2.service_account.Credentials)
13
+
14
+
15
+ def test_nonexistent_file():
16
+ with pytest.raises(ValueError, match="Service account file does not exist"):
17
+ get_service_account_credentials(
18
+ service_account_file="/path/to/nonexistent/file.json"
19
+ )
20
+
21
+
22
+ def test_data(load_settings):
23
+ settings = settings_manager.get_settings("service_account_data")
24
+ credentials = get_service_account_credentials(
25
+ service_account_data=settings.get_service_account_data()
26
+ )
27
+ assert isinstance(credentials, google.oauth2.service_account.Credentials)
@@ -0,0 +1,76 @@
1
+ from google.oauth2.credentials import Credentials
2
+ import pytest
3
+
4
+ from kiarina.lib.google.auth import (
5
+ CredentialsCache,
6
+ settings_manager,
7
+ get_user_account_credentials,
8
+ )
9
+
10
+
11
+ def test_file(load_settings):
12
+ settings = settings_manager.get_settings("user_account_file")
13
+ credentials = get_user_account_credentials(
14
+ authorized_user_file=settings.authorized_user_file,
15
+ scopes=settings.scopes,
16
+ )
17
+ assert isinstance(credentials, Credentials)
18
+
19
+
20
+ def test_nonexistent_file():
21
+ with pytest.raises(ValueError, match="Authorized user file does not exist"):
22
+ get_user_account_credentials(
23
+ authorized_user_file="/path/to/nonexistent/file.json",
24
+ scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
25
+ )
26
+
27
+
28
+ def test_data(load_settings):
29
+ settings = settings_manager.get_settings("user_account_data")
30
+ credentials = get_user_account_credentials(
31
+ authorized_user_data=settings.get_authorized_user_data(),
32
+ scopes=settings.scopes,
33
+ )
34
+ assert isinstance(credentials, Credentials)
35
+
36
+
37
+ def test_cache(load_settings):
38
+ set_counter = 0
39
+
40
+ class InMemoryCache(CredentialsCache):
41
+ def __init__(self):
42
+ self._cache: str | None = None
43
+
44
+ def get(self) -> str | None:
45
+ return self._cache
46
+
47
+ def set(self, value: str) -> None:
48
+ self._cache = value
49
+
50
+ nonlocal set_counter
51
+ set_counter += 1
52
+
53
+ cache = InMemoryCache()
54
+
55
+ settings = settings_manager.get_settings("user_account_data")
56
+ credentials = get_user_account_credentials(
57
+ authorized_user_data=settings.get_authorized_user_data(),
58
+ scopes=settings.scopes,
59
+ cache=cache,
60
+ )
61
+
62
+ assert isinstance(credentials, Credentials)
63
+ assert credentials.valid is True
64
+ assert cache.get() is not None
65
+ assert set_counter == 1
66
+
67
+ credentials2 = get_user_account_credentials(
68
+ authorized_user_data=settings.get_authorized_user_data(),
69
+ scopes=settings.scopes,
70
+ cache=cache,
71
+ )
72
+
73
+ assert isinstance(credentials2, Credentials)
74
+ assert credentials2.valid is True
75
+ assert credentials2.token == credentials.token
76
+ assert set_counter == 1 # Cache should be used, so set() not called
File without changes
@@ -1,83 +0,0 @@
1
- import os
2
-
3
- import google.auth.compute_engine.credentials
4
- import google.oauth2.credentials
5
- import google.oauth2.service_account
6
- from google.auth import impersonated_credentials
7
- import pytest
8
-
9
- from kiarina.lib.google.auth import GoogleAuthSettings, get_credentials
10
-
11
-
12
- @pytest.mark.xfail(
13
- not os.path.exists(
14
- os.path.expanduser("~/.config/gcloud/application_default_credentials.json")
15
- ),
16
- reason="ADC file not set",
17
- )
18
- def test_default():
19
- credentials = get_credentials(settings=GoogleAuthSettings())
20
- assert isinstance(
21
- credentials,
22
- (
23
- google.auth.compute_engine.credentials.Credentials,
24
- google.oauth2.service_account.Credentials,
25
- google.oauth2.credentials.Credentials,
26
- ),
27
- )
28
-
29
-
30
- @pytest.mark.xfail(
31
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE" not in os.environ,
32
- reason="GCP SA key file not set",
33
- )
34
- def test_service_account():
35
- credentials = get_credentials(
36
- settings=GoogleAuthSettings(
37
- type="service_account",
38
- service_account_file=os.environ[
39
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE"
40
- ],
41
- )
42
- )
43
- assert isinstance(credentials, google.oauth2.service_account.Credentials)
44
-
45
-
46
- @pytest.mark.xfail(
47
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE" not in os.environ,
48
- reason="GCP authorized user file not set",
49
- )
50
- def test_user_account():
51
- credentials = get_credentials(
52
- settings=GoogleAuthSettings(
53
- type="user_account",
54
- authorized_user_file=os.environ[
55
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE"
56
- ],
57
- scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
58
- )
59
- )
60
- assert isinstance(credentials, google.oauth2.credentials.Credentials)
61
-
62
-
63
- @pytest.mark.xfail(
64
- (
65
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE" not in os.environ
66
- or "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_IMPERSONATE_SA" not in os.environ
67
- ),
68
- reason="GCP SA key file not set",
69
- )
70
- def test_impersonate_service_account():
71
- credentials = get_credentials(
72
- settings=GoogleAuthSettings(
73
- type="service_account",
74
- service_account_file=os.environ[
75
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE"
76
- ],
77
- impersonate_service_account=os.environ[
78
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_IMPERSONATE_SA"
79
- ],
80
- scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
81
- )
82
- )
83
- assert isinstance(credentials, impersonated_credentials.Credentials)
@@ -1,22 +0,0 @@
1
- import os
2
-
3
- import pytest
4
-
5
- from kiarina.lib.google.auth import GoogleAuthSettings, get_self_signed_jwt
6
-
7
-
8
- @pytest.mark.xfail(
9
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE" not in os.environ,
10
- reason="GCP SA key file not set",
11
- )
12
- def test_get_self_signed_jwt():
13
- jwt = get_self_signed_jwt(
14
- settings=GoogleAuthSettings(
15
- type="service_account",
16
- service_account_file=os.environ[
17
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE"
18
- ],
19
- ),
20
- audience="https://blazeworks.jp/",
21
- )
22
- assert jwt.count(".") == 2
@@ -1,38 +0,0 @@
1
- import json
2
- import os
3
-
4
- import google.oauth2.service_account
5
- import pytest
6
-
7
- from kiarina.lib.google.auth import get_service_account_credentials
8
-
9
-
10
- @pytest.mark.xfail(
11
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE" not in os.environ,
12
- reason="GCP SA key file not set",
13
- )
14
- def test_file():
15
- credentials = get_service_account_credentials(
16
- service_account_file=os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE"]
17
- )
18
- assert isinstance(credentials, google.oauth2.service_account.Credentials)
19
-
20
-
21
- def test_nonexistent_file():
22
- with pytest.raises(ValueError, match="Service account file does not exist"):
23
- get_service_account_credentials(
24
- service_account_file="/path/to/nonexistent/file.json"
25
- )
26
-
27
-
28
- @pytest.mark.xfail(
29
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_DATA" not in os.environ,
30
- reason="GCP SA key data not set",
31
- )
32
- def test_data():
33
- credentials = get_service_account_credentials(
34
- service_account_data=json.loads(
35
- os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_DATA"]
36
- )
37
- )
38
- assert isinstance(credentials, google.oauth2.service_account.Credentials)
@@ -1,125 +0,0 @@
1
- import json
2
- import os
3
-
4
- from google.oauth2.credentials import Credentials
5
- import pytest
6
-
7
- from kiarina.lib.google.auth import CredentialsCache, get_user_account_credentials
8
-
9
-
10
- @pytest.mark.xfail(
11
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE" not in os.environ,
12
- reason="GCP authorized user file not set",
13
- )
14
- def test_file():
15
- credentials = get_user_account_credentials(
16
- authorized_user_file=os.environ[
17
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE"
18
- ],
19
- scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
20
- )
21
- assert isinstance(credentials, Credentials)
22
-
23
-
24
- def test_nonexistent_file():
25
- with pytest.raises(ValueError, match="Authorized user file does not exist"):
26
- get_user_account_credentials(
27
- authorized_user_file="/path/to/nonexistent/file.json",
28
- scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
29
- )
30
-
31
-
32
- @pytest.mark.xfail(
33
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA" not in os.environ,
34
- reason="GCP authorized user data not set",
35
- )
36
- def test_data():
37
- credentials = get_user_account_credentials(
38
- authorized_user_data=json.loads(
39
- os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA"]
40
- ),
41
- scopes=["https://www.googleapis.com/auth/devstorage.read_only"],
42
- )
43
- assert isinstance(credentials, Credentials)
44
-
45
-
46
- @pytest.mark.xfail(
47
- "KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA" not in os.environ,
48
- reason="GCP authorized user data not set",
49
- )
50
- def test_cache():
51
- from unittest.mock import patch, MagicMock
52
-
53
- class InMemoryCache(CredentialsCache):
54
- def __init__(self):
55
- self._cache: str | None = None
56
-
57
- def get(self) -> str | None:
58
- return self._cache
59
-
60
- def set(self, value: str) -> None:
61
- self._cache = value
62
-
63
- cache = InMemoryCache()
64
- scopes = ["https://www.googleapis.com/auth/devstorage.read_only"]
65
-
66
- # Mock Credentials to control valid/expired state
67
- with patch(
68
- "kiarina.lib.google.auth._utils.get_user_account_credentials.Credentials"
69
- ) as MockCredentials:
70
- # First call: credentials are invalid and need refresh
71
- mock_creds_invalid = MagicMock(spec=Credentials)
72
- mock_creds_invalid.valid = False
73
- mock_creds_invalid.expired = True
74
- mock_creds_invalid.refresh_token = "mock_refresh_token"
75
- mock_creds_invalid.to_json.return_value = json.dumps(
76
- {
77
- "type": "authorized_user",
78
- "client_id": "mock_client_id",
79
- "client_secret": "mock_client_secret",
80
- "refresh_token": "mock_refresh_token",
81
- }
82
- )
83
-
84
- # After refresh, credentials become valid
85
- def refresh_side_effect(_):
86
- mock_creds_invalid.valid = True
87
- mock_creds_invalid.expired = False
88
-
89
- mock_creds_invalid.refresh.side_effect = refresh_side_effect
90
-
91
- MockCredentials.from_authorized_user_info.return_value = mock_creds_invalid
92
-
93
- # First call: should refresh and cache
94
- credentials = get_user_account_credentials(
95
- authorized_user_data=json.loads(
96
- os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA"]
97
- ),
98
- scopes=scopes,
99
- cache=cache,
100
- )
101
-
102
- assert isinstance(credentials, MagicMock)
103
- assert credentials.valid is True
104
- assert cache.get() is not None
105
- mock_creds_invalid.refresh.assert_called_once()
106
-
107
- # Second call: should use cached credentials
108
- mock_creds_cached = MagicMock(spec=Credentials)
109
- mock_creds_cached.valid = True
110
- mock_creds_cached.expired = False
111
-
112
- MockCredentials.from_authorized_user_info.return_value = mock_creds_cached
113
-
114
- credentials2 = get_user_account_credentials(
115
- authorized_user_data=json.loads(
116
- os.environ["KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA"]
117
- ),
118
- scopes=scopes,
119
- cache=cache,
120
- )
121
-
122
- assert isinstance(credentials2, MagicMock)
123
- assert credentials2.valid is True
124
- # Cached credentials should not need refresh
125
- mock_creds_cached.refresh.assert_not_called()
@@ -12,6 +12,34 @@ class GoogleAuthSettings(BaseSettings):
12
12
 
13
13
  type: Literal["default", "service_account", "user_account"] = "default"
14
14
 
15
+ # --------------------------------------------------
16
+ # Fields (common)
17
+ # --------------------------------------------------
18
+
19
+ project_id: str | None = None
20
+
21
+ impersonate_service_account: str | None = None
22
+ """
23
+ Email address of the service account to impersonate
24
+
25
+ The source principal requires the roles/iam.serviceAccountTokenCreator role.
26
+ Note that this required permission is not included in the roles/owner role.
27
+ """
28
+
29
+ scopes: list[str] = Field(
30
+ default_factory=lambda: [
31
+ "https://www.googleapis.com/auth/cloud-platform", # All GCP resources
32
+ "https://www.googleapis.com/auth/drive", # Google Drive resources
33
+ "https://www.googleapis.com/auth/spreadsheets", # Google Sheets resources
34
+ ]
35
+ )
36
+ """
37
+ List of scopes to request during the authentication
38
+
39
+ Specify the scopes required for impersonation authentication.
40
+ Specify the scopes required for user account authentication.
41
+ """
42
+
15
43
  # --------------------------------------------------
16
44
  # Fields (service_account)
17
45
  # --------------------------------------------------
@@ -48,34 +76,6 @@ class GoogleAuthSettings(BaseSettings):
48
76
  Refreshed credentials will be cached.
49
77
  """
50
78
 
51
- # --------------------------------------------------
52
- # Fields (common)
53
- # --------------------------------------------------
54
-
55
- impersonate_service_account: str | None = None
56
- """
57
- Email address of the service account to impersonate
58
-
59
- The source principal requires the roles/iam.serviceAccountTokenCreator role.
60
- Note that this required permission is not included in the roles/owner role.
61
- """
62
-
63
- scopes: list[str] = Field(
64
- default_factory=lambda: [
65
- "https://www.googleapis.com/auth/cloud-platform", # All GCP resources
66
- "https://www.googleapis.com/auth/drive", # Google Drive resources
67
- "https://www.googleapis.com/auth/spreadsheets", # Google Sheets resources
68
- ]
69
- )
70
- """
71
- List of scopes to request during the authentication
72
-
73
- Specify the scopes required for impersonation authentication.
74
- Specify the scopes required for user account authentication.
75
- """
76
-
77
- project_id: str | None = None
78
-
79
79
  # --------------------------------------------------
80
80
  # Validators
81
81
  # --------------------------------------------------