Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3a1b976
feat(backend): create operator kratos identity on backend startup
njlie Aug 28, 2024
90373b3
chore: formatting
njlie Aug 28, 2024
9e403ac
fix: handle new cases
njlie Aug 28, 2024
350a0f4
feat(frontend,backend): tenant management api
njlie Aug 29, 2024
e4d0b9b
Add migration files
sanducb Aug 27, 2024
bd208cb
Update migration files
sanducb Aug 27, 2024
b311b5c
feat(tenant): basic tenant admin api schema and service
golobitch Aug 27, 2024
ee58eaf
Fix file name for migrations
sanducb Aug 27, 2024
7090b00
feat(auth): create basic tenant service and model plus graphql schema
golobitch Aug 27, 2024
78407d1
feat(auth): add basic tenant schema and appropriate resources like mo…
golobitch Aug 28, 2024
029099d
feat(backend): add apollo client do dependencies
golobitch Aug 28, 2024
ef7af00
feat(auth): delete tenant
golobitch Aug 28, 2024
607d650
chore(auth): format
golobitch Aug 28, 2024
54ae837
feat(backend): create tenant service implementation
golobitch Aug 28, 2024
41a7a15
feat(packages): make multi tenant work wip
golobitch Aug 28, 2024
a00dbc6
feat(backend): update resolvers with tenant id and finish the tenant …
golobitch Aug 29, 2024
3118adf
feat(backend): small changes to schema + mapping of tenant to graphql…
golobitch Aug 29, 2024
2655885
feat(backend,frontend): create kratos identity when tenants are creat…
njlie Aug 30, 2024
28c2533
fix: tenant service functions
njlie Sep 4, 2024
1afea35
feat: better kratos check conditionals
njlie Sep 6, 2024
b56ed94
fix: operator secret for non-session api calls
njlie Sep 10, 2024
6c40743
fix: wallet address tests
njlie Sep 10, 2024
4382f23
fix: wallet address model test fixes
njlie Sep 11, 2024
09436fc
fix: incoming payment tests
njlie Sep 11, 2024
5282e9f
fix: outgoing/quote tests
njlie Sep 11, 2024
1eccd3e
fix: combined payments tests
njlie Sep 11, 2024
27bbe04
fix(backend): non-OP resource test fixes
njlie Sep 12, 2024
bcc6bae
fix: receiver tests
njlie Sep 12, 2024
9340cd0
fix: wallet address keys
njlie Sep 12, 2024
5fed82c
fix: wallet address middleware tests
njlie Sep 12, 2024
bcb4204
fix: ilp payment method tests
njlie Sep 12, 2024
9f6bb0d
fix: assets, shared service tests
njlie Sep 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions localenv/cloud-nine-wallet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ services:
IDP_SECRET: 2pEcn2kkCclbOHQiGNEwhJ0rucATZhrA807HTm2rNXE=
DISPLAY_NAME: Cloud Nine Wallet
DISPLAY_ICON: wallet-icon.svg
OPERATOR_API_SECRET: tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E=
volumes:
- ../cloud-nine-wallet/seed.yml:/workspace/seed.yml
- ../cloud-nine-wallet/private-key.pem:/workspace/private-key.pem
Expand Down Expand Up @@ -79,6 +80,7 @@ services:
AUTH_ADMIN_API_SECRET: rPoZpe9tVyBNCigm05QDco7WLcYa0xMao7lO5KG1XG4=
OPERATOR_IDP_CONSENT_URL: http://localhost:3030/mock-idp/
OPERATOR_IDP_SECRET: 2pEcn2kkCclbOHQiGNEwhJ0rucATZhrA807HTm2rNXE=
OPERATOR_API_SECRET: tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E=
depends_on:
- shared-database
- shared-redis
Expand Down
2 changes: 2 additions & 0 deletions localenv/happy-life-bank/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ services:
IDP_SECRET: 2pEcn2kkCclbOHQiGNEwhJ0rucATZhrA807HTm2rNXE=
DISPLAY_NAME: Happy Life Bank
DISPLAY_ICON: bank-icon.svg
OPERATOR_API_SECRET: tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E=
volumes:
- ../happy-life-bank/seed.yml:/workspace/seed.yml
- ../happy-life-bank/private-key.pem:/workspace/private-key.pem
Expand Down Expand Up @@ -71,6 +72,7 @@ services:
AUTH_ADMIN_API_SECRET: rPoZpe9tVyBNCigm05QDco7WLcYa0xMao7lO5KG1XG4=
OPERATOR_IDP_CONSENT_URL: http://localhost:3031/mock-idp/
OPERATOR_IDP_SECRET: 2pEcn2kkCclbOHQiGNEwhJ0rucATZhrA807HTm2rNXE=
OPERATOR_API_SECRET: tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E=
depends_on:
- cloud-nine-backend
happy-life-auth:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ export const CONFIG: Config = {
testnetAutoPeerUrl: process.env.TESTNET_AUTOPEER_URL ?? '',
authServerDomain: process.env.AUTH_SERVER_DOMAIN || 'http://localhost:3006',
graphqlUrl: process.env.GRAPHQL_URL ?? '',
idpSecret: process.env.IDP_SECRET
idpSecret: process.env.IDP_SECRET,
operatorApiSecret: process.env.OPERATOR_API_SECRET ?? ''
}
12 changes: 12 additions & 0 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ export function initIocContainer(
}
)

container.singleton(
'tenantService',
async (deps: IocContract<AppServices>) => {
const [logger, knex] = await Promise.all([
deps.use('logger'),
deps.use('knex')
])

return createTenantService({ logger, knex })
}
)

container.singleton(
'accessService',
async (deps: IocContract<AppServices>) => {
Expand Down
1 change: 1 addition & 0 deletions packages/backend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ process.env.AUTH_ADMIN_URL = 'http://127.0.0.1:3003/graphql'
process.env.AUTH_ADMIN_API_SECRET =
'rPoZpe9tVyBNCigm05QDco7WLcYa0xMao7lO5KG1XG4='
process.env.KRATOS_PUBLIC_URL = 'http://127.0.0.1:4433/graphql'
process.env.OPERATOR_API_SECRET = 'tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E='

module.exports = {
...baseConfig,
Expand Down
23 changes: 17 additions & 6 deletions packages/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ import { TelemetryService } from './telemetry/service'
import { ApolloArmor } from '@escape.tech/graphql-armor'
import { openPaymentsServerErrorMiddleware } from './open_payments/route-errors'
import {
// getTenantIdFromRequestHeaders,
getTenantIdFromOperatorSecret,
getTenantIdFromRequestHeaders,
verifyApiSignature
} from './shared/utils'
import { WalletAddress } from './open_payments/wallet_address/model'
Expand Down Expand Up @@ -427,11 +428,21 @@ export class App {
}

// Determine Kratos Identity
// TODO: Comment out for now until seed script has a good way to acquire a kratos session
// koa.use(async (ctx: TenantedAppContext, next: Koa.Next): Promise<void> => {
// await getTenantIdFromRequestHeaders(ctx, this.config)
// return next()
// })
// TODO: We need a better solution for non-session-based authentication (i.e. requests not using a Kratos session)
koa.use(async (ctx: TenantedAppContext, next: Koa.Next): Promise<void> => {
const { headers } = ctx.request
this.logger.info(
{ headers, operatorApiSecret: this.config.operatorApiSecret },
'checking for secret'
)
if (headers['x-operator-secret'] === this.config.operatorApiSecret) {
await getTenantIdFromOperatorSecret(ctx, this.config)
return next()
} else {
await getTenantIdFromRequestHeaders(ctx, this.config)
return next()
}
})

koa.use(
koaMiddleware(this.apolloServer, {
Expand Down
22 changes: 22 additions & 0 deletions packages/backend/src/asset/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { WalletAddressService } from '../open_payments/wallet_address/service'
import { isWalletAddressError } from '../open_payments/wallet_address/errors'
import { PeerService } from '../payment-method/ilp/peer/service'
import { isPeerError } from '../payment-method/ilp/peer/errors'
import { createTenant } from '../tests/tenant'
import { EndpointType } from '../tenant/endpoints/model'

describe('Asset Service', (): void => {
let deps: IocContract<AppServices>
Expand Down Expand Up @@ -271,9 +273,29 @@ describe('Asset Service', (): void => {
assert.ok(!isAssetError(newAsset))
const newAssetId = newAsset.id

const nock = (global as unknown as { nock: typeof import('nock') }).nock
const config = await deps.use('config')
const tenantEmail = faker.internet.email()
nock(config.kratosAdminUrl)
.get('/identities')
.query({ credentials_identifier: tenantEmail })
.reply(200, [{ id: uuid(), metadata_public: {} }])
.persist()
const tenantId = (
await createTenant(deps, {
email: tenantEmail,
idpSecret: 'testsecret',
idpConsentEndpoint: faker.internet.url(),
endpoints: [
{ type: EndpointType.WebhookBaseUrl, value: faker.internet.url() }
]
})
).id

// make sure there is at least 1 wallet address using asset
const walletAddress = walletAddressService.create({
url: 'https://alice.me/.well-known/pay',
tenantId,
assetId: newAssetId
})
assert.ok(!isWalletAddressError(walletAddress))
Expand Down
5 changes: 4 additions & 1 deletion packages/backend/src/config/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ export const Config = {
kratosAdminUrl: envString('KRATOS_ADMIN_URL'),
kratosAdminEmail: envString('KRATOS_ADMIN_EMAIL'),
operatorIdpSecret: envString('OPERATOR_IDP_SECRET'),
operatorIdpConsentUrl: envString('OPERATOR_IDP_CONSENT_URL')
operatorIdpConsentUrl: envString('OPERATOR_IDP_CONSENT_URL'),
// TODO: something more permanent & agreed upon by the team
// Used by seed scripts/Bruno collection
operatorApiSecret: envString('OPERATOR_API_SECRET')
}

function parseRedisTlsConfig(
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,9 @@ export const start = async (
await app.startAdminServer(config.adminPort)
logger.info(`Admin listening on ${app.getAdminPort()}`)

await app.createOperatorIdentity()
logger.info('Operator identity created on Kratos')

await app.startOpenPaymentsServer(config.openPaymentsPort)
logger.info(`Open Payments listening on ${app.getOpenPaymentsPort()}`)

Expand All @@ -755,9 +758,6 @@ export const start = async (
`Auto-peering server listening on ${config.autoPeeringServerPort}`
)
}

await app.createOperatorIdentity()
logger.info('Operator identity created on Kratos')
}

// If this script is run directly, start the server
Expand Down
21 changes: 20 additions & 1 deletion packages/backend/src/open_payments/auth/middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { parseLimits } from '../payment/outgoing/limits'
import { AccessAction, AccessType } from '@interledger/open-payments'
import { OpenPaymentsServerRouteError } from '../route-errors'
import assert from 'assert'
import { createTenant } from '../../tests/tenant'
import { EndpointType } from '../../tenant/endpoints/model'

const nock = (global as unknown as { nock: typeof import('nock') }).nock

Expand Down Expand Up @@ -71,14 +73,31 @@ describe('Auth Middleware', (): void => {
})

beforeEach(async (): Promise<void> => {
const config = await deps.use('config')
const tenantEmail = faker.internet.email()
nock(config.kratosAdminUrl)
.get('/identities')
.query({ credentials_identifier: tenantEmail })
.reply(200, [{ id: uuid(), metadata_public: {} }])
.persist()
const tenantId = (
await createTenant(deps, {
email: tenantEmail,
idpSecret: 'testsecret',
idpConsentEndpoint: faker.internet.url(),
endpoints: [
{ type: EndpointType.WebhookBaseUrl, value: faker.internet.url() }
]
})
).id
ctx = setup({
reqOpts: {
headers: {
Accept: 'application/json',
Authorization: `GNAP ${token}`
}
},
walletAddress: await createWalletAddress(deps)
walletAddress: await createWalletAddress(deps, tenantId)
})
ctx.container = deps
})
Expand Down
Loading