Skip to content

Commit

Permalink
WeatherComputer client validation and deployment workflow changes (#21)
Browse files Browse the repository at this point in the history
* feat: auth: add client validation for weather computer

* fix: weather-data: include author when querying for duplicate data on commit

* chore: ci authenticated through GCP WFI

* fix: issues in github workflow

* fix: set permissions in github workflow

* fix: use node 20 following github workflow removing support for node 16

* fix: debug github workflow cannot find package.json error

* fix: use GCP WFI instead of firebase token to deploy

* fix: debug github workflow env vars not set

* fix: debug github workflow use wfi instead of firebase token

* chore: use service account for authenticating through wif

* chore: workflow authentication with latest tools

* chore: workflow authentication using service account key

* chore: deploy debug workflow

* chore: deploy workflow with env vars

* docs: deploy workflow config
  • Loading branch information
lihini authored Apr 26, 2024
1 parent a49b86b commit d106404
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 27 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/configuring-workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Deploying the project to Firebase Functions

Github actions are configured through `firebase-deploy.yml` to deploy dev and prod environments to firebase.

Service account authentication is used to authenticate Github with Firebase (GCP) because Workload Identity Federation is not yet supported by Firebase API.

## Instructions
1. Create a Google Cloud Service Account with following permissions.
- Cloud Functions Developer
- Cloud Scheduler Admin
- Service Account User
2. Create service account key
3. Copy the JSON and update Github secret `GITHUBDEPLOY_GCP_SERVICE_ACCOUNT`


For future references:
- [Workload Identity Federation: Howto](https://github.com/google-github-actions/auth?tab=readme-ov-file)
- [Using WIF from Github actions - notes](https://medium.com/@bbeesley/notes-on-workload-identity-federation-from-github-actions-to-google-cloud-platform-7a818da2c33e)
38 changes: 30 additions & 8 deletions .github/workflows/firebase-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,40 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: '16'
- name: Install dependencies.
run: npm install
node-version: 20
- name: Set correct firebase project based on git branch.
run: echo "FIREBASE_PROJECT=$(if [ ${{ github.ref }} == 'refs/heads/main' ]; then echo 'prod'; else echo 'dev'; fi)" >> $GITHUB_ENV
- name: Install dependencies.
run: npm ci
- name: Set env vars
run: |
if [ ${{ github.ref }} == 'refs/heads/main' ]; then
DB=${{ secrets.WEATHERKIDS_DB_URL_PROD }}
FILE='.env.prod'
JWTSECRET=${{ secrets.WEATHERKIDS_JWT_SECRET_PROD }}
else
DB=${{ secrets.WEATHERKIDS_DB_URL_DEV }}
FILE='.env.dev'
JWTSECRET=secret
fi
echo "DB_FOR_BRANCH=$DB" >> $GITHUB_ENV
echo "FILE_FOR_BRANCH=$FILE" >> $GITHUB_ENV
echo "SECRET_FOR_BRANCH=$JWTSECRET" >> $GITHUB_ENV
- name: Make envfile
uses: SpicyPizza/[email protected]
with:
file_name: ${{ env.FILE_FOR_BRANCH }}
envkey_MOBILE_CLIENT_ID: ${{ secrets.MOBILE_CLIENT_ID }}
envkey_WEATHERCOM_CLIENT_ID: ${{ secrets.WEATHERCOM_CLIENT_ID }}
envkey_MONGO_URL: ${{ env.DB_FOR_BRANCH }}
envkey_JWT_SECRET: ${{ env.SECRET_FOR_BRANCH }}
- name: Deploy to firebase cloud functions.
uses: w9jds/firebase-action@v13.4.0
uses: w9jds/firebase-action@v13.6.0
with:
args: deploy --only functions --project ${{ env.FIREBASE_PROJECT }}
args: deploy --only functions --project ${{ env.FIREBASE_PROJECT }} --non-interactive
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
GCP_SA_KEY: ${{ secrets.GITHUBDEPLOY_GCP_SERVICE_ACCOUNT }}
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "weatherkids-data-api",
"version": "0.0.5",
"version": "0.0.6",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"main": "dist/index.js",
"engines": {
"node": "16"
"node": "20"
},
"scripts": {
"build": "nest build",
Expand Down
15 changes: 7 additions & 8 deletions src/modules/common/guards/gavesha-client.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ export class ValidateGaveshaClientGuard implements CanActivate {
// This guard will protect the routes that require a Gavesha client such as the Gavesha mobile app.
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
try {
// Assume we want to check the client id of the request source to be the Gavesha mobile app.
await this.tokenService.validateMobileClientId(
request.headers['client-id'],
);
const header = request.headers['client-id'];
if (this.tokenService.validateMobileClientId(header)) {
return true;
} catch (error) {
console.error('Error validating admin user', error);
throw new HttpException(error, 401);
} else if (this.tokenService.validateComClientId(header)) {
return true;
} else {
console.error('Error validating client: ', header);
throw new HttpException('Invalid Client Id', 401);
}
}
}
12 changes: 7 additions & 5 deletions src/modules/users/token/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ export class TokenService {
return user;
}

public async validateMobileClientId(clientId: string) {
if (clientId !== process.env.MOBILE_CLIENT_ID) {
throw new HttpException('Invalid Mobile Client Id', 401);
}
public validateMobileClientId(clientId: string) {
return clientId === process.env.MOBILE_CLIENT_ID;
}

public validateComClientId(clientId: string) {
return clientId === process.env.WEATHERCOM_CLIENT_ID;
}
}
}
3 changes: 2 additions & 1 deletion src/modules/weather-data/weather-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class WeatherDataService {
timestamp: {
$in: data.map((datum) => datum.timestamp),
},
'metadata.author_user_id': author_user_id,
})
.exec();

Expand Down Expand Up @@ -269,7 +270,7 @@ export class WeatherDataService {
weatherStationId: string,
): Promise<GetWeatherDatumDto> {
const datum = (await this.weatherDatumModel
.findOne({ "metadata.weather_station_id": weatherStationId })
.findOne({ 'metadata.weather_station_id': weatherStationId })
.sort({ timestamp: -1 })
.exec()) as WeatherDatum;

Expand Down

0 comments on commit d106404

Please sign in to comment.