@@ -26,6 +26,7 @@ import (
26
26
"github.com/stacklok/toolhive/pkg/container/docker/sdk"
27
27
"github.com/stacklok/toolhive/pkg/container/images"
28
28
"github.com/stacklok/toolhive/pkg/container/runtime"
29
+ "github.com/stacklok/toolhive/pkg/ignore"
29
30
lb "github.com/stacklok/toolhive/pkg/labels"
30
31
"github.com/stacklok/toolhive/pkg/logger"
31
32
"github.com/stacklok/toolhive/pkg/networking"
@@ -83,12 +84,21 @@ func convertEnvVars(envVars map[string]string) []string {
83
84
func convertMounts (mounts []runtime.Mount ) []mount.Mount {
84
85
result := make ([]mount.Mount , 0 , len (mounts ))
85
86
for _ , m := range mounts {
86
- result = append (result , mount.Mount {
87
- Type : mount .TypeBind ,
88
- Source : m .Source ,
89
- Target : m .Target ,
90
- ReadOnly : m .ReadOnly ,
91
- })
87
+ if m .Type == runtime .MountTypeTmpfs {
88
+ // Create tmpfs mount to mask/hide sensitive directories
89
+ result = append (result , mount.Mount {
90
+ Type : mount .TypeTmpfs ,
91
+ Target : m .Target ,
92
+ // No TmpfsOptions needed - default size is sufficient for masking
93
+ })
94
+ } else {
95
+ result = append (result , mount.Mount {
96
+ Type : mount .TypeBind ,
97
+ Source : m .Source ,
98
+ Target : m .Target ,
99
+ ReadOnly : m .ReadOnly ,
100
+ })
101
+ }
92
102
}
93
103
return result
94
104
}
@@ -432,6 +442,8 @@ func generatePortBindings(labels map[string]string,
432
442
// DeployWorkload creates and starts a workload.
433
443
// It configures the workload based on the provided permission profile and transport type.
434
444
// If options is nil, default options will be used.
445
+ //
446
+ //nolint:gocyclo // This function has high complexity due to comprehensive workload setup
435
447
func (c * Client ) DeployWorkload (
436
448
ctx context.Context ,
437
449
image ,
@@ -445,7 +457,11 @@ func (c *Client) DeployWorkload(
445
457
isolateNetwork bool ,
446
458
) (string , int , error ) {
447
459
// Get permission config from profile
448
- permissionConfig , err := c .getPermissionConfigFromProfile (permissionProfile , transportType )
460
+ var ignoreConfig * ignore.Config
461
+ if options != nil {
462
+ ignoreConfig = options .IgnoreConfig
463
+ }
464
+ permissionConfig , err := c .getPermissionConfigFromProfile (permissionProfile , transportType , ignoreConfig )
449
465
if err != nil {
450
466
return "" , 0 , fmt .Errorf ("failed to get permission config: %w" , err )
451
467
}
@@ -894,7 +910,11 @@ func (c *Client) IsRunning(ctx context.Context) error {
894
910
// getPermissionConfigFromProfile converts a permission profile to a container permission config
895
911
// with transport-specific settings (internal function)
896
912
// addReadOnlyMounts adds read-only mounts to the permission config
897
- func (* Client ) addReadOnlyMounts (config * runtime.PermissionConfig , mounts []permissions.MountDeclaration ) {
913
+ func (* Client ) addReadOnlyMounts (
914
+ config * runtime.PermissionConfig ,
915
+ mounts []permissions.MountDeclaration ,
916
+ ignoreConfig * ignore.Config ,
917
+ ) {
898
918
for _ , mountDecl := range mounts {
899
919
source , target , err := mountDecl .Parse ()
900
920
if err != nil {
@@ -919,12 +939,20 @@ func (*Client) addReadOnlyMounts(config *runtime.PermissionConfig, mounts []perm
919
939
Source : absPath ,
920
940
Target : target ,
921
941
ReadOnly : true ,
942
+ Type : runtime .MountTypeBind ,
922
943
})
944
+
945
+ // Process ignore patterns and add tmpfs overlays
946
+ addIgnoreOverlays (config , absPath , target , ignoreConfig )
923
947
}
924
948
}
925
949
926
950
// addReadWriteMounts adds read-write mounts to the permission config
927
- func (* Client ) addReadWriteMounts (config * runtime.PermissionConfig , mounts []permissions.MountDeclaration ) {
951
+ func (* Client ) addReadWriteMounts (
952
+ config * runtime.PermissionConfig ,
953
+ mounts []permissions.MountDeclaration ,
954
+ ignoreConfig * ignore.Config ,
955
+ ) {
928
956
for _ , mountDecl := range mounts {
929
957
source , target , err := mountDecl .Parse ()
930
958
if err != nil {
@@ -962,8 +990,62 @@ func (*Client) addReadWriteMounts(config *runtime.PermissionConfig, mounts []per
962
990
Source : absPath ,
963
991
Target : target ,
964
992
ReadOnly : false ,
993
+ Type : runtime .MountTypeBind ,
965
994
})
966
995
}
996
+
997
+ // Process ignore patterns and add tmpfs overlays
998
+ addIgnoreOverlays (config , absPath , target , ignoreConfig )
999
+ }
1000
+ }
1001
+
1002
+ // addIgnoreOverlays processes ignore patterns for a mount and adds overlay mounts
1003
+ func addIgnoreOverlays (config * runtime.PermissionConfig , sourceDir , containerPath string , ignoreConfig * ignore.Config ) {
1004
+ // Skip if no ignore configuration is provided
1005
+ if ignoreConfig == nil {
1006
+ return
1007
+ }
1008
+
1009
+ // Create ignore processor with configuration
1010
+ ignoreProcessor := ignore .NewProcessor (ignoreConfig )
1011
+
1012
+ // Load global ignore patterns if enabled
1013
+ if ignoreConfig .LoadGlobal {
1014
+ if err := ignoreProcessor .LoadGlobal (); err != nil {
1015
+ logger .Debugf ("Failed to load global ignore patterns: %v" , err )
1016
+ // Continue without global patterns
1017
+ }
1018
+ }
1019
+
1020
+ // Load local ignore patterns from the source directory
1021
+ if err := ignoreProcessor .LoadLocal (sourceDir ); err != nil {
1022
+ logger .Debugf ("Failed to load local ignore patterns from %s: %v" , sourceDir , err )
1023
+ // Continue without local patterns
1024
+ }
1025
+
1026
+ // Get overlay mounts (both tmpfs for directories and bind for files)
1027
+ overlayMounts := ignoreProcessor .GetOverlayMounts (sourceDir , containerPath )
1028
+
1029
+ // Add overlay mounts to the configuration
1030
+ for _ , overlayMount := range overlayMounts {
1031
+ var mountType runtime.MountType
1032
+ var source string
1033
+
1034
+ if overlayMount .Type == "tmpfs" {
1035
+ mountType = runtime .MountTypeTmpfs
1036
+ source = "" // No source for tmpfs
1037
+ } else {
1038
+ mountType = runtime .MountTypeBind
1039
+ source = overlayMount .HostPath
1040
+ }
1041
+
1042
+ config .Mounts = append (config .Mounts , runtime.Mount {
1043
+ Source : source ,
1044
+ Target : overlayMount .ContainerPath ,
1045
+ ReadOnly : false ,
1046
+ Type : mountType ,
1047
+ })
1048
+ logger .Debugf ("Added %s overlay for ignored path: %s -> %s" , overlayMount .Type , source , overlayMount .ContainerPath )
967
1049
}
968
1050
}
969
1051
@@ -992,6 +1074,7 @@ func convertRelativePathToAbsolute(source string, mountDecl permissions.MountDec
992
1074
func (c * Client ) getPermissionConfigFromProfile (
993
1075
profile * permissions.Profile ,
994
1076
transportType string ,
1077
+ ignoreConfig * ignore.Config ,
995
1078
) (* runtime.PermissionConfig , error ) {
996
1079
// Start with a default permission config
997
1080
config := & runtime.PermissionConfig {
@@ -1003,8 +1086,8 @@ func (c *Client) getPermissionConfigFromProfile(
1003
1086
}
1004
1087
1005
1088
// Add mounts
1006
- c .addReadOnlyMounts (config , profile .Read )
1007
- c .addReadWriteMounts (config , profile .Write )
1089
+ c .addReadOnlyMounts (config , profile .Read , ignoreConfig )
1090
+ c .addReadWriteMounts (config , profile .Write , ignoreConfig )
1008
1091
1009
1092
// Validate transport type
1010
1093
switch transportType {
0 commit comments