Skip to content

Commit 5aeeb4c

Browse files
committed
only embed module source in Linux builds
1 parent 9941a8f commit 5aeeb4c

File tree

6 files changed

+127
-130
lines changed

6 files changed

+127
-130
lines changed

assets/install-scripts/install-selinux.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ while getopts "c:t:" opt; do
4141
done
4242

4343
# Write SELinux module source to a temporary directory
44-
WORK_DIR="$(mktemp -d teleport-selinux.XXXXXXXX)"
44+
WORK_DIR="$(mktemp -d --suffix teleport-selinux.XXXXXXXX)"
4545
trap 'rm -rf "${WORK_DIR}"' EXIT INT TERM
4646

4747
"${TELEPORT}" selinux-ssh module-source > "${WORK_DIR}/teleport_ssh.te"

lib/selinux/module.go

Lines changed: 0 additions & 75 deletions
This file was deleted.

lib/selinux/read_config_linux.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2025 Open Container Initiative
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
//
14+
// Original source: https://github.com/opencontainers/selinux/blob/main/go-selinux/selinux_linux.go#L229
15+
//
16+
// Modified to return an error.
17+
18+
package selinux
19+
20+
import (
21+
"bufio"
22+
"bytes"
23+
"os"
24+
25+
"github.com/gravitational/trace"
26+
)
27+
28+
func readConfig(target string) (string, error) {
29+
in, err := os.Open(selinuxConfig)
30+
if err != nil {
31+
return "", trace.Wrap(err)
32+
}
33+
defer in.Close()
34+
35+
scanner := bufio.NewScanner(in)
36+
37+
for scanner.Scan() {
38+
line := bytes.TrimSpace(scanner.Bytes())
39+
if len(line) == 0 {
40+
// Skip blank lines
41+
continue
42+
}
43+
if line[0] == ';' || line[0] == '#' {
44+
// Skip comments
45+
continue
46+
}
47+
fields := bytes.SplitN(line, []byte{'='}, 2)
48+
if len(fields) != 2 {
49+
continue
50+
}
51+
if string(fields[0]) == target {
52+
return string(bytes.Trim(fields[1], `"`)), nil
53+
}
54+
}
55+
56+
return "", nil
57+
}

lib/selinux/selinux_linux.go

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,70 +19,68 @@
1919
package selinux
2020

2121
import (
22-
"bufio"
2322
"bytes"
2423
"context"
24+
_ "embed"
2525
"io/fs"
2626
"log/slog"
27-
"os"
2827
"path/filepath"
2928
"strings"
29+
"text/template"
3030

3131
"github.com/gravitational/trace"
3232
ocselinux "github.com/opencontainers/selinux/go-selinux"
33+
34+
"github.com/gravitational/teleport/lib/versioncontrol"
3335
)
3436

3537
const (
3638
selinuxConfig = "/etc/selinux/config"
3739
selinuxTypeTag = "SELINUXTYPE"
40+
moduleName = "teleport_ssh"
41+
domain = "teleport_ssh_t"
3842
permissiveModuleName = "permissive_" + domain
3943
)
4044

41-
// Copyright 2025 Open Container Initiative
42-
//
43-
// Licensed under the Apache License, Version 2.0 (the "License");
44-
// you may not use this file except in compliance with the License.
45-
// You may obtain a copy of the License at
46-
//
47-
// http://www.apache.org/licenses/LICENSE-2.0
48-
//
49-
// Unless required by applicable law or agreed to in writing, software
50-
// distributed under the License is distributed on an "AS IS" BASIS,
51-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52-
// See the License for the specific language governing permissions and
53-
// limitations under the License.
54-
//
55-
// Original source: https://github.com/opencontainers/selinux/blob/main/go-selinux/selinux_linux.go#L229
56-
// Modified to return an error.
57-
func readConfig(target string) (string, error) {
58-
in, err := os.Open(selinuxConfig)
45+
//go:embed teleport_ssh.te
46+
var module string
47+
48+
//go:embed teleport_ssh.fc.tmpl
49+
var fileContexts string
50+
51+
// ModuleSource returns the source of the SELinux SSH module.
52+
func ModuleSource() string {
53+
return module
54+
}
55+
56+
type filePaths struct {
57+
InstallDir string
58+
DataDir string
59+
ConfigPath string
60+
UpgradeUnitDir string
61+
}
62+
63+
// FileContexts returns file contexts for the SELinux SSH module.
64+
func FileContexts(installDir, dataDir, configPath string) (string, error) {
65+
fcTempl, err := template.New("selinux file contexts").Parse(fileContexts)
5966
if err != nil {
60-
return "", trace.Wrap(err)
67+
return "", trace.Wrap(err, "failed to parse file contexts template")
6168
}
62-
defer in.Close()
6369

64-
scanner := bufio.NewScanner(in)
65-
66-
for scanner.Scan() {
67-
line := bytes.TrimSpace(scanner.Bytes())
68-
if len(line) == 0 {
69-
// Skip blank lines
70-
continue
71-
}
72-
if line[0] == ';' || line[0] == '#' {
73-
// Skip comments
74-
continue
75-
}
76-
fields := bytes.SplitN(line, []byte{'='}, 2)
77-
if len(fields) != 2 {
78-
continue
79-
}
80-
if string(fields[0]) == target {
81-
return string(bytes.Trim(fields[1], `"`)), nil
82-
}
70+
// Generate a file specifying the locations of important dirs so SELinux
71+
// will allow Teleport SSH to be able to access them.
72+
var buf bytes.Buffer
73+
err = fcTempl.Execute(&buf, filePaths{
74+
InstallDir: installDir,
75+
DataDir: dataDir,
76+
ConfigPath: configPath,
77+
UpgradeUnitDir: versioncontrol.UnitConfigDir,
78+
})
79+
if err != nil {
80+
return "", trace.Wrap(err, "failed to expand file contexts template")
8381
}
8482

85-
return "", nil
83+
return buf.String(), nil
8684
}
8785

8886
// CheckConfiguration returns an error if SELinux is not configured to

lib/selinux/selinux_others.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,31 @@
2121
package selinux
2222

2323
import (
24-
"errors"
2524
"log/slog"
25+
26+
"github.com/gravitational/trace"
2627
)
2728

28-
var errPlatformNotSupported = errors.New("platform not supported")
29+
const errPlatformNotSupportedMsg = "platform not supported"
30+
31+
// ModuleSource returns the source of the SELinux SSH module.
32+
func ModuleSource() string {
33+
return ""
34+
}
35+
36+
// FileContexts returns file contexts for the SELinux SSH module.
37+
func FileContexts(installDir, dataDir, configPath string) (string, error) {
38+
return "", trace.Errorf(errPlatformNotSupportedMsg)
39+
}
2940

3041
// CheckConfiguration returns an error if SELinux is not configured to
3142
// enforce the SSH service correctly.
3243
func CheckConfiguration(ensureEnforced bool, logger *slog.Logger) error {
33-
return errPlatformNotSupported
44+
return trace.Errorf(errPlatformNotSupportedMsg)
3445
}
3546

3647
// UserContext returns the SELinux context that should be used when
3748
// creating processes as a certain user.
3849
func UserContext(login string) (string, error) {
39-
return "", errPlatformNotSupported
50+
return "", trace.Errorf(errPlatformNotSupportedMsg)
4051
}

tool/teleport/common/teleport.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"os/user"
3030
"path"
3131
"path/filepath"
32+
"runtime"
3233
"slices"
3334
"strconv"
3435
"strings"
@@ -201,8 +202,10 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con
201202
"AWS region AWS hosted database instance is running in.").Hidden().
202203
StringVar(&ccf.DatabaseAWSRegion)
203204
start.Flag("no-debug-service", "Disables debug service.").BoolVar(&ccf.DisableDebugService)
204-
start.Flag("enable-selinux", "Enables SELinux support for Teleport SSH and exits if SELinux is not configured correctly.").Hidden().BoolVar(&ccf.EnableSELinux)
205-
start.Flag("ensure-selinux-enforcing", "Exits with an error if SELinux is not configured to enforce Teleport SSH.").Hidden().BoolVar(&ccf.EnsureSELinuxEnforcing)
205+
if runtime.GOOS == "linux" {
206+
start.Flag("enable-selinux", "Enables SELinux support for Teleport SSH and exits if SELinux is not configured correctly.").Hidden().BoolVar(&ccf.EnableSELinux)
207+
start.Flag("ensure-selinux-enforcing", "Exits with an error if SELinux is not configured to enforce Teleport SSH.").Hidden().BoolVar(&ccf.EnsureSELinuxEnforcing)
208+
}
206209

207210
// define start's usage info (we use kingpin's "alias" field for this)
208211
start.Alias(usageNotes + usageExamples)
@@ -588,11 +591,14 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con
588591
collectProfilesCmd.Arg("PROFILES", fmt.Sprintf("Comma-separated profile names to be exported. Supported profiles: %s. Default: %s", strings.Join(slices.Collect(maps.Keys(debugclient.SupportedProfiles)), ","), strings.Join(defaultCollectProfiles, ","))).StringVar(&ccf.Profiles)
589592
collectProfilesCmd.Flag("seconds", "For CPU and trace profiles, profile for the given duration (if set to 0, it returns a profile snapshot). For other profiles, return a delta profile. Default: 0").Short('s').Default("0").IntVar(&ccf.ProfileSeconds)
590593

591-
selinuxCmd := app.Command("selinux-ssh", "Commands related to SSH SELinux module.").Hidden()
592-
selinuxCmd.Flag("config", fmt.Sprintf("Path to a configuration file [%v].", defaults.ConfigFilePath)).Short('c').ExistingFileVar(&ccf.ConfigFile)
593-
moduleSourceCmd := selinuxCmd.Command("module-source", "Export SSH SELinux module source to stdout.").Hidden()
594-
fileContextsCmd := selinuxCmd.Command("file-contexts", "Export SSH SELinux file contexts to stdout.").Hidden()
595-
selinuxDirsCmd := selinuxCmd.Command("dirs", "Export directories that may need to be labeled for SSH SELinux module to work correctly.").Hidden()
594+
var moduleSourceCmd, fileContextsCmd, selinuxDirsCmd *kingpin.CmdClause
595+
if runtime.GOOS == "linux" {
596+
selinuxCmd := app.Command("selinux-ssh", "Commands related to SSH SELinux module.").Hidden()
597+
selinuxCmd.Flag("config", fmt.Sprintf("Path to a configuration file [%v].", defaults.ConfigFilePath)).Short('c').ExistingFileVar(&ccf.ConfigFile)
598+
moduleSourceCmd = selinuxCmd.Command("module-source", "Export SSH SELinux module source to stdout.").Hidden()
599+
fileContextsCmd = selinuxCmd.Command("file-contexts", "Export SSH SELinux file contexts to stdout.").Hidden()
600+
selinuxDirsCmd = selinuxCmd.Command("dirs", "Export directories that may need to be labeled for SSH SELinux module to work correctly.").Hidden()
601+
}
596602

597603
backendCmd := app.Command("backend", "Commands for managing backend data.")
598604
backendCmd.Hidden()
@@ -1148,8 +1154,8 @@ func onSELinuxFileContexts(configPath string) error {
11481154
if err != nil {
11491155
return trace.Wrap(err)
11501156
}
1157+
fmt.Println(fileContexts)
11511158

1152-
fmt.Printf("%s", fileContexts)
11531159
return nil
11541160
}
11551161

0 commit comments

Comments
 (0)