add mount types.

This commit is contained in:
Miroslav Šedivý
2021-05-22 17:50:16 +02:00
parent 97b577ff55
commit 3cb777e047
6 changed files with 107 additions and 18 deletions
+4
View File
@@ -246,6 +246,10 @@ components:
RoomMount:
type: object
properties:
type:
type: string
enum: [ private, template, public ]
example: private
host_path:
type: string
example: /profile
+17
View File
@@ -113,6 +113,12 @@ export interface RoomMember {
* @interface RoomMount
*/
export interface RoomMount {
/**
*
* @type {string}
* @memberof RoomMount
*/
type?: RoomMountTypeEnum;
/**
*
* @type {string}
@@ -126,6 +132,17 @@ export interface RoomMount {
*/
container_path?: string;
}
/**
* @export
* @enum {string}
*/
export enum RoomMountTypeEnum {
private = 'private',
template = 'template',
public = 'public'
}
/**
*
* @export
+1 -1
View File
@@ -210,7 +210,7 @@
</v-row>
<v-row align="center" no-gutters class="mt-3">
<h2> Mounts </h2>
<v-btn @click="data.mounts = [ ...data.mounts, { host_path: '', container_path: '' }]" icon color="green"><v-icon>mdi-plus</v-icon></v-btn>
<v-btn @click="data.mounts = [ ...data.mounts, { type: 'private', host_path: '', container_path: '' }]" icon color="green"><v-icon>mdi-plus</v-icon></v-btn>
</v-row>
<v-row align="center" v-for="({ host_path, container_path }, index) in data.mounts" :key="index">
<v-col class="py-0">
+16
View File
@@ -22,6 +22,8 @@ type Room struct {
StorageInternal string
StorageExternal string
MountsWhitelist []string
InstanceName string
InstanceUrl string
@@ -73,6 +75,11 @@ func (Room) Init(cmd *cobra.Command) error {
return err
}
cmd.PersistentFlags().StringSlice("mounts.whitelist", []string{}, "whitelisted public mounts for containers")
if err := viper.BindPFlag("mounts.whitelist", cmd.PersistentFlags().Lookup("mounts.whitelist")); err != nil {
return err
}
// Instance
cmd.PersistentFlags().String("instance.name", "neko-rooms", "unique instance name (if running muliple on the same host)")
@@ -159,6 +166,15 @@ func (s *Room) Set() {
s.StorageEnabled = false
}
s.MountsWhitelist = viper.GetStringSlice("mounts.whitelist")
for _, path := range s.MountsWhitelist {
path = filepath.Clean(path)
if !filepath.IsAbs(path) {
log.Panic().Msg("invalid `mounts.whitelist`, must be an absolute path")
}
}
s.InstanceName = viper.GetString("instance.name")
if !dockerNames.RestrictedNamePattern.MatchString(s.InstanceName) {
log.Panic().Msg("invalid `instance.name`, must match " + dockerNames.RestrictedNameChars)
+54 -11
View File
@@ -27,9 +27,10 @@ import (
const (
frontendPort = 8080
roomStoragePath = "./rooms"
roomStorageUid = 1000
roomStorageGid = 1000
templateStoragePath = "./templates"
privateStoragePath = "./rooms"
privateStorageUid = 1000
privateStorageGid = 1000
)
func New(config *config.Room) *RoomManagerCtx {
@@ -195,6 +196,8 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
mounts := []dockerMount.Mount{}
for _, mount := range settings.Mounts {
readOnly := false
hostPath := filepath.Clean(mount.HostPath)
containerPath := filepath.Clean(mount.ContainerPath)
@@ -202,23 +205,49 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
return "", fmt.Errorf("mount paths must be absolute")
}
externalPath := path.Join(manager.config.StorageExternal, roomStoragePath, roomName, hostPath)
internalPath := path.Join(manager.config.StorageInternal, roomStoragePath, roomName, hostPath)
// private container's data
if mount.Type == types.MountPrivate {
// ensure that target exists
internalPath := path.Join(manager.config.StorageInternal, privateStoragePath, roomName, hostPath)
if err := os.MkdirAll(internalPath, os.ModePerm); err != nil {
return "", err
}
if err := utils.ChownR(internalPath, roomStorageUid, roomStorageGid); err != nil {
if err := utils.ChownR(internalPath, privateStorageUid, privateStorageGid); err != nil {
return "", err
}
// prefix host path
hostPath = path.Join(manager.config.StorageExternal, privateStoragePath, roomName, hostPath)
} else if mount.Type == types.MountTemplate {
// readonly template data
readOnly = true
// prefix host path
hostPath = path.Join(manager.config.StorageExternal, templateStoragePath, hostPath)
} else if mount.Type == types.MountPublic {
// public whitelisted mounts
var isAllowed = false
for _, path := range manager.config.MountsWhitelist {
if strings.HasPrefix(hostPath, path) {
isAllowed = true
break
}
}
if !isAllowed {
return "", fmt.Errorf("mount path is not whitelisted in config")
}
} else {
return "", fmt.Errorf("unknown mount type %q", mount.Type)
}
mounts = append(mounts,
dockerMount.Mount{
Type: dockerMount.TypeBind,
Source: externalPath,
Source: hostPath,
Target: containerPath,
ReadOnly: false,
ReadOnly: readOnly,
Consistency: dockerMount.ConsistencyDefault,
BindOptions: &dockerMount.BindOptions{
@@ -349,11 +378,25 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro
return nil, err
}
privateStorageRoot := path.Join(manager.config.StorageExternal, privateStoragePath, roomName)
templateStorageRoot := path.Join(manager.config.StorageExternal, templateStoragePath)
mounts := []types.RoomMount{}
dataRoot := path.Join(manager.config.StorageExternal, roomStoragePath, roomName)
for _, mount := range container.Mounts {
mountType := types.MountPublic
hostPath := mount.Source
if strings.HasPrefix(hostPath, privateStorageRoot) {
mountType = types.MountPrivate
hostPath = strings.TrimPrefix(hostPath, privateStorageRoot)
} else if strings.HasPrefix(hostPath, templateStorageRoot) {
mountType = types.MountTemplate
hostPath = strings.TrimPrefix(hostPath, templateStorageRoot)
}
mounts = append(mounts, types.RoomMount{
HostPath: strings.TrimPrefix(mount.Source, dataRoot),
Type: mountType,
HostPath: hostPath,
ContainerPath: mount.Destination,
})
}
+9
View File
@@ -39,7 +39,16 @@ type RoomEntry struct {
Created time.Time `json:"created"`
}
type MountType string
const (
MountPrivate MountType = "private"
MountTemplate MountType = "template"
MountPublic MountType = "public"
)
type RoomMount struct {
Type MountType `json:"type"`
HostPath string `json:"host_path"`
ContainerPath string `json:"container_path"`
}