Skip to content
Snippets Groups Projects
Commit a20aa27a authored by zdravko iliev's avatar zdravko iliev
Browse files

feat: add principal manager and infra repo into compose dir, fix docker images

parent 576d95f5
No related branches found
No related tags found
1 merge request!6feat: add principal manager
Showing
with 1117 additions and 65 deletions
......@@ -3,7 +3,23 @@
#### Dependencies
Node 12
Python 2.5.0 >= <3.0.0
pnpm
### Installation
### Setup local
1. pnpm install
2. pnpm prisma:generate
3. pnpm /app/:build
app options: attestation, connection, principal, ssi
### Docker compose
1. Go to compose dir
2. docker-compose up
## Example Flows (OCM Usage)
Please refer to [OCM-flow-overview](documentation/ocm-flow-overview.md)
yarn
FROM node:20-alpine3.16 AS builder
FROM node:16-slim AS builder
WORKDIR /usr/src/app
RUN yarn global add @nestjs/cli
RUN apt-get update
RUN apt-get install -y openssl
COPY package.json ./
COPY yarn.lock ./
WORKDIR /app
# --prod works if @types/node is in deps (not devDeps)
RUN yarn --frozen-lockfile --prod
RUN npm i -g pnpm
COPY . .
RUN yarn prisma:generate
RUN pnpm install
RUN pnpm -F attestation-manager prisma:generate
RUN yarn build
RUN pnpm -F attestation-manager build
FROM node:16-slim
RUN apt-get update
RUN apt-get install -y openssl
FROM node:14-alpine3.15
ENV PATH /usr/src/app/node_modules/.bin:$PATH
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/dist ./dist
COPY --from=builder /usr/src/app/start.sh ./start.sh
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/src/prisma prisma
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/start.sh ./start.sh
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/src/prisma prisma
EXPOSE 3005
......
FROM node:14-alpine3.15
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json ./
COPY yarn.lock ./
COPY . .
RUN yarn
RUN yarn prisma:generate
EXPOSE 3005
CMD ["yarn", "start:docker"]
FROM node:16-alpine3.15 AS builder
FROM node:16-slim AS builder
WORKDIR /usr/src/app
RUN yarn global add @nestjs/cli
RUN apt-get update
RUN apt-get install -y openssl
COPY package.json ./
COPY yarn.lock ./
WORKDIR /app
# --prod works if @types/node is in deps (not devDeps)
RUN yarn --frozen-lockfile --prod
RUN npm i -g pnpm
COPY . .
RUN yarn prisma:generate
RUN pnpm install
RUN pnpm -F connection-manager prisma:generate
RUN yarn build
RUN pnpm -F connection-manager build
FROM node:16-slim
RUN apt-get update
RUN apt-get install -y openssl
FROM node:14-alpine3.15
ENV PATH /usr/src/app/node_modules/.bin:$PATH
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/dist ./dist
COPY --from=builder /usr/src/app/start.sh ./start.sh
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/src/prisma prisma
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/start.sh ./start.sh
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/src/prisma prisma
EXPOSE 3003
RUN chmod +x ./start.sh
CMD ["./start.sh"]
CMD ["./start.sh"]
\ No newline at end of file
FROM node:16-alpine3.15
WORKDIR /usr/src/app
COPY . .
RUN pnpm install --frozen-lockfile
RUN pnpm -F connection-manager build
EXPOSE 3003
CMD ["pnpm", "-F", "connection-manager", "start:docker"]
Dockerfile
Jenkinsfile
coverage
docker-compose.yml
docs
node_modules
yarn-error.log
*.md
!README.md
.circle*
.codecov*
.coveralls*
.dockerignore
.drone*
.editorconfig
# .env
.git*
.huskyrc*
.lintstagedrc*
.npmignore
.prettierrc*
dist
\ No newline at end of file
PORT=3008
DATABASE_URL=postgresql://root:password@localhost:5432/postgres?schema=principal
ECSURL=http://localhost:9200/
CONNECTION_MANAGER_URL=http://3.111.77.38:3003
ATTESTATION_MANAGER_URL=http://3.111.77.38:3005
NATS_URL=nats://localhost:4222
USE_AUTH=false
OAUTH_CLIENT_ID=clientid
OAUTH_CLIENT_SECRET=clientsecret
OAUTH_TOKEN_URL=https://tokenurl
\ No newline at end of file
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'airbnb-base',
'airbnb-typescript/base',
],
parserOptions: {
project: './tsconfig.json',
},
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
{
"singleQuote": true,
"trailingComma": "all"
}
\ No newline at end of file
# GDPR Compliance Document
The objective of this document is to detail, the data being stored and proccessed by the Organization Credential Manager's, Principal Manger.
## What information is stored
### Source User Information
No personal data is accessed or processed
### Technical User Information (Public)
- Refrence id
## How is the information stored
The Technical User Information is encrypted using the Private Key of the Organizations SSI Agent and stored internally (on the agent) on PostgreSQL and externally/ metadata (shared between the OCM services) on PostgreSQL of Organization.
## Who can access the information
The Technical User Information both are accessible only by the Organization specific SSI agent's private key.
## How long will the information stay
The Technical User Information is wiped out according to the retention periods (not defined yet).
{
"openapi": "3.0.0",
"paths": {
"/v1/health": {
"get": {
"operationId": "HealthController_getHealth",
"parameters": [],
"responses": {
"200": {
"description": ""
}
}
}
},
"/v1/map-user-info": {
"post": {
"operationId": "PrincipalController_mapUserInfo",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MapUserInfoDTO"
}
}
}
},
"responses": {
"201": {
"description": ""
}
}
}
}
},
"info": {
"title": "XFSC Principal Manager API",
"description": "API documentation for XFSC Principal Manager",
"version": "1.0",
"contact": {}
},
"tags": [],
"servers": [{
"url": "http://localhost:3008/",
"description": "Localhost with docker configuration."
}
],
"components": {
"schemas": {
"MapUserInfoDTO": {
"type": "object",
"properties": {
"userInfoURL": {
"type": "string"
}
},
"required": [
"userInfoURL"
]
}
}
}
}
\ No newline at end of file
This diff is collapsed.
# OCM Principal Manager
## Description
<hr/>
The Principal Manager is the microservice responsible for handling the authentication and credential issuance for an individual PCM user.
## Usage
<hr/>
### Swagger Documentation:
[Swagger/OpenAPI](swagger.json)
## Installation
<hr/>
### Pre-requisite
* yarn
* docker
* docker-compose
* Postgres
### OCM Services Dependencies
* SSI Abstraction
## Running the app
<hr/>
**Each service in the Organizational Credential Manager can be run from the infrastructure repository with Docker.**
**The .env files are in the infrastructure repository under /env**
```bash
## production in:
./deployment/ci
## development in:
./deployment/dev
```
* (optional) Edit docker-compose.yml in "infrastructure" to use either **/ci/** or **/dev/** Dockerfiles.
* Run while in **"infrastructure"** project:
```bash
$ docker-compose up --build attestation-m
```
to run only Attestation Manager or
```bash
$ docker-compose up --build
```
to run all the services.
## Build
```
yarn build
```
## Run
```
yarn start
```
### Environment variable required
```
1. PORT
2. DATABASE_URL
3. ECSURL
4. NATS_URL
5. AGENT_URL
```
### Outgoing communication services
```
1. CONNECTION MANAGER
```
### Incoming communication services
```
1. ATTESTATION MANAGER
```
## Features supported
```
1. Issue Membership credential
```
## Test
```bash
# unit tests
$ yarn test
# e2e tests
$ yarn test:e2e
# test coverage
$ yarn test:cov
```
## GDPR
<hr/>
[GDPR](GDPR.md)
## Dependencies
<hr/>
[Dependencies](package.json)
## License
<hr/>
[Apache 2.0 license](LICENSE)
const config = () => ({
PORT: Number(process.env.PORT),
nats: {
url: process.env.NATS_URL,
},
auth: {
useAuth: process.env.USE_AUTH || 'false',
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
tokenUrl: process.env.OAUTH_TOKEN_URL,
},
DATABASE: {
type: 'postgres',
port: 5432,
synchronize: false,
logging: false,
entities: [`${__dirname}/../**/**.model{.ts,.js}`],
},
ECSURL: process.env.ECSURL,
});
export default config;
import * as Joi from 'joi';
const validationSchema = Joi.object({
DATABASE_URL: Joi.string().required(),
NATS_URL: Joi.string().required(),
PORT: Joi.number().required(),
USE_AUTH: Joi.string(),
OAUTH_CLIENT_ID: Joi.string(),
OAUTH_CLIENT_SECRET: Joi.string(),
OAUTH_TOKEN_URL: Joi.string(),
});
export default validationSchema;
FROM node:16-slim AS builder
RUN apt-get update
RUN apt-get install -y openssl
WORKDIR /app
RUN npm i -g pnpm
COPY . .
RUN pnpm install
RUN pnpm -F principal-manager prisma:generate
RUN pnpm -F principal-manager build
FROM node:16-slim
RUN apt-get update
RUN apt-get install -y openssl
ENV PATH /usr/src/app/node_modules/.bin:$PATH
WORKDIR /usr/src/app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/start.sh ./start.sh
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/src/prisma prisma
EXPOSE 3008
RUN chmod +x ./start.sh
CMD ["./start.sh"]
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
{
"name": "principal-manager",
"version": "0.0.1",
"description": "",
"author": "Sagar",
"private": true,
"license": "Apache 2.0",
"scripts": {
"clean": "rm -r dist",
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"dbSchema": "npx prisma db push --schema=./src/prisma/schema.prisma",
"prisma:generate": "prisma generate --schema=./src/prisma/schema.prisma",
"prisma:migrate": "npx prisma migrate deploy --schema=./src/prisma/schema.prisma",
"prismaStudio": "npx prisma studio",
"start": "nest start",
"start:docker": "yarn prisma:migrate && yarn start",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@elastic/ecs-winston-format": "^1.3.1",
"@nestjs/axios": "^0.0.8",
"@nestjs/common": "^8.0.0",
"@nestjs/config": "^1.1.6",
"@nestjs/core": "^8.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/microservices": "^8.2.6",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/schedule": "^1.0.2",
"@nestjs/swagger": "^5.2.0",
"@nestjs/terminus": "^8.0.4",
"@prisma/client": "^3.9.2",
"@types/node": "^16.0.0",
"class-validator": "^0.13.2",
"express": "^4.17.3",
"joi": "^17.6.0",
"jsonwebtoken": "^8.5.1",
"jwks-rsa": "^3.0.0",
"liquibase": "^4.4.0",
"moment": "^2.29.1",
"nats": "^2.6.0",
"openid-client": "^5.1.6",
"pg": "^8.7.3",
"prisma": "^3.9.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"swagger-ui-express": "^4.3.0",
"winston": "^3.6.0",
"winston-elasticsearch": "^0.16.1"
},
"devDependencies": {
"@nestjs/cli": "^8.0.0",
"@nestjs/schematics": "^8.0.0",
"@nestjs/testing": "^8.0.0",
"@types/express": "^4.17.13",
"@types/jest": "27.0.2",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"dotenv-cli": "^4.1.1",
"eslint": "^8.12.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.4",
"jest": "^27.2.5",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "^27.0.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "^3.10.1",
"typescript": "^4.3.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node",
"setupFiles": [
"<rootDir>/../setup.js"
],
"coveragePathIgnorePatterns": [
"<rootDir>/main"
],
"moduleNameMapper": {
"@src/(.*)": [
"<rootDir>/$1"
],
"@client/(.*)": [
"<rootDir>/client/$1"
],
"@config/(.*)": [
"<rootDir>/../config/$1"
],
"@utils/*": [
"<rootDir>/utils/$1"
],
"@common/(.*)": [
"<rootDir>/common/$1"
],
"@principal/(.*)": [
"<rootDir>/principal/$1"
],
"@health/(.*)": [
"<rootDir>/health/$1"
],
"@DB/(.*)": [
"<rootDir>/prisma/$1"
]
}
}
}
process.env.PORT = 3000
\ No newline at end of file
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import AppModule from './app.module';
describe('App Module', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('should work', () => {
expect(true).toBe(true);
});
afterAll(async () => {
await app.close();
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment