Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authenticate using Snowflake authentication mechanism #4315

Merged
merged 21 commits into from
Oct 4, 2024

Conversation

iliyan-velichkov
Copy link
Contributor

@iliyan-velichkov iliyan-velichkov commented Sep 26, 2024

When the Dirigible is deployed on Snowflake as container service, users should be able to authenticated in the application with Snowflake authentication mechanism only. Currently, double authentication is used.

The PR adds a new spring profile for Snowflake called snowflake.
The profile relies on the propagated logged in user for the authentication as described in this tutorial. Additional details here.

Example env variable: SPRING_PROFILES_ACTIVE=snowflake

An additional optional env variable was introduced called DIRIGIBLE_SNOWFLAKE_ADMIN_USERNAME.
Using this configuration, an user can be automatically initialized with all available Dirigible roles. Later on, you can use this user to assign roles to other users.

When a user loggin to the application for the first time, a new user registration is automatically created in the system DB if missing.

I didn't find a proper way to implement logout. I have created a Snowflake ticket for that.

I verified the Snowflake UDF scenario works with the current implementation.

Login flow:

Screen.Recording.2024-09-26.at.15.23.43.mov

Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
Signed-off-by: Iliyan Velichkov <[email protected]>
@iliyan-velichkov iliyan-velichkov changed the title Snowflake authentication profile Authenticate using Snowflake authentication mechanism Sep 26, 2024
Signed-off-by: Iliyan Velichkov <[email protected]>
Copy link
Contributor

@ThuF ThuF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Seems good to me

…ation

# Conflicts:
#	components/data/data-source-snowpark/src/main/java/org/eclipse/dirigible/components/data/source/snowpark/SnowflakeDatabaseConfigurator.java
…rkaround for invalidating the cookie

Signed-off-by: Iliyan Velichkov <[email protected]>
@iliyan-velichkov
Copy link
Contributor Author

iliyan-velichkov commented Oct 1, 2024

  • tested a proposed solution (to use SYSTEM$ABORT_SESSION) by Snowflake support - it doesn't work
  • I managed to invalidate the snowflake auth cookie to enforce logout
login-logout.mov

Signed-off-by: Iliyan Velichkov <[email protected]>
@@ -44,7 +42,7 @@
SecurityFilterChain filterChain(HttpSecurity http, TenantContextInitFilter tenantContextInitFilter) throws Exception {
http.cors(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.csrf(csrf -> csrf.disable())// if enabled, some functionalities will not work - like creating a project

Check failure

Code scanning / CodeQL

Disabled Spring CSRF protection High

CSRF vulnerability due to protection being disabled.

Copilot Autofix AI about 1 month ago

To fix the problem, we need to enable CSRF protection and handle any specific functionalities that might break due to this change. One approach is to selectively disable CSRF protection for specific endpoints that require it, while keeping it enabled for the rest of the application.

  1. Enable CSRF Protection: Remove the csrf.disable() line to enable CSRF protection globally.
  2. Selective CSRF Disabling: If certain endpoints need CSRF protection to be disabled, configure the HttpSecurity object to selectively disable CSRF for those endpoints.
Suggested changeset 1
components/core/core-tenants/src/main/java/org/eclipse/dirigible/components/tenants/security/BasicSecurityConfig.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/core/core-tenants/src/main/java/org/eclipse/dirigible/components/tenants/security/BasicSecurityConfig.java b/components/core/core-tenants/src/main/java/org/eclipse/dirigible/components/tenants/security/BasicSecurityConfig.java
--- a/components/core/core-tenants/src/main/java/org/eclipse/dirigible/components/tenants/security/BasicSecurityConfig.java
+++ b/components/core/core-tenants/src/main/java/org/eclipse/dirigible/components/tenants/security/BasicSecurityConfig.java
@@ -44,3 +44,3 @@
             .httpBasic(Customizer.withDefaults())
-            .csrf(csrf -> csrf.disable())// if enabled, some functionalities will not work - like creating a project
+            .csrf(Customizer.withDefaults()) // Enable CSRF protection
             .addFilterBefore(tenantContextInitFilter, UsernamePasswordAuthenticationFilter.class)
EOF
@@ -44,3 +44,3 @@
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())// if enabled, some functionalities will not work - like creating a project
.csrf(Customizer.withDefaults()) // Enable CSRF protection
.addFilterBefore(tenantContextInitFilter, UsernamePasswordAuthenticationFilter.class)
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
SecurityFilterChain filterChain(HttpSecurity http, TenantContextInitFilter tenantContextInitFilter) throws Exception {
LOGGER.info("Configure snowflake security configurations");
http.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable()) // if enabled, some functionalities will not work - like creating a project

Check failure

Code scanning / CodeQL

Disabled Spring CSRF protection High

CSRF vulnerability due to protection being disabled.

Copilot Autofix AI about 1 month ago

To fix the problem, we need to enable CSRF protection while ensuring that the application's functionalities are not broken. This can be achieved by configuring CSRF protection to ignore specific endpoints or using CSRF tokens appropriately.

  1. Enable CSRF Protection: Remove the csrf.disable() call.
  2. Configure CSRF Protection: If certain endpoints need to be excluded from CSRF protection, configure them explicitly.
  3. Update Methods and Imports: Ensure that the necessary methods and imports are in place to support the new configuration.
Suggested changeset 1
components/security/security-snowflake/src/main/java/org/eclipse/dirigible/components/security/snowflake/SnowflakeSecurityConfig.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/security/security-snowflake/src/main/java/org/eclipse/dirigible/components/security/snowflake/SnowflakeSecurityConfig.java b/components/security/security-snowflake/src/main/java/org/eclipse/dirigible/components/security/snowflake/SnowflakeSecurityConfig.java
--- a/components/security/security-snowflake/src/main/java/org/eclipse/dirigible/components/security/snowflake/SnowflakeSecurityConfig.java
+++ b/components/security/security-snowflake/src/main/java/org/eclipse/dirigible/components/security/snowflake/SnowflakeSecurityConfig.java
@@ -46,3 +46,3 @@
         http.cors(Customizer.withDefaults())
-            .csrf(csrf -> csrf.disable()) // if enabled, some functionalities will not work - like creating a project
+            .csrf(csrf -> csrf.ignoringAntMatchers("/specific-endpoint-to-ignore")) // Enable CSRF protection and ignore specific endpoints if necessary
             .logout(logout -> logout.deleteCookies("JSESSIONID")
EOF
@@ -46,3 +46,3 @@
http.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable()) // if enabled, some functionalities will not work - like creating a project
.csrf(csrf -> csrf.ignoringAntMatchers("/specific-endpoint-to-ignore")) // Enable CSRF protection and ignore specific endpoints if necessary
.logout(logout -> logout.deleteCookies("JSESSIONID")
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
with zero the ingress returns 500

Signed-off-by: Iliyan Velichkov <[email protected]>
@iliyan-velichkov
Copy link
Contributor Author

Example flow for the scenario in which path /sfc-endpoint/logout is used after logout (currently, not implemented in the PR)

logout-using-path.mov

Copy link
Member

@delchev delchev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Copy link
Contributor

@ThuF ThuF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Seems good to me.

@iliyan-velichkov iliyan-velichkov merged commit e6c4481 into master Oct 4, 2024
8 of 9 checks passed
@iliyan-velichkov iliyan-velichkov deleted the snowflake-authentication branch October 4, 2024 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants