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

feat(backend,frontend,mock-ase): use hmac signature to secure admin api #2632

Merged
merged 8 commits into from
Apr 24, 2024

Conversation

njlie
Copy link
Contributor

@njlie njlie commented Apr 3, 2024

Changes proposed in this pull request

  • Adds middleware to the backend Admin Server that validates a signature comprised of a timestamp and a HMAC digest of the request body.
  • Adds an ApolloLink to the Apollo Clients of frontend and mock-ase that generates a signature from a timestamp and the request body.

Context

Fixes #2218 and fixes #2596 and fixes #2568.

This signature scheme is pulled from the one used for the webhook service on the backend:
https://github.com/interledger/rafiki/blob/main/packages/backend/src/webhook/service.ts#L218-L235

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Documentation added
  • Make sure that all checks pass
  • Bruno collection updated

@github-actions github-actions bot added pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. type: source Changes business logic pkg: mock-ase labels Apr 3, 2024
Copy link

netlify bot commented Apr 3, 2024

Deploy Preview for brilliant-pasca-3e80ec canceled.

Name Link
🔨 Latest commit 4483b51
🔍 Latest deploy log https://app.netlify.com/sites/brilliant-pasca-3e80ec/deploys/66280f9963250b0008e14660

@njlie njlie force-pushed the nl/2218/admin-api-security-signature branch 2 times, most recently from 92708f1 to 5474689 Compare April 11, 2024 17:07
@njlie njlie force-pushed the nl/2218/admin-api-security-signature branch from db0ea0b to 08c0fe9 Compare April 16, 2024 18:49
@njlie njlie marked this pull request as ready for review April 16, 2024 18:57
.replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key))
.replace(
/{{([A-Za-z]\w+)}}/g,
(_, key) => bru.getVar(key) || bru.getEnvVar(key)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bruno Collection variables take precedence over Bruno Environment Variables, per the docs.

Copy link
Member

Choose a reason for hiding this comment

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

But we don't have collection variables, do we?

Copy link
Contributor Author

@njlie njlie Apr 17, 2024

Choose a reason for hiding this comment

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

I didn't check every API request for this, but Deposit Asset Liquidity definitely does with transferId and idempotencyKey.

@@ -138,6 +138,8 @@ export const Config = {
signatureSecret: process.env.SIGNATURE_SECRET, // optional
signatureVersion: envInt('SIGNATURE_VERSION', 1),

apiSecret: process.env.API_SECRET, // optional
Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is that the apiSecret is an optional environment variable that secures the admin api if provided, and if not, it's unsecured. I'm just wondering if we want it to be secure by default instead? I guess this way is more backwards compatible I just find my initial assumptions were secure by default.

Noticed when I was surprised the integration tests didn't fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't remember where I heard this, but I had thought I'd heard at some point that securing the admin apio should be optional.

Copy link
Contributor

@BlairCurrey BlairCurrey Apr 17, 2024

Choose a reason for hiding this comment

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

Yeah I recall that as well. Just wondering if it should be opt-in or opt-out. It's not necessarily a suggestion, just thinking out loud.

I generally assume people should have to explicitly opt-out of the more secure way but perhaps in this specific case it doesnt matter? Since its currently insecure and not meant to be exposed to the internet. I think the configuration for opt-in (how you have it now) is probably simpler than enabling by default (by expecting apiSecret unless some additional env var is set to bypass it or something).

Comment on lines +29 to +58
const authLink = setContext((request, { headers }) => {
if (!process.env.SIGNATURE_SECRET || !process.env.SIGNATURE_VERSION)
return { headers }
const timestamp = Math.round(new Date().getTime() / 1000)
const version = process.env.SIGNATURE_VERSION

const { query, variables, operationName } = request
const formattedRequest = {
variables,
operationName,
query: print(query)
}

const payload = `${timestamp}.${canonicalize(formattedRequest)}`
const hmac = createHmac('sha256', process.env.SIGNATURE_SECRET)
hmac.update(payload)
const digest = hmac.digest('hex')

return {
headers: {
...headers,
signature: `t=${timestamp}, v${version}=${digest}`
}
}
})

const httpLink = createHttpLink({
uri: process.env.GRAPHQL_URL ?? 'http://localhost:3001/graphql'
})

Copy link
Contributor

@BlairCurrey BlairCurrey Apr 17, 2024

Choose a reason for hiding this comment

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

It would be nice if we could share this between frontend and mock-account-servicing-entity. And potentially integration in the future. I recall @sabineschaller brought up a similar need for something else recently (I don't recall what exactly).

I could definitely see a case for a lib, rafiki-lib, internal (to borrow a Go convention), or something else, where this and anything else we wanted to share internally (standardized pino log factory function?).

I guess we dont necessarily need to do that in this PR but but this certainly illustrates the point.

pnpm-workspace.yaml Outdated Show resolved Hide resolved
@njlie njlie force-pushed the nl/2218/admin-api-security-signature branch from f8aa97a to 1c3da27 Compare April 18, 2024 17:03
BlairCurrey
BlairCurrey previously approved these changes Apr 22, 2024
@njlie njlie force-pushed the nl/2218/admin-api-security-signature branch from 3be6f98 to f8e4101 Compare April 23, 2024 14:34
@njlie njlie force-pushed the nl/2218/admin-api-security-signature branch from f8e4101 to 4483b51 Compare April 23, 2024 19:44
@njlie njlie merged commit bf66c6b into main Apr 24, 2024
44 checks passed
@njlie njlie deleted the nl/2218/admin-api-security-signature branch April 24, 2024 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. pkg: mock-ase type: source Changes business logic
Projects
None yet
4 participants