mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 18:29:21 +00:00 
			
		
		
		
	Solved oauth2 proxy configuration bugs
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| - name: "set _tmp_database_application_id (Needed due to lazzy loading issue)" | ||||
| - name: "set database_application_id (Needed due to lazzy loading issue)" | ||||
|   set_fact: | ||||
|     database_application_id: "{{ application_id }}" | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| - name: "Transfering oauth2-proxy-keycloak.cfg.j2 to {{docker_compose.directories.volumes}}" | ||||
|   template: | ||||
|     src: oauth2-proxy-keycloak.cfg.j2 | ||||
|     dest: "{{docker_compose.directories.volumes}}{{applications.oauth2_proxy.configuration_file}}" | ||||
|     dest: "{{docker_compose.directories.volumes}}{{applications[application_id].configuration_file}}" | ||||
|   notify: | ||||
|     - docker compose project setup | ||||
| @@ -1,20 +1,20 @@ | ||||
| http_address            =   "0.0.0.0:4180" | ||||
| cookie_secret           =   "{{ applications[application_id].credentials.oauth2_proxy_cookie_secret }}" | ||||
| email_domains           =   "{{primary_domain}}" | ||||
| cookie_secret           =   "{{ applications[oauth2_proxy_application_id].credentials.oauth2_proxy_cookie_secret }}" | ||||
| email_domains           =   "{{ primary_domain }}" | ||||
| cookie_secure           =   "true"                                                  # True is necessary to force the cookie set via https | ||||
| upstreams               =   "http://{{applications[application_id].oauth2_proxy.application}}:{{applications[application_id].oauth2_proxy.port}}" | ||||
| cookie_domains          =   ["{{domain}}", "{{domains.keycloak}}"]                  # Required so cookie can be read on all subdomains. | ||||
| whitelist_domains       =   [".{{primary_domain}}"]                                 # Required to allow redirection back to original requested target. | ||||
| upstreams               =   "http://{{ applications[oauth2_proxy_application_id].oauth2_proxy.application }}:{{ applications[oauth2_proxy_application_id].oauth2_proxy.port }}" | ||||
| cookie_domains          =   ["{{ domain }}", "{{ domains.keycloak }}"]                  # Required so cookie can be read on all subdomains. | ||||
| whitelist_domains       =   [".{{ primary_domain }}"]                                 # Required to allow redirection back to original requested target. | ||||
|  | ||||
| # keycloak provider | ||||
| client_secret           =   "{{oidc.client.secret}}" | ||||
| client_id               =   "{{oidc.client.id}}" | ||||
| client_secret           =   "{{ oidc.client.secret }}" | ||||
| client_id               =   "{{ oidc.client.id }}" | ||||
| redirect_url            =   "{{ web_protocol }}://{{domain}}/oauth2/callback" | ||||
| oidc_issuer_url         =   "{{oidc.client.issuer_url}}" | ||||
| oidc_issuer_url         =   "{{ oidc.client.issuer_url }}" | ||||
| provider                =   "oidc" | ||||
| provider_display_name   =   "Keycloak" | ||||
|  | ||||
| # role restrictions | ||||
| #cookie_roles           =   "realm_access.roles" | ||||
| #allowed_groups         =   "{{applications.oauth2_proxy.allowed_roles}}"           # This is not correct here. needs to be placed in applications @todo move there when implementing | ||||
| #allowed_groups         =   "{{ applications[oauth2_proxy_application_id].allowed_roles }}"           # This is not correct here. needs to be placed in applications @todo move there when implementing | ||||
| # @see https://chatgpt.com/share/67f42607-bf68-800f-b587-bd56fe9067b5 | ||||
							
								
								
									
										1
									
								
								roles/docker-oauth2-proxy/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								roles/docker-oauth2-proxy/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| application_id: oauth2-proxy | ||||
| @@ -7,8 +7,13 @@ | ||||
|     src:  "{{ vhost_template_src }}" | ||||
|     dest: "{{ configuration_destination }}" | ||||
|   notify: restart nginx | ||||
|    | ||||
|  | ||||
| - name: "set oauth2_proxy_application_id (Needed due to lazzy loading issue)" | ||||
|   set_fact: | ||||
|     oauth2_proxy_application_id: "{{ application_id }}" | ||||
|   when: "{{applications[application_id].get('features', {}).get('oauth2', False)}}" | ||||
|  | ||||
| - name: "include the docker-oauth2-proxy role {{domain}}" | ||||
|   include_role: | ||||
|     name: docker-oauth2-proxy | ||||
|   when: final_oauth2_enabled | bool | ||||
|   when: "{{applications[application_id].get('features', {}).get('oauth2', False)}}" | ||||
| @@ -1,2 +1 @@ | ||||
| configuration_destination:  "{{nginx.directories.http.servers}}{{domain}}.conf" | ||||
| final_oauth2_enabled:       "{{applications[application_id].get('features', {}).get('oauth2', False)}}" | ||||
| configuration_destination:  "{{nginx.directories.http.servers}}{{domain}}.conf" | ||||
							
								
								
									
										92
									
								
								tests/unit/test_configuration_filters.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								tests/unit/test_configuration_filters.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| # tests/unit/test_configuration_filters.py | ||||
|  | ||||
| import unittest | ||||
| from filter_plugins.configuration_filters import ( | ||||
|     is_feature_enabled, | ||||
|     get_csp_whitelist, | ||||
|     get_csp_flags, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestConfigurationFilters(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         # Sample applications data for testing | ||||
|         self.applications = { | ||||
|             'app1': { | ||||
|                 'features': { | ||||
|                     'oauth2': True, | ||||
|                 }, | ||||
|                 'csp': { | ||||
|                     'whitelist': { | ||||
|                         # directive with a list | ||||
|                         'script-src': ['https://example.com'], | ||||
|                         # directive with a single string | ||||
|                         'connect-src': 'https://api.example.com', | ||||
|                     }, | ||||
|                     'flags': { | ||||
|                         # both flags for script-src | ||||
|                         'script-src': { | ||||
|                             'unsafe_eval': True, | ||||
|                             'unsafe_inline': False, | ||||
|                         }, | ||||
|                         # only unsafe_inline for style-src | ||||
|                         'style-src': { | ||||
|                             'unsafe_inline': True, | ||||
|                         }, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|             'app2': { | ||||
|                 # no features or csp defined | ||||
|             }, | ||||
|         } | ||||
|  | ||||
|     # Tests for is_feature_enabled | ||||
|     def test_is_feature_enabled_true(self): | ||||
|         self.assertTrue(is_feature_enabled(self.applications, 'oauth2', 'app1')) | ||||
|  | ||||
|     def test_is_feature_enabled_false_missing_feature(self): | ||||
|         self.assertFalse(is_feature_enabled(self.applications, 'nonexistent', 'app1')) | ||||
|  | ||||
|     def test_is_feature_enabled_false_missing_app(self): | ||||
|         self.assertFalse(is_feature_enabled(self.applications, 'oauth2', 'unknown_app')) | ||||
|  | ||||
|     # Tests for get_csp_whitelist | ||||
|     def test_get_csp_whitelist_returns_list_as_is(self): | ||||
|         result = get_csp_whitelist(self.applications, 'app1', 'script-src') | ||||
|         self.assertEqual(result, ['https://example.com']) | ||||
|  | ||||
|     def test_get_csp_whitelist_wraps_string_in_list(self): | ||||
|         result = get_csp_whitelist(self.applications, 'app1', 'connect-src') | ||||
|         self.assertEqual(result, ['https://api.example.com']) | ||||
|  | ||||
|     def test_get_csp_whitelist_empty_when_not_defined(self): | ||||
|         result = get_csp_whitelist(self.applications, 'app1', 'frame-src') | ||||
|         self.assertEqual(result, []) | ||||
|  | ||||
|     def test_get_csp_whitelist_empty_when_app_missing(self): | ||||
|         result = get_csp_whitelist(self.applications, 'nonexistent_app', 'script-src') | ||||
|         self.assertEqual(result, []) | ||||
|  | ||||
|     # Tests for get_csp_flags | ||||
|     def test_get_csp_flags_includes_unsafe_eval(self): | ||||
|         result = get_csp_flags(self.applications, 'app1', 'script-src') | ||||
|         self.assertIn("'unsafe-eval'", result) | ||||
|         self.assertNotIn("'unsafe-inline'", result) | ||||
|  | ||||
|     def test_get_csp_flags_includes_unsafe_inline(self): | ||||
|         result = get_csp_flags(self.applications, 'app1', 'style-src') | ||||
|         self.assertIn("'unsafe-inline'", result) | ||||
|         self.assertNotIn("'unsafe-eval'", result) | ||||
|  | ||||
|     def test_get_csp_flags_empty_when_none_configured(self): | ||||
|         result = get_csp_flags(self.applications, 'app1', 'connect-src') | ||||
|         self.assertEqual(result, []) | ||||
|  | ||||
|     def test_get_csp_flags_empty_when_app_missing(self): | ||||
|         result = get_csp_flags(self.applications, 'nonexistent_app', 'script-src') | ||||
|         self.assertEqual(result, []) | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
		Reference in New Issue
	
	Block a user