Compare commits
13 Commits
v2023.7.6-
...
v2024.2.21
Author | SHA1 | Date | |
---|---|---|---|
f91c14e5d4 | |||
1602626e8c | |||
e2e38841f4 | |||
c23d8e3adb | |||
a3f44cf123 | |||
5453988419 | |||
1e392f94a7 | |||
b44ff2a68e | |||
c719fdca37 | |||
2b91c1e167 | |||
cebf1daf72 | |||
6734cf6526 | |||
368273f1ee |
14
Dockerfile
14
Dockerfile
@ -1,4 +1,4 @@
|
||||
FROM golang:1.20 AS BUILD
|
||||
FROM reg.cadoles.com/proxy_cache/library/golang:1.21.6 AS BUILD
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y make
|
||||
@ -21,17 +21,11 @@ RUN /src/dist/bouncer_linux_amd64_v1/bouncer -c '' config dump > /src/dist/bounc
|
||||
&& yq -i '.admin.auth.privateKey = "/etc/bouncer/admin-key.json"' /src/dist/bouncer_linux_amd64_v1/config.yml \
|
||||
&& yq -i '.redis.adresses = ["redis:6379"]' /src/dist/bouncer_linux_amd64_v1/config.yml
|
||||
|
||||
FROM alpine:3.18 AS RUNTIME
|
||||
FROM reg.cadoles.com/proxy_cache/library/alpine:3.19.1 AS RUNTIME
|
||||
|
||||
ARG DUMB_INIT_VERSION=1.2.5
|
||||
RUN apk add --no-cache ca-certificates dumb-init
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
RUN mkdir -p /usr/local/bin \
|
||||
&& wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
|
||||
&& chmod +x /usr/local/bin/dumb-init
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
RUN mkdir -p /usr/local/bin /usr/share/bouncer/bin /etc/bouncer
|
||||
|
||||
|
27
Jenkinsfile
vendored
27
Jenkinsfile
vendored
@ -29,7 +29,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Release') {
|
||||
stage('Release binaries and packages') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'
|
||||
@ -50,6 +50,31 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build and release Docker image') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'
|
||||
branch 'develop'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
withCredentials([
|
||||
usernamePassword([
|
||||
credentialsId: 'kipp-credentials',
|
||||
usernameVariable: 'DOCKER_REGISTRY_USERNAME',
|
||||
passwordVariable: 'DOCKER_REGISTRY_PASSWORD'
|
||||
])
|
||||
]) {
|
||||
sh """
|
||||
echo '${env.DOCKER_REGISTRY_PASSWORD}' | docker login --username '${env.DOCKER_REGISTRY_USERNAME}' --password-stdin reg.cadoles.com
|
||||
make docker-build docker-release
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
|
20
Makefile
20
Makefile
@ -101,6 +101,12 @@ gitea-release: tools/gitea-release/bin/gitea-release.sh goreleaser
|
||||
GITEA_RELEASE_ATTACHMENTS="$$(find .gitea-release/* -type f)" \
|
||||
tools/gitea-release/bin/gitea-release.sh
|
||||
|
||||
grafterm: tools/grafterm/bin/grafterm
|
||||
tools/grafterm/bin/grafterm -c ./misc/grafterm/dashboard.json -v job=bouncer-proxy -r 5s
|
||||
|
||||
siege:
|
||||
siege -i -c 100 -f ./misc/siege/urls.txt
|
||||
|
||||
tools/gitea-release/bin/gitea-release.sh:
|
||||
mkdir -p tools/gitea-release/bin
|
||||
curl --output tools/gitea-release/bin/gitea-release.sh https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/gitea/gitea-release.sh
|
||||
@ -110,6 +116,10 @@ tools/modd/bin/modd:
|
||||
mkdir -p tools/modd/bin
|
||||
GOBIN=$(PWD)/tools/modd/bin go install github.com/cortesi/modd/cmd/modd@latest
|
||||
|
||||
tools/grafterm/bin/grafterm:
|
||||
mkdir -p tools/grafterm/bin
|
||||
GOBIN=$(PWD)/tools/grafterm/bin go install github.com/slok/grafterm/cmd/grafterm@v0.2.0
|
||||
|
||||
full-version:
|
||||
@echo $(FULL_VERSION)
|
||||
|
||||
@ -128,4 +138,12 @@ run-redis:
|
||||
redis-shell:
|
||||
docker exec -it \
|
||||
bouncer-redis \
|
||||
redis-cli
|
||||
redis-cli
|
||||
|
||||
run-prometheus:
|
||||
docker kill bouncer-prometheus || exit 0
|
||||
docker run --rm -t \
|
||||
--name bouncer-prometheus \
|
||||
--network host \
|
||||
-v $(PWD)/misc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
|
||||
prom/prometheus
|
@ -10,6 +10,7 @@
|
||||
|
||||
- [(FR) - Layers](./fr/references/layers/README.md)
|
||||
- [(FR) - Fichier de configuration](../misc/packaging/common/config.yml)
|
||||
- [(FR) - API d'administration](./fr/references/admin_api.md)
|
||||
|
||||
## Tutoriels
|
||||
|
||||
|
182
doc/fr/references/admin_api.md
Normal file
182
doc/fr/references/admin_api.md
Normal file
@ -0,0 +1,182 @@
|
||||
# API d'administration
|
||||
|
||||
## Authentification
|
||||
|
||||
L'ensemble des appels aux APIs HTTP du service `bouncer-admin` sont authentifiées via l'utilisation d'un jeton [JWT](https://datatracker.ietf.org/doc/html/rfc7519) signé par la clé privée du serveur.
|
||||
|
||||
Le jeton d'accès doit être transmis avec l'ensemble des appels aux points d'entrée via l'entête HTTP `Authorization` en respectant la forme suivante:
|
||||
|
||||
```
|
||||
Authorization: Bearer <jwt>
|
||||
```
|
||||
|
||||
### Génération d'un jeton d'authentification
|
||||
|
||||
La génération d'un jeton d'authentification s'effectue via la commande suivante:
|
||||
|
||||
```shell
|
||||
bouncer auth create-token --subject "<subject>" --role "<role>"
|
||||
```
|
||||
|
||||
Où:
|
||||
|
||||
- `"<subject>"` est une chaîne de caractère arbitraire ayant pour objectif d'identifier de manière unique l'utilisateur associé au jeton;
|
||||
- `"<role>"` peut prendre une des deux valeurs `reader` ou `writer` correspondant aux droits suivants respectifs:
|
||||
- droit en lecture sur l'ensemble des entités (proxy, layer);
|
||||
- droit en lecture ET en écriture sur l'ensemble des entités.
|
||||
|
||||
|
||||
## Points d'entrée
|
||||
|
||||
### `POST /api/v1/proxies`
|
||||
|
||||
Créer un nouveau proxy
|
||||
|
||||
#### Exemple de corps de requête
|
||||
|
||||
```json5
|
||||
{
|
||||
"name": "myproxy", // OBLIGATOIRE - Nom du proxy
|
||||
"to": "https://www.cadoles.com", // OBLIGATOIRE - Site distant ciblé par le proxy
|
||||
"from": ["*"] // OPTIONNEL - Liste de patrons de filtrage associés au proxy
|
||||
}
|
||||
```
|
||||
|
||||
#### Exemple de résultat
|
||||
|
||||
```json5
|
||||
{
|
||||
"data": {
|
||||
"proxy": {
|
||||
"name": "myproxy",
|
||||
"weight": 0,
|
||||
"enabled": false,
|
||||
"to": "https://www.cadoles.com",
|
||||
"from": ["*"],
|
||||
"createdAt": "2018-12-10T13:45:00.000Z",
|
||||
"updatedAt": "2018-12-10T13:45:00.000Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Source
|
||||
|
||||
Voir [`internal/admin/proxy_route.go#createProxy()`](../../../internal/admin/proxy_route.go#createProxy)
|
||||
|
||||
### `GET /api/v1/proxies/{proxyName}`
|
||||
|
||||
Récupérer les informations complètes sur un proxy
|
||||
|
||||
#### Paramètres
|
||||
|
||||
- `{proxyName}` - Nom du proxy
|
||||
|
||||
#### Exemple de résultat
|
||||
|
||||
```json5
|
||||
{
|
||||
"data": {
|
||||
"proxy": {
|
||||
"name": "myproxy",
|
||||
"weight": 0,
|
||||
"enabled": false,
|
||||
"to": "https://www.cadoles.com",
|
||||
"from": ["*"],
|
||||
"createdAt": "2018-12-10T13:45:00.000Z",
|
||||
"updatedAt": "2018-12-10T13:45:00.000Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Source
|
||||
|
||||
Voir [`internal/admin/proxy_route.go#getProxy()`](../../../internal/admin/proxy_route.go#getProxy)
|
||||
|
||||
### `PUT /api/v1/proxies/{proxyName}`
|
||||
|
||||
Modifier un proxy
|
||||
|
||||
#### Exemple de corps de requête
|
||||
|
||||
```json5
|
||||
{
|
||||
"to": "https://www.cadoles.com", // OPTIONNEL - Site distant ciblé par le proxy
|
||||
"from": ["mylocalproxydomain:*"], // OPTIONNEL - Liste de patrons de filtrage associés au proxy
|
||||
"weight": 100, // OPTIONNEL - Poids à associer au proxy
|
||||
"enabled": true, // OPTIONNEL - Activer/désactiver le proxy
|
||||
}
|
||||
```
|
||||
|
||||
#### Exemple de résultat
|
||||
|
||||
```json5
|
||||
{
|
||||
"data": {
|
||||
"proxy": {
|
||||
"name": "myproxy",
|
||||
"weight": 100,
|
||||
"enabled": true,
|
||||
"to": "https://www.cadoles.com",
|
||||
"from": ["mylocalproxydomain:*"],
|
||||
"createdAt": "2018-12-10T13:45:00.000Z",
|
||||
"updatedAt": "2020-10-02T15:09:00.000Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Source
|
||||
|
||||
Voir [`internal/admin/proxy_route.go#updateProxy()`](../../../internal/admin/proxy_route.go#updateProxy)
|
||||
|
||||
### `GET /api/v1/proxies?names={name1,name2,...}`
|
||||
|
||||
Lister les proxies existants
|
||||
|
||||
#### Paramètres
|
||||
|
||||
- `{names}` - Optionnel - Liste des noms de proxy à appliquer en tant que filtre
|
||||
|
||||
#### Exemple de résultat
|
||||
|
||||
```json5
|
||||
{
|
||||
"data": {
|
||||
"proxies": [
|
||||
{
|
||||
"name": "myproxy",
|
||||
"weight": 0,
|
||||
"enabled": false,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Source
|
||||
|
||||
Voir [`internal/admin/proxy_route.go#queryProxy()`](../../../internal/admin/proxy_route.go#queryProxy)
|
||||
|
||||
## `DELETE /api/v1/proxies/{proxyName}`
|
||||
|
||||
Supprimer le proxy
|
||||
|
||||
#### Paramètres
|
||||
|
||||
- `{proxyName}` - Nom du proxy
|
||||
|
||||
#### Exemple de résultat
|
||||
|
||||
```json5
|
||||
{
|
||||
"data": {
|
||||
"proxyName": "myproxy"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Source
|
||||
|
||||
Voir [`internal/admin/proxy_route.go#deleteProxy()`](../../../internal/admin/proxy_route.go#deleteProxy)
|
@ -70,15 +70,15 @@ docker run --rm -t \
|
||||
|
||||
Surveiller les sources, compiler celles ci en cas de modifications et lancer les services `bouncer-proxy` et `bouncer-admin`.
|
||||
|
||||
#### `make test`
|
||||
### `make test`
|
||||
|
||||
Exécuter les tests unitaires/d'intégration du projet.
|
||||
|
||||
#### `make build`
|
||||
### `make build`
|
||||
|
||||
Compiler une version de développement du binaire `bouncer`.
|
||||
|
||||
#### `make docker-build`
|
||||
### `make docker-build`
|
||||
|
||||
Construire une image Docker pour Bouncer.
|
||||
|
||||
@ -92,6 +92,13 @@ docker run \
|
||||
bouncer server proxy run
|
||||
```
|
||||
|
||||
### `make grafterm`
|
||||
|
||||
Afficher un tableau de bord [`grafterm`](https://github.com/slok/grafterm) branché sur l'instance Prometheus locale.
|
||||
|
||||
### `make siege`
|
||||
|
||||
Lancer une session de test [`siege`](https://github.com/JoeDog/siege) sur l'instance `bouncer-proxy` locale.
|
||||
## Arborescence du projet
|
||||
|
||||
```bash
|
||||
|
16
go.mod
16
go.mod
@ -6,6 +6,7 @@ require (
|
||||
forge.cadoles.com/Cadoles/go-proxy v0.0.0-20230701194111-c6b3d482cca6
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||
github.com/drone/envsubst v1.0.3
|
||||
github.com/getsentry/sentry-go v0.22.0
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.6
|
||||
@ -52,13 +53,14 @@ require (
|
||||
github.com/qri-io/jsonpointer v0.1.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
@ -68,7 +70,7 @@ require (
|
||||
cdr.dev/slog v1.4.2 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.9.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/go-chi/cors v1.2.1
|
||||
@ -78,11 +80,11 @@ require (
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.19
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/lib/pq v1.10.0 // indirect
|
||||
github.com/lithammer/shortuuid/v4 v4.0.0
|
||||
@ -94,10 +96,10 @@ require (
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/mod v0.9.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/term v0.7.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
|
||||
|
49
go.sum
49
go.sum
@ -144,8 +144,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
@ -162,6 +162,8 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@ -322,17 +324,16 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
|
||||
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
||||
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
|
||||
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9 h1:TRX4Q630UXxPVLvP5vGaqVJO7S+0PE6msRZUsFSBoC8=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9/go.mod h1:K68euYaR95FnL0hIQB8VvzL70vB7pSifbJUydCTPmgM=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.19 h1:ekv1qEZE6BVct89QA+pRF6+4pCpfVrOnEJnTnT4RXoY=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.19/go.mod h1:l3im3coce1lL2cDeAjqmaR+Awx+X8Ih+2k8BuHNJ4CU=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
||||
@ -421,6 +422,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
@ -446,8 +449,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
@ -493,9 +495,8 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -532,7 +533,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -577,9 +577,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -608,7 +606,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -680,17 +677,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -701,10 +695,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -763,7 +755,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -5,15 +5,28 @@ import (
|
||||
"strings"
|
||||
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/admin"
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/auth/jwt"
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/command/common"
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/jwk"
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
flagPrintDefaultToken = "print-default-token"
|
||||
)
|
||||
|
||||
func RunCommand() *cli.Command {
|
||||
flags := common.Flags()
|
||||
flags := append(
|
||||
common.Flags(),
|
||||
&cli.BoolFlag{
|
||||
Name: flagPrintDefaultToken,
|
||||
Usage: "Generate and print a default writer token in console at startup",
|
||||
Value: true,
|
||||
},
|
||||
)
|
||||
|
||||
return &cli.Command{
|
||||
Name: "run",
|
||||
@ -36,6 +49,22 @@ func RunCommand() *cli.Command {
|
||||
|
||||
defer flushSentry()
|
||||
|
||||
if printDefaultToken := ctx.Bool(flagPrintDefaultToken); printDefaultToken {
|
||||
key, err := jwk.Generate(jwk.DefaultKeySize)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not generate default key")
|
||||
}
|
||||
|
||||
token, err := jwt.GenerateToken(ctx.Context, key, string(conf.Admin.Auth.Issuer), "default-admin", jwt.Role(jwt.RoleWriter))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.SetLevel(logger.LevelInfo)
|
||||
logger.Info(ctx.Context, "default writer token", logger.F("token", token))
|
||||
logger.SetLevel(logger.Level(conf.Logger.Level))
|
||||
}
|
||||
|
||||
srv := admin.NewServer(
|
||||
admin.WithServerConfig(conf.Admin),
|
||||
admin.WithRedisConfig(conf.Redis),
|
||||
|
@ -6,11 +6,13 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/drone/envsubst"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var reVar = regexp.MustCompile(`^\${(\w+)}$`)
|
||||
// var reVar = regexp.MustCompile(`^\${(\w+)}$`)
|
||||
var reVar = regexp.MustCompile(`\${(.*?)}`)
|
||||
|
||||
type InterpolatedString string
|
||||
|
||||
@ -130,14 +132,22 @@ type InterpolatedStringSlice []string
|
||||
|
||||
func (iss *InterpolatedStringSlice) UnmarshalYAML(value *yaml.Node) error {
|
||||
var data []string
|
||||
var evErr error
|
||||
|
||||
if err := value.Decode(&data); err != nil {
|
||||
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into map", value.Value, value.Line)
|
||||
}
|
||||
|
||||
for index, value := range data {
|
||||
if match := reVar.FindStringSubmatch(value); len(match) > 0 {
|
||||
value = os.Getenv(match[1])
|
||||
//match := reVar.FindStringSubmatch(value)
|
||||
re := regexp.MustCompile(`\${(.*?)}`)
|
||||
|
||||
res := re.FindAllStringSubmatch(value, 10)
|
||||
if len(res) > 0 {
|
||||
value, evErr = envsubst.EvalEnv(value)
|
||||
if evErr != nil {
|
||||
return evErr
|
||||
}
|
||||
}
|
||||
|
||||
data[index] = value
|
||||
|
4
internal/config/testdata/config.yml
vendored
4
internal/config/testdata/config.yml
vendored
@ -2,5 +2,5 @@ logger:
|
||||
level: 0
|
||||
format: human
|
||||
http:
|
||||
host: "0.0.0.0"
|
||||
port: 3000
|
||||
host: "${LISTEN_ADDR}"
|
||||
port: 3000
|
||||
|
@ -2,6 +2,7 @@ package testsuite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
||||
@ -48,6 +49,187 @@ var layerRepositoryTestCases = []layerRepositoryTestCase{
|
||||
return errors.Errorf("layer.UpdatedAt should not be zero value")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Create then get layer",
|
||||
Do: func(repo store.LayerRepository) error {
|
||||
ctx := context.Background()
|
||||
|
||||
var proxyName store.ProxyName = "create_then_get_layer_proxy"
|
||||
var layerName store.LayerName = "create_then_get_layer"
|
||||
var layerType store.LayerType = "dummy"
|
||||
var layerOptions store.LayerOptions = store.LayerOptions{
|
||||
"foo": "bar",
|
||||
"test": struct {
|
||||
Items []int `json:"items"`
|
||||
}{
|
||||
Items: []int{1, 2, 3},
|
||||
},
|
||||
}
|
||||
|
||||
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
foundLayer, err := repo.GetLayer(ctx, proxyName, layerName)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.Name, foundLayer.Name; e != g {
|
||||
return errors.Errorf("foundLayer.Name: expected '%v', got '%v'", createdLayer.Name, foundLayer.Name)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.CreatedAt, foundLayer.CreatedAt; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.CreatedAt: expected '%v', got '%v'", createdLayer.CreatedAt, foundLayer.CreatedAt)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.UpdatedAt, foundLayer.UpdatedAt; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.UpdatedAt: expected '%v', got '%v'", createdLayer.UpdatedAt, foundLayer.UpdatedAt)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.Enabled, foundLayer.Enabled; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.Enabled: expected '%v', got '%v'", createdLayer.Enabled, foundLayer.Enabled)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.Weight, foundLayer.Weight; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.Weight: expected '%v', got '%v'", createdLayer.Weight, foundLayer.Weight)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.Proxy, foundLayer.Proxy; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.Proxy: expected '%v', got '%v'", createdLayer.Proxy, foundLayer.Proxy)
|
||||
}
|
||||
|
||||
if e, g := createdLayer.Options, foundLayer.Options; !reflect.DeepEqual(e, g) {
|
||||
return errors.Errorf("foundLayer.Options: expected '%v', got '%v'", createdLayer.Options, foundLayer.Options)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Create then delete layer",
|
||||
Do: func(repo store.LayerRepository) error {
|
||||
ctx := context.Background()
|
||||
|
||||
var layerName store.LayerName = "create_then_delete_layer"
|
||||
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
||||
var layerType store.LayerType = "dummy"
|
||||
var layerOptions store.LayerOptions = store.LayerOptions{
|
||||
"foo": "bar",
|
||||
"test": struct {
|
||||
Items []int `json:"items"`
|
||||
}{
|
||||
Items: []int{1, 2, 3},
|
||||
},
|
||||
}
|
||||
|
||||
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := repo.DeleteLayer(ctx, createdLayer.Proxy, createdLayer.Name); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
foundLayer, err := repo.GetLayer(ctx, createdLayer.Proxy, createdLayer.Name)
|
||||
if err == nil {
|
||||
return errors.New("err should not be nil")
|
||||
}
|
||||
|
||||
if !errors.Is(err, store.ErrNotFound) {
|
||||
return errors.Errorf("err should be store.ErrNotFound, got '%+v'", err)
|
||||
}
|
||||
|
||||
if foundLayer != nil {
|
||||
return errors.Errorf("foundLayer should be nil, got '%v'", foundLayer)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Create already existing layer",
|
||||
Do: func(repo store.LayerRepository) error {
|
||||
ctx := context.Background()
|
||||
|
||||
var layerName store.LayerName = "create_already_existing_layer"
|
||||
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
||||
var layerType store.LayerType = "dummy"
|
||||
var layerOptions store.LayerOptions = store.LayerOptions{
|
||||
"foo": "bar",
|
||||
"test": struct {
|
||||
Items []int `json:"items"`
|
||||
}{
|
||||
Items: []int{1, 2, 3},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
_, err = repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
||||
if err == nil {
|
||||
return errors.New("err should not be nil")
|
||||
}
|
||||
|
||||
if !errors.Is(err, store.ErrAlreadyExist) {
|
||||
return errors.Errorf("err: expected store.ErrAlreadyExists, got '%+v'", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Create then query layer",
|
||||
Do: func(repo store.LayerRepository) error {
|
||||
ctx := context.Background()
|
||||
|
||||
var layerName store.LayerName = "create_then_query_layer"
|
||||
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
||||
var layerType store.LayerType = "dummy"
|
||||
var layerOptions store.LayerOptions = store.LayerOptions{
|
||||
"foo": "bar",
|
||||
"test": struct {
|
||||
Items []int `json:"items"`
|
||||
}{
|
||||
Items: []int{1, 2, 3},
|
||||
},
|
||||
}
|
||||
|
||||
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
headers, err := repo.QueryLayers(ctx, createdLayer.Proxy)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if len(headers) < 1 {
|
||||
return errors.Errorf("len(headers): expected value > 1, got '%v'", len(headers))
|
||||
}
|
||||
|
||||
found := false
|
||||
|
||||
for _, h := range headers {
|
||||
if h.Name == createdLayer.Name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return errors.New("could not find created layer in query results")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
@ -83,6 +83,14 @@ var proxyRepositoryTestCases = []proxyRepositoryTestCase{
|
||||
return errors.Errorf("foundProxy.To: expected '%v', got '%v'", createdProxy.To, foundProxy.To)
|
||||
}
|
||||
|
||||
if e, g := createdProxy.Enabled, foundProxy.Enabled; e != g {
|
||||
return errors.Errorf("foundProxy.Enabled: expected '%v', got '%v'", createdProxy.Enabled, foundProxy.Enabled)
|
||||
}
|
||||
|
||||
if e, g := createdProxy.Weight, foundProxy.Weight; e != g {
|
||||
return errors.Errorf("foundProxy.Weight: expected '%v', got '%v'", createdProxy.Weight, foundProxy.Weight)
|
||||
}
|
||||
|
||||
if e, g := createdProxy.CreatedAt, foundProxy.CreatedAt; e != g {
|
||||
return errors.Errorf("foundProxy.CreatedAt: expected '%v', got '%v'", createdProxy.CreatedAt, foundProxy.CreatedAt)
|
||||
}
|
||||
@ -127,7 +135,7 @@ var proxyRepositoryTestCases = []proxyRepositoryTestCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Create then query",
|
||||
Name: "Create then query layer",
|
||||
Do: func(repo store.ProxyRepository) error {
|
||||
ctx := context.Background()
|
||||
|
||||
|
196
misc/grafterm/dashboard.json
Normal file
196
misc/grafterm/dashboard.json
Normal file
@ -0,0 +1,196 @@
|
||||
{
|
||||
"version": "v1",
|
||||
"datasources": {
|
||||
"prometheus": {
|
||||
"prometheus": {
|
||||
"address": "http://127.0.0.1:9090"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"variables": {
|
||||
"job": {
|
||||
"constant": { "value": "bouncer-proxy" }
|
||||
},
|
||||
"interval": {
|
||||
"interval": { "steps": 50 }
|
||||
}
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"title": "Bouncer - Total queue sessions",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"thresholds": [{ "color": "#47D038" }],
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(bouncer_layer_queue_sessions{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Bouncer Traffic",
|
||||
"gridPos": {
|
||||
"w": 80
|
||||
},
|
||||
"graph": {
|
||||
"queries": [
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(rate(bouncer_proxy_director_proxy_requests_total{job=\"{{.job}}\"}[{{.interval}}]))",
|
||||
"legend": "req/s"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Goroutines",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"thresholds": [{ "color": "#47D038" }],
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_goroutines{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "GC duration",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"unit": "second",
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "max(go_gc_duration_seconds{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Stack",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"unit": "bytes",
|
||||
"thresholds": [{ "color": "#22F1F1" }],
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_stack_inuse_bytes{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Heap",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"unit": "bytes",
|
||||
"thresholds": [{ "color": "#22F1F1" }],
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_heap_inuse_bytes{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Alloc",
|
||||
"gridPos": { "w": 20 },
|
||||
"singlestat": {
|
||||
"unit": "bytes",
|
||||
"thresholds": [{ "color": "#22F1F1" }],
|
||||
"query": {
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_alloc_bytes{job=\"{{.job}}\"})"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Goroutines",
|
||||
"gridPos": { "w": 50 },
|
||||
"graph": {
|
||||
"visualization": {
|
||||
"legend": { "disable": true },
|
||||
"yAxis": { "unit": "", "decimals": 2 }
|
||||
},
|
||||
"queries": [
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_goroutines{job=\"{{.job}}\"})"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "GC duration",
|
||||
"gridPos": { "w": 50 },
|
||||
"graph": {
|
||||
"queries": [
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "max(go_gc_duration_seconds{job=\"{{.job}}\"}) by (quantile)",
|
||||
"legend": "Q{{.quantile}}"
|
||||
}
|
||||
],
|
||||
"visualization": {
|
||||
"yAxis": { "unit": "second" },
|
||||
"seriesOverride": [
|
||||
{ "regex": "^Q0$", "color": "#F9E2D2" },
|
||||
{ "regex": "^Q0.25$", "color": "#F2C96D" },
|
||||
{ "regex": "^Q0.5(0)?$", "color": "#EAB839" },
|
||||
{ "regex": "^Q0.75$", "color": "#EF843C" },
|
||||
{ "regex": "^Q1(.0)?$", "color": "#E24D42" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Memory",
|
||||
"gridPos": { "w": 50 },
|
||||
"graph": {
|
||||
"visualization": {
|
||||
"yAxis": { "unit": "byte", "decimals": 0 }
|
||||
},
|
||||
"queries": [
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_stack_inuse_bytes{job=\"{{.job}}\"})",
|
||||
"legend": "stack inuse"
|
||||
},
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_heap_inuse_bytes{job=\"{{.job}}\"})",
|
||||
"legend": "heap inuse"
|
||||
},
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(go_memstats_alloc_bytes{job=\"{{.job}}\"})",
|
||||
"legend": "alloc"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Memory ops rate",
|
||||
"gridPos": {
|
||||
"w": 50
|
||||
},
|
||||
"graph": {
|
||||
"queries": [
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(rate(go_memstats_frees_total{job=\"{{.job}}\"}[{{.interval}}]))",
|
||||
"legend": "frees/s"
|
||||
},
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(rate(go_memstats_mallocs_total{job=\"{{.job}}\"}[{{.interval}}]))",
|
||||
"legend": "mallocs/s"
|
||||
},
|
||||
{
|
||||
"datasourceID": "prometheus",
|
||||
"expr": "sum(rate(go_memstats_lookups_total{job=\"{{.job}}\"}[{{.interval}}]))",
|
||||
"legend": "lookups/s"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -7,12 +7,22 @@ ARG https_proxy=
|
||||
|
||||
# Install dev environment dependencies
|
||||
RUN export DEBIAN_FRONTEND=noninteractive &&\
|
||||
apt clean &&\
|
||||
apt-get update -y &&\
|
||||
apt-get install -y --no-install-recommends curl ca-certificates build-essential wget unzip tar git jq
|
||||
apt-get install -y --no-install-recommends curl ca-certificates build-essential wget unzip tar git jq gnupg
|
||||
|
||||
# Add LetsEncrypt certificates
|
||||
RUN curl -k https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/common/add-letsencrypt-ca.sh | bash
|
||||
|
||||
RUN install -m 0755 -d /etc/apt/keyrings \
|
||||
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
||||
&& chmod a+r /etc/apt/keyrings/docker.gpg \
|
||||
&& echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" \
|
||||
| tee /etc/apt/sources.list.d/docker.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y docker-ce-cli
|
||||
|
||||
ARG GO_VERSION=1.20.4
|
||||
|
||||
# Install Go
|
||||
|
7
misc/prometheus/prometheus.yml
Normal file
7
misc/prometheus/prometheus.yml
Normal file
@ -0,0 +1,7 @@
|
||||
scrape_configs:
|
||||
- job_name: bouncer-proxy
|
||||
metrics_path: /.bouncer/metrics
|
||||
static_configs:
|
||||
- targets:
|
||||
- "localhost:8080"
|
||||
scrape_interval: 5s
|
6
misc/siege/urls.txt
Normal file
6
misc/siege/urls.txt
Normal file
@ -0,0 +1,6 @@
|
||||
http://localhost:8080/blog/
|
||||
http://localhost:8080/services/
|
||||
http://localhost:8080/
|
||||
http://localhost:8080/recrutement/
|
||||
http://localhost:8080/faq/
|
||||
http://localhost:8080/societe/histoire/
|
Reference in New Issue
Block a user