Compare commits
No commits in common. "master" and "php" have entirely different histories.
898 changed files with 66394 additions and 65000 deletions
|
|
@ -1,33 +1,7 @@
|
||||||
admin/admin
|
.git
|
||||||
checker/checker
|
TODO
|
||||||
dashboard/dashboard
|
db
|
||||||
evdist/evdist
|
docs/guide
|
||||||
generator/generator
|
front_synchro
|
||||||
receiver/receiver
|
misc
|
||||||
repochecker/repochecker
|
perl-mcrypt
|
||||||
frontend/fic/build
|
|
||||||
frontend/fic/node_modules
|
|
||||||
qa/ui/build
|
|
||||||
qa/ui/node_modules
|
|
||||||
fickit-backend-initrd.img
|
|
||||||
fickit-backend-kernel
|
|
||||||
fickit-backend-squashfs.img
|
|
||||||
fickit-backend-state
|
|
||||||
fickit-frontend-initrd.img
|
|
||||||
fickit-frontend-kernel
|
|
||||||
fickit-frontend-squashfs.img
|
|
||||||
fickit-frontend-state
|
|
||||||
fickit-prepare-initrd.img
|
|
||||||
fickit-prepare-kernel
|
|
||||||
fickit-update-initrd.img
|
|
||||||
fickit-update-kernel
|
|
||||||
DASHBOARD
|
|
||||||
FILES
|
|
||||||
PKI
|
|
||||||
REMOTE
|
|
||||||
repochecker/*.so
|
|
||||||
SETTINGS
|
|
||||||
SETTINGSDIST
|
|
||||||
submissions
|
|
||||||
TEAMS
|
|
||||||
vendor
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-admin:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-admin:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-admin:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-admin:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-checker:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-checker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-checker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-checker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-dashboard:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-dashboard:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-dashboard:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-dashboard:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-evdist:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-evdist:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-evdist:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-evdist:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-frontend-ui:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-frontend-ui:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-frontend-ui:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-frontend-ui:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-generator:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-generator:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-generator:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-generator:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-get-remote-files:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-get-remote-files:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-get-remote-files:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-get-remote-files:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-qa:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-qa:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-qa:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-qa:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-receiver:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-receiver:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-receiver:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-receiver:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fic-repochecker:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fic-repochecker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fic-repochecker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fic-repochecker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
image: nemunaire/fickit-deploy:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
- image: nemunaire/fickit-deploy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
- image: nemunaire/fickit-deploy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
- image: nemunaire/fickit-deploy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
||||||
816
.drone.yml
816
.drone.yml
|
|
@ -1,816 +0,0 @@
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: build-amd64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
workspace:
|
|
||||||
base: /go
|
|
||||||
path: src/srs.epita.fr/fic-server
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: get deps
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add git
|
|
||||||
- go get -v -d ./...
|
|
||||||
- mkdir deploy
|
|
||||||
|
|
||||||
- name: build qa ui
|
|
||||||
image: node:23-alpine
|
|
||||||
commands:
|
|
||||||
- cd qa/ui
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
- tar chjf ../../deploy/htdocs-qa.tar.bz2 build
|
|
||||||
|
|
||||||
- name: vet and tests
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go vet -buildvcs=false -tags gitgo ./...
|
|
||||||
- go vet -buildvcs=false ./...
|
|
||||||
- go test ./...
|
|
||||||
|
|
||||||
- name: build admin
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -tags gitgo -o deploy/admin-gitgo-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/admin
|
|
||||||
- go build -buildvcs=false -o deploy/admin-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/admin
|
|
||||||
- tar chjf deploy/htdocs-admin.tar.bz2 htdocs-admin
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build checker
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/checker-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/checker
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build evdist
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/evdist-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/evdist
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build generator
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/generator-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/generator
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build receiver
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/receiver-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/receiver
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build frontend fic ui
|
|
||||||
image: node:23-alpine
|
|
||||||
commands:
|
|
||||||
- cd frontend/fic
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
- tar chjf ../../deploy/htdocs-frontend-fic.tar.bz2 build
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build dashboard
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/dashboard-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/dashboard
|
|
||||||
- tar chjf deploy/htdocs-dashboard.tar.bz2 htdocs-dashboard
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build repochecker
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go build -buildvcs=false --tags checkupdate -o deploy/repochecker-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/repochecker
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -o deploy/repochecker-epita-rules-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.so srs.epita.fr/fic-server/repochecker/epita
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -o deploy/repochecker-file-inspector-rules-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.so srs.epita.fr/fic-server/repochecker/file-inspector
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -o deploy/repochecker-grammalecte-rules-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.so srs.epita.fr/fic-server/repochecker/grammalecte
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -o deploy/repochecker-pcap-inspector-rules-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.so srs.epita.fr/fic-server/repochecker/pcap-inspector
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -o deploy/repochecker-videos-rules-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.so srs.epita.fr/fic-server/repochecker/videos
|
|
||||||
- grep "const version" repochecker/update.go | sed -r 's/^.*=\s*(\S.*)$/\1/' > deploy/repochecker.version
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build qa
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/qa-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/qa
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker admin
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-admin
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-admin
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker checker
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-checker
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-checker
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker evdist
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-evdist
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-evdist
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker generator
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-generator
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-generator
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker receiver
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-receiver
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-receiver
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker frontend nginx
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-nginx
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-nginx
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker frontend ui
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-frontend-ui
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-frontend-ui
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker dashboard
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-dashboard
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-dashboard
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker qa
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-qa
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-qa
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker repochecker
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-repochecker
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-repochecker
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker remote-scores-sync-zqds
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-remote-scores-sync-zqds
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-remote-scores-sync-zqds
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker remote-challenge-sync-airbus
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-remote-challenge-sync-airbus
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-remote-challenge-sync-airbus
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker fic-get-remote-files
|
|
||||||
failure: ignore
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-get-remote-files
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-get-remote-files
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker fickit-deploy
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fickit-deploy
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-deploy
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- cron
|
|
||||||
- push
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: build-arm64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: arm64
|
|
||||||
|
|
||||||
workspace:
|
|
||||||
base: /go
|
|
||||||
path: src/srs.epita.fr/fic-server
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: get deps
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add git
|
|
||||||
- go get -d ./...
|
|
||||||
- mkdir deploy
|
|
||||||
|
|
||||||
- name: build admin
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go build -buildvcs=false -o deploy/admin-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/admin
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build checker
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/checker-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/checker
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build evdist
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/evdist-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/evdist
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build generator
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/generator-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/generator
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build receiver
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/receiver-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/receiver
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build frontend fic ui
|
|
||||||
image: node:23-alpine
|
|
||||||
commands:
|
|
||||||
- cd frontend/fic
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build dashboard
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/dashboard-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/dashboard
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build repochecker
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go build -buildvcs=false --tags checkupdate -o deploy/repochecker-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/repochecker
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build repochecker for macOS
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go build -buildvcs=false --tags checkupdate -o deploy/repochecker-darwin-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/repochecker
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
GOOS: darwin
|
|
||||||
GOARCH: arm64
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build qa ui
|
|
||||||
image: node:23-alpine
|
|
||||||
commands:
|
|
||||||
- cd qa/ui
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
- tar chjf ../../deploy/htdocs-qa.tar.bz2 build
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: build qa
|
|
||||||
image: golang:alpine
|
|
||||||
commands:
|
|
||||||
- go build -buildvcs=false -o deploy/qa-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} srs.epita.fr/fic-server/qa
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker admin
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-admin
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-admin
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker checker
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-checker
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-checker
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker evdist
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-evdist
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-evdist
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker generator
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-generator
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-generator
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker fic-get-remote-files
|
|
||||||
failure: ignore
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-get-remote-files
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-get-remote-files
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker receiver
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-receiver
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-receiver
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker frontend nginx
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-nginx
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-nginx
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker dashboard
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-dashboard
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-dashboard
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker qa
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-qa
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-qa
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: docker repochecker
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-repochecker
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-repochecker
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- cron
|
|
||||||
- push
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: docker-manifest
|
|
||||||
steps:
|
|
||||||
- name: publish admin
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-admin.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish checker
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-checker.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish evdist
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-evdist.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish generator
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-generator.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish receiver
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-receiver.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish frontend nginx
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-nginx.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish frontend ui
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-frontend-ui.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish dashboard
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-dashboard.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish repochecker
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-repochecker.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: publish qa
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fic-qa.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
- name: docker fic-get-remote-files
|
|
||||||
failure: ignore
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
repo: nemunaire/fic-get-remote-files
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}
|
|
||||||
dockerfile: Dockerfile-get-remote-files
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
|
|
||||||
- name: publish fickit-deploy
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: .drone-manifest-fickit-deploy.yml
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- tag
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- build-amd64
|
|
||||||
- build-arm64
|
|
||||||
55
.gitignore
vendored
55
.gitignore
vendored
|
|
@ -1,43 +1,12 @@
|
||||||
vendor/
|
*.swp
|
||||||
DASHBOARD/
|
*~
|
||||||
FILES/
|
*#
|
||||||
PKI/
|
.#*
|
||||||
REMOTE/
|
onyx/cache/*.cache.php
|
||||||
SETTINGS/
|
onyx/cache/templates/*/*.php
|
||||||
SETTINGSDIST/
|
onyx/log/*
|
||||||
TEAMS/
|
onyx/config/root.xml
|
||||||
submissions/
|
onyx/db/*.profile.php
|
||||||
admin/sync/README.html
|
onyx/tpl/*/*.html
|
||||||
fickit-boot-cmdline
|
submission/*
|
||||||
fickit-boot-initrd.img
|
libmcrypt-perl_2.5.7.0-1_amd64.deb
|
||||||
fickit-boot-kernel
|
|
||||||
fickit-backend-cmdline
|
|
||||||
fickit-backend-initrd.img
|
|
||||||
fickit-backend-squashfs.img
|
|
||||||
fickit-backend-kernel
|
|
||||||
fickit-backend-state
|
|
||||||
fickit-frontend-cmdline
|
|
||||||
fickit-frontend-initrd.img
|
|
||||||
fickit-frontend-squashfs.img
|
|
||||||
fickit-frontend-kernel
|
|
||||||
fickit-frontend-state
|
|
||||||
fickit-prepare-bios.img
|
|
||||||
fickit-prepare-cmdline
|
|
||||||
fickit-prepare-initrd.img
|
|
||||||
fickit-prepare-kernel
|
|
||||||
fickit-prepare-state
|
|
||||||
fickit-update-cmdline
|
|
||||||
fickit-update-initrd.img
|
|
||||||
fickit-update-kernel
|
|
||||||
fickit-update-squashfs.img
|
|
||||||
result
|
|
||||||
started
|
|
||||||
|
|
||||||
# Standalone binaries
|
|
||||||
admin/get-remote-files/get-remote-files
|
|
||||||
fic-admin
|
|
||||||
fic-backend
|
|
||||||
fic-dashboard
|
|
||||||
fic-frontend
|
|
||||||
fic-qa
|
|
||||||
fic-repochecker
|
|
||||||
|
|
|
||||||
122
.gitlab-ci.yml
122
.gitlab-ci.yml
|
|
@ -1,122 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- deps
|
|
||||||
- build
|
|
||||||
- fickit
|
|
||||||
- sast
|
|
||||||
- qa
|
|
||||||
- image
|
|
||||||
- container_scanning
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .go/pkg/mod/
|
|
||||||
- qa/ui/node_modules/
|
|
||||||
- frontend/ui/node_modules/
|
|
||||||
|
|
||||||
include:
|
|
||||||
- '.gitlab-ci/build.yml'
|
|
||||||
- '.gitlab-ci/image.yml'
|
|
||||||
- template: SAST.gitlab-ci.yml
|
|
||||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
|
||||||
- template: Security/Secret-Detection.gitlab-ci.yml
|
|
||||||
- template: Security/Container-Scanning.gitlab-ci.yml
|
|
||||||
|
|
||||||
.scanners-matrix:
|
|
||||||
parallel:
|
|
||||||
matrix:
|
|
||||||
- IMAGE_NAME: [checker, admin, evdist, frontend-ui, nginx, dashboard, repochecker, qa, receiver, generator, remote-challenge-sync-airbus]
|
|
||||||
|
|
||||||
container_scanning:
|
|
||||||
stage: container_scanning
|
|
||||||
extends:
|
|
||||||
- .scanners-matrix
|
|
||||||
variables:
|
|
||||||
DOCKER_SERVICE: localhost
|
|
||||||
DOCKERFILE_PATH: Dockerfile-${IMAGE_NAME}
|
|
||||||
CI_APPLICATION_REPOSITORY: ${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}/${IMAGE_NAME}
|
|
||||||
CI_APPLICATION_TAG: latest
|
|
||||||
GIT_STRATEGY: fetch
|
|
||||||
before_script:
|
|
||||||
- 'echo "Scanning: ${IMAGE_NAME}"'
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
|
||||||
|
|
||||||
sast:
|
|
||||||
stage: sast
|
|
||||||
interruptible: true
|
|
||||||
needs: []
|
|
||||||
before_script:
|
|
||||||
- rm -rf .go/
|
|
||||||
|
|
||||||
secret_detection:
|
|
||||||
stage: sast
|
|
||||||
interruptible: true
|
|
||||||
needs: []
|
|
||||||
|
|
||||||
dependency_scanning:
|
|
||||||
stage: qa
|
|
||||||
interruptible: true
|
|
||||||
needs: []
|
|
||||||
|
|
||||||
get-deps:
|
|
||||||
stage: deps
|
|
||||||
image: golang:1-alpine
|
|
||||||
before_script:
|
|
||||||
- export GOPATH="$CI_PROJECT_DIR/.go"
|
|
||||||
- mkdir -p .go
|
|
||||||
script:
|
|
||||||
- apk --no-cache add git
|
|
||||||
- go get -v -d ./...
|
|
||||||
|
|
||||||
vet:
|
|
||||||
stage: sast
|
|
||||||
needs: ["build-qa-ui"]
|
|
||||||
dependencies:
|
|
||||||
- build-qa-ui
|
|
||||||
image: golang:1-alpine
|
|
||||||
before_script:
|
|
||||||
- export GOPATH="$CI_PROJECT_DIR/.go"
|
|
||||||
- mkdir -p .go
|
|
||||||
script:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go vet -v -buildvcs=false -tags gitgo ./...
|
|
||||||
- go vet -v -buildvcs=false ./...
|
|
||||||
|
|
||||||
fickit:
|
|
||||||
stage: fickit
|
|
||||||
interruptible: true
|
|
||||||
needs: ["build-admin","build-checker","build-dashboard","build-evdist","build-generator","build-qa","build-receiver","build-repochecker"]
|
|
||||||
image: nemunaire/linuxkit
|
|
||||||
tags: ['docker']
|
|
||||||
before_script:
|
|
||||||
- mkdir -p ~/.docker
|
|
||||||
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"username\":\"${CI_REGISTRY_USER}\",\"password\":\"${CI_REGISTRY_PASSWORD}\"}}}" > ~/.docker/config.json
|
|
||||||
script:
|
|
||||||
- dockerd & sleep 5
|
|
||||||
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/boot/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/kexec/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/mariadb-client/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/mdadm/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/rsync/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/syslinux/
|
|
||||||
- linuxkit pkg push -force -org "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}" fickit-pkg/unbound/
|
|
||||||
|
|
||||||
- sed -i "s@nemunaire/fic-@${CI_REGISTRY_IMAGE}/master/@;s@nemunaire/@${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}/@" fickit-backend.yml fickit-boot.yml fickit-frontend.yml fickit-prepare.yml fickit-update.yml
|
|
||||||
|
|
||||||
- linuxkit build -format kernel+squashfs fickit-backend.yml
|
|
||||||
- linuxkit build -format kernel+squashfs fickit-frontend.yml
|
|
||||||
- linuxkit build -format kernel+initrd fickit-boot.yml
|
|
||||||
- linuxkit build -format kernel+initrd fickit-prepare.yml
|
|
||||||
- linuxkit build -format kernel+initrd fickit-update.yml
|
|
||||||
artifacts:
|
|
||||||
expire_in: 8 hours
|
|
||||||
paths:
|
|
||||||
- fickit-backend-squashfs.img
|
|
||||||
- fickit-frontend-squashfs.img
|
|
||||||
- fickit-boot-kernel
|
|
||||||
- fickit-boot-initrd.img
|
|
||||||
- fickit-prepare-initrd.img
|
|
||||||
- fickit-update-initrd.img
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
.build:
|
|
||||||
stage: build
|
|
||||||
image: golang:1-alpine
|
|
||||||
before_script:
|
|
||||||
- export GOPATH="$CI_PROJECT_DIR/.go"
|
|
||||||
- mkdir -p .go
|
|
||||||
variables:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
|
|
||||||
build-qa-ui:
|
|
||||||
stage: build
|
|
||||||
image: node:21-alpine
|
|
||||||
before_script:
|
|
||||||
script:
|
|
||||||
- cd qa/ui
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- qa/ui/build/
|
|
||||||
when: on_success
|
|
||||||
|
|
||||||
build-checker:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/checker srs.epita.fr/fic-server/checker
|
|
||||||
|
|
||||||
build-generator:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/generator srs.epita.fr/fic-server/generator
|
|
||||||
|
|
||||||
build-receiver:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/receiver srs.epita.fr/fic-server/receiver
|
|
||||||
|
|
||||||
build-admin:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -tags gitgo -o deploy/admin-gitgo srs.epita.fr/fic-server/admin
|
|
||||||
- go build -v -buildvcs=false -o deploy/admin srs.epita.fr/fic-server/admin
|
|
||||||
|
|
||||||
build-evdist:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/evdist srs.epita.fr/fic-server/evdist
|
|
||||||
|
|
||||||
build-frontend-ui:
|
|
||||||
stage: build
|
|
||||||
image: node:21-alpine
|
|
||||||
before_script:
|
|
||||||
script:
|
|
||||||
- cd frontend/fic
|
|
||||||
- npm install --network-timeout=100000
|
|
||||||
- npm run build
|
|
||||||
|
|
||||||
build-dashboard:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/dashboard srs.epita.fr/fic-server/dashboard
|
|
||||||
|
|
||||||
build-repochecker:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
variables:
|
|
||||||
CGO_ENABLED: 1
|
|
||||||
script:
|
|
||||||
- apk --no-cache add build-base
|
|
||||||
- go build -buildvcs=false --tags checkupdate -v -o deploy/repochecker srs.epita.fr/fic-server/repochecker
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -v -o deploy/repochecker-epita-rules.so srs.epita.fr/fic-server/repochecker/epita
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -v -o deploy/repochecker-file-inspector-rules.so srs.epita.fr/fic-server/repochecker/file-inspector
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -v -o deploy/repochecker-grammalecte-rules.so srs.epita.fr/fic-server/repochecker/grammalecte
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -v -o deploy/repochecker-pcap-inspector-rules.so srs.epita.fr/fic-server/repochecker/pcap-inspector
|
|
||||||
- go build -buildvcs=false -buildmode=plugin -v -o deploy/repochecker-videos-rules.so srs.epita.fr/fic-server/repochecker/videos
|
|
||||||
- grep "const version" repochecker/update.go | sed -r 's/^.*=\s*(\S.*)$/\1/' > deploy/repochecker.version
|
|
||||||
|
|
||||||
build-qa:
|
|
||||||
extends:
|
|
||||||
- .build
|
|
||||||
needs: ["build-qa-ui"]
|
|
||||||
dependencies:
|
|
||||||
- build-qa-ui
|
|
||||||
script:
|
|
||||||
- go build -v -buildvcs=false -o deploy/qa srs.epita.fr/fic-server/qa
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
.push:
|
|
||||||
stage: image
|
|
||||||
interruptible: true
|
|
||||||
needs: []
|
|
||||||
image:
|
|
||||||
name: gcr.io/kaniko-project/executor:v1.9.0-debug
|
|
||||||
entrypoint: [""]
|
|
||||||
before_script:
|
|
||||||
- mkdir -p /kaniko/.docker
|
|
||||||
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"username\":\"${CI_REGISTRY_USER}\",\"password\":\"${CI_REGISTRY_PASSWORD}\"}}}" > /kaniko/.docker/config.json
|
|
||||||
script:
|
|
||||||
- |
|
|
||||||
/kaniko/executor \
|
|
||||||
--context . \
|
|
||||||
--dockerfile "${DOCKERFILE}" \
|
|
||||||
--destination "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}/${CI_JOB_NAME}:${CI_COMMIT_SHA}" \
|
|
||||||
--destination "${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}/${CI_JOB_NAME}:latest"
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
checker:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-checker
|
|
||||||
|
|
||||||
receiver:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-receiver
|
|
||||||
|
|
||||||
generator:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-generator
|
|
||||||
|
|
||||||
admin:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-admin
|
|
||||||
|
|
||||||
fickit-deploy:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-deploy
|
|
||||||
|
|
||||||
get-remote-files:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-get-remote-files
|
|
||||||
|
|
||||||
evdist:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-evdist
|
|
||||||
|
|
||||||
frontend-ui:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-frontend-ui
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-nginx
|
|
||||||
|
|
||||||
dashboard:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-dashboard
|
|
||||||
|
|
||||||
repochecker:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-repochecker
|
|
||||||
|
|
||||||
qa:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-qa
|
|
||||||
|
|
||||||
remote-challenge-sync-airbus:
|
|
||||||
extends:
|
|
||||||
- .push
|
|
||||||
variables:
|
|
||||||
DOCKERFILE: Dockerfile-remote-challenge-sync-airbus
|
|
||||||
61
Dockerfile
Normal file
61
Dockerfile
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
# /!\ WARNING: the container generated through this Dockerfile is made only for development purpose; it is NOT SAFE or production ready.
|
||||||
|
|
||||||
|
FROM debian:wheezy
|
||||||
|
MAINTAINER Pierre-Olivier Mercier <nemunaire@nemunai.re>
|
||||||
|
|
||||||
|
# Install packages ####################################################
|
||||||
|
|
||||||
|
RUN apt-get -y update && \
|
||||||
|
apt-get install -y \
|
||||||
|
most \
|
||||||
|
realpath \
|
||||||
|
nginx-light \
|
||||||
|
php5-fpm \
|
||||||
|
php5-mysql \
|
||||||
|
php5-mcrypt \
|
||||||
|
libmcrypt4 \
|
||||||
|
libwww-perl \
|
||||||
|
libdigest-whirlpool-perl \
|
||||||
|
libdbi-perl \
|
||||||
|
libdbd-mysql-perl \
|
||||||
|
pwgen \
|
||||||
|
curl \
|
||||||
|
openssl \
|
||||||
|
rsync \
|
||||||
|
openssh-client \
|
||||||
|
&& \
|
||||||
|
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
|
RUN useradd -d /var/www/fic-server -M -N -g www-data synchro
|
||||||
|
|
||||||
|
# ENVIRONNEMENT #######################################################
|
||||||
|
|
||||||
|
EXPOSE 80/tcp 443/tcp
|
||||||
|
VOLUME ["/var/www/fic-server/out","/var/www/fic-server/files","/var/www/fic-server/submission","/var/www/fic-server/shared"]
|
||||||
|
|
||||||
|
WORKDIR /var/www/fic-server
|
||||||
|
|
||||||
|
ENTRYPOINT ["/var/www/fic-server/entrypoint.sh"]
|
||||||
|
|
||||||
|
CMD service nginx start && \
|
||||||
|
service php5-fpm start && \
|
||||||
|
./nginx_gen_team.sh > ./shared/nginx-teams.conf && \
|
||||||
|
chown www-data ./shared/nginx-teams.conf && \
|
||||||
|
(./launch.sh &); \
|
||||||
|
/bin/bash
|
||||||
|
|
||||||
|
# Copying files #######################################################
|
||||||
|
|
||||||
|
COPY . /var/www/fic-server/
|
||||||
|
|
||||||
|
# Configure softwares #################################################
|
||||||
|
|
||||||
|
RUN dpkg -i /var/www/fic-server/libmcrypt-perl*.deb || \
|
||||||
|
(echo "Please build perl-mcrypt first. Consult the given README!"; exit 1) && \
|
||||||
|
rm /var/www/fic-server/libmcrypt-perl*.deb && \
|
||||||
|
ln -sf /var/www/fic-server/nginx-server.conf /etc/nginx/sites-enabled/default && \
|
||||||
|
ln -sf /var/www/fic-server/php-fpm.conf /etc/php5/fpm/pool.d/www.conf && \
|
||||||
|
\
|
||||||
|
ln -sf /var/www/fic-server/onyx/config/sample.root.xml /var/www/fic-server/onyx/config/root.xml && \
|
||||||
|
sed -i "s/challenge-public//" /var/www/fic-server/onyx/config/root.xml && \
|
||||||
|
chmod 777 /var/www/fic-server/onyx/cache/ /var/www/fic-server/onyx/cache/templates/cache/ /var/www/fic-server/onyx/cache/templates/compile/
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
RUN apk add --no-cache binutils-gold build-base
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY admin ./admin/
|
|
||||||
COPY repochecker ./repochecker/
|
|
||||||
|
|
||||||
RUN go get -d -v ./admin && \
|
|
||||||
go build -v -o admin/admin ./admin && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/epita-rules.so ./repochecker/epita && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/file-inspector.so ./repochecker/file-inspector && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/grammalecte-rules.so ./repochecker/grammalecte && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/videos-rules.so ./repochecker/videos
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
ca-certificates \
|
|
||||||
git \
|
|
||||||
git-lfs \
|
|
||||||
openssh-client-default \
|
|
||||||
openssl
|
|
||||||
|
|
||||||
EXPOSE 8081
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/admin", "-bind=:8081", "-baseurl=/admin/"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/admin/admin /srv/admin
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/epita-rules.so /srv/epita-rules.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/file-inspector.so /usr/lib/file-inspector.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/grammalecte-rules.so /usr/lib/grammalecte-rules.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/videos-rules.so /usr/lib/videos-rules.so
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY checker ./checker/
|
|
||||||
|
|
||||||
RUN go get -d -v ./checker && \
|
|
||||||
go build -v -buildvcs=false -o checker/checker ./checker
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/checker"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/checker/checker /srv/checker
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY dashboard ./dashboard/
|
|
||||||
|
|
||||||
RUN go get -d -v ./dashboard && \
|
|
||||||
go build -v -buildvcs=false -o dashboard/dashboard ./dashboard
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
EXPOSE 8082
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/dashboard", "--bind=:8082"]
|
|
||||||
|
|
||||||
VOLUME /srv/htdocs-dashboard/
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/dashboard/dashboard /srv/dashboard
|
|
||||||
COPY dashboard/static/index.html /srv/htdocs-dashboard/
|
|
||||||
COPY admin/static/css/bootstrap.min.css dashboard/static/css/fic.css admin/static/css/glyphicon.css /srv/htdocs-dashboard/css/
|
|
||||||
COPY admin/static/fonts /srv/htdocs-dashboard/fonts
|
|
||||||
COPY dashboard/static/img/srs.png /srv/htdocs-dashboard/img/
|
|
||||||
COPY dashboard/static/js/dashboard.js admin/static/js/angular.min.js dashboard/static/js/angular-animate.min.js admin/static/js/angular-route.min.js admin/static/js/angular-sanitize.min.js admin/static/js/bootstrap.min.js admin/static/js/common.js admin/static/js/d3.v3.min.js admin/static/js/jquery.min.js /srv/htdocs-dashboard/js/
|
|
||||||
COPY admin/static/js/i18n/* /srv/htdocs-dashboard/js/i18n/
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
EXPOSE 67/udp
|
|
||||||
EXPOSE 69/udp
|
|
||||||
EXPOSE 80/tcp
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/sbin/initial-config.sh"]
|
|
||||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
|
||||||
|
|
||||||
WORKDIR /srv/s
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
busybox-extras \
|
|
||||||
supervisor \
|
|
||||||
syslinux \
|
|
||||||
tftp-hpa
|
|
||||||
|
|
||||||
RUN touch /var/lib/udhcpd/udhcpd.leases && \
|
|
||||||
mv /usr/share/syslinux/* /srv
|
|
||||||
|
|
||||||
COPY configs/deploy-initial-config.sh /usr/sbin/initial-config.sh
|
|
||||||
COPY configs/deploy-supervisord.conf /etc/supervisord.conf
|
|
||||||
COPY configs/udhcpd-sample.conf /etc/udhcpd.conf
|
|
||||||
COPY configs/pxelinux.cfg /srv/pxelinux.cfg/default
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY evdist ./evdist/
|
|
||||||
|
|
||||||
RUN go get -d -v ./evdist && \
|
|
||||||
go build -v -buildvcs=false -o evdist/evdist ./evdist
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/evdist"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/evdist/evdist /srv/evdist
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
FROM node:23-alpine AS nodebuild
|
|
||||||
|
|
||||||
WORKDIR /ui
|
|
||||||
|
|
||||||
COPY frontend/fic/ .
|
|
||||||
|
|
||||||
RUN npm install --network-timeout=100000 && \
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
|
|
||||||
FROM scratch
|
|
||||||
|
|
||||||
COPY --from=nodebuild /ui/build/ /www/htdocs-frontend
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY generator ./generator/
|
|
||||||
|
|
||||||
RUN go get -d -v ./generator && \
|
|
||||||
go build -v -buildvcs=false -o generator/generator ./generator
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/generator"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/generator/generator /srv/generator
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
RUN apk add --no-cache build-base
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY admin ./admin/
|
|
||||||
|
|
||||||
RUN go get -d -v ./admin && \
|
|
||||||
go build -v -o get-remote-files ./admin/get-remote-files
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
ca-certificates
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/get-remote-files", "/mnt/fic/"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/get-remote-files /srv/get-remote-files
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
FROM node:23-alpine AS nodebuild
|
|
||||||
|
|
||||||
WORKDIR /ui
|
|
||||||
|
|
||||||
COPY frontend/fic/ .
|
|
||||||
|
|
||||||
RUN npm install --network-timeout=100000 && \
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
|
|
||||||
FROM nginx:stable-alpine-slim
|
|
||||||
|
|
||||||
ENV FIC_BASEURL /
|
|
||||||
ENV HOST_RECEIVER receiver:8080
|
|
||||||
ENV HOST_ADMIN admin:8081
|
|
||||||
ENV HOST_DASHBOARD dashboard:8082
|
|
||||||
ENV HOST_QA qa:8083
|
|
||||||
ENV PATH_FILES /srv/FILES
|
|
||||||
ENV PATH_STARTINGBLOCK /srv/STARTINGBLOCK
|
|
||||||
ENV PATH_STATIC /srv/htdocs-frontend
|
|
||||||
ENV PATH_SETTINGS /srv/SETTINGSDIST
|
|
||||||
ENV PATH_TEAMS /srv/TEAMS
|
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
COPY configs/nginx-chbase.sh /docker-entrypoint.d/40-update-baseurl.sh
|
|
||||||
|
|
||||||
COPY configs/nginx/get-team/upstream.conf /etc/nginx/fic-get-team.conf
|
|
||||||
COPY configs/nginx/auth/none.conf /etc/nginx/fic-auth.conf
|
|
||||||
COPY configs/nginx/base/docker.conf /etc/nginx/templates/default.conf.template
|
|
||||||
|
|
||||||
COPY --from=nodebuild /ui/build/ /srv/htdocs-frontend
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
FROM node:23-alpine AS nodebuild
|
|
||||||
|
|
||||||
WORKDIR /ui
|
|
||||||
|
|
||||||
COPY qa/ui/ .
|
|
||||||
|
|
||||||
RUN npm install --network-timeout=100000 && \
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
|
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY --from=nodebuild /ui ./qa/ui
|
|
||||||
COPY qa ./qa/
|
|
||||||
COPY admin ./admin/
|
|
||||||
|
|
||||||
RUN go get -d -v ./qa && \
|
|
||||||
go build -v -buildvcs=false -o qa/qa ./qa
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
EXPOSE 8083
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/qa", "--bind=:8083"]
|
|
||||||
|
|
||||||
VOLUME /srv/htdocs-qa/
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/qa/qa /srv/qa
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY receiver ./receiver/
|
|
||||||
|
|
||||||
RUN go get -d -v ./receiver && \
|
|
||||||
go build -v -buildvcs=false -o ./receiver/receiver ./receiver
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/sbin/entrypoint.sh"]
|
|
||||||
CMD ["--bind=:8080"]
|
|
||||||
|
|
||||||
COPY entrypoint-receiver.sh /usr/sbin/entrypoint.sh
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/receiver/receiver /srv/receiver
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY settings ./settings/
|
|
||||||
COPY remote/challenge-sync-airbus ./remote/challenge-sync-airbus/
|
|
||||||
|
|
||||||
RUN go get -d -v ./remote/challenge-sync-airbus && \
|
|
||||||
go build -v -buildvcs=false -o ./challenge-sync-airbus ./remote/challenge-sync-airbus
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
RUN apk add --no-cache openssl ca-certificates
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/challenge-sync-airbus"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/challenge-sync-airbus /srv/challenge-sync-airbus
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY settings ./settings/
|
|
||||||
COPY remote/scores-sync-zqds ./remote/scores-sync-zqds/
|
|
||||||
|
|
||||||
RUN go get -d -v ./remote/scores-sync-zqds && \
|
|
||||||
go build -v -buildvcs=false -o ./scores-sync-zqds ./remote/scores-sync-zqds
|
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
|
|
||||||
RUN apk add --no-cache openssl ca-certificates
|
|
||||||
|
|
||||||
WORKDIR /srv
|
|
||||||
|
|
||||||
ENTRYPOINT ["/srv/scores-sync-zqds"]
|
|
||||||
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/scores-sync-zqds /srv/scores-sync-zqds
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
FROM golang:1-alpine AS gobuild
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
WORKDIR /go/src/srs.epita.fr/fic-server/
|
|
||||||
|
|
||||||
RUN apk add --no-cache binutils-gold build-base
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
COPY settings settings/
|
|
||||||
COPY libfic ./libfic/
|
|
||||||
COPY admin ./admin/
|
|
||||||
COPY repochecker ./repochecker/
|
|
||||||
|
|
||||||
RUN go get -d -v ./repochecker && \
|
|
||||||
go build -v -o repochecker/repochecker ./repochecker && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/epita-rules.so ./repochecker/epita && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/file-inspector.so ./repochecker/file-inspector && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/grammalecte-rules.so ./repochecker/grammalecte && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/pcap-inspector.so ./repochecker/pcap-inspector && \
|
|
||||||
go build -v -buildmode=plugin -o repochecker/videos-rules.so ./repochecker/videos
|
|
||||||
|
|
||||||
|
|
||||||
ENV GRAMMALECTE_VERSION 2.1.1
|
|
||||||
|
|
||||||
ADD https://web.archive.org/web/20240926154729if_/https://grammalecte.net/zip/Grammalecte-fr-v$GRAMMALECTE_VERSION.zip /srv/grammalecte.zip
|
|
||||||
|
|
||||||
RUN mkdir /srv/grammalecte && cd /srv/grammalecte && unzip /srv/grammalecte.zip && sed -i 's/if sys.version_info.major < (3, 7):/if False:/' /srv/grammalecte/grammalecte-server.py
|
|
||||||
|
|
||||||
FROM alpine:3.19
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/repochecker", "--rules-plugins=/usr/lib/epita-rules.so", "--rules-plugins=/usr/lib/file-inspector.so", "--rules-plugins=/usr/lib/grammalecte-rules.so", "--rules-plugins=/usr/lib/pcap-inspector.so", "--rules-plugins=/usr/lib/videos-rules.so"]
|
|
||||||
|
|
||||||
RUN apk add --no-cache git python3 ffmpeg
|
|
||||||
|
|
||||||
COPY --from=gobuild /srv/grammalecte /srv/grammalecte
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/repochecker /usr/bin/repochecker
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/epita-rules.so /usr/lib/epita-rules.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/file-inspector.so /usr/lib/file-inspector.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/grammalecte-rules.so /usr/lib/grammalecte-rules.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/pcap-inspector.so /usr/lib/pcap-inspector.so
|
|
||||||
COPY --from=gobuild /go/src/srs.epita.fr/fic-server/repochecker/videos-rules.so /usr/lib/videos-rules.so
|
|
||||||
21
LICENSE
21
LICENSE
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2016-2018 Pierre-Olivier Mercier <nemunaire@nemunai.re>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
442
README.md
442
README.md
|
|
@ -1,238 +1,314 @@
|
||||||
FIC Forensic CTF Platform
|
FIC forensic challenge validation server
|
||||||
=========================
|
========================================
|
||||||
|
|
||||||
This is a CTF server for distributing and validating challenges. It is design
|
This is a CTF server for distributing and validating exercices. It is design to
|
||||||
to be robust, so it uses some uncommon technics like client certificate for
|
be robust, so it uses some uncommon technologies like client certificate for
|
||||||
authentication, lots of state of the art cryptographic methods and aims to be
|
authentication, cryptographic functions and DMZ network architecture.
|
||||||
deployed in a DMZ network architecture.
|
|
||||||
|
|
||||||
## Features
|
Development And Testing
|
||||||
|
-----------------------
|
||||||
|
|
||||||
- **Collaborative Challenge Design and Review:** Facilitates large team collaboration for challenge creation and review.
|
The easiest way to have a working server is to build a Docker container.
|
||||||
- **Versatile Flag Formats:** Supports flags as strings, numbers, multiple-choice questions, unique-choice questions, selects, multiline inputs, and strings with capture regexp.
|
|
||||||
- **Engaging Challenge Interface:** A visually appealing interface that incorporates images to illustrate exercises.
|
### Docker
|
||||||
- **Public Dashboard:** Allow spectators to follow the competition alongside players.
|
|
||||||
- **Archival Mode:** Preserve past challenges and data in a static form, with no code. Your archive can lied on a S3 bucket.
|
First, build the container with the following command:
|
||||||
- **Export Capabilities:** Export challenges to other CTF platforms.
|
|
||||||
- **Security-Focused:** Designed with security as a top priority. Each service aims to be isolated with right restrictions. Answers are not stored in the database, ...
|
```
|
||||||
- **Choose your Authentication:** Authentication is not part of this project, integrate your own authentication methods.
|
docker build -t fic .
|
||||||
- **Extensible:** Easily extend and customize the platform. The main codebase in Golang is highly documented, each frontend part can be recreated in another language with ease.
|
```
|
||||||
- **Comprehensive Settings:** A wide range of settings for challenge customization. You can have first blood or not, dynamic exercice gain, evenemential bonus, ...
|
|
||||||
- **Git Integration:** Seamless verification and integration with Git.
|
Then, run it with:
|
||||||
- **Infrastructure as Code (IaC):** Ensure read-only and reproducible infrastructure.
|
|
||||||
- **Last-Minute Checks:** Ensure your challenge is ready with a comprehensive set of checks that can be performed anytime, verifying that downloadable files are as expected by the challenge creators.
|
```
|
||||||
- **Lightweight:** Optimized for minimal resource consumption, supporting features like serving gzipped files directly to browsers without CPU usage.
|
docker run -t -i -P fic
|
||||||
- **Scalable:** Designed to handle large-scale competitions with multiple receivers and frontend servers, smoothly queuing activity peaks on the backend.
|
```
|
||||||
- **Offline Capability:** Run your challenges offline.
|
|
||||||
- **Integrated Exercise Issue Ticketing System:** Manage and track issues related to exercises during the competition directly with teams. During designing phase, this transform in a complete dedicated QA platform.
|
It will ask you for a passphrase, you must provide one with at least 4
|
||||||
- **Detailed Statistics:** Provide administrators with insights into exercise preferences and complexity.
|
characters. This key is used to generate the server certificate.
|
||||||
- **Change Planning:** Schedule events in advance, such as new exercise availability or ephemeral bonuses, with second-by-second precision.
|
|
||||||
- **Frontend Time Synchronization:** Ensure accurate remaining time and event synchronization between servers and players.
|
When you see:
|
||||||
|
|
||||||
|
```
|
||||||
|
root@xxxxxxxxxxxx:/var/www/fic-server#
|
||||||
|
```
|
||||||
|
|
||||||
|
congratulations, the container is running!
|
||||||
|
|
||||||
|
Use `docker ps` to view to which local ports was assigned the contained
|
||||||
|
webserver.
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
### Database
|
||||||
|
|
||||||
This is a [monorepo](https://danluu.com/monorepo/), containing several
|
Demo data are available in `/var/www/fic-server/db/feed.sql`. In test
|
||||||
micro-services :
|
environment, you can run the following command:
|
||||||
|
|
||||||
- `admin` is the web interface and API used to control the challenge
|
mysql -u root fic < /var/www/fic-server/db/feed.sql
|
||||||
and doing synchronization.
|
|
||||||
- `checker` is an inotify reacting service that handles submissions
|
|
||||||
checking.
|
|
||||||
- `dashboard` is a public interface to explain and follow the
|
|
||||||
conquest, aims to animate the challenge for visitors.
|
|
||||||
- `evdist` is an inotify reacting service that handles settings
|
|
||||||
changes during the challenge (eg. a 30 minutes event where hints are
|
|
||||||
free, ...).
|
|
||||||
- `generator` takes care of global and team's files generation.
|
|
||||||
- `qa` is an interface dedicated to challenge development, it stores
|
|
||||||
reports to be treated by challenges creators.
|
|
||||||
- `receiver` is only responsible for receiving submissions. It is the
|
|
||||||
only dynamic part accessibe to players, so it's codebase is reduce
|
|
||||||
to the minimum. It does not parse or try to understand players
|
|
||||||
submissions, it just write it down to a file in the file
|
|
||||||
system. Parsing and treatment is made by the `checker`.
|
|
||||||
- `remote/challenge-sync-airbus` is an inotify reacting service that
|
|
||||||
allows us to synchronize scores and exercice validations with the
|
|
||||||
Airbus scoring platform.
|
|
||||||
- `remote/scores-sync-zqds` is an inotify reacting service that allows
|
|
||||||
us to synchronize scores with the ZQDS scoring platform.
|
|
||||||
- `repochecker` is a side project to check offline for synchronization
|
|
||||||
issues.
|
|
||||||
|
|
||||||
Here is how thoses services speak to each others:
|
|
||||||
|
|
||||||

|
### Frontend container
|
||||||
|
|
||||||
In the production setup, each micro-service runs in a dedicated
|
To run the frontend on the same machine as the backend (but in another
|
||||||
container, isolated from each other. Moreover, two physical machines
|
container), run the following command:
|
||||||
should be used:
|
|
||||||
|
|
||||||
- `phobos` communicates with players: displaying the web interface,
|
docker run -P -ti --volumes-from BACKEND_CNTNR_NAME FRONTEND_IMG
|
||||||
authenticate teams and players, storing contest files and handling
|
|
||||||
submissions retrieval without understanding them. It can't access
|
|
||||||
`deimos` so its job stops after writing requests on the filesystem.
|
|
||||||
- `deimos` is hidden from players, isolated from the network. It can
|
|
||||||
only access `phobos` via a restricted ssh connection, to retrieve
|
|
||||||
requests from `phobos` filesystem and pushing to it newly generated
|
|
||||||
static files.
|
|
||||||
|
|
||||||
Concretely, the L2 looks like this:
|
|
||||||
|
|
||||||

|
Production Environnement
|
||||||
|
------------------------
|
||||||
|
|
||||||
So, the general filesystem is organized this way:
|
### Setup
|
||||||
|
|
||||||
- `DASHBOARD` contains files structuring the content of the dashboard
|
You should compile/install hardened kernel (with latest stable GrSec patch) on
|
||||||
screen(s).
|
each machine.
|
||||||
- `FILES` stores the contest file to be downloaded by players. To be
|
|
||||||
accessible without authentication and to avoid bruteforce, each file
|
|
||||||
is placed into a directory with a hashed name (the original file
|
|
||||||
name is preserved). It's rsynced as is to `deimos`.
|
|
||||||
- `GENERATOR` contains a socket to allow other services to communicate
|
|
||||||
with the `generator`.
|
|
||||||
- `PKI` takes care of the PKI used for the client certiciate
|
|
||||||
authorization process, and more generaly, all authentication related
|
|
||||||
files (htpasswd, dexidp config, ...). Only the `shared` subdirectory
|
|
||||||
is shared with `deimos`, private key and teams P12 don't go out.
|
|
||||||
- `SETTINGS` stores the challenge config as wanted by admins. It's not
|
|
||||||
always the config in use: it uses can be delayed waiting for a
|
|
||||||
trigger.
|
|
||||||
- `SETTINGSDIST` is the challenge configuration in use. It is the one
|
|
||||||
shared with players.
|
|
||||||
- `startingblock` keep the `started` state of the challenge. This
|
|
||||||
helps `nginx` to know when it can start distributing exercices
|
|
||||||
related files.
|
|
||||||
- `TEAMS` stores the static files generated by the `generator`, there is
|
|
||||||
one subdirectory by team (id of the team), plus some files at the
|
|
||||||
root, which are common to all teams. There is also symlink pointing
|
|
||||||
to team directory, each symlink represent an authentication
|
|
||||||
association (certificate ID, OpenID username, htpasswd user, ...).
|
|
||||||
- `submissions` is the directory where the `receiver` writes
|
|
||||||
requests. It creates subdirectories at the name of the
|
|
||||||
authentication association, as seen in `TEAMS`, `checker` then
|
|
||||||
resolve the association regarding `TEAMS` directory. There is also a
|
|
||||||
special directory to handle team registration.
|
|
||||||
|
|
||||||
Here is a diagram showing how each micro-service uses directories it has access to (blue for read access, red for write access):
|
Prefer GNU/Linux distributions where most packages are compiled with `-fPIC`
|
||||||
|
and `-fstack-protector`, like Ubuntu or
|
||||||
|
[Gentoo Hardened](http://www.gentoo.org/proj/en/hardened/).
|
||||||
|
|
||||||

|
As machines aren't always in safe place (transportation, night before CTF,
|
||||||
|
...), disks should be encrypted.
|
||||||
|
|
||||||
Local developer setup
|
**Always set strong password when it is possible** eg. SSL certificats, ...
|
||||||
---------------------
|
|
||||||
|
|
||||||
### Using Docker
|
|
||||||
|
|
||||||
Use `docker-compose build`, then `docker-compose up` to launch the infrastructure.
|
#### Backend
|
||||||
|
|
||||||
After booting, you'll be able to reach the main interface at:
|
##### Docker containers
|
||||||
<http://localhost:8042/> and the admin one at: <http://localhost:8081/> (or at <http://localhost:8042/admin/>).
|
|
||||||
The dashboard is available at <http://localhost:8042/dashboard/> and the QA service at <http://localhost:8042/qa/>.
|
|
||||||
|
|
||||||
In this setup, there is no authentication. You are identfied [as a team](./configs/nginx/get-team/team-1.conf). On first use you'll need to register.
|
Main Docker backend container relies on several other container:
|
||||||
|
|
||||||
#### Import folder
|
* MySQL database;
|
||||||
|
* Database storage (as data only container);
|
||||||
|
* PKI storage;
|
||||||
|
* PKI shared storage;
|
||||||
|
* challenge files containers;
|
||||||
|
* the backend.
|
||||||
|
|
||||||
##### Local import folder
|
To have a fully working backend:
|
||||||
The following changes is only required if your are trying to change the local import folder `~/fic` location.
|
|
||||||
|
|
||||||
Make the following changes inside this file `docker-compose.yml`:
|
1. Create a data-only container:
|
||||||
|
|
||||||
23 volumes:
|
```
|
||||||
24 - - ~/fic:/mnt/fic:ro
|
docker run --name mysql_data -v /var/lib/mysql busybox
|
||||||
24 + - <custom-path-to-import-folder>/fic:/mnt/fic:ro
|
```
|
||||||
|
|
||||||
##### Git import
|
2. Setup the MySQL server:
|
||||||
A git repository can be used:
|
|
||||||
|
|
||||||
29 - command: --baseurl /admin/ -localimport /mnt/fic -localimportsymlink
|
```
|
||||||
29 + command: --baseurl /admin/ -localimport /mnt/fic -localimportsymlink -git-import-remote git@gitlab.cri.epita.fr:ing/majeures/srs/fic/2042/challenges.git
|
docker run -d --name db_setup --volumes-from mysql_data -e MYSQL_ROOT_PASSWORD=mysecretpassword -e MYSQL_USER=fic -e MYSQL_PASSWORD=anotherpassword -e MYSQL_DATABASE=fic mysql mysqld --skip-name-resolve
|
||||||
|
```
|
||||||
|
|
||||||
##### Owncloud import folder
|
Fill the database:
|
||||||
If your are trying to use the folder available with the Owncloud service, make the following changes inside this file `docker-compose.yml`:
|
|
||||||
|
|
||||||
29 - command: --baseurl /admin/ -localimport /mnt/fic -localimportsymlink
|
```
|
||||||
29 + command: --baseurl /admin/ -clouddav=https://owncloud.srs.epita.fr/remote.php/webdav/FIC%202019/ -clouduser <login_x> -cloudpass '<passwd>'
|
docker build -t db_filler db/
|
||||||
|
docker run --rm -it --link db_setup:db db_filler
|
||||||
|
```
|
||||||
|
|
||||||
### Manual builds
|
Stop it:
|
||||||
|
|
||||||
Running this project requires a web server (configuration is given for nginx),
|
```
|
||||||
a database (currently supporting only MySQL/MariaDB), a Go compiler for the
|
docker stop db_setup
|
||||||
revision 1.18 at least and a `inotify`-aware system. You'll also need NodeJS to
|
docker rm db_setup
|
||||||
compile some user interfaces.
|
```
|
||||||
|
|
||||||
1. Above all, you need to build Node projects:
|
3. Run the database container:
|
||||||
|
|
||||||
cd frontend/fic; npm install && npm run build
|
```
|
||||||
cd qa/ui; npm install && npm run build
|
docker run -d --name db --volumes-from mysql_data -e MYSQL_USER=fic -e MYSQL_PASSWORD=anotherpassword -e MYSQL_DATABASE=fic mysql mysqld --skip-name-resolve
|
||||||
|
```
|
||||||
|
|
||||||
2. First, you'll need to retrieve the dependencies:
|
Here, we use the `--skip-name-resolve` option, because without internet connection, MySQL try to find hostname from IP and hang a lot.
|
||||||
|
|
||||||
go mod vendor
|
4. Setup the PKI storages:
|
||||||
|
|
||||||
2. Then, build the three Go projects:
|
```
|
||||||
|
docker run --name pki_storage -v /var/www/fic-server/PKI busybox
|
||||||
|
docker run --name shared_storage -v /var/www/fic-server/shared busybox
|
||||||
|
```
|
||||||
|
|
||||||
go build -o fic-admin ./admin
|
5. Build the PKI configuration container:
|
||||||
go build -o fic-checker ./checker
|
|
||||||
go build -o fic-dashboard ./dashboard
|
|
||||||
go build -o fic-generator ./generator
|
|
||||||
go build -o fic-qa ./qa
|
|
||||||
go build -o fic-receiver ./receiver
|
|
||||||
go build -o fic-repochecker ./repochecker
|
|
||||||
...
|
|
||||||
|
|
||||||
3. Before launching anything, you need to create a database:
|
```
|
||||||
|
docker build -t pki_setup pki/
|
||||||
|
```
|
||||||
|
|
||||||
mysql -u root -p <<EOF
|
6. Configure the PKI
|
||||||
CREATE DATABASE fic;
|
|
||||||
CREATE USER fic@localhost IDENTIFIED BY 'fic';
|
|
||||||
GRANT ALL ON fic.* TO fic@localhost;
|
|
||||||
EOF
|
|
||||||
|
|
||||||
By default, expected credentials for development purpose is `fic`,
|
For development purpose, you can run the default setup:
|
||||||
for both username, password and database name. If you want to use
|
|
||||||
other credentials, define the corresponding environment variable:
|
|
||||||
`MYSQL_HOST`, `MYSQL_USER`, `MYSQL_PASSWORD` and
|
|
||||||
`MYSQL_DATABASE`. Those variables are the one used by the `mysql`
|
|
||||||
docker image, so just link them together if you use containers.
|
|
||||||
|
|
||||||
4. Launch it!
|
```
|
||||||
|
docker run --rm -it --volumes-from pki_storage --volumes-from shared_storage pki_setup
|
||||||
|
```
|
||||||
|
|
||||||
./fic-admin &
|
For production environment:
|
||||||
|
|
||||||
After initializing the database, the server will listen on
|
```
|
||||||
<http://localhost:8081/>: this is the administration part.
|
docker run --rm -it --volumes-from pki_storage --volumes-from shared_storage pki_setup IPorURL
|
||||||
|
```
|
||||||
|
|
||||||
./fic-generator &
|
Where `IPorURL` is the way the certificat will authenticate: if challengers
|
||||||
|
will access the frontend with a custom domain, indicate this domain
|
||||||
|
(eg. `epita_challenge.fic.local`); else indicate the IP of the **front** host
|
||||||
|
on the network (eg. `192.168.0.5`).
|
||||||
|
|
||||||
This daemon generates static and team related files and then waits
|
For example, 2015 PKI generation looks like:
|
||||||
another process to tell it to regenerate some files.
|
|
||||||
|
|
||||||
./fic-receiver &
|
```
|
||||||
|
docker run --rm -it --volumes-from pki_storage --volumes-from shared_storage pki_setup 192.168.0.5
|
||||||
|
```
|
||||||
|
|
||||||
This one exposes an API that gives time synchronization to clients and
|
7. Build the perl `Mcrypt` debian package
|
||||||
handle submission reception (but without treating them).
|
|
||||||
|
|
||||||
./fic-checker &
|
```
|
||||||
|
docker build -t perl-mcrypt perl-mcrypt/
|
||||||
|
docker run --name mcrypt_builder perl-mcrypt
|
||||||
|
docker cp mcrypt_builder:$(docker diff mcrypt_builder | grep -oE '[^ ]+deb$') ./
|
||||||
|
docker rm mcrypt_builder
|
||||||
|
```
|
||||||
|
|
||||||
This service waits for new submissions (expected in `submissions`
|
8. Build and run the backend:
|
||||||
directory). It only watchs modifications on the file system, it has no web
|
|
||||||
interface.
|
|
||||||
|
|
||||||
./fic-dashboard &
|
```
|
||||||
|
docker build -t backend .
|
||||||
|
docker run --rm -it --link db:db --volumes-from pki_storage --volumes-from shared_storage -v /home/files:/var/www/fic-server/files-in backend
|
||||||
|
```
|
||||||
|
|
||||||
This last server runs the public dashboard. It serves all file, without the
|
Where `/home/files` is your local directory containing all challenge files.
|
||||||
need of a webserver. It listens on port 8082 by default.
|
|
||||||
|
|
||||||
./fic-qa &
|
|
||||||
|
|
||||||
If you need it, this will launch a web interface on the port 8083 by
|
##### Requirements
|
||||||
default, to perform quality control.
|
|
||||||
|
|
||||||
For the moment, a web server is mandatory to serve static files, look
|
* `realpath`;
|
||||||
at the samples given in the `configs/nginx` directory. You need to
|
* `mysql`;
|
||||||
pick one base configation flavor in the `configs/nginx/base`
|
* `nginx` with `fastcgi` module;
|
||||||
directory, and associated with an authentication mechanism in
|
* `php-fpm` with `mysql` module;
|
||||||
`configs/nginx/auth` (named the file `fic-auth.conf` in `/etc/nginx`),
|
* `openssl` and `pwgen` for client certificat generation;
|
||||||
and also pick the corresponding `configs/nginx/get-team` file, you
|
* `mcrypt`;
|
||||||
named `fic-get-team.conf`.
|
* `HTTP::Request::Common` perl module (provided by `libwww-perl`);
|
||||||
|
* `Digest::Whirlpool` perl module (provided by `lib-digest-whirlpool-perl`);
|
||||||
|
* `Mcrypt` from CPAN (`cpan -i Mcrypt`, on Debian, it requires `libltdl-dev` and
|
||||||
|
`build-essential`) to decrypt submissions (see
|
||||||
|
https://metacpan.org/pod/Mcrypt);
|
||||||
|
|
||||||
|
##### Files distribution
|
||||||
|
|
||||||
|
You need to manually place challenge given files in the tree. To avoid path
|
||||||
|
guessing, files path are hashed. To generate hashed paths, use the script
|
||||||
|
`gen_hash_link_files.sh`:
|
||||||
|
|
||||||
|
mkdir $TO
|
||||||
|
./gen_hash_link_files.sh FROM TO
|
||||||
|
|
||||||
|
Where `FROM` is the directory with the orignal tree and `TO` the directory
|
||||||
|
where placed symlink.
|
||||||
|
|
||||||
|
##### Firewall rules
|
||||||
|
|
||||||
|
This machine shouldn't have any network connection, except outgoing one to the
|
||||||
|
frontend for synchronization.
|
||||||
|
|
||||||
|
##### Others setups
|
||||||
|
|
||||||
|
Indicate in `/etc/hosts.conf` IP(s) of the frontend.
|
||||||
|
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
Two scripts are available, depending if directories synchronization has to be
|
||||||
|
made or not.
|
||||||
|
|
||||||
|
You don't need to handle synchronization if it's done by a separate container
|
||||||
|
or if frontend is linked to backend.
|
||||||
|
|
||||||
|
The `launch.sh` and `launch_local.sh` scripts do all backend stuff for you:
|
||||||
|
synchronization with frontend (only `launch.sh`), submission checking and
|
||||||
|
smart static pages regeneration.
|
||||||
|
|
||||||
|
|
||||||
|
#### Frontend
|
||||||
|
|
||||||
|
Keep in mind that this is the machine exposed to participant.
|
||||||
|
|
||||||
|
##### Docker containers
|
||||||
|
|
||||||
|
1. Generate the synchronization SSH key on the backend:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo su -c "ssh-keygen -t rsa -b 8192 -N '' -f /var/www/fic_server/.ssh/id_rsa" synchro
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy `~synchro/.ssh/id_rsa.pub` into `front_synchro/authorized_keys` file.
|
||||||
|
|
||||||
|
3. Run the `front_synchro` container:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t synchro front_synchro/
|
||||||
|
docker run -d --name fsync -p 2242:22 synchro
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run the backend.
|
||||||
|
|
||||||
|
A first synchronization have to be made before the next step. This
|
||||||
|
synchronization will copy the frontend private key and various required
|
||||||
|
certificates.
|
||||||
|
|
||||||
|
5. Run the frontend container:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t frontend front/
|
||||||
|
docker run --rm -it -p 80:80 -p 443:443 --volumes-from fsync frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### Requirements
|
||||||
|
|
||||||
|
* `nginx` with those modules: `aio` (for fast delivery of huge
|
||||||
|
content), `fastcgi`, `rewrite`, `ssl`;
|
||||||
|
* `php-fpm` with `mcrypt` module (for submission encryption);
|
||||||
|
|
||||||
|
##### Firewall rules
|
||||||
|
|
||||||
|
Expose to participants only 80 and 443 ports.
|
||||||
|
|
||||||
|
Expose on synchronization interface the 22 port, used for synchronization and
|
||||||
|
administration purpose from backend.
|
||||||
|
|
||||||
|
DROP **has to be** the default rule for INPUT, FORWARD and OUTPUT chains; use
|
||||||
|
CONNTRACK states.
|
||||||
|
|
||||||
|
|
||||||
|
### History
|
||||||
|
|
||||||
|
#### FIC2014
|
||||||
|
|
||||||
|
Two machines (DC7900: Core 2 Quad) were used : one for backend (Deimos) and one
|
||||||
|
for frontend (Phobos). They ran a GNU/Linux Gentoo Hardened with custom 3.2
|
||||||
|
kernel without module loading, unused and unecessary components and with all
|
||||||
|
GrSecurity features activated.
|
||||||
|
|
||||||
|
Each machine was two network interfaces: one was used to permit to the backend
|
||||||
|
machine to connect to the frontend (over IPv6). The second interface on the
|
||||||
|
backend was used for administration purpose (with a laptop not connected to
|
||||||
|
Internet). The second interface on the frontend was used to provide network
|
||||||
|
connectivity to participants.
|
||||||
|
|
||||||
|
Both frontend and backend were 2 500GB hard-drives with software RAID1. The
|
||||||
|
whole logical RAID disk was LUKS encrypted using Serpent algorithm.
|
||||||
|
|
||||||
|
|
||||||
|
The D Day
|
||||||
|
---------
|
||||||
|
|
||||||
|
### Interact with the scheduler
|
||||||
|
|
||||||
|
When you launch `launch.sh` or `launch_local.sh` script, a socket is open at
|
||||||
|
`/tmp/scheduler.sock`. Use `perl comm-socket.pl /tmp/scheduler.sock` to connect
|
||||||
|
to the scheduler. Consult `gen_site.pl` manual (`perldoc gen_site.pl`) for list
|
||||||
|
of available instructions.
|
||||||
|
|
||||||
|
### More
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
|
||||||
28
TODO
Normal file
28
TODO
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
* Lien sur la pages d'accueil sans /
|
||||||
|
* HTML/CSS/Templates
|
||||||
|
** TODO Mettre à jour les logos
|
||||||
|
** TODO trop de thèmes dans l'interface d'admin => menu
|
||||||
|
** TODO avoir la page avec le résumé
|
||||||
|
* PHP
|
||||||
|
** TODO les mauvaises pages sont generees (pas debug et non liens prod)
|
||||||
|
** TODO sur le frontend, en mode productoin, il va chercher les pages de debug
|
||||||
|
** TODO numéro des exercices
|
||||||
|
** TODO pouvoir désactiver les équipes qui ne participent pas (pour accélérer la génération)
|
||||||
|
** TODO ajouter des teams sans passer par l'import XML
|
||||||
|
** TODO page de statistiques
|
||||||
|
select count(*) as t, id_exercice, name from solved S inner join exercices E ON E.id = S.id_exercice INNER JOIN themes T ON E.id_theme = T.id group by id_exercice order by t DESC;
|
||||||
|
select id_team, COUNT(*) AS t from exercice_tries group by id_team ORDER BY t;
|
||||||
|
** Admin
|
||||||
|
*** TODO valider les documents avec la DTD Ã l'import
|
||||||
|
*** TODO upload/MAJ de fichiers depuis l'interface d'admin?
|
||||||
|
*** TODO lors de l'import, vérifier que les ID existent => afficher les erreurs MySQL
|
||||||
|
* Perl/shell
|
||||||
|
** TODO Gerer les espaces dans les fichiers (gen_hash_file plante)
|
||||||
|
** TODO Couleur l'output de check.pl
|
||||||
|
** TODO Pouvoir regénérer une série d'exercices pour toutes les teams
|
||||||
|
* Security
|
||||||
|
** TODO Quand est généré la CRL ?
|
||||||
|
* Other
|
||||||
|
** TODO docker pour monitorer
|
||||||
|
** TODO versionner la DTD et la doc associée
|
||||||
|
** TODO image dans la description des XML
|
||||||
5
admin/.gitignore
vendored
5
admin/.gitignore
vendored
|
|
@ -1,5 +0,0 @@
|
||||||
admin
|
|
||||||
fic.db
|
|
||||||
PKI/
|
|
||||||
FILES/
|
|
||||||
static/full_import_report.json
|
|
||||||
|
|
@ -1,479 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/base32"
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"srs.epita.fr/fic-server/admin/pki"
|
|
||||||
"srs.epita.fr/fic-server/libfic"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
var TeamsDir string
|
|
||||||
|
|
||||||
func declareCertificateRoutes(router *gin.RouterGroup) {
|
|
||||||
router.GET("/htpasswd", func(c *gin.Context) {
|
|
||||||
ret, err := genHtpasswd(true)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, ret)
|
|
||||||
})
|
|
||||||
router.POST("/htpasswd", func(c *gin.Context) {
|
|
||||||
if htpasswd, err := genHtpasswd(true); err != nil {
|
|
||||||
log.Println("Unable to generate htpasswd:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
} else if err := ioutil.WriteFile(path.Join(pki.PKIDir, "shared", "ficpasswd"), []byte(htpasswd), 0644); err != nil {
|
|
||||||
log.Println("Unable to write htpasswd:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.AbortWithStatus(http.StatusOK)
|
|
||||||
})
|
|
||||||
router.DELETE("/htpasswd", func(c *gin.Context) {
|
|
||||||
if err := os.Remove(path.Join(pki.PKIDir, "shared", "ficpasswd")); err != nil {
|
|
||||||
log.Println("Unable to remove htpasswd:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.AbortWithStatus(http.StatusOK)
|
|
||||||
})
|
|
||||||
router.GET("/htpasswd.apr1", func(c *gin.Context) {
|
|
||||||
ret, err := genHtpasswd(false)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, ret)
|
|
||||||
})
|
|
||||||
router.GET("/ca", infoCA)
|
|
||||||
router.GET("/ca.pem", getCAPEM)
|
|
||||||
router.POST("/ca/new", func(c *gin.Context) {
|
|
||||||
var upki PKISettings
|
|
||||||
err := c.ShouldBindJSON(&upki)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pki.GenerateCA(upki.NotBefore, upki.NotAfter); err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusCreated, true)
|
|
||||||
})
|
|
||||||
|
|
||||||
router.GET("/certs", getCertificates)
|
|
||||||
router.POST("/certs", generateClientCert)
|
|
||||||
router.DELETE("/certs", func(c *gin.Context) {
|
|
||||||
v, err := fic.ClearCertificates()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to ClearCertificates:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, v)
|
|
||||||
})
|
|
||||||
|
|
||||||
apiCertificatesRoutes := router.Group("/certs/:certid")
|
|
||||||
apiCertificatesRoutes.Use(CertificateHandler)
|
|
||||||
apiCertificatesRoutes.HEAD("", getTeamP12File)
|
|
||||||
apiCertificatesRoutes.GET("", getTeamP12File)
|
|
||||||
apiCertificatesRoutes.PUT("", updateCertificateAssociation)
|
|
||||||
apiCertificatesRoutes.DELETE("", func(c *gin.Context) {
|
|
||||||
cert := c.MustGet("cert").(*fic.Certificate)
|
|
||||||
|
|
||||||
v, err := cert.Revoke()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to Revoke:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func declareTeamCertificateRoutes(router *gin.RouterGroup) {
|
|
||||||
router.GET("/certificates", func(c *gin.Context) {
|
|
||||||
team := c.MustGet("team").(*fic.Team)
|
|
||||||
|
|
||||||
if serials, err := pki.GetTeamSerials(TeamsDir, team.Id); err != nil {
|
|
||||||
log.Println("Unable to GetTeamSerials:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
var certs []CertExported
|
|
||||||
for _, serial := range serials {
|
|
||||||
if cert, err := fic.GetCertificate(serial); err == nil {
|
|
||||||
certs = append(certs, CertExported{fmt.Sprintf("%0[2]*[1]X", cert.Id, int(math.Ceil(math.Log2(float64(cert.Id))/8)*2)), cert.Creation, cert.Password, &team.Id, cert.Revoked})
|
|
||||||
} else {
|
|
||||||
log.Println("Unable to get back certificate, whereas an association exists on disk: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, certs)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.GET("/associations", func(c *gin.Context) {
|
|
||||||
team := c.MustGet("team").(*fic.Team)
|
|
||||||
|
|
||||||
assocs, err := pki.GetTeamAssociations(TeamsDir, team.Id)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to GetTeamAssociations:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, assocs)
|
|
||||||
})
|
|
||||||
|
|
||||||
apiTeamAssociationsRoutes := router.Group("/associations/:assoc")
|
|
||||||
apiTeamAssociationsRoutes.POST("", func(c *gin.Context) {
|
|
||||||
team := c.MustGet("team").(*fic.Team)
|
|
||||||
|
|
||||||
if err := os.Symlink(fmt.Sprintf("%d", team.Id), path.Join(TeamsDir, c.Params.ByName("assoc"))); err != nil {
|
|
||||||
log.Println("Unable to create association symlink:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to create association symlink: %s", err.Error())})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, c.Params.ByName("assoc"))
|
|
||||||
})
|
|
||||||
apiTeamAssociationsRoutes.DELETE("", func(c *gin.Context) {
|
|
||||||
err := pki.DeleteTeamAssociation(TeamsDir, c.Params.ByName("assoc"))
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Unable to DeleteTeamAssociation(%s): %s", c.Params.ByName("assoc"), err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to delete association symlink: %s", err.Error())})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func CertificateHandler(c *gin.Context) {
|
|
||||||
var certid uint64
|
|
||||||
var err error
|
|
||||||
|
|
||||||
cid := strings.TrimSuffix(string(c.Params.ByName("certid")), ".p12")
|
|
||||||
if certid, err = strconv.ParseUint(cid, 10, 64); err != nil {
|
|
||||||
if certid, err = strconv.ParseUint(cid, 16, 64); err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Invalid certficate identifier"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, err := fic.GetCertificate(certid)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Certificate not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set("cert", cert)
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func genHtpasswd(ssha bool) (ret string, err error) {
|
|
||||||
var teams []*fic.Team
|
|
||||||
teams, err = fic.GetTeams()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, team := range teams {
|
|
||||||
var serials []uint64
|
|
||||||
serials, err = pki.GetTeamSerials(TeamsDir, team.Id)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(serials) == 0 {
|
|
||||||
// Don't include teams that don't have associated certificates
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, serial := range serials {
|
|
||||||
var cert *fic.Certificate
|
|
||||||
cert, err = fic.GetCertificate(serial)
|
|
||||||
if err != nil {
|
|
||||||
// Ignore invalid/incorrect/non-existant certificates
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if cert.Revoked != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
salt := make([]byte, 5)
|
|
||||||
if _, err = rand.Read(salt); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ssha {
|
|
||||||
hash := sha1.New()
|
|
||||||
hash.Write([]byte(cert.Password))
|
|
||||||
hash.Write([]byte(salt))
|
|
||||||
|
|
||||||
passwdline := fmt.Sprintf(":{SSHA}%s\n", base64.StdEncoding.EncodeToString(append(hash.Sum(nil), salt...)))
|
|
||||||
|
|
||||||
ret += strings.ToLower(team.Name) + passwdline
|
|
||||||
ret += fmt.Sprintf("%0[2]*[1]x", cert.Id, int(math.Ceil(math.Log2(float64(cert.Id))/8)*2)) + passwdline
|
|
||||||
ret += fmt.Sprintf("%0[2]*[1]X", cert.Id, int(math.Ceil(math.Log2(float64(cert.Id))/8)*2)) + passwdline
|
|
||||||
teamAssociations, _ := pki.GetTeamAssociations(TeamsDir, team.Id)
|
|
||||||
log.Println(path.Join(TeamsDir, fmt.Sprintf("%d", team.Id)), teamAssociations)
|
|
||||||
for _, ta := range teamAssociations {
|
|
||||||
ret += strings.Replace(ta, ":", "", -1) + passwdline
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
salt32 := base32.StdEncoding.EncodeToString(salt)
|
|
||||||
ret += fmt.Sprintf(
|
|
||||||
"%s:$apr1$%s$%s\n",
|
|
||||||
strings.ToLower(team.Name),
|
|
||||||
salt32,
|
|
||||||
fic.Apr1Md5(cert.Password, salt32),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type PKISettings struct {
|
|
||||||
Version int `json:"version"`
|
|
||||||
SerialNumber *big.Int `json:"serialnumber"`
|
|
||||||
Issuer pkix.Name `json:"issuer"`
|
|
||||||
Subject pkix.Name `json:"subject"`
|
|
||||||
NotBefore time.Time `json:"notbefore"`
|
|
||||||
NotAfter time.Time `json:"notafter"`
|
|
||||||
SignatureAlgorithm x509.SignatureAlgorithm `json:"signatureAlgorithm,"`
|
|
||||||
PublicKeyAlgorithm x509.PublicKeyAlgorithm `json:"publicKeyAlgorithm"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func infoCA(c *gin.Context) {
|
|
||||||
_, cacert, err := pki.LoadCA()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "CA not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, PKISettings{
|
|
||||||
Version: cacert.Version,
|
|
||||||
SerialNumber: cacert.SerialNumber,
|
|
||||||
Issuer: cacert.Issuer,
|
|
||||||
Subject: cacert.Subject,
|
|
||||||
NotBefore: cacert.NotBefore,
|
|
||||||
NotAfter: cacert.NotAfter,
|
|
||||||
SignatureAlgorithm: cacert.SignatureAlgorithm,
|
|
||||||
PublicKeyAlgorithm: cacert.PublicKeyAlgorithm,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCAPEM(c *gin.Context) {
|
|
||||||
if _, err := os.Stat(pki.CACertPath()); os.IsNotExist(err) {
|
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to locate the CA root certificate. Have you generated it?"})
|
|
||||||
return
|
|
||||||
} else if fd, err := os.Open(pki.CACertPath()); err != nil {
|
|
||||||
log.Println("Unable to open CA root certificate:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
defer fd.Close()
|
|
||||||
|
|
||||||
cnt, err := ioutil.ReadAll(fd)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to read CA root certificate:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.String(http.StatusOK, string(cnt))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeamP12File(c *gin.Context) {
|
|
||||||
cert := c.MustGet("cert").(*fic.Certificate)
|
|
||||||
|
|
||||||
// Create p12 if necessary
|
|
||||||
if _, err := os.Stat(pki.ClientP12Path(cert.Id)); os.IsNotExist(err) {
|
|
||||||
if err := pki.WriteP12(cert.Id, cert.Password); err != nil {
|
|
||||||
log.Println("Unable to WriteP12:", err.Error())
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(pki.ClientP12Path(cert.Id)); os.IsNotExist(err) {
|
|
||||||
log.Println("Unable to compute ClientP12Path:", err.Error())
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, errors.New("Unable to locate the p12. Have you generated it?"))
|
|
||||||
return
|
|
||||||
} else if fd, err := os.Open(pki.ClientP12Path(cert.Id)); err != nil {
|
|
||||||
log.Println("Unable to open ClientP12Path:", err.Error())
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("Unable to open the p12: %w", err))
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
defer fd.Close()
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(fd)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to open ClientP12Path:", err.Error())
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("Unable to open the p12: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Data(http.StatusOK, "application/x-pkcs12", data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateClientCert(c *gin.Context) {
|
|
||||||
// First, generate a new, unique, serial
|
|
||||||
var serial_gen [8]byte
|
|
||||||
if _, err := rand.Read(serial_gen[:]); err != nil {
|
|
||||||
log.Println("Unable to read enough entropy to generate client certificate:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to read enough entropy"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for fic.ExistingCertSerial(serial_gen) {
|
|
||||||
if _, err := rand.Read(serial_gen[:]); err != nil {
|
|
||||||
log.Println("Unable to read enough entropy to generate client certificate:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to read enough entropy"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var serial_b big.Int
|
|
||||||
serial_b.SetBytes(serial_gen[:])
|
|
||||||
serial := serial_b.Uint64()
|
|
||||||
|
|
||||||
// Let's pick a random password
|
|
||||||
password, err := fic.GeneratePassword()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to generate password:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to generate password: " + err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok, now load CA
|
|
||||||
capriv, cacert, err := pki.LoadCA()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to load the CA:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to load the CA"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate our privkey
|
|
||||||
if err := pki.GenerateClient(serial, cacert.NotBefore, cacert.NotAfter, &cacert, &capriv); err != nil {
|
|
||||||
log.Println("Unable to generate private key:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to generate private key: " + err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save in DB
|
|
||||||
cert, err := fic.RegisterCertificate(serial, password)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to register certificate:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to register certificate."})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, CertExported{fmt.Sprintf("%0[2]*[1]X", cert.Id, int(math.Ceil(math.Log2(float64(cert.Id))/8)*2)), cert.Creation, cert.Password, nil, cert.Revoked})
|
|
||||||
}
|
|
||||||
|
|
||||||
type CertExported struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Creation time.Time `json:"creation"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
IdTeam *int64 `json:"id_team"`
|
|
||||||
Revoked *time.Time `json:"revoked"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertificates(c *gin.Context) {
|
|
||||||
certificates, err := fic.GetCertificates()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to retrieve certificates list:", err)
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during certificates retrieval."})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret := make([]CertExported, 0)
|
|
||||||
for _, cert := range certificates {
|
|
||||||
dstLinkPath := path.Join(TeamsDir, pki.GetCertificateAssociation(cert.Id))
|
|
||||||
|
|
||||||
var idTeam *int64 = nil
|
|
||||||
if lnk, err := os.Readlink(dstLinkPath); err == nil {
|
|
||||||
if tid, err := strconv.ParseInt(lnk, 10, 64); err == nil {
|
|
||||||
idTeam = &tid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = append(ret, CertExported{fmt.Sprintf("%0[2]*[1]X", cert.Id, int(math.Ceil(math.Log2(float64(cert.Id))/8)*2)), cert.Creation, "", idTeam, cert.Revoked})
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
type CertUploaded struct {
|
|
||||||
Team *int64 `json:"id_team"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateCertificateAssociation(c *gin.Context) {
|
|
||||||
cert := c.MustGet("cert").(*fic.Certificate)
|
|
||||||
|
|
||||||
var uc CertUploaded
|
|
||||||
err := c.ShouldBindJSON(&uc)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dstLinkPath := path.Join(TeamsDir, pki.GetCertificateAssociation(cert.Id))
|
|
||||||
|
|
||||||
if uc.Team != nil {
|
|
||||||
srcLinkPath := fmt.Sprintf("%d", *uc.Team)
|
|
||||||
if err := os.Symlink(srcLinkPath, dstLinkPath); err != nil {
|
|
||||||
log.Println("Unable to create certificate symlink:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to create certificate symlink: %s", err.Error())})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark team as active to ensure it'll be generated
|
|
||||||
if ut, err := fic.GetTeam(*uc.Team); err != nil {
|
|
||||||
log.Println("Unable to GetTeam:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during team retrieval."})
|
|
||||||
return
|
|
||||||
} else if !ut.Active {
|
|
||||||
ut.Active = true
|
|
||||||
_, err := ut.Update()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to UpdateTeam after updateCertificateAssociation:", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
os.Remove(dstLinkPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, cert)
|
|
||||||
}
|
|
||||||
|
|
@ -1,499 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"srs.epita.fr/fic-server/admin/generation"
|
|
||||||
"srs.epita.fr/fic-server/libfic"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func declareClaimsRoutes(router *gin.RouterGroup) {
|
|
||||||
// Tasks
|
|
||||||
router.GET("/claims", getClaims)
|
|
||||||
router.POST("/claims", newClaim)
|
|
||||||
router.DELETE("/claims", clearClaims)
|
|
||||||
|
|
||||||
apiClaimsRoutes := router.Group("/claims/:cid")
|
|
||||||
apiClaimsRoutes.Use(ClaimHandler)
|
|
||||||
apiClaimsRoutes.GET("", showClaim)
|
|
||||||
apiClaimsRoutes.PUT("", updateClaim)
|
|
||||||
apiClaimsRoutes.POST("", addClaimDescription)
|
|
||||||
apiClaimsRoutes.DELETE("", deleteClaim)
|
|
||||||
|
|
||||||
apiClaimsRoutes.GET("/last_update", getClaimLastUpdate)
|
|
||||||
apiClaimsRoutes.PUT("/descriptions", updateClaimDescription)
|
|
||||||
|
|
||||||
// Assignees
|
|
||||||
router.GET("/claims-assignees", getAssignees)
|
|
||||||
router.POST("/claims-assignees", newAssignee)
|
|
||||||
|
|
||||||
apiClaimAssigneesRoutes := router.Group("/claims-assignees/:aid")
|
|
||||||
apiClaimAssigneesRoutes.Use(ClaimAssigneeHandler)
|
|
||||||
router.GET("/claims-assignees/:aid", showClaimAssignee)
|
|
||||||
router.PUT("/claims-assignees/:aid", updateClaimAssignee)
|
|
||||||
router.DELETE("/claims-assignees/:aid", deleteClaimAssignee)
|
|
||||||
}
|
|
||||||
|
|
||||||
func declareExerciceClaimsRoutes(router *gin.RouterGroup) {
|
|
||||||
router.GET("/claims", getExerciceClaims)
|
|
||||||
}
|
|
||||||
|
|
||||||
func declareTeamClaimsRoutes(router *gin.RouterGroup) {
|
|
||||||
router.GET("/api/teams/:tid/issue.json", func(c *gin.Context) {
|
|
||||||
team := c.MustGet("team").(*fic.Team)
|
|
||||||
|
|
||||||
issues, err := team.MyIssueFile()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Unable to MyIssueFile(tid=%d): %s", team.Id, err.Error())
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to generate issues.json."})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, issues)
|
|
||||||
})
|
|
||||||
|
|
||||||
router.GET("/claims", getTeamClaims)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClaimHandler(c *gin.Context) {
|
|
||||||
cid, err := strconv.ParseInt(string(c.Params.ByName("cid")), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Invalid claim identifier"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
claim, err := fic.GetClaim(cid)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Requested claim not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set("claim", claim)
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClaimAssigneeHandler(c *gin.Context) {
|
|
||||||
aid, err := strconv.ParseInt(string(c.Params.ByName("aid")), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Invalid claim assignee identifier"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
assignee, err := fic.GetAssignee(aid)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Requested claim-assignee not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set("claim-assignee", assignee)
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getClaims(c *gin.Context) {
|
|
||||||
claims, err := fic.GetClaims()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to getClaims:", err.Error())
|
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during claims retrieval."})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, claims)
|
|
||||||
}
|
|
||||||