From 40228ed7be2d62d4d091f6b2bb0b085ecfafecae Mon Sep 17 00:00:00 2001 From: Heiko Burkhardt Date: Fri, 10 Nov 2023 09:28:48 +0100 Subject: [PATCH] feat: support https --- .github/workflows/deploy-billboard.yml | 25 ++++++++------- docker/billboard/docker-compose.yml | 26 ++++++++++++++-- docker/billboard/nginx.conf | 31 ++++++++++++++++--- .../src/rpc/methods/handleSubmitMessage.ts | 2 +- packages/lib/delivery/src/Messages.ts | 9 ++++++ packages/lib/delivery/src/Session.ts | 18 ++++++++++- packages/lib/delivery/src/UserProfile.ts | 5 ++- .../offchain-resolver/src/http/profile.ts | 10 +++--- 8 files changed, 101 insertions(+), 25 deletions(-) diff --git a/.github/workflows/deploy-billboard.yml b/.github/workflows/deploy-billboard.yml index 73fd3719a..fa24a35df 100644 --- a/.github/workflows/deploy-billboard.yml +++ b/.github/workflows/deploy-billboard.yml @@ -2,10 +2,10 @@ name: Staging billboard deploy on: push jobs: - messenger-demo-deploy: + billboard-deploy: + environment: staging-billboard runs-on: ubuntu-latest # if: ${{ contains( github.ref, vars.STAGING_BRANCH) }} - environment: staging-billboard steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v3 @@ -28,15 +28,16 @@ jobs: - name: Create .env file env: TARGET_HOST: ${{ secrets.STAGING_HOST }} + TARGET_IP: ${{ secrets.IP_ADDRESS }} run: | - echo "REACT_APP_ADDR_ENS_SUBDOMAIN=.bb-addr.dm3.eth" >> ./.env.react - echo "REACT_APP_BACKEND=http://${{ secrets.STAGING_HOST }}/api" >> ./.env.react - echo "REACT_APP_DEFAULT_DELIVERY_SERVICE=beta-ds.dm3.eth" >> ./.env.react - echo "REACT_APP_DEFAULT_SERVICE=http://${{ secrets.STAGING_HOST }}/api" >> ./.env.react + echo "REACT_APP_ADDR_ENS_SUBDOMAIN=.addr.devconnect.dm3.eth" >> ./.env.react + echo "REACT_APP_BACKEND=https://${{ secrets.STAGING_HOST }}/api" >> ./.env.react + echo "REACT_APP_DEFAULT_DELIVERY_SERVICE=bb-ds.devconnect.dm3.eth" >> ./.env.react + echo "REACT_APP_DEFAULT_SERVICE=https://${{ secrets.STAGING_HOST }}/api" >> ./.env.react echo "REACT_APP_ETHEREUM_PROVIDER=${{ secrets.REACT_APP_ETHEREUM_PROVIDER }}" >> ./.env.react - echo "REACT_APP_PROFILE_BASE_URL=http://${{ secrets.STAGING_HOST }}/api" >> ./.env.react - echo "REACT_APP_RESOLVER_BACKEND=http://${{ secrets.STAGING_HOST }}/resolver-handler" >> ./.env.react - echo "REACT_APP_USER_ENS_SUBDOMAIN=.beta-user.dm3.eth" >> ./.env.react + echo "REACT_APP_PROFILE_BASE_URL=https://${{ secrets.STAGING_HOST }}/api" >> ./.env.react + echo "REACT_APP_RESOLVER_BACKEND=https://${{ secrets.STAGING_HOST }}/resolver-handler" >> ./.env.react + echo "REACT_APP_USER_ENS_SUBDOMAIN=.user.devconnect.dm3.eth" >> ./.env.react echo "REACT_APP_WALLET_CONNECT_PROJECT_ID=${{ secrets.REACT_APP_WALLET_CONNECT_PROJECT_ID }}" >> ./.env.react echo "REACT_APP_COMMIT_HASH=${{ env.sha_short }}" >> ./.env.react echo "REACT_APP_BRANCH=${{ env.branch }}" >> ./.env.react @@ -55,7 +56,9 @@ jobs: echo "interceptor=${{ secrets.INTERCEPTOR }}" >> ./.env echo "DISABLE_SESSION_CHECK='true'" >> ./.env echo "BILLBOARD_NAMES=${{ secrets.BILLBOARD_NAMES }}" >> ./.env - envsubst '${SSL_CERTIFICATE_BASE_LOC} ${TLS_CERTIFICATE_LOCATION} ${TARGET_HOST}' < ./docker/billboard/nginx.conf > ./nginx.conf + echo "CERT_MAIL=${{ secrets.CERT_MAIL }}" >> ./.env + echo "URL=${{ secrets.STAGING_HOST }}" >> ./.env + envsubst '${TARGET_HOST}' < ./docker/billboard/nginx.conf > ./nginx.conf cat ./.env - name: Build docker image run: | @@ -82,7 +85,7 @@ jobs: - name: Firewall config run: | ssh -i ./ssh-key root@${{ secrets.STAGING_HOST }} "\ - ufw allow from 172.18.0.1/16 proto tcp to ${{ secrets.STAGING_HOST }} port 80" + ufw allow from 172.18.0.1/16 proto tcp to ${{ secrets.IP_ADDRESS }} port 80" - name: Start run: | ssh -i ./ssh-key app@${{ secrets.STAGING_HOST }} "\ diff --git a/docker/billboard/docker-compose.yml b/docker/billboard/docker-compose.yml index 24bfb91e5..adf1f4eee 100644 --- a/docker/billboard/docker-compose.yml +++ b/docker/billboard/docker-compose.yml @@ -11,6 +11,9 @@ services: - ccip-resolver volumes: - ./nginx.conf:/etc/nginx/nginx.conf + - web-root:/var/www/html + - certbot-etc:/etc/letsencrypt + - certbot-var:/var/lib/letsencrypt ports: - "80:80" - "443:443" @@ -92,6 +95,17 @@ services: # REACT_APP_WALLET_CONNECT_PROJECT_ID: ${REACT_APP_WALLET_CONNECT_PROJECT_ID} # RESOLVER_ADDR: ${RESOLVER_ADDR} + certbot: + image: certbot/certbot + container_name: certbot + volumes: + - certbot-etc:/etc/letsencrypt + - certbot-var:/var/lib/letsencrypt + - web-root:/var/www/html + depends_on: + - nginx + command: certonly --webroot --webroot-path=/var/www/html --email ${CERT_MAIL} --agree-tos --no-eff-email -d ${URL} + ccip-resolver: image: dm3org/ccip-resolver:v0.2.7 restart: always @@ -103,10 +117,18 @@ services: LOG_LEVEL: debug CONFIG: | { - "0x26139b2349282de5ee2bd9c7a53171a28d6a6c84": { + "0xc9bf092673b3a066df088a2a911e23e9b69b82f2": { "type": "signing", "handlerUrl": "http://offchain-resolver:8082" } } PORT: 8181 - +volumes: + certbot-etc: + certbot-var: + web-root: + driver: local + driver_opts: + type: none + device: /home/app/dm3/webroot/ + o: bind diff --git a/docker/billboard/nginx.conf b/docker/billboard/nginx.conf index 9f0ade838..5a89fbdcc 100644 --- a/docker/billboard/nginx.conf +++ b/docker/billboard/nginx.conf @@ -11,6 +11,23 @@ http { listen 80; server_name ${TARGET_HOST}; + return 301 https://$server_name$request_uri; + } + + server { + listen 80; + server_name ${TARGET_IP}; + + return 301 https://${TARGET_HOST}$request_uri; + } + + server { + listen 443 ssl; + server_name ${TARGET_HOST}; + + ssl_certificate /etc/letsencrypt/live/${TARGET_HOST}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${TARGET_HOST}/privkey.pem; + # location / { # limit_req zone=standardlimit burst=50; # proxy_pass http://web:8080; @@ -30,7 +47,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_ssl_verify off; proxy_redirect off; } @@ -42,7 +59,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_ssl_verify off; proxy_redirect off; } @@ -54,7 +71,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_ssl_verify off; proxy_redirect off; } @@ -66,7 +83,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_ssl_verify off; proxy_redirect off; } @@ -79,6 +96,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; + proxy_ssl_verify off; proxy_set_header Host $host; } @@ -95,6 +113,11 @@ http { proxy_set_header Host $host; } + location ~ /.well-known/acme-challenge { + allow all; + root /var/www/html; + } + } } \ No newline at end of file diff --git a/packages/backend/src/rpc/methods/handleSubmitMessage.ts b/packages/backend/src/rpc/methods/handleSubmitMessage.ts index f0edcd138..e7f737bff 100644 --- a/packages/backend/src/rpc/methods/handleSubmitMessage.ts +++ b/packages/backend/src/rpc/methods/handleSubmitMessage.ts @@ -62,7 +62,7 @@ export async function handleSubmitMessage( } catch (error) { global.logger.warn({ method: 'RPC SUBMIT MESSAGE', - error, + error: JSON.stringify(error), }); logError({ text: '[handleSubmitMessage]', diff --git a/packages/lib/delivery/src/Messages.ts b/packages/lib/delivery/src/Messages.ts index 6a9edb108..cce392eb9 100644 --- a/packages/lib/delivery/src/Messages.ts +++ b/packages/lib/delivery/src/Messages.ts @@ -138,12 +138,18 @@ export async function incomingMessage( if (!tokenIsValid) { //Token is invalid + logDebug({ + text: 'incomingMessage token invalid', + }); throw Error('Token check failed'); } //Retrives the session of the receiver const receiverSession = await getSession(deliveryInformation.to); if (!receiverSession) { + logDebug({ + text: 'incomingMessage unknown session', + }); throw Error('unknown session'); } logDebug({ @@ -155,6 +161,9 @@ export async function incomingMessage( //Checkes if the message is spam if (await isSpam(provider, receiverSession, deliveryInformation)) { + logDebug({ + text: 'incomingMessage is spam', + }); throw Error('Message does not match spam criteria'); } diff --git a/packages/lib/delivery/src/Session.ts b/packages/lib/delivery/src/Session.ts index 427687456..fec298b0b 100644 --- a/packages/lib/delivery/src/Session.ts +++ b/packages/lib/delivery/src/Session.ts @@ -1,5 +1,6 @@ import { ethers } from 'ethers'; import { ProfileExtension, SignedUserProfile } from 'dm3-lib-profile'; +import { logDebug } from 'dm3-lib-shared'; //1Year const TTL = 31536000000; @@ -23,17 +24,26 @@ export async function checkToken( ensName: string, token: string, ): Promise { + logDebug({ + text: 'checkToken', + }); const address = await provider.resolveName(ensName); if (!address) { // Couln't resolve ENS name + logDebug({ + text: `checkToken - Couln't resolve ENS name`, + }); return false; } const session = await getSession(ensName.toLocaleLowerCase()); - //There is now account for the requesting accoung + //There is no account for the requesting accoung if (!session) { + logDebug({ + text: `checkToken - There is no account for the requesting accoung`, + }); return false; } @@ -41,12 +51,18 @@ export async function checkToken( //The account has a session but the token is wrong if (!tokenIsValid) { + logDebug({ + text: `checkToken - The account has a session but the token is wrong`, + }); return false; } const isTokenExpired = session.createdAt + TTL < new Date().getTime(); //The token is exceeded if (isTokenExpired) { + logDebug({ + text: `checkToken - The token is exceeded`, + }); return false; } diff --git a/packages/lib/delivery/src/UserProfile.ts b/packages/lib/delivery/src/UserProfile.ts index b5e57459f..15a1ba685 100644 --- a/packages/lib/delivery/src/UserProfile.ts +++ b/packages/lib/delivery/src/UserProfile.ts @@ -7,6 +7,7 @@ import { getDefaultProfileExtension } from 'dm3-lib-profile'; import { Session } from './Session'; import { v4 as uuidv4 } from 'uuid'; import { ethers } from 'ethers'; +import { logDebug } from 'dm3-lib-shared'; const handlePendingConversations = async ( ensName: string, @@ -40,6 +41,7 @@ export async function submitUserProfile( const account = normalizeEnsName(ensName); if (!(await checkUserProfile(provider, signedUserProfile, account))) { + logDebug('submitUserProfile - Signature invalid'); throw Error('Signature invalid.'); } //TODO: remvoe DISABLE_SESSION_CHECK @@ -48,6 +50,7 @@ export async function submitUserProfile( process.env.DISABLE_SESSION_CHECK !== 'true' && (await getSession(account)) ) { + logDebug('submitUserProfile - Profile exists already'); throw Error('Profile exists already'); } const session: Session = { @@ -57,7 +60,7 @@ export async function submitUserProfile( createdAt: new Date().getTime(), profileExtension: getDefaultProfileExtension(), }; - + logDebug({ text: 'submitUserProfile', session }); await setSession(account.toLocaleLowerCase(), session); await handlePendingConversations( account, diff --git a/packages/offchain-resolver/src/http/profile.ts b/packages/offchain-resolver/src/http/profile.ts index f2f8a23bd..85643b61b 100644 --- a/packages/offchain-resolver/src/http/profile.ts +++ b/packages/offchain-resolver/src/http/profile.ts @@ -87,17 +87,17 @@ export function profile(web3Provider: ethers.providers.BaseProvider) { } global.logger.debug({ message: 'nameP setAlias', - hotAddr: hotAddr + '.bb-addr.dm3.eth', - alias: `${address}.bb-user.dm3.eth`, + hotAddr: hotAddr + '.addr.devconnect.dm3.eth', + alias: `${address}.user.devconnect.dm3.eth`, }); await req.app.locals.db.removeAlias( - `${address}.bb-user.dm3.eth`, + `${address}.user.devconnect.dm3.eth`, ); await req.app.locals.db.setAlias( - hotAddr + '.bb-addr.dm3.eth', - `${address}.bb-user.dm3.eth`, + hotAddr + '.addr.devconnect.dm3.eth', + `${address}.user.devconnect.dm3.eth`, ); return res.sendStatus(200);