Skip to content

Commit

Permalink
Merge pull request #157 from stellar/release/1.1.0
Browse files Browse the repository at this point in the history
Release 1.1.0 to main
  • Loading branch information
ziyliu authored Feb 1, 2024
2 parents 67c4af6 + a8ebd65 commit e12d7db
Show file tree
Hide file tree
Showing 122 changed files with 5,765 additions and 1,870 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# we set `sdp-backend` as code owners
# require approval from 1 member of `sdp-backend` team
@stellar/sdp-backend
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

#### PR Structure

* [ ] This PR has reasonably narrow scope (if not, break it down into smaller PRs).
* [ ] This PR has a reasonably narrow scope (if not, break it down into smaller PRs).
* [ ] This PR title and description are clear enough for anyone to review it.
* [ ] This PR does not mix refactoring changes with feature changes (split into two PRs otherwise).
* [ ] This PR's title starts with the name of the package, area, or subject affected by the change.

#### Thoroughness

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/anchor_platform_integration_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
runs-on: ubuntu-latest
environment: "Anchor Integration Tests"
env:
DISTRIBUTION_PUBLIC_KEY: ${{ secrets.DISTRIBUTION_PUBLIC_KEY }}
DISTRIBUTION_SEED: ${{ secrets.DISTRIBUTION_SEED }}
SEP10_SIGNING_PUBLIC_KEY: ${{ secrets.SEP10_SIGNING_PUBLIC_KEY }}
SEP10_SIGNING_PRIVATE_KEY: ${{ secrets.SEP10_SIGNING_PRIVATE_KEY }}
DISTRIBUTION_PUBLIC_KEY: ${{ vars.DISTRIBUTION_PUBLIC_KEY }}
DISTRIBUTION_SEED: ${{ vars.DISTRIBUTION_SEED }}
SEP10_SIGNING_PUBLIC_KEY: ${{ vars.SEP10_SIGNING_PUBLIC_KEY }}
SEP10_SIGNING_PRIVATE_KEY: ${{ vars.SEP10_SIGNING_PRIVATE_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
36 changes: 35 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,40 @@ jobs:
- name: Run ./gomod.sh
run: ./gomod.sh

- name: Install github.com/nishanths/exhaustive
run: go install github.com/nishanths/exhaustive/cmd/exhaustive@latest

- name: Run exhaustive
run: exhaustive -default-signifies-exhaustive ./...

check-helm-readme:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install NodeJs
uses: actions/setup-node@v2
with:
node-version: 14

- name: Install Helm Readme Generator (@bitnami/readme-generator-for-helm)
run: npm install -g @bitnami/readme-generator-for-helm

- name: Generate README.md for comparison
run: readme-generator -v helmchart/sdp/values.yaml -r helmchart/sdp/README.md

- name: Check if helmchart/sdp/README.md is in sync with helmchart/sdp/values.yaml
run: |
if git diff --exit-code --stat helmchart/sdp/README.md; then
echo "✅ helmchart/sdp/README.md is in sync with helmchart/sdp/values.yaml"
else
echo "🚨 helmchart/sdp/README.md needs to be re-generated!"
echo "Run 'readme-generator -v helmchart/sdp/values.yaml -r helmchart/sdp/README.md' locally and commit the changes."
echo "Refer to https://github.com/bitnami/readme-generator-for-helm for more information."
exit 1
fi
build:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -104,7 +138,7 @@ jobs:
complete:
if: always()
needs: [check, build, test]
needs: [check, check-helm-readme, build, test]
runs-on: ubuntu-latest
steps:
- if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/e2e_integration_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
runs-on: ubuntu-latest
environment: "Receiver Registration - E2E Integration Tests"
env:
DISTRIBUTION_PUBLIC_KEY: ${{ secrets.DISTRIBUTION_PUBLIC_KEY }}
DISTRIBUTION_SEED: ${{ secrets.DISTRIBUTION_SEED }}
SEP10_SIGNING_PUBLIC_KEY: ${{ secrets.SEP10_SIGNING_PUBLIC_KEY }}
SEP10_SIGNING_PRIVATE_KEY: ${{ secrets.SEP10_SIGNING_PRIVATE_KEY }}
DISTRIBUTION_PUBLIC_KEY: ${{ vars.DISTRIBUTION_PUBLIC_KEY }}
DISTRIBUTION_SEED: ${{ vars.DISTRIBUTION_SEED }}
SEP10_SIGNING_PUBLIC_KEY: ${{ vars.SEP10_SIGNING_PUBLIC_KEY }}
SEP10_SIGNING_PRIVATE_KEY: ${{ vars.SEP10_SIGNING_PRIVATE_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
51 changes: 50 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,56 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased

> Place unreleased changes here.
None

## [1.1.0](https://github.com/stellar/stellar-disbursement-platform-backend/compare/1.0.1...1.1.0)

### Changed

- Change `POST /disbursements` to accept different verification types [#103](https://github.com/stellar/stellar-disbursement-platform-backend/pull/103)
- Change `SEP-24` Flow to display different verifications based on disbursement verification type [#116](https://github.com/stellar/stellar-disbursement-platform-backend/pull/116)
- Add sorting to `GET /users` endpoint [#104](https://github.com/stellar/stellar-disbursement-platform-backend/pull/104)
- Change read permission for receiver details to include business roles [#144](https://github.com/stellar/stellar-disbursement-platform-backend/pull/144)
- Add support for unique payment ID to disbursement instructions file as an optional field in `GET /payments/{id}` [#131](https://github.com/stellar/stellar-disbursement-platform-backend/pull/131)
- Add support for SMS preview & editing before sending a new disbursement [#146](https://github.com/stellar/stellar-disbursement-platform-backend/pull/146)
- Add metadata for users that created and started a disbursement in disbursement details `GET /disbursements`, `GET /disbursements/{id}` [#151](https://github.com/stellar/stellar-disbursement-platform-backend/pull/151)
- Update CI check to run the exhaustive validator [#163](https://github.com/stellar/stellar-disbursement-platform-backend/pull/163)
- Preload reCAPTCHA script in attempt to mitigate component loading issues upon login [#152](https://github.com/stellar/stellar-disbursement-platform-backend/pull/152)
- Validate distribution account balance before starting disbursement [#161](https://github.com/stellar/stellar-disbursement-platform-backend/pull/161)

### Added

- Support automatic cancellation of payments in `READY` status after a certain time period [#121](https://github.com/stellar/stellar-disbursement-platform-backend/pull/121)
- API endpoint for cancelling payments in `READY` status: `PATCH /payments/{id}/status` [#130](https://github.com/stellar/stellar-disbursement-platform-backend/pull/130)
- Use CI to make sure the helm README is up to date [#164](https://github.com/stellar/stellar-disbursement-platform-backend/pull/164)

### Fixed

- Verification DOB validation missing when date is in the future [#101](https://github.com/stellar/stellar-disbursement-platform-backend/pull/101)
- Support disbursements from two or more wallet providers to the same address [#87](https://github.com/stellar/stellar-disbursement-platform-backend/pull/87)
- [TSS] Stale channel account not cleared after switching distribution keys [#91](https://github.com/stellar/stellar-disbursement-platform-backend/pull/91)
- Make setup-wallets-for-network tests more flexible [#95](https://github.com/stellar/stellar-disbursement-platform-backend/pull/95)
- Make `POST /assets` idempotent [#122](https://github.com/stellar/stellar-disbursement-platform-backend/pull/122)
- Add missing space when building query [#121](https://github.com/stellar/stellar-disbursement-platform-backend/pull/121)

### Security

- Stellar Protocol 20 Horizon SDK upgrade [#107](https://github.com/stellar/stellar-disbursement-platform-backend/pull/107)
- Coinspect Issues:
- Add "Secure Operation Manual" section and updated the code to enforce MFA and reCAPTCHA [#150](https://github.com/stellar/stellar-disbursement-platform-backend/pull/150)
- Coinspect SDP-006 Weak password policy [#143](https://github.com/stellar/stellar-disbursement-platform-backend/pull/143)
- Coinspect SDP-007: Log user activity when updating user info [#139](https://github.com/stellar/stellar-disbursement-platform-backend/pull/139)
- Coinspect SDP-012 Enhance User Awareness for SMS One-Time Password (OTP) Usage [#138](https://github.com/stellar/stellar-disbursement-platform-backend/pull/138)

## [1.0.1](https://github.com/stellar/stellar-disbursement-platform-backend/compare/1.0.0...1.0.1)

### Changed

- Update log message for better debugging. [#125](https://github.com/stellar/stellar-disbursement-platform-backend/pull/125)

### Fixed

- Fix client_domain from the Viobrant Assist wallet. [#126](https://github.com/stellar/stellar-disbursement-platform-backend/pull/126)

## [1.0.1](https://github.com/stellar/stellar-disbursement-platform-backend/compare/1.0.0...1.0.1)

Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,48 @@ stellar-disbursement-platform --help

To quickly test the SDP using preconfigured values, see the [Quick Start Guide](./dev/README.md).

## Secure Operation Manual

This manual outlines the security measures implemented in the Stellar Disbursement Platform (SDP) to protect the integrity of the platform and its users. By adhering to these guidelines, you can ensure that your use of the SDP is as secure as possible.

Security is a critical aspect of the SDP. The measures outlined in this document are designed to mitigate risks and enhance the security of the platform. Users are strongly encouraged to follow these guidelines to protect their accounts and operations.

### Implementation of reCAPTCHA

Google's reCAPTCHA has been integrated into the SDP to prevent automated attacks and ensure that interactions are performed by humans, not bots.

ReCAPTCHA is enabled by default and can be disabled in the development environment by setting the `DISABLE_RECAPTCHA` environment variable to `true`.

**Note:** Disabling reCAPTCHA is not supported for production environments due to security risks.

### Enforcement of Multi-Factor Authentication

Multi-Factor Authentication (MFA) provides an additional layer of security to user accounts. It is enforced by default on the SDP and it relies on OTPs sent to the account's email.

MFA is enabled by default and can be disabled in the development environment by setting the `DISABLE_MFA` environment variable to `true`.

**Note:** Disabling MFA is not supported for production environments due to security risks.

### Best Practices for Wallet Management

The SDP wallet should be used primarily as a hot wallet with a limited amount of funds to minimize potential losses.

#### Hot and Cold Wallets

- A hot wallet is connected to the internet and allows for quick transactions.
- A cold wallet is offline and used for storing funds securely.
- Learn more about these concepts at [Investopedia](https://www.investopedia.com/hot-wallet-vs-cold-wallet-7098461).

### Distribution of Disbursement Responsibilities

To enhance security, disbursement responsibilities should be distributed among multiple financial controller users.

#### Recommended Configuration

1. **Approval Flow**: Enable the approval flow on the organization page to require two users for the disbursement process. The owner can do that at *Profile > Organization > ... > Edit details > Approval flow > Confirm*.
2. **Financial Controller Role**: Create two users with the *Financial Controller* role on the organization page to enforce separation of duties. The owner can do hat at *Settings > Team Members*.
3. **Owner Account Management**: Use the Owner account solely for user management and organization configuration. Avoid using the Owner account for financial controller tasks to minimize the exposure of that account.

## Architecture

![high_level_architecture](./docs/images/high_level_architecture.png)
Expand Down
63 changes: 36 additions & 27 deletions cmd/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
"strings"
"testing"

"github.com/stellar/stellar-disbursement-platform-backend/internal/services/assets"

"github.com/stellar/go/keypair"
"github.com/stellar/go/network"
"github.com/stellar/go/support/log"
"github.com/stellar/stellar-disbursement-platform-backend/internal/data"
"github.com/stellar/stellar-disbursement-platform-backend/internal/db"
"github.com/stellar/stellar-disbursement-platform-backend/internal/db/dbtest"
"github.com/stellar/stellar-disbursement-platform-backend/internal/services"
"github.com/stellar/stellar-disbursement-platform-backend/internal/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -158,12 +158,12 @@ func Test_DatabaseCommand_db_setup_for_network(t *testing.T) {
testnetUSDCIssuer := keypair.MustRandom().Address()
data.CreateAssetFixture(t, ctx, dbConnectionPool, "USDC", testnetUSDCIssuer)

assets, err := models.Assets.GetAll(ctx)
actualAssets, err := models.Assets.GetAll(ctx)
require.NoError(t, err)

assert.Len(t, assets, 1)
assert.Equal(t, "USDC", assets[0].Code)
assert.Equal(t, testnetUSDCIssuer, assets[0].Issuer)
assert.Len(t, actualAssets, 1)
assert.Equal(t, "USDC", actualAssets[0].Code)
assert.Equal(t, testnetUSDCIssuer, actualAssets[0].Issuer)

// Wallets
data.CreateWalletFixture(t, ctx, dbConnectionPool, "Vibrant Assist", "https://vibrantapp.com", "api-dev.vibrantapp.com", "https://vibrantapp.com/sdp-dev")
Expand Down Expand Up @@ -196,39 +196,48 @@ func Test_DatabaseCommand_db_setup_for_network(t *testing.T) {
require.NoError(t, err)

// Validating assets
assets, err = models.Assets.GetAll(ctx)
actualAssets, err = models.Assets.GetAll(ctx)
require.NoError(t, err)

assert.Len(t, assets, 2)
assert.Equal(t, "USDC", assets[0].Code)
assert.NotEqual(t, testnetUSDCIssuer, assets[0].Issuer)
assert.Equal(t, services.DefaultAssetsNetworkMap[utils.PubnetNetworkType]["USDC"], assets[0].Issuer)
assert.Equal(t, "XLM", assets[1].Code)
assert.Empty(t, assets[1].Issuer)
require.Len(t, actualAssets, 2)
require.Equal(t, assets.USDCAssetPubnet.Code, actualAssets[0].Code)
require.Equal(t, assets.USDCAssetPubnet.Issuer, actualAssets[0].Issuer)
require.Equal(t, assets.XLMAsset.Code, actualAssets[1].Code)
require.Empty(t, assets.XLMAsset.Issuer)

// Validating wallets
wallets, err = models.Wallets.GetAll(ctx)
require.NoError(t, err)

assert.Len(t, wallets, 2)
// assert.Equal(t, "Beans App", wallets[0].Name)
// assert.Equal(t, "https://www.beansapp.com/disbursements", wallets[0].Homepage)
// assert.Equal(t, "api.beansapp.com", wallets[0].SEP10ClientDomain)
// assert.Equal(t, "https://www.beansapp.com/disbursements/registration?redirect=true", wallets[0].DeepLinkSchema)
assert.Equal(t, "Vibrant Assist", wallets[0].Name)
assert.Equal(t, "https://vibrantapp.com/vibrant-assist", wallets[0].Homepage)
assert.Equal(t, "vibrantapp.com", wallets[0].SEP10ClientDomain)
assert.Equal(t, "https://vibrantapp.com/sdp", wallets[0].DeepLinkSchema)
// Test only on Vibrant Assist and Vibrant Assist RC. This will help adding wallets without breaking tests.
var vibrantAssist, vibrantAssistRC data.Wallet

for _, w := range wallets {
if w.Name == "Vibrant Assist" {
vibrantAssist = w
} else if w.Name == "Vibrant Assist RC" {
vibrantAssistRC = w
}
}

require.NotNil(t, vibrantAssist, "Vibrant Assist wallet not found")
require.NotNil(t, vibrantAssistRC, "Vibrant Assist RC wallet not found")

// Test the two wallets
assert.Equal(t, "Vibrant Assist", vibrantAssist.Name)
assert.Equal(t, "https://vibrantapp.com/vibrant-assist", vibrantAssist.Homepage)
assert.Equal(t, "vibrantapp.com", vibrantAssist.SEP10ClientDomain)
assert.Equal(t, "https://vibrantapp.com/sdp", vibrantAssist.DeepLinkSchema)

assert.Equal(t, "Vibrant Assist RC", wallets[1].Name)
assert.Equal(t, "vibrantapp.com/vibrant-assist", wallets[1].Homepage)
assert.Equal(t, "vibrantapp.com", wallets[1].SEP10ClientDomain)
assert.Equal(t, "https://vibrantapp.com/sdp-rc", wallets[1].DeepLinkSchema)
assert.Equal(t, "Vibrant Assist RC", vibrantAssistRC.Name)
assert.Equal(t, "vibrantapp.com/vibrant-assist", vibrantAssistRC.Homepage)
assert.Equal(t, "vibrantapp.com", vibrantAssistRC.SEP10ClientDomain)
assert.Equal(t, "https://vibrantapp.com/sdp-rc", vibrantAssistRC.DeepLinkSchema)

expectedLogs := []string{
"updating/inserting assets for the 'pubnet' network",
"Code: USDC",
fmt.Sprintf("Issuer: %s", services.DefaultAssetsNetworkMap[utils.PubnetNetworkType]["USDC"]),
fmt.Sprintf("Issuer: %s", assets.USDCAssetPubnet.Issuer),
"Code: XLM",
"Issuer: ",
"updating/inserting wallets for the 'pubnet' network",
Expand Down
17 changes: 9 additions & 8 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (s *ServerService) GetSchedulerJobRegistrars(ctx context.Context, serveOpts
}),
scheduler.WithAPAuthEnforcementJob(apAPIService, serveOpts.MonitorService, serveOpts.CrashTrackerClient.Clone()),
scheduler.WithPatchAnchorPlatformTransactionsCompletionJobOption(apAPIService, models),
scheduler.WithReadyPaymentsCancellationJobOption(models),
}, nil
}

Expand Down Expand Up @@ -244,19 +245,19 @@ func (c *ServeCommand) Command(serverService ServerServiceInterface, monitorServ
Required: true,
},
{
Name: "enable-mfa",
Usage: "Enable MFA using email.",
Name: "disable-mfa",
Usage: "Disables the email Multi-Factor Authentication (MFA).",
OptType: types.Bool,
ConfigKey: &serveOpts.EnableMFA,
FlagDefault: true,
ConfigKey: &serveOpts.DisableMFA,
FlagDefault: false,
Required: false,
},
{
Name: "enable-recaptcha",
Usage: "Enable ReCAPTCHA for login and forgot password.",
Name: "disable-recaptcha",
Usage: "Disables ReCAPTCHA for login and forgot password.",
OptType: types.Bool,
ConfigKey: &serveOpts.EnableReCAPTCHA,
FlagDefault: true,
ConfigKey: &serveOpts.DisableReCAPTCHA,
FlagDefault: false,
Required: false,
},
{
Expand Down
7 changes: 5 additions & 2 deletions cmd/serve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"bytes"
"context"
"fmt"
"sync"
"testing"

Expand Down Expand Up @@ -109,8 +110,8 @@ func Test_serve(t *testing.T) {
DistributionSeed: "SBHQEYSACD5DOK5I656NKLAMOHC6VT64ATOWWM2VJ3URGDGMVGNPG4ON",
ReCAPTCHASiteKey: "reCAPTCHASiteKey",
ReCAPTCHASiteSecretKey: "reCAPTCHASiteSecretKey",
EnableMFA: true,
EnableReCAPTCHA: true,
DisableMFA: false,
DisableReCAPTCHA: false,
}
var err error
serveOpts.AnchorPlatformAPIService, err = anchorplatform.NewAnchorPlatformAPIService(httpclient.DefaultClient(), serveOpts.AnchorPlatformBasePlatformURL, serveOpts.AnchorPlatformOutgoingJWTSecret)
Expand Down Expand Up @@ -186,6 +187,8 @@ func Test_serve(t *testing.T) {
t.Setenv("ANCHOR_PLATFORM_OUTGOING_JWT_SECRET", serveOpts.AnchorPlatformOutgoingJWTSecret)
t.Setenv("DISTRIBUTION_PUBLIC_KEY", serveOpts.DistributionPublicKey)
t.Setenv("DISTRIBUTION_SEED", serveOpts.DistributionSeed)
t.Setenv("DISABLE_MFA", fmt.Sprintf("%t", serveOpts.DisableMFA))
t.Setenv("DISABLE_RECAPTCHA", fmt.Sprintf("%t", serveOpts.DisableMFA))
t.Setenv("BASE_URL", serveOpts.BaseURL)
t.Setenv("RECAPTCHA_SITE_KEY", serveOpts.ReCAPTCHASiteKey)
t.Setenv("RECAPTCHA_SITE_SECRET_KEY", serveOpts.ReCAPTCHASiteSecretKey)
Expand Down
3 changes: 0 additions & 3 deletions dev/docker-compose-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@ services:
- "3000:80"
volumes:
- ./env-config.js:/usr/share/nginx/html/settings/env-config.js
depends_on:
- db
- sdp-api
Loading

0 comments on commit e12d7db

Please sign in to comment.