legate 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +345 -0
- data/bin/legate +13 -0
- data/examples/00_quickstart.rb +51 -0
- data/examples/01_simple_agent.rb +105 -0
- data/examples/02_multi_tool_agent.rb +140 -0
- data/examples/03_custom_tool.rb +93 -0
- data/examples/04_agent_instructions.rb +84 -0
- data/examples/05_state_and_sessions.rb +91 -0
- data/examples/06_callbacks.rb +186 -0
- data/examples/07_async_jobs.rb +112 -0
- data/examples/08_loop_agent.rb +197 -0
- data/examples/09_sequential_workflow.rb +40 -0
- data/examples/10_parallel_workflow.rb +34 -0
- data/examples/11_agent_delegation.rb +24 -0
- data/examples/12_http_client_tool.rb +156 -0
- data/examples/13_authentication.rb +220 -0
- data/examples/14_mcp_client.rb +154 -0
- data/examples/15_mcp_server.rb +79 -0
- data/examples/16_webhooks.rb +91 -0
- data/examples/README_sequential_agents.md +164 -0
- data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
- data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
- data/examples/advanced/auth/excon_middleware.rb +317 -0
- data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
- data/examples/advanced/auth/fiber_auth_example.rb +281 -0
- data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
- data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
- data/examples/advanced/auth/oauth2_auth.rb +419 -0
- data/examples/advanced/auth/oidc_auth.rb +514 -0
- data/examples/advanced/auth/openweather_api.rb +251 -0
- data/examples/advanced/auth/openweather_tool.rb +153 -0
- data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
- data/examples/advanced/auth/service_account.rb +135 -0
- data/examples/advanced/auth/test_with_httpbin.rb +202 -0
- data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
- data/examples/advanced/callback_monitoring.rb +679 -0
- data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
- data/examples/advanced/mas/loop_workflow.rb +28 -0
- data/examples/advanced/mas/mock_planner.rb +77 -0
- data/examples/advanced/mas/proper_delegation_example.rb +276 -0
- data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
- data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
- data/examples/advanced/mcp/mcp_server_async.rb +76 -0
- data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
- data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
- data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
- data/examples/advanced/random_calculator.rb +104 -0
- data/examples/advanced/sleep_agent.rb +153 -0
- data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
- data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
- data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
- data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
- data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
- data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
- data/examples/tools/oauth2_example.rb +136 -0
- data/examples/tools/sleepy_tool.rb +42 -0
- data/lib/legate/activity_log.rb +71 -0
- data/lib/legate/agent.rb +959 -0
- data/lib/legate/agent_code_generator.rb +185 -0
- data/lib/legate/agent_definition.rb +812 -0
- data/lib/legate/agentic/decision.rb +49 -0
- data/lib/legate/agentic/loop.rb +134 -0
- data/lib/legate/agentic.rb +5 -0
- data/lib/legate/agents/loop_agent.rb +248 -0
- data/lib/legate/agents/parallel_agent.rb +163 -0
- data/lib/legate/agents/sequential_agent.rb +190 -0
- data/lib/legate/agents.rb +14 -0
- data/lib/legate/auth/config.rb +148 -0
- data/lib/legate/auth/coordinator.rb +218 -0
- data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
- data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
- data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
- data/lib/legate/auth/credential.rb +157 -0
- data/lib/legate/auth/encryption.rb +108 -0
- data/lib/legate/auth/error.rb +94 -0
- data/lib/legate/auth/exchanged_credential.rb +180 -0
- data/lib/legate/auth/excon_middleware.rb +285 -0
- data/lib/legate/auth/http_client_utils.rb +364 -0
- data/lib/legate/auth/manager.rb +531 -0
- data/lib/legate/auth/manager_store.rb +394 -0
- data/lib/legate/auth/middleware_factory.rb +290 -0
- data/lib/legate/auth/runner.rb +279 -0
- data/lib/legate/auth/scheme.rb +125 -0
- data/lib/legate/auth/schemes/api_key.rb +212 -0
- data/lib/legate/auth/schemes/google_service_account.rb +108 -0
- data/lib/legate/auth/schemes/http_bearer.rb +98 -0
- data/lib/legate/auth/schemes/oauth2.rb +396 -0
- data/lib/legate/auth/schemes/openid_connect.rb +346 -0
- data/lib/legate/auth/schemes/service_account.rb +388 -0
- data/lib/legate/auth/schemes.rb +40 -0
- data/lib/legate/auth/token_manager.rb +362 -0
- data/lib/legate/auth/token_store.rb +86 -0
- data/lib/legate/auth/tool_context_extension.rb +97 -0
- data/lib/legate/auth/tool_integration.rb +188 -0
- data/lib/legate/auth/url_guard.rb +81 -0
- data/lib/legate/auth.rb +453 -0
- data/lib/legate/callbacks/callback_context.rb +71 -0
- data/lib/legate/cli/agent_commands.rb +950 -0
- data/lib/legate/cli/auth_commands.rb +520 -0
- data/lib/legate/cli/base_command.rb +24 -0
- data/lib/legate/cli/deployment_commands.rb +934 -0
- data/lib/legate/cli/output_helper.rb +108 -0
- data/lib/legate/cli/session_commands.rb +138 -0
- data/lib/legate/cli/skaffold_commands.rb +223 -0
- data/lib/legate/cli/tool_commands.rb +261 -0
- data/lib/legate/cli/web_commands.rb +182 -0
- data/lib/legate/cli.rb +40 -0
- data/lib/legate/configuration/webhooks.rb +113 -0
- data/lib/legate/configuration.rb +39 -0
- data/lib/legate/definition_store.rb +23 -0
- data/lib/legate/errors.rb +118 -0
- data/lib/legate/event.rb +161 -0
- data/lib/legate/gemini_ai_beta_patch.rb +39 -0
- data/lib/legate/generators/agent_generator.rb +412 -0
- data/lib/legate/generators/code_validator.rb +48 -0
- data/lib/legate/generators/legate/install_generator.rb +35 -0
- data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
- data/lib/legate/generators/legate/templates/initializer.rb +18 -0
- data/lib/legate/generators/runtime_tool_loader.rb +76 -0
- data/lib/legate/generators/tool_generator.rb +408 -0
- data/lib/legate/generators.rb +11 -0
- data/lib/legate/global_definition_registry.rb +506 -0
- data/lib/legate/global_tool_manager.rb +135 -0
- data/lib/legate/llm/adapter.rb +69 -0
- data/lib/legate/llm/gemini.rb +172 -0
- data/lib/legate/llm/ollama.rb +80 -0
- data/lib/legate/llm.rb +34 -0
- data/lib/legate/mcp/client.rb +320 -0
- data/lib/legate/mcp/connection/sse.rb +292 -0
- data/lib/legate/mcp/connection/stdio.rb +273 -0
- data/lib/legate/mcp/connection_manager.rb +103 -0
- data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
- data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
- data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
- data/lib/legate/mcp/tool_wrapper.rb +138 -0
- data/lib/legate/mcp/util/schema_converter.rb +134 -0
- data/lib/legate/mcp.rb +23 -0
- data/lib/legate/plan_executor.rb +375 -0
- data/lib/legate/planner.rb +839 -0
- data/lib/legate/rails/railtie.rb +43 -0
- data/lib/legate/rails.rb +9 -0
- data/lib/legate/redaction.rb +32 -0
- data/lib/legate/session.rb +299 -0
- data/lib/legate/session_service/active_record.rb +300 -0
- data/lib/legate/session_service/base.rb +68 -0
- data/lib/legate/session_service/event_broadcast.rb +74 -0
- data/lib/legate/session_service/in_memory.rb +188 -0
- data/lib/legate/tool/metadata_dsl.rb +122 -0
- data/lib/legate/tool.rb +276 -0
- data/lib/legate/tool_code_generator.rb +103 -0
- data/lib/legate/tool_context.rb +350 -0
- data/lib/legate/tool_loader.rb +39 -0
- data/lib/legate/tool_registry.rb +73 -0
- data/lib/legate/tool_result.rb +61 -0
- data/lib/legate/tools/agent_tool.rb +187 -0
- data/lib/legate/tools/base/http_client.rb +319 -0
- data/lib/legate/tools/base/safe_url.rb +56 -0
- data/lib/legate/tools/base_async_job_tool.rb +91 -0
- data/lib/legate/tools/calculator.rb +89 -0
- data/lib/legate/tools/cat_facts.rb +81 -0
- data/lib/legate/tools/check_job_status_tool.rb +48 -0
- data/lib/legate/tools/current_time_tool.rb +64 -0
- data/lib/legate/tools/echo.rb +43 -0
- data/lib/legate/tools/http_request_tool.rb +105 -0
- data/lib/legate/tools/random_number_tool.rb +64 -0
- data/lib/legate/tools/read_webpage_tool.rb +92 -0
- data/lib/legate/tools/sleepy_tool.rb +74 -0
- data/lib/legate/tools/webhook_tool.rb +146 -0
- data/lib/legate/version.rb +5 -0
- data/lib/legate/web/app.rb +984 -0
- data/lib/legate/web/public/css/main.css +4980 -0
- data/lib/legate/web/public/images/favicon-256.png +0 -0
- data/lib/legate/web/public/images/favicon-32.png +0 -0
- data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
- data/lib/legate/web/public/images/legate-logo-light.png +0 -0
- data/lib/legate/web/public/js/legate.js +616 -0
- data/lib/legate/web/public/styles/main.scss +4402 -0
- data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
- data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
- data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
- data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
- data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
- data/lib/legate/web/routes/api_routes.rb +56 -0
- data/lib/legate/web/routes/authentication_routes.rb +1541 -0
- data/lib/legate/web/routes/core_routes.rb +111 -0
- data/lib/legate/web/routes/documentation_routes.rb +220 -0
- data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
- data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
- data/lib/legate/web/sass_compiler.rb +73 -0
- data/lib/legate/web/views/_active_session_info.slim +25 -0
- data/lib/legate/web/views/_activity_list.slim +55 -0
- data/lib/legate/web/views/_agent_card.slim +56 -0
- data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
- data/lib/legate/web/views/_agent_status_controls.slim +71 -0
- data/lib/legate/web/views/_agent_tool_table.slim +74 -0
- data/lib/legate/web/views/_chat_message.slim +95 -0
- data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
- data/lib/legate/web/views/_display_agent_description.slim +11 -0
- data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
- data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
- data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
- data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
- data/lib/legate/web/views/_display_agent_model.slim +17 -0
- data/lib/legate/web/views/_display_agent_name.slim +42 -0
- data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
- data/lib/legate/web/views/_display_agent_type.slim +65 -0
- data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
- data/lib/legate/web/views/_edit_agent_description.slim +16 -0
- data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
- data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
- data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
- data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
- data/lib/legate/web/views/_edit_agent_model.slim +23 -0
- data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
- data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
- data/lib/legate/web/views/_edit_agent_type.slim +67 -0
- data/lib/legate/web/views/_session_error.slim +4 -0
- data/lib/legate/web/views/_skeleton.slim +69 -0
- data/lib/legate/web/views/_tool_card.slim +9 -0
- data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
- data/lib/legate/web/views/agent.slim +436 -0
- data/lib/legate/web/views/agent_auth.slim +562 -0
- data/lib/legate/web/views/agents.slim +369 -0
- data/lib/legate/web/views/auth.slim +112 -0
- data/lib/legate/web/views/auth_credential_detail.slim +327 -0
- data/lib/legate/web/views/auth_credentials.slim +261 -0
- data/lib/legate/web/views/auth_debug.slim +94 -0
- data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
- data/lib/legate/web/views/auth_mapping_new.slim +123 -0
- data/lib/legate/web/views/auth_mappings.slim +120 -0
- data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
- data/lib/legate/web/views/auth_schemes.slim +259 -0
- data/lib/legate/web/views/auth_test.slim +418 -0
- data/lib/legate/web/views/chat.slim +192 -0
- data/lib/legate/web/views/docs_index.slim +105 -0
- data/lib/legate/web/views/docs_show.slim +105 -0
- data/lib/legate/web/views/error_404.slim +5 -0
- data/lib/legate/web/views/index.slim +148 -0
- data/lib/legate/web/views/layout.slim +144 -0
- data/lib/legate/web/views/tool_detail.slim +87 -0
- data/lib/legate/web/views/tools.slim +50 -0
- data/lib/legate/web/webhook_listener.rb +367 -0
- data/lib/legate/web.rb +9 -0
- data/lib/legate.rb +220 -0
- data/public/docs/advanced/callbacks.md +828 -0
- data/public/docs/advanced/mcp_schema_conversion.md +59 -0
- data/public/docs/authentication/api_reference/config.md +210 -0
- data/public/docs/authentication/api_reference/credential.md +246 -0
- data/public/docs/authentication/api_reference/encryption.md +218 -0
- data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
- data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
- data/public/docs/authentication/api_reference/index.md +30 -0
- data/public/docs/authentication/api_reference/scheme.md +250 -0
- data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
- data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
- data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
- data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
- data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
- data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
- data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
- data/public/docs/authentication/api_reference/token_manager.md +221 -0
- data/public/docs/authentication/api_reference/token_store.md +146 -0
- data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
- data/public/docs/authentication/guides/api_key.md +190 -0
- data/public/docs/authentication/guides/bearer.md +172 -0
- data/public/docs/authentication/guides/configuration.md +255 -0
- data/public/docs/authentication/guides/custom_flow.md +523 -0
- data/public/docs/authentication/guides/index.md +24 -0
- data/public/docs/authentication/guides/migration.md +435 -0
- data/public/docs/authentication/guides/oauth2.md +252 -0
- data/public/docs/authentication/guides/oidc.md +241 -0
- data/public/docs/authentication/guides/overview.md +155 -0
- data/public/docs/authentication/guides/secure_storage.md +301 -0
- data/public/docs/authentication/guides/service_account.md +228 -0
- data/public/docs/authentication/guides/token_lifecycle.md +295 -0
- data/public/docs/authentication/guides/web_ui_integration.md +504 -0
- data/public/docs/authentication/index.md +58 -0
- data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
- data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
- data/public/docs/authentication/troubleshooting/index.md +11 -0
- data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
- data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
- data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
- data/public/docs/cli/legate_cli_usage.md +363 -0
- data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
- data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
- data/public/docs/core_concepts/legate_configuration.md +116 -0
- data/public/docs/core_concepts/legate_definition_store.md +102 -0
- data/public/docs/core_concepts/legate_planner.md +94 -0
- data/public/docs/core_concepts/legate_session_service.md +104 -0
- data/public/docs/error_handling/legate_error_handling.md +122 -0
- data/public/docs/examples.md +199 -0
- data/public/docs/getting_started.md +111 -0
- data/public/docs/guides/agentic_agents.md +137 -0
- data/public/docs/guides/ai_code_generators.md +437 -0
- data/public/docs/guides/auto_loading.md +326 -0
- data/public/docs/guides/configuring_agent_webhooks.md +219 -0
- data/public/docs/guides/http_client_usage.md +264 -0
- data/public/docs/guides/llm_providers.md +137 -0
- data/public/docs/guides/mcp_client_integration.md +232 -0
- data/public/docs/guides/mcp_server_exposure.md +206 -0
- data/public/docs/guides/rails_integration.md +128 -0
- data/public/docs/guides/sending_outbound_webhooks.md +227 -0
- data/public/docs/guides/streaming.md +112 -0
- data/public/docs/guides/webhooks.md +288 -0
- data/public/docs/introduction.md +51 -0
- data/public/docs/multi_agent_systems/advanced_features.md +57 -0
- data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
- data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
- data/public/docs/multi_agent_systems/state_management.md +47 -0
- data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
- data/public/docs/tools/legate_built_in_tools.md +332 -0
- data/public/docs/tools/legate_tools_and_registry.md +263 -0
- data/public/docs/web_ui/legate_web_ui.md +137 -0
- metadata +823 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
# File: lib/legate/auth/manager.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'singleton'
|
|
5
|
+
require_relative '../errors'
|
|
6
|
+
require_relative 'error'
|
|
7
|
+
require_relative 'credential'
|
|
8
|
+
require_relative 'manager_store'
|
|
9
|
+
require_relative 'schemes/api_key'
|
|
10
|
+
require_relative 'schemes/http_bearer'
|
|
11
|
+
require_relative 'schemes/oauth2'
|
|
12
|
+
require_relative 'schemes/openid_connect'
|
|
13
|
+
require_relative 'schemes/service_account'
|
|
14
|
+
require_relative 'schemes/google_service_account'
|
|
15
|
+
|
|
16
|
+
module Legate
|
|
17
|
+
module Auth
|
|
18
|
+
# The AuthManager is a singleton that manages authentication schemes and credentials.
|
|
19
|
+
# It provides a centralized registry for authentication schemes and credentials,
|
|
20
|
+
# as well as methods for finding the appropriate scheme and credential for a given URL.
|
|
21
|
+
class Manager
|
|
22
|
+
include Singleton
|
|
23
|
+
|
|
24
|
+
# @return [Legate::Auth::ManagerStore::RedisStore, Legate::Auth::ManagerStore::InMemoryStore, nil]
|
|
25
|
+
attr_reader :store
|
|
26
|
+
|
|
27
|
+
# Read access to the registered schemes/credentials/url-mappings. Exposed so
|
|
28
|
+
# callers (e.g. the web routes) don't reach in via instance_variable_get.
|
|
29
|
+
# @return [Hash{Symbol => Legate::Auth::Scheme}]
|
|
30
|
+
attr_reader :schemes
|
|
31
|
+
# @return [Hash{Symbol => Legate::Auth::Credential}]
|
|
32
|
+
attr_reader :credentials
|
|
33
|
+
# @return [Array<Hash>]
|
|
34
|
+
attr_reader :url_mappings
|
|
35
|
+
|
|
36
|
+
def initialize
|
|
37
|
+
@schemes = {}
|
|
38
|
+
@credentials = {}
|
|
39
|
+
@url_mappings = []
|
|
40
|
+
@store = nil
|
|
41
|
+
@loaded_from_store = false
|
|
42
|
+
|
|
43
|
+
# Register built-in schemes
|
|
44
|
+
register_default_schemes
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Set the persistence store and load existing data
|
|
48
|
+
# @param store [Legate::Auth::ManagerStore::RedisStore, Legate::Auth::ManagerStore::InMemoryStore]
|
|
49
|
+
# @param load_immediately [Boolean] Whether to load data from store immediately (default: true)
|
|
50
|
+
def set_store(store, load_immediately: true)
|
|
51
|
+
@store = store
|
|
52
|
+
load_from_store if load_immediately && store&.available?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Load all schemes, credentials, and URL mappings from the store
|
|
56
|
+
# @return [Boolean] true if successful
|
|
57
|
+
def load_from_store
|
|
58
|
+
return false unless @store&.available?
|
|
59
|
+
return true if @loaded_from_store # Don't reload if already loaded
|
|
60
|
+
|
|
61
|
+
Legate.logger&.info('Loading authentication configuration from store...')
|
|
62
|
+
|
|
63
|
+
# Load credentials first (schemes might depend on them for URL mappings)
|
|
64
|
+
load_credentials_from_store
|
|
65
|
+
|
|
66
|
+
# Load schemes (will overwrite defaults with stored config)
|
|
67
|
+
load_schemes_from_store
|
|
68
|
+
|
|
69
|
+
# Load URL mappings
|
|
70
|
+
load_url_mappings_from_store
|
|
71
|
+
|
|
72
|
+
@loaded_from_store = true
|
|
73
|
+
Legate.logger&.info('Authentication configuration loaded from store.')
|
|
74
|
+
true
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
Legate.logger&.error("Failed to load auth config from store: #{e.message}")
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Force reload from store (useful after external changes)
|
|
81
|
+
def reload_from_store
|
|
82
|
+
@loaded_from_store = false
|
|
83
|
+
load_from_store
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Register an authentication scheme
|
|
87
|
+
# @param scheme [Legate::Auth::Scheme] The scheme to register
|
|
88
|
+
# @param name [Symbol, String] Optional name for the scheme (defaults to scheme type)
|
|
89
|
+
# @param persist [Boolean] Whether to persist to store (default: true)
|
|
90
|
+
# @return [Symbol] The name the scheme was registered under
|
|
91
|
+
def register_scheme(scheme, name = nil, persist: true)
|
|
92
|
+
raise ArgumentError, 'Scheme must be an Legate::Auth::Scheme' unless scheme.is_a?(Legate::Auth::Scheme)
|
|
93
|
+
|
|
94
|
+
# Use scheme type as name if not provided
|
|
95
|
+
name ||= scheme.scheme_type
|
|
96
|
+
name = name.to_sym
|
|
97
|
+
|
|
98
|
+
@schemes[name] = scheme
|
|
99
|
+
|
|
100
|
+
# Persist to store if available and persistence is enabled
|
|
101
|
+
@store&.save_scheme(name, scheme) if persist && @store&.available?
|
|
102
|
+
|
|
103
|
+
name
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Unregister/delete a scheme
|
|
107
|
+
# @param name [Symbol, String] The scheme name
|
|
108
|
+
# @param persist [Boolean] Whether to persist the deletion (default: true)
|
|
109
|
+
# @return [Boolean] true if deleted
|
|
110
|
+
def unregister_scheme(name, persist: true)
|
|
111
|
+
name = name.to_sym
|
|
112
|
+
deleted = @schemes.delete(name)
|
|
113
|
+
|
|
114
|
+
@store&.delete_scheme(name) if persist && deleted && @store&.available?
|
|
115
|
+
|
|
116
|
+
!deleted.nil?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Register a credential
|
|
120
|
+
# @param credential [Legate::Auth::Credential] The credential to register
|
|
121
|
+
# @param name [Symbol, String] The name to register the credential under
|
|
122
|
+
# @param persist [Boolean] Whether to persist to store (default: true)
|
|
123
|
+
# @return [Symbol] The name the credential was registered under
|
|
124
|
+
def register_credential(credential, name, persist: true)
|
|
125
|
+
raise ArgumentError, 'Credential must be an Legate::Auth::Credential' unless credential.is_a?(Legate::Auth::Credential)
|
|
126
|
+
raise ArgumentError, 'Name must be provided' if name.nil?
|
|
127
|
+
|
|
128
|
+
name = name.to_sym
|
|
129
|
+
@credentials[name] = credential
|
|
130
|
+
|
|
131
|
+
# Persist to store if available and persistence is enabled
|
|
132
|
+
@store&.save_credential(name, credential) if persist && @store&.available?
|
|
133
|
+
|
|
134
|
+
name
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Unregister/delete a credential
|
|
138
|
+
# @param name [Symbol, String] The credential name
|
|
139
|
+
# @param persist [Boolean] Whether to persist the deletion (default: true)
|
|
140
|
+
# @return [Boolean] true if deleted
|
|
141
|
+
def unregister_credential(name, persist: true)
|
|
142
|
+
name = name.to_sym
|
|
143
|
+
deleted = @credentials.delete(name)
|
|
144
|
+
|
|
145
|
+
@store&.delete_credential(name) if persist && deleted && @store&.available?
|
|
146
|
+
|
|
147
|
+
!deleted.nil?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Register a URL mapping to a scheme and credential
|
|
151
|
+
# @param url_pattern [String, Regexp] The URL pattern to match
|
|
152
|
+
# @param scheme_name [Symbol, String] The name of the scheme to use
|
|
153
|
+
# @param credential_name [Symbol, String] The name of the credential to use
|
|
154
|
+
# @param persist [Boolean] Whether to persist to store (default: true)
|
|
155
|
+
def register_url_mapping(url_pattern, scheme_name, credential_name, persist: true)
|
|
156
|
+
scheme_name = scheme_name.to_sym
|
|
157
|
+
credential_name = credential_name.to_sym
|
|
158
|
+
|
|
159
|
+
raise ArgumentError, "Unknown scheme: #{scheme_name}" unless @schemes.key?(scheme_name)
|
|
160
|
+
|
|
161
|
+
raise ArgumentError, "Unknown credential: #{credential_name}" unless @credentials.key?(credential_name)
|
|
162
|
+
|
|
163
|
+
@url_mappings << {
|
|
164
|
+
pattern: url_pattern,
|
|
165
|
+
scheme_name: scheme_name,
|
|
166
|
+
credential_name: credential_name
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# Persist all URL mappings to store
|
|
170
|
+
@store&.save_url_mappings(@url_mappings) if persist && @store&.available?
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Remove a URL mapping by index
|
|
174
|
+
# @param index [Integer] The index of the mapping to remove
|
|
175
|
+
# @param persist [Boolean] Whether to persist the deletion (default: true)
|
|
176
|
+
# @return [Boolean] true if removed
|
|
177
|
+
def remove_url_mapping(index, persist: true)
|
|
178
|
+
return false if index < 0 || index >= @url_mappings.size
|
|
179
|
+
|
|
180
|
+
@url_mappings.delete_at(index)
|
|
181
|
+
|
|
182
|
+
# Persist all URL mappings to store
|
|
183
|
+
@store&.save_url_mappings(@url_mappings) if persist && @store&.available?
|
|
184
|
+
|
|
185
|
+
true
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Replaces the full set of URL mappings and persists them. Used by the web
|
|
189
|
+
# UI, which manages a richer mapping shape (pattern/priority/active) than
|
|
190
|
+
# register_url_mapping and edits the array in place before saving.
|
|
191
|
+
# @param mappings [Array<Hash>] the new mapping set
|
|
192
|
+
# @param persist [Boolean] whether to persist (default: true)
|
|
193
|
+
# @return [Array<Hash>] the stored mappings
|
|
194
|
+
def replace_url_mappings(mappings, persist: true)
|
|
195
|
+
@url_mappings = mappings
|
|
196
|
+
@store&.save_url_mappings(@url_mappings) if persist && @store&.available?
|
|
197
|
+
@url_mappings
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Get a registered scheme
|
|
201
|
+
# @param name [Symbol, String] The name of the scheme
|
|
202
|
+
# @return [Legate::Auth::Scheme, nil] The scheme or nil if not found
|
|
203
|
+
def get_scheme(name)
|
|
204
|
+
@schemes[name.to_sym]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Get a registered credential
|
|
208
|
+
# @param name [Symbol, String] The name of the credential
|
|
209
|
+
# @return [Legate::Auth::Credential, nil] The credential or nil if not found
|
|
210
|
+
def get_credential(name)
|
|
211
|
+
@credentials[name.to_sym]
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Find a scheme by type without requiring credentials
|
|
215
|
+
# @param scheme_type [Symbol, String] The scheme type to find
|
|
216
|
+
# @return [Legate::Auth::Scheme, nil] The scheme or nil if not found
|
|
217
|
+
def find_scheme(scheme_type)
|
|
218
|
+
scheme_sym = scheme_type.to_sym
|
|
219
|
+
|
|
220
|
+
# Try to find by exact scheme_type match first
|
|
221
|
+
scheme = @schemes.values.find { |s| s.scheme_type == scheme_sym }
|
|
222
|
+
|
|
223
|
+
# If not found by scheme_type, try to find by registration name
|
|
224
|
+
# This handles cases like :oidc -> OpenIDConnect where scheme_type is :openid_connect
|
|
225
|
+
scheme ||= @schemes[scheme_sym]
|
|
226
|
+
|
|
227
|
+
# Special mappings for backward compatibility and aliases
|
|
228
|
+
if scheme.nil?
|
|
229
|
+
scheme_mappings = {
|
|
230
|
+
oidc: :openid_connect,
|
|
231
|
+
openid_connect: :oidc
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
# Try the mapped scheme type
|
|
235
|
+
mapped_type = scheme_mappings[scheme_sym]
|
|
236
|
+
if mapped_type
|
|
237
|
+
scheme = @schemes.values.find { |s| s.scheme_type == mapped_type } ||
|
|
238
|
+
@schemes[mapped_type]
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
scheme
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Find the appropriate scheme and credential for a URL
|
|
246
|
+
# @param url [String] The URL to find a scheme and credential for
|
|
247
|
+
# @param scheme_type [Symbol, nil] Optional scheme type to filter by
|
|
248
|
+
# @param credential_name [Symbol, String, nil] Optional credential name to use
|
|
249
|
+
# @return [Array<Legate::Auth::Scheme, Legate::Auth::Credential>, nil] The scheme and credential, or nil if not found
|
|
250
|
+
def find_scheme_and_credential(url: nil, scheme_type: nil, credential_name: nil)
|
|
251
|
+
# Case 1: Direct credential and matching scheme specified
|
|
252
|
+
if credential_name
|
|
253
|
+
credential = get_credential(credential_name)
|
|
254
|
+
return nil unless credential
|
|
255
|
+
|
|
256
|
+
if scheme_type
|
|
257
|
+
# Find scheme of the specified type
|
|
258
|
+
scheme = @schemes.values.find { |s| s.scheme_type == scheme_type.to_sym }
|
|
259
|
+
return [scheme, credential] if scheme
|
|
260
|
+
else
|
|
261
|
+
# Try to find a compatible scheme for this credential
|
|
262
|
+
scheme = find_compatible_scheme(credential)
|
|
263
|
+
return [scheme, credential] if scheme
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Case 2: URL matching
|
|
268
|
+
if url
|
|
269
|
+
found_mapping = @url_mappings.find do |mapping|
|
|
270
|
+
pattern = mapping[:pattern]
|
|
271
|
+
|
|
272
|
+
# Check if URL matches the pattern
|
|
273
|
+
(pattern.is_a?(Regexp) && url =~ pattern) ||
|
|
274
|
+
(pattern.is_a?(String) && url.include?(pattern))
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
if found_mapping
|
|
278
|
+
scheme = get_scheme(found_mapping[:scheme_name])
|
|
279
|
+
credential = get_credential(found_mapping[:credential_name])
|
|
280
|
+
|
|
281
|
+
# Skip if we're filtering by scheme_type and it doesn't match
|
|
282
|
+
return nil if scheme_type && scheme.scheme_type != scheme_type.to_sym
|
|
283
|
+
|
|
284
|
+
return [scheme, credential] if scheme && credential
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# No matching URL mapping found, if a URL was provided and no mapping matched
|
|
288
|
+
# but scheme_type was specified, we shouldn't continue to Case 3
|
|
289
|
+
return nil if scheme_type && url
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Case 3: Just trying to find by scheme_type with any credential
|
|
293
|
+
if scheme_type
|
|
294
|
+
scheme_sym = scheme_type.to_sym
|
|
295
|
+
|
|
296
|
+
# Try to find by exact scheme_type match first
|
|
297
|
+
scheme = @schemes.values.find { |s| s.scheme_type == scheme_sym }
|
|
298
|
+
|
|
299
|
+
# If not found by scheme_type, try to find by registration name
|
|
300
|
+
# This handles cases like :oidc -> OpenIDConnect where scheme_type is :openid_connect
|
|
301
|
+
scheme ||= @schemes[scheme_sym]
|
|
302
|
+
|
|
303
|
+
# Special mappings for backward compatibility and aliases
|
|
304
|
+
if scheme.nil?
|
|
305
|
+
scheme_mappings = {
|
|
306
|
+
oidc: :openid_connect,
|
|
307
|
+
openid_connect: :oidc
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
# Try the mapped scheme type
|
|
311
|
+
mapped_type = scheme_mappings[scheme_sym]
|
|
312
|
+
if mapped_type
|
|
313
|
+
scheme = @schemes.values.find { |s| s.scheme_type == mapped_type } ||
|
|
314
|
+
@schemes[mapped_type]
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
return nil unless scheme
|
|
319
|
+
|
|
320
|
+
# Find any compatible credential
|
|
321
|
+
@credentials.each_value do |cred|
|
|
322
|
+
return [scheme, cred] if credential_compatible_with_scheme?(cred, scheme)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
nil
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
private
|
|
330
|
+
|
|
331
|
+
# Register the default built-in schemes
|
|
332
|
+
def register_default_schemes
|
|
333
|
+
register_scheme(Legate::Auth::Schemes::ApiKey.new, :api_key)
|
|
334
|
+
register_scheme(Legate::Auth::Schemes::HTTPBearer.new, :http_bearer)
|
|
335
|
+
|
|
336
|
+
# Set default values for OAuth2 and other schemes regardless of environment
|
|
337
|
+
oauth2 = Legate::Auth::Schemes::OAuth2.new(
|
|
338
|
+
authorization_url: 'https://example.com/oauth/authorize',
|
|
339
|
+
token_url: 'https://example.com/oauth/token'
|
|
340
|
+
)
|
|
341
|
+
register_scheme(oauth2, :oauth2)
|
|
342
|
+
|
|
343
|
+
oidc = Legate::Auth::Schemes::OpenIDConnect.new(
|
|
344
|
+
authorization_url: 'https://example.com/oidc/authorize',
|
|
345
|
+
token_url: 'https://example.com/oidc/token'
|
|
346
|
+
)
|
|
347
|
+
register_scheme(oidc, :oidc)
|
|
348
|
+
|
|
349
|
+
# Set test environment before creating service account schemes
|
|
350
|
+
# This allows the schemes to be created without requiring real credentials
|
|
351
|
+
original_env = ENV['RSPEC_ENV']
|
|
352
|
+
ENV['RSPEC_ENV'] = 'test'
|
|
353
|
+
|
|
354
|
+
begin
|
|
355
|
+
service_account = Legate::Auth::Schemes::ServiceAccount.new(
|
|
356
|
+
token_url: 'https://example.com/token'
|
|
357
|
+
)
|
|
358
|
+
register_scheme(service_account, :service_account)
|
|
359
|
+
|
|
360
|
+
google_service_account = Legate::Auth::Schemes::GoogleServiceAccount.new(
|
|
361
|
+
scopes: ['https://www.googleapis.com/auth/cloud-platform']
|
|
362
|
+
)
|
|
363
|
+
register_scheme(google_service_account, :google_service_account)
|
|
364
|
+
ensure
|
|
365
|
+
# Restore original environment
|
|
366
|
+
if original_env
|
|
367
|
+
ENV['RSPEC_ENV'] = original_env
|
|
368
|
+
else
|
|
369
|
+
ENV.delete('RSPEC_ENV')
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# Find a compatible scheme for a credential
|
|
375
|
+
# @param credential [Legate::Auth::Credential] The credential
|
|
376
|
+
# @return [Legate::Auth::Scheme, nil] A compatible scheme or nil
|
|
377
|
+
def find_compatible_scheme(credential)
|
|
378
|
+
@schemes.each_value do |scheme|
|
|
379
|
+
return scheme if credential_compatible_with_scheme?(credential, scheme)
|
|
380
|
+
end
|
|
381
|
+
nil
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Check if a credential is compatible with a scheme
|
|
385
|
+
# @param credential [Legate::Auth::Credential] The credential
|
|
386
|
+
# @param scheme [Legate::Auth::Scheme] The scheme
|
|
387
|
+
# @return [Boolean] True if compatible
|
|
388
|
+
def credential_compatible_with_scheme?(credential, scheme)
|
|
389
|
+
scheme_type = scheme.scheme_type
|
|
390
|
+
|
|
391
|
+
case scheme_type
|
|
392
|
+
when :api_key
|
|
393
|
+
credential[:api_key, resolve_env: false]
|
|
394
|
+
when :http_bearer
|
|
395
|
+
# Check for bearer token or basic auth credentials
|
|
396
|
+
credential[:bearer_token, resolve_env: false] ||
|
|
397
|
+
(credential[:username, resolve_env: false] && credential[:password, resolve_env: false])
|
|
398
|
+
when :oauth2, :oidc, :openid_connect
|
|
399
|
+
credential[:client_id, resolve_env: false] &&
|
|
400
|
+
credential[:client_secret, resolve_env: false]
|
|
401
|
+
when :service_account, :google_service_account
|
|
402
|
+
# For service accounts, check for either service_account_key or individual fields
|
|
403
|
+
credential[:service_account_key, resolve_env: false] ||
|
|
404
|
+
(credential[:client_email, resolve_env: false] &&
|
|
405
|
+
credential[:private_key, resolve_env: false])
|
|
406
|
+
when :basic
|
|
407
|
+
credential[:username, resolve_env: false] &&
|
|
408
|
+
credential[:password, resolve_env: false]
|
|
409
|
+
else
|
|
410
|
+
false
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Load credentials from store
|
|
415
|
+
def load_credentials_from_store
|
|
416
|
+
return unless @store&.available?
|
|
417
|
+
|
|
418
|
+
stored_credentials = @store.load_all_credentials
|
|
419
|
+
stored_credentials.each do |name, data|
|
|
420
|
+
credential = deserialize_credential(data)
|
|
421
|
+
@credentials[name] = credential if credential
|
|
422
|
+
rescue StandardError => e
|
|
423
|
+
Legate.logger&.warn("Failed to load credential '#{name}': #{e.message}")
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
Legate.logger&.debug("Loaded #{stored_credentials.size} credentials from store")
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Load schemes from store
|
|
430
|
+
def load_schemes_from_store
|
|
431
|
+
return unless @store&.available?
|
|
432
|
+
|
|
433
|
+
stored_schemes = @store.load_all_schemes
|
|
434
|
+
stored_schemes.each do |name, data|
|
|
435
|
+
scheme = deserialize_scheme(data)
|
|
436
|
+
@schemes[name] = scheme if scheme
|
|
437
|
+
rescue StandardError => e
|
|
438
|
+
Legate.logger&.warn("Failed to load scheme '#{name}': #{e.message}")
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
Legate.logger&.debug("Loaded #{stored_schemes.size} schemes from store")
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# Load URL mappings from store
|
|
445
|
+
def load_url_mappings_from_store
|
|
446
|
+
return unless @store&.available?
|
|
447
|
+
|
|
448
|
+
@url_mappings = @store.load_url_mappings
|
|
449
|
+
Legate.logger&.debug("Loaded #{@url_mappings.size} URL mappings from store")
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Deserialize a credential from stored data
|
|
453
|
+
# @param data [Hash] The stored credential data
|
|
454
|
+
# @return [Legate::Auth::Credential, nil]
|
|
455
|
+
def deserialize_credential(data)
|
|
456
|
+
return nil unless data && data[:auth_type]
|
|
457
|
+
|
|
458
|
+
auth_type = data[:auth_type].to_sym
|
|
459
|
+
attributes = data.reject { |k, _| k == :auth_type }
|
|
460
|
+
|
|
461
|
+
Legate::Auth::Credential.new(auth_type: auth_type, **attributes)
|
|
462
|
+
rescue StandardError => e
|
|
463
|
+
Legate.logger&.warn("Failed to deserialize credential: #{e.message}")
|
|
464
|
+
nil
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
# Deserialize a scheme from stored data
|
|
468
|
+
# @param data [Hash] The stored scheme data
|
|
469
|
+
# @return [Legate::Auth::Scheme, nil]
|
|
470
|
+
def deserialize_scheme(data)
|
|
471
|
+
return nil unless data && data[:scheme_type]
|
|
472
|
+
|
|
473
|
+
scheme_type = data[:scheme_type].to_sym
|
|
474
|
+
|
|
475
|
+
case scheme_type
|
|
476
|
+
when :api_key
|
|
477
|
+
Legate::Auth::Schemes::ApiKey.new(
|
|
478
|
+
header_name: data[:header_name],
|
|
479
|
+
query_param_name: data[:query_param_name],
|
|
480
|
+
location: data[:location]&.to_sym
|
|
481
|
+
)
|
|
482
|
+
when :http_bearer
|
|
483
|
+
Legate::Auth::Schemes::HTTPBearer.new
|
|
484
|
+
when :oauth2
|
|
485
|
+
Legate::Auth::Schemes::OAuth2.new(
|
|
486
|
+
authorization_url: data[:authorization_url] || 'https://example.com/oauth/authorize',
|
|
487
|
+
token_url: data[:token_url] || 'https://example.com/oauth/token',
|
|
488
|
+
scopes: data[:scopes],
|
|
489
|
+
use_pkce: data[:use_pkce],
|
|
490
|
+
revocation_url: data[:revocation_url]
|
|
491
|
+
)
|
|
492
|
+
when :openid_connect, :oidc
|
|
493
|
+
Legate::Auth::Schemes::OpenIDConnect.new(
|
|
494
|
+
authorization_url: data[:authorization_url] || 'https://example.com/oidc/authorize',
|
|
495
|
+
token_url: data[:token_url] || 'https://example.com/oidc/token',
|
|
496
|
+
scopes: data[:scopes],
|
|
497
|
+
use_pkce: data[:use_pkce],
|
|
498
|
+
revocation_url: data[:revocation_url]
|
|
499
|
+
)
|
|
500
|
+
when :service_account
|
|
501
|
+
# Temporarily set test env to allow scheme creation without real credentials
|
|
502
|
+
original_env = ENV['RSPEC_ENV']
|
|
503
|
+
ENV['RSPEC_ENV'] = 'test'
|
|
504
|
+
begin
|
|
505
|
+
Legate::Auth::Schemes::ServiceAccount.new(
|
|
506
|
+
token_url: data[:token_url] || 'https://example.com/token'
|
|
507
|
+
)
|
|
508
|
+
ensure
|
|
509
|
+
original_env ? ENV['RSPEC_ENV'] = original_env : ENV.delete('RSPEC_ENV')
|
|
510
|
+
end
|
|
511
|
+
when :google_service_account
|
|
512
|
+
original_env = ENV['RSPEC_ENV']
|
|
513
|
+
ENV['RSPEC_ENV'] = 'test'
|
|
514
|
+
begin
|
|
515
|
+
Legate::Auth::Schemes::GoogleServiceAccount.new(
|
|
516
|
+
scopes: data[:scopes] || ['https://www.googleapis.com/auth/cloud-platform']
|
|
517
|
+
)
|
|
518
|
+
ensure
|
|
519
|
+
original_env ? ENV['RSPEC_ENV'] = original_env : ENV.delete('RSPEC_ENV')
|
|
520
|
+
end
|
|
521
|
+
else
|
|
522
|
+
Legate.logger&.warn("Unknown scheme type: #{scheme_type}")
|
|
523
|
+
nil
|
|
524
|
+
end
|
|
525
|
+
rescue StandardError => e
|
|
526
|
+
Legate.logger&.warn("Failed to deserialize scheme: #{e.message}")
|
|
527
|
+
nil
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
end
|