FINERACT-2310: collate and improve security documentation

* fix various typos, spacing, formatting issues
* fix links to legacy docs in API docs
* update keycloak oauth dev instructions
* update default oauth URL for latest Keycloak
* use consistent quoting in oauth docs (single quotes)
* use asciidoc auto-enumerated lists whenever possible
* migrate security topics from readme into asciidoc: oauth, 2FA, HTTPS
* move :hardbreaks: setting to config file so all config settings are in one place. (I think it's fine that `license.adoc` will use hardbreaks -- that's how the plain text version is formatted so it should look more familiar)
* add intro to security chapter
* migrate in Securing Fineract wiki content from https://cwiki.apache.org/confluence/display/FINERACT/Securing+Fineract
* just say "oauth" (not "oauth2") to conform terminology throughout docs -- OAuth 2.0 is just the latest version
* cross-ref HTTPS section from Securing Fineract
* reposition hardening options as tips
* see also: https://lists.apache.org/thread/81qdxttffp6wn23c48zvk93hc13373qv
* simplify/clarify example oauth curl requests
  * Testing just now and I didn't need --location.
  * Also I imagine folks will need --insecure with the self-signed default cert in dev.
* don't change default oauth URL
  * no surprises for existing deployments
  * clarifies the keycloak v26 example
This commit is contained in:
Adam Monsen
2025-06-16 15:12:55 -07:00
parent 2c77f6a277
commit f28d252f17
16 changed files with 199 additions and 96 deletions
@@ -1,6 +1,6 @@
= HTTPS
Because Apache Fineract deals with customer sensitive personally identifiable information (PII), it very strongly encourages all developers, implementors and end-users to always only use HTTPS. This is why it does not run on HTTP even for local development and enforces use of HTTPS.
Because Apache Fineract deals with customer sensitive personally identifiable information (PII), it very strongly encourages all developers, implementors and end-users to always only use HTTPS. This is why it does not run on HTTP even for local development and enforces use of HTTPS by default.
For this purpose, Fineract includes a built-in default SSL certificate. This cert is intended for development on `localhost`, only. It is not trusted by your browser (because it's self signed).
@@ -11,3 +11,7 @@ Such products, when correctly configured, add the conventional `X-Forwarded-For`
Alternatively, you could replace the built-in default SSL certificate with one you obtained from a Certificate Authority. We currently do not document how to do this, because we do not recommend this approach, as it's cumbersome to configure and support and less secure than a managed auto rotating solution.
The Fineract API client supports an insecure mode (`FineractClient.Builder#insecure()`), and API users such as mobile apps may expose Settings to let end-users accept the self signed certificate. This should always be used for testing only, never in production.
All SSL-related properties are tunable. SSL can be turned off by setting the environment variable `FINERACT_SERVER_SSL_ENABLED` to false. If you do that then please make sure to also change the server port to `8080` via the variable `FINERACT_SERVER_PORT`, just for the sake of keeping the conventions.
To use a different SSL keystore, set `FINERACT_SERVER_SSL_KEY_STORE` to a path to a different (not embedded) keystore. The password can be set via `FINERACT_SERVER_SSL_KEY_STORE_PASSWORD`. See the `application.properties` file and the https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html[latest Spring Boot documentation] for details.
@@ -0,0 +1,17 @@
= Two-factor authentication
You can enable 2FA authentication. Depending on how you start Fineract add the following:
. Use environment variables (best choice if you run with Docker Compose):
+
[source,bash]
----
FINERACT_SECURITY_2FA_ENABLED=true
----
. Use JVM parameter (best choice if you run the Spring Boot JAR):
+
[source,bash]
----
java -Dfineract.security.2fa.enabled=true -jar fineract-provider.jar
----
@@ -0,0 +1,18 @@
= HTTP Basic Authentication
By default Fineract is configured with a HTTP Basic Authentication scheme, so you actually don't have to do anything if you want to use it. But if you would like to explicitly choose this authentication scheme then there are two ways to enable it:
. Use environment variables (best choice if you run with Docker Compose):
+
[source,bash]
----
FINERACT_SECURITY_BASICAUTH_ENABLED=true
FINERACT_SECURITY_OAUTH_ENABLED=false
----
. Use JVM parameters (best choice if you run the Spring Boot JAR):
+
[source,bash]
----
java -Dfineract.security.basicauth.enabled=true -Dfineract.security.oauth.enabled=false -jar fineract-provider.jar
----
@@ -0,0 +1,81 @@
= Securing Fineract
This section covers best practices in securing the use of Fineract.
Security hardening is a continuum and Fineract is adaptable to your security needs. There's no one way to correctly deploy it and the open source project offers no warranty. It's up to you to deploy and maintain it carefully, according to your organization's needs and compliance requirements.
Since Fineract is a financial application with PII (personally identifiable information), it is vital that it is secured in production whenever it is setup. If you are a small financial entity, bank, credit union, microfinance organization, or non-banking financial institution, the project urges you to identify and work with the vendors that work regularly with Fineract and are regular contributors to the security fixes. In this way, we encourage a community of contributions that keep the overall solution secure. Open source gets the benefit of many people reviewing the code and suggesting issues and solutions - let's ensure that virtuous cycle can work by supporting those working on security at Fineract.
Members of the Security team can be reached at security AT fineract.apache.org. The reporting mechanisms for vulnerabilities and exploits are there, not on the public dev list.
See apache security practices for more information. https://security.apache.org
Also, we recommend you familiarize yourself with the OWASP foundation and the "Cheat Sheet" series https://cheatsheetseries.owasp.org
== Tips for securing the Fineract infrastructure
=== Run it isolated and/or disconnected
In the world of Microfinance or small banking operations (in some geographies), it is possible that you can run Fineract on a private network, or isolated from the internet by being hosted locally and securing all connections. This could involve establishing a VPN with limited ports open, and only accepting connections within that VPN. At the far end of this spectrum, is running it isolated and air-gapped as a backend accounting system, where there is no internet connection on that device. In such scenarios, you are limiting the vectors of attack to just those employees you give access to. You are also limiting the functionality to accounting and basic operations, so this is rarely appropriate. Even in these scenarios, it is important that you establish reviews of logs and accounts on a periodic basis to determine if any internal fraud is occurring. Such things should be part of your operational manual. There are a number of resources available for this topic, please find them online. For Fineract in particular, be mindful of the set up of approvals and and the access you give to each person or role in your organization
=== Running it connected but behind a firewalls
It should be clear that running it on the internet directly, without API monitoring and filtering, is a bad idea. This is especially true if your Fineract instance is connected to a payment mechanism of any kind. Imagine an exploit being used to gain access and then to send funds from an account to an outside merchant or bank. An attacker could drain an account before you can detect the issue. And, then it will depend on the payment scheme rules whether any of those funds are recoverable.
There are multiple ways to enhance the security that is built into Fineract, but none of them are bulletproof and so you must have defense in depth. One key thing is to run the Fineract instance behind an API gateway, and to prevent certain API patterns or calls that are likely to be fraudulent. The important thing is to recognize that while you may not be a target institution now, at any moment this can change, and your IP will be listed on the dark web as a potential target for exploit. Your IT team must also have ways to quickly turn off services to limit the damage.
It is recommended to run it with at least API Gateway, WAF (Web Application Firewall) and SQL Injection filtering tool if connecting to the internet. Fineract must be hardened to run in production.
=== Fraud prevention
Even if you have secured your infrastructure, you will need the ability to monitor fraudulent traffic, and then to stop that fraud in real time. Fraud can occur even when your infrastructure is good, but a user account has been accessed through a phishing attack or similar vector. And, in the world of real time payments and multiple payment types and channels, there is a need for additional real time monitoring, and inline processing of potential fraudulent transactions. Detection and blocking needs to occur in real time and then resolution can occur more leisurely with additional manual and help desk interventions.
If you are a small institution and you are getting into this situation, you should consider having holds on all payment and transfers built into your process, until you can enable effective tools.
There are a number of fraud prevention tools that are available in market from fraud prevention vendors. When looking for solution providers, the ideal scenario is a vendor with longevity and a track record in your market for detecting recent fraudulent activities. Pattern detection is a key part of this, and for that, it is important to be able to get enough data from your systems to identify the anomalies.
There are a number of GitHub projects that cover algorithms for conducting ML on transactions to detect anomalies. There is also an open source project, Tazama, which provides a kind of framework for your own logic and algorithms: https://github.com/frmscoe/docs.
Fraud exploits are on the rise, supercharged by AI tooling. AI tooling can also be used to fight these trends, but it is an ever escalating area of concern for financial providers globally.
=== Self-service APIs
It is recommended that you leave the Self Service APIs disabled to avoid any potential exploits there. Apps should not be developed to use those APIs.
There is a way to run those APIs endpoint (re-written but consistent) in a separate isolated component, where there is a way to control the ingress and egress of data. Once that component is linked up with authenticated users with a fully designed authorization scheme, then the APIs can be accessed. This is an area of exploration by the project. Currently, Fineract should not be run in a way that allows access to those APIs. We strongly advise against using any APP that connects to those APIs without revising the architecture as described, except in a test or demo environment.
=== User Education and Training
Educating and training your team is another limb of your organizational cybersecurity defense. Equipped with engaging security awareness training sessions, end-users can be prepared with both knowledge and skills on how to identify potential security threats and react to them. You can get more information from some of the resources offered in the course during CISA Training: https://www.cisa.gov/c
=== Regular Security Audits and Compliance Checks
Know your compliance surface. Regularly conduct routine security audits and compliance checks. This can be helpful in finding all the vulnerabilities and their fix prior to exploitation, thereby helping to reduce the exposure window. A combined automated tool with manual expert reviews provides complete coverage. There are multiple vendors available that scan for compliance with existing security standards. We don't recommend any vendor in particular, but for pointers you can look at https://owasp.org/www-community/Vulnerability_Scanning_Tools
=== Key Management and Data Encryption Strategies
Implement strong data encryption strategies to protect sensitive information. Key management should be something that your IT team does, utilizing best practices. Just like a physical key, you should keep it in a secure location with limited access and take special care not to copy it to digital locations that can be scanned or found, including email systems. Make sure you have procedures in place.
You would probably want to encrypt the data at rest with AES-256 and <<HTTPS,in transit>> via TLS 1.3. Create and maintain binding standards for encryption in your organization. And remember, key management to encryption is the key. Every cloud providers provides key management services that help you manage and secure your keys.
Examples:
* https://aws.amazon.com/kms/
* https://cloud.google.com/docs/security/key-management-deep-dive
* https://learn.microsoft.com/en-us/azure/security/fundamentals/key-management
* https://github.com/getsops/sops
* https://github.com/Infisical/infisical
=== Secure Coding Practices
Secure code by following secure coding practices and standards, such as OWASP's top ten, for any kind of vulnerability at the code level. Use tools like SonarQube for finding security problems in your source code through static application security testing (SAST) prior to deploying an application. Note that SonarQube has already been integrated into our automation build process.
Apache Software Foundation has an account with SonarQube and Fineract scans can be found in that account.
=== Multi-factor Authentication (MFA)
Enhance your security layers with MFA (or 2FA: two-factor authentication). One such approach, built on three things: something the user knows (like a password), something the user has (like a security token), and something the user is (biometric verification, for example). When MFA is used, it adds another layer of security. Solutions such as Duo Security may be a good implementation for MFA.
=== Leverage Community Support
You should stay engaged with the Fineract community to stay on top of security updates, patches, and best practices. Also, look for the possibility of collaboration with cybersecurity firms that would help you increase the capability of your threat detection and response system. Such relationships may avail specialized skills, technologies, and intelligence that may strengthen the security posturing of your organization.
@@ -1,5 +1,19 @@
= Security
TBD
Fineract is *secure by design*. It is designed and built from the ground up to accept, manage, and present data securely. This chapter will detail its various security-related features and settings, along with best practices for secure deployment.
If you believe you have found a security vulnerability in Fineract itself, https://fineract.apache.org/#contribute[let us know privately].
Your task as bank CTO, sysadmin, vendor, or other entity responsible for hosting Fineract securely is to thoroughly consider these sections and thoughtfully apply them in your work. While a Fineract release _is_ secure by design, it is _not_ sufficient for a sysadmin to simply start it up and hope for the best. Careful steps must be taken to ensure a deployment is and remains secure despite software environment changes, attacks, staff transitions, and anything else that may arise.
We'll first cover the various supported authentication schemes and will continue on to recommendations for securing a Fineract deployment.
NOTE: The HTTP Basic and OAuth authentication schemes are mutually exclusive. You can't enable them both at the same time. Fineract checks these settings on startup and will fail if more than one authentication scheme is enabled.
include::basic.adoc[leveloffset=+1]
include::oauth.adoc[leveloffset=+1]
include::2fa.adoc[leveloffset=+1]
include::harden.adoc[leveloffset=+1]
@@ -1,66 +1,75 @@
= OAuth
Fineract has a (basic) OAuth2 support based on Spring Boot Security. Here's how to use it:
Fineract has basic OAuth support based on Spring Boot Security.
== Build
You must re-build the distribution JAR (or WAR) using the special `-Psecurity=oauth` flag:
This can be enabled at runtime in one of two ways:
. Use environment variables (best choice if you run with Docker Compose):
+
[source,bash]
----
./gradlew bootRun -Psecurity=oauth
FINERACT_SECURITY_BASICAUTH_ENABLED=false
FINERACT_SECURITY_OAUTH_ENABLED=true
FINERACT_SERVER_OAUTH_RESOURCE_URL=http://localhost:9000/realms/fineract
----
Downloads from https://fineract.apache.org, or using e.g. the https://hub.docker.com/r/apache/fineract container image, or on https://www.fineract.dev, this will not work, because they have not been built using this flag.
. Use JVM parameters (best choice if you run the Spring Boot JAR):
+
[source,bash]
----
java -Dfineract.security.basicauth.enabled=false -Dfineract.security.oauth.enabled=true -jar fineract-provider.jar
----
Previous versions of Fineract included a built-in authorisation server for issuing OAuth tokens. However, as the spring-security-oauth2 package was deprecated and replaced by built-in OAuth support in Spring Security, this is no longer supported as part of the package. Instead, you need to run a separate OAuth authorization server (e.g. https://github.com/spring-projects/spring-authorization-server) or use a 3rd-party OAuth authorization provider (https://en.wikipedia.org/wiki/List_of_OAuth_providers)
This instruction describes how to get Fineract OAuth working with a Keycloak (http://keycloak.org) based authentication provider running in a Docker container. The steps required for other OAuth providers will be similar.
Here's how to test OAuth with https://www.keycloak.org[Keycloak].
The steps required for other OAuth providers will be similar.
== Set up Keycloak
1. From terminal, run: 'docker run -p 9000:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2'
2. Go to URL 'http://localhost:9000/auth/admin' and login with admin/admin
3. Hover your mouse over text "Master" and click on "Add realm"
4. Enter name "fineract" for your realm
5. Click on tab "Users" on the left, then "Add user" and create user with username "mifos"
6. Click on tab "Credentials" at the top, and set password to "password", turning "temporary" setting to off
7. Click on tab "Clients" on the left, and create client with ID 'community-app'
8. In settings tab, set 'access-type' to 'confidential' and enter 'localhost' in the valid redirect URIs.
9. In credentials tab, copy string in field 'secret' as this will be needed in the step to request the access token
. From terminal, run: `docker run -p 9000:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.5 start-dev`
. Go to URL 'http://localhost:9000/admin' and login with admin/admin
. Click 'Manage realms', then 'Create realm'
. Enter name `fineract` for the realm name
. Click on tab 'Users' on the left, then 'Create new user' with username `mifos`, email `test@example.com`, First name `Mifos`, Last name `User`
. Click on tab 'Credentials' at the top, and set password to `password`, turning 'temporary' setting to off
. Click on tab 'Clients' on the left, and create client with ID `community-app`
. In Settings tab, set 'Valid redirect URIs' to `localhost`, enable 'Client authentication', check 'Direct access grants'
. Click 'Save' and a 'Credentials' tab will appear
. In Credentials tab, copy string in field 'secret' as this will be needed in the step to request the access token
Finally we need to change Keycloak configuration so that it uses the username as a subject of the token:
1. Choose client 'community-app' in the tab 'Clients'
2. Go to tab 'Mappers' and click on 'Create'
3. Enter 'usernameInSub' as 'Name'
4. Choose mapper type 'User Property'
5. Enter 'username' into the field 'Property' and 'sub' into the field 'Token Claim Name'. Choose 'String' as 'Claim JSON Type'
. Choose client `community-app` in the tab 'Clients'
. Click on tab 'Client scopes', then `community-app-dedicated`
. Go to tab 'Mappers', click 'Configure a new mapper' and choose 'User Property'
. Enter `usernameInSub` as 'Name'
. Enter `username` into the field 'Property' and `sub` into the field 'Token Claim Name'
You are now ready to test out OAuth:
== Retrieve an access token from Keycloak
[source,bash]
----
curl --location --request POST \
'http://localhost:9000/auth/realms/fineract/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=mifos' \
--data-urlencode 'password=password' \
--data-urlencode 'client_id=community-app' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_secret=<enter the client secret from credentials tab>'
curl --request POST \
"$FINERACT_SERVER_OAUTH_RESOURCE_URL/protocol/openid-connect/token" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=mifos' \
--data-urlencode 'password=password' \
--data-urlencode 'client_id=community-app' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_secret=<enter the client secret from credentials tab>'
----
The reply should contain a field 'access_token'. Copy the field's value and use it in the API call below:
The reply should contain a field `access_token`. Copy the field's value and use it in the API call below:
== Invoke APIs and pass `Authorization: bearer ...` header
[source,bash]
----
curl --location --request GET \
'https://localhost:8443/fineract-provider/api/v1/offices' \
--header 'Fineract-Platform-TenantId: default' \
--header 'Authorization: bearer <enter the value of the access_token field>'
curl --insecure \
'https://localhost:8443/fineract-provider/api/v1/offices' \
--header 'Fineract-Platform-TenantId: default' \
--header 'Authorization: bearer <enter the value of the access_token field>'
----
NOTE: See also https://fineract.apache.org/legacy-docs/apiLive.htm#authentication_oauth
NOTE: See also https://fineract.apache.org/docs/legacy/#authentication_oauth
+2 -1
View File
@@ -25,6 +25,7 @@
:email: dev@fineract.apache.org
:checkedbox: pass:normal[{startsb}&#10004;{endsb}]
:table-stripes: even
:hardbreaks:
// ifeval::["{draft}"=="true"]
// :title-page-background-image: image:{commondir}/images/draft.svg[position=top]
@@ -43,4 +44,4 @@ ifdef::env-github[]
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]
endif::[]
-2
View File
@@ -1,8 +1,6 @@
[preface]
= Preface
:hardbreaks:
*Apache Fineract*
Website: https://fineract.apache.org[]
Email: mailto:dev@fineract.apache.org[]