Ajouter key-auth à /v1 et quelques routes

Ajouter route POST /v1/seed pour seeder minio avec server.documents.buckets

Ajouter route GET /v1/bucket/:bucket pour lire les objects d'un bucket

Renommer handleV1Bucket -> handleV1BucketList
This commit is contained in:
Victor Lacasse-Beaudoin 2023-04-21 21:34:18 -04:00
parent 0314d7a8eb
commit 9bbeb4b7ee

View file

@ -5,7 +5,9 @@ package cmd
import ( import (
"context" "context"
"crypto/subtle"
"fmt" "fmt"
"log"
"embed" "embed"
"html/template" "html/template"
@ -69,6 +71,14 @@ func init() {
// server.documents.buckets - --server-documents-buckets // server.documents.buckets - --server-documents-buckets
serverCmd.Flags().StringSlice("server-documents-buckets", nil, "Buckets that are allowed to be accessed by the API (config: server.documents.buckets)") serverCmd.Flags().StringSlice("server-documents-buckets", nil, "Buckets that are allowed to be accessed by the API (config: server.documents.buckets)")
viper.BindPFlag("server.documents.buckets", serverCmd.Flags().Lookup("server-documents-buckets")) viper.BindPFlag("server.documents.buckets", serverCmd.Flags().Lookup("server-documents-buckets"))
// server.api.auth - --server-api-auth
serverCmd.Flags().Bool("server-api-auth", false, "Enable to allow key authentication for /v1 routes (config: server.api.auth)")
viper.BindPFlag("server.api.auth", serverCmd.Flags().Lookup("server-api-auth"))
// server.api.key - --server-api-key
serverCmd.Flags().String("server-api-key", "", "Key to use for authenticating to /v1 routes")
viper.BindPFlag("server.api.key", serverCmd.Flags().Lookup("server-api-key"))
} }
func RunServer() { func RunServer() {
@ -82,11 +92,29 @@ func RunServer() {
e.Pre(middleware.RemoveTrailingSlash()) e.Pre(middleware.RemoveTrailingSlash())
groupV1 := e.Group("/v1")
groupV1.Use(middleware.AddTrailingSlash())
if viper.GetBool("server.api.auth") {
if len(viper.GetString("server.api.key")) < 10 {
log.Fatal("server.api.auth is enabled, but server.api.key is too small (needs at least 10 characters)")
}
groupV1.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
return subtle.ConstantTimeCompare([]byte(key), []byte(viper.GetString("server.api.key"))) == 1, nil
}))
}
// API Routes // API Routes
e.GET("/v1", handleV1) groupV1.GET("", handleV1)
e.GET("/v1/bucket", handleV1Bucket) groupV1.POST("/seed", handleV1Seed)
groupV1.GET("/bucket", handleV1BucketList)
groupV1.GET("/bucket/:bucket", handleV1BucketRead)
// Static Routes // Static Routes
@ -130,8 +158,45 @@ func handleV1(c echo.Context) error {
return c.JSON(http.StatusOK, routes) return c.JSON(http.StatusOK, routes)
} }
// handleV1Bucket affiche les buckets permis par server.documents.buckets, qui existent. // handleV1Seed créé des buckets dans minio selon la liste de buckets dans server.documents.buckets
func handleV1Bucket(c echo.Context) error { // Les buckets sont créés avec paramètres par défaut, et sont ensuite visible dans /v1/bucket.
func handleV1Seed(c echo.Context) error {
documents_buckets := viper.GetStringSlice("server.documents.buckets")
documents_endpoint := viper.GetString("server.documents.endpoint")
documents_access_key_id := viper.GetString("server.documents.access_key_id")
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
// Initialize minio client object
client, err := minio.New(documents_endpoint, &minio.Options{
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
Secure: documents_use_ssl,
})
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Error during minio#New",
})
}
var new_buckets []string
for _, bucket := range documents_buckets {
if err = client.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{}); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Error during minio#MakeBucket",
})
}
new_buckets = append(new_buckets, bucket)
}
return c.JSON(http.StatusOK, map[string]interface{}{
"message": "Buckets successfully created",
"buckets": new_buckets,
})
}
// handleV1BucketList affiche les buckets permis par server.documents.buckets, qui existent.
func handleV1BucketList(c echo.Context) error {
documents_buckets := viper.GetStringSlice("server.documents.buckets") documents_buckets := viper.GetStringSlice("server.documents.buckets")
documents_endpoint := viper.GetString("server.documents.endpoint") documents_endpoint := viper.GetString("server.documents.endpoint")
documents_access_key_id := viper.GetString("server.documents.access_key_id") documents_access_key_id := viper.GetString("server.documents.access_key_id")
@ -165,6 +230,54 @@ func handleV1Bucket(c echo.Context) error {
return c.JSON(http.StatusOK, buckets) return c.JSON(http.StatusOK, buckets)
} }
func handleV1BucketRead(c echo.Context) error {
documents_endpoint := viper.GetString("server.documents.endpoint")
documents_access_key_id := viper.GetString("server.documents.access_key_id")
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
bucket := c.Param("bucket")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Initialize minio client object
client, err := minio.New(documents_endpoint, &minio.Options{
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
Secure: documents_use_ssl,
})
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Error during minio#New",
})
}
exists, err := client.BucketExists(ctx, bucket)
if err != nil {
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
}
if !exists {
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not found"})
}
var keys []string
objectCh := client.ListObjects(ctx, bucket, minio.ListObjectsOptions{})
for object := range objectCh {
if object.Err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Error during minio#ListObjects",
})
}
keys = append(keys, object.Key)
}
return c.JSON(http.StatusOK, keys)
}
// HTML Handlers // HTML Handlers
func handleIndex(c echo.Context) error { func handleIndex(c echo.Context) error {