diff --git a/.env.example b/.env.example index c32af84..538328c 100644 --- a/.env.example +++ b/.env.example @@ -29,3 +29,5 @@ S3_CF_DIST_URL=https://xxxx.poapper.club # This needs only for local development AWS_ACCESS_KEY_ID=xxxx AWS_SECRET_ACCESS_KEY=xxxx + +NODE_ENV=local diff --git a/.gitignore b/.gitignore index 46a8775..95e7be6 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ lerna-debug.log* .env .env* *.sql + +# local certs +*.csr +*.pem diff --git a/local-certs/README.md b/local-certs/README.md new file mode 100644 index 0000000..14e26fb --- /dev/null +++ b/local-certs/README.md @@ -0,0 +1,63 @@ +# How to setup local certificates + +로컬에서 popo-nest-api 서버를 개발할 때, https를 적용하는 방법에 대해 다룹니다. + +요걸 세팅 해야 popo-{public, admin}-web에서 HTTPS 엔드포인트를 요구하는 각종 auth 및 cookie 기반 Request를 로컬에서도 테스트 할 수 있습니다. + +## Generate Self-signed certificates + +```sh +# 폴더 이동 +$ cd local-certs + +# 개인키 생성 +$ openssl genrsa -out private-key.pem 2048 + +# 개인키를 사용한 새로운 인증서 요청서 생성 +$ openssl req -new -key private-key.pem -out cert-request.csr + +# 요청서를 사용한 자체 서명 인증서 생성 +$ openssl x509 -req -in cert-request.csr -signkey private-key.pem -out cert.pem +``` + +본래 Production 서비스는 권위 있는 기관에 SSL Cert의 서명을 받아야 한다. +그러나 로컬에서는 그런게 필요없기 때문에 Self-signed SSL Cert를 사용해도 충분하다. + +## Setup HTTPS on NestJS Application + +`main.ts` 폴더에 아래 코드를 작성한다. 참고로 현재 POPO 코드에서는 아래 내용이 이미 반영 되어 있다. 따로 작업할 필요는 X + +```ts +import * as fs from "fs"; +import * as https from "https"; + +async function bootstrap() { + const httpsOptions = { + key: fs.readFileSync("./private-key.pem"), + cert: fs.readFileSync("./cert.pem"), + }; + const app = await NestFactory.create(AppModule, { + httpsOptions, + }); + await app.listen(3000); +} +bootstrap(); +``` + +위의 것까지만 하고 로컬에서 `npm run start:dev`를 실행하면, `https://localhost:4000`에 popo-nest-api 서버가 구동된다. + +POPO 코드에서는 `NODE_ENV=local`이어야 제대로 동작한다. `.env` 파일에 아래 내용을 추가하자. + +```sh +NODE_ENV=local +``` + +## Setup HTTPS on Client-side + +로컬 HTTPS를 제대로 활용하려면, 클라이언트 사이드(public & admin web)에서도 HTTPS를 세팅해야 한다. + +클라이언트 사이드에서 HTTPS를 세팅 하는 방법은 그쪽 레포의 README를 읽어보자. + +세팅 후에 클라이언트에서 요청하는 로컬 popo-nest-api 서버의 주소가 `http://localhost:4000`에서 `https://localhost:4000`으로 바뀌어야 한다는 것도 잊지 말자!! + + diff --git a/src/main.ts b/src/main.ts index cda90f6..3a10adf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,26 +3,45 @@ import { AppModule } from './app.module'; import * as cookieParser from 'cookie-parser'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; +import * as fs from 'fs'; +import { INestApplication } from '@nestjs/common'; + async function bootstrap() { - const app = await NestFactory.create(AppModule); + let app: INestApplication; + const isLocalDeploy = process.env.NODE_ENV == 'local'; + if (isLocalDeploy) { + const httpsOptions = { + key: fs.readFileSync("./local-certs/private-key.pem"), + cert: fs.readFileSync("./local-certs/cert.pem"), + }; + app = await NestFactory.create(AppModule, { httpsOptions }); + } else { + app = await NestFactory.create(AppModule); + } + app.use(cookieParser()); - app.enableCors({ - origin: [ - 'http://localhost:3000', - 'http://localhost:3001', - 'https://localhost:3000', - 'https://localhost:3001', - - 'https://popo.poapper.club', - 'https://popo-dev.poapper.club', - - 'https://admin.popo.poapper.club', - 'https://admin.popo-dev.poapper.club', - - 'https://popo.postech.ac.kr', - ], - credentials: true, - }); + + if (isLocalDeploy) { + app.enableCors({ + origin: [ + 'https://localhost:3000', + 'https://localhost:3001', + ], + credentials: true, + }); + + } else { + app.enableCors({ + origin: [ + 'https://popo.poapper.club', + 'https://popo-dev.poapper.club', + 'https://admin.popo.poapper.club', + 'https://admin.popo-dev.poapper.club', + 'https://popo.postech.ac.kr', + ], + credentials: true, + }); + } const swaggerConfig = new DocumentBuilder() .setTitle('POPO API')