feat: report SELinux labels
This will be useful for debugging SELinux implementation. Make API report other xattrs for further development like IMA/EVM Signed-off-by: Dmitry Sharshakov <dmitry.sharshakov@siderolabs.com>
This commit is contained in:
parent
8fe39eacba
commit
4834a61a8e
@ -452,6 +452,8 @@ message ListRequest {
|
||||
// Types indicates what file type should be returned. If not indicated,
|
||||
// all files will be returned.
|
||||
repeated Type types = 4;
|
||||
// Report xattrs
|
||||
bool report_xattrs = 5;
|
||||
}
|
||||
|
||||
// DiskUsageRequest describes a request to list disk usage of directories and regular files
|
||||
@ -492,6 +494,13 @@ message FileInfo {
|
||||
uint32 uid = 10;
|
||||
// Owner gid
|
||||
uint32 gid = 11;
|
||||
// Extended attributes (if present and requested)
|
||||
repeated Xattr xattrs = 12;
|
||||
}
|
||||
|
||||
message Xattr {
|
||||
string name = 1;
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
// DiskUsageInfo describes a file or directory's information for du command
|
||||
|
@ -85,6 +85,7 @@ var lsCmd = &cobra.Command{
|
||||
Recurse: recursionDepth > 1 || recurse,
|
||||
RecursionDepth: recursionDepth,
|
||||
Types: reqTypes,
|
||||
ReportXattrs: long,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching logs: %s", err)
|
||||
@ -117,7 +118,7 @@ var lsCmd = &cobra.Command{
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
defer w.Flush() //nolint:errcheck
|
||||
|
||||
fmt.Fprintln(w, "NODE\tMODE\tUID\tGID\tSIZE(B)\tLASTMOD\tNAME")
|
||||
fmt.Fprintln(w, "NODE\tMODE\tUID\tGID\tSIZE(B)\tLASTMOD\tLABEL\tNAME")
|
||||
|
||||
return helpers.ReadGRPCStream(stream, func(info *machineapi.FileInfo, node string, multipleNodes bool) error {
|
||||
if info.Error != "" {
|
||||
@ -148,13 +149,25 @@ var lsCmd = &cobra.Command{
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%d\t%d\t%s\t%s\t%s\n",
|
||||
label := ""
|
||||
if info.Xattrs != nil {
|
||||
for _, l := range info.Xattrs {
|
||||
if l.Name == "security.selinux" {
|
||||
label = string(l.Data)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%d\t%d\t%s\t%s\t%s\t%s\n",
|
||||
node,
|
||||
os.FileMode(info.Mode).String(),
|
||||
info.Uid,
|
||||
info.Gid,
|
||||
size,
|
||||
timestampFormatted,
|
||||
label,
|
||||
display,
|
||||
)
|
||||
|
||||
|
1
go.mod
1
go.mod
@ -117,6 +117,7 @@ require (
|
||||
github.com/packethost/packngo v0.31.0
|
||||
github.com/pelletier/go-toml/v2 v2.2.2
|
||||
github.com/pin/tftp/v3 v3.1.0
|
||||
github.com/pkg/xattr v0.4.9
|
||||
github.com/pmorjan/kmod v1.1.1
|
||||
github.com/prometheus/procfs v0.15.1
|
||||
github.com/rivo/tview v0.0.0-20240807095714-a8dd8799d63b
|
||||
|
3
go.sum
3
go.sum
@ -526,6 +526,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE=
|
||||
github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
|
||||
github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=
|
||||
github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -871,6 +873,7 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"github.com/gopacket/gopacket/afpacket"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/nberlee/go-netstat/netstat"
|
||||
"github.com/pkg/xattr"
|
||||
"github.com/prometheus/procfs"
|
||||
"github.com/rs/xid"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
@ -831,11 +832,24 @@ func (s *Server) List(req *machine.ListRequest, obj machine.MachineService_ListS
|
||||
}
|
||||
|
||||
for fi := range files {
|
||||
xattrs := []*machine.Xattr{}
|
||||
|
||||
if req.ReportXattrs {
|
||||
if list, err := xattr.List(fi.FullPath); err == nil {
|
||||
for _, attr := range list {
|
||||
if data, err := xattr.Get(fi.FullPath, attr); err == nil {
|
||||
xattrs = append(xattrs, &machine.Xattr{Name: attr, Data: data})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if fi.Error != nil {
|
||||
err = obj.Send(&machine.FileInfo{
|
||||
Name: fi.FullPath,
|
||||
RelativeName: fi.RelPath,
|
||||
Error: fi.Error.Error(),
|
||||
Xattrs: xattrs,
|
||||
})
|
||||
} else {
|
||||
err = obj.Send(&machine.FileInfo{
|
||||
@ -848,6 +862,7 @@ func (s *Server) List(req *machine.ListRequest, obj machine.MachineService_ListS
|
||||
Link: fi.Link,
|
||||
Uid: fi.FileInfo.Sys().(*syscall.Stat_t).Uid,
|
||||
Gid: fi.FileInfo.Sys().(*syscall.Stat_t).Gid,
|
||||
Xattrs: xattrs,
|
||||
})
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2623,6 +2623,16 @@ func (m *ListRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.ReportXattrs {
|
||||
i--
|
||||
if m.ReportXattrs {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x28
|
||||
}
|
||||
if len(m.Types) > 0 {
|
||||
var pksize2 int
|
||||
for _, num := range m.Types {
|
||||
@ -2761,6 +2771,18 @@ func (m *FileInfo) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Xattrs) > 0 {
|
||||
for iNdEx := len(m.Xattrs) - 1; iNdEx >= 0; iNdEx-- {
|
||||
size, err := m.Xattrs[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||
i--
|
||||
dAtA[i] = 0x62
|
||||
}
|
||||
}
|
||||
if m.Gid != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Gid))
|
||||
i--
|
||||
@ -2849,6 +2871,53 @@ func (m *FileInfo) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Xattr) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Xattr) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Xattr) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Data) > 0 {
|
||||
i -= len(m.Data)
|
||||
copy(dAtA[i:], m.Data)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Data)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *DiskUsageInfo) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
@ -11137,6 +11206,9 @@ func (m *ListRequest) SizeVT() (n int) {
|
||||
}
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(l)) + l
|
||||
}
|
||||
if m.ReportXattrs {
|
||||
n += 2
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
@ -11216,6 +11288,30 @@ func (m *FileInfo) SizeVT() (n int) {
|
||||
if m.Gid != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.Gid))
|
||||
}
|
||||
if len(m.Xattrs) > 0 {
|
||||
for _, e := range m.Xattrs {
|
||||
l = e.SizeVT()
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Xattr) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Data)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
@ -19735,6 +19831,26 @@ func (m *ListRequest) UnmarshalVT(dAtA []byte) error {
|
||||
} else {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Types", wireType)
|
||||
}
|
||||
case 5:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ReportXattrs", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.ReportXattrs = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
@ -20214,6 +20330,157 @@ func (m *FileInfo) UnmarshalVT(dAtA []byte) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 12:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Xattrs", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Xattrs = append(m.Xattrs, &Xattr{})
|
||||
if err := m.Xattrs[len(m.Xattrs)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Xattr) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Xattr: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Xattr: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Data == nil {
|
||||
m.Data = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
|
@ -445,6 +445,7 @@ description: Talos gRPC API reference.
|
||||
- [Version](#machine.Version)
|
||||
- [VersionInfo](#machine.VersionInfo)
|
||||
- [VersionResponse](#machine.VersionResponse)
|
||||
- [Xattr](#machine.Xattr)
|
||||
|
||||
- [ApplyConfigurationRequest.Mode](#machine.ApplyConfigurationRequest.Mode)
|
||||
- [ConnectRecord.State](#machine.ConnectRecord.State)
|
||||
@ -5973,6 +5974,7 @@ FileInfo describes a file or directory's information
|
||||
| relative_name | [string](#string) | | RelativeName is the name of the file or directory relative to the RootPath |
|
||||
| uid | [uint32](#uint32) | | Owner uid |
|
||||
| gid | [uint32](#uint32) | | Owner gid |
|
||||
| xattrs | [Xattr](#machine.Xattr) | repeated | Extended attributes (if present and requested) |
|
||||
|
||||
|
||||
|
||||
@ -6219,6 +6221,7 @@ ListRequest describes a request to list the contents of a directory.
|
||||
| recurse | [bool](#bool) | | Recurse indicates that subdirectories should be recursed. |
|
||||
| recursion_depth | [int32](#int32) | | RecursionDepth indicates how many levels of subdirectories should be recursed. The default (0) indicates that no limit should be enforced. |
|
||||
| types | [ListRequest.Type](#machine.ListRequest.Type) | repeated | Types indicates what file type should be returned. If not indicated, all files will be returned. |
|
||||
| report_xattrs | [bool](#bool) | | Report xattrs |
|
||||
|
||||
|
||||
|
||||
@ -7734,6 +7737,22 @@ rpc upgrade
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.Xattr"></a>
|
||||
|
||||
### Xattr
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| name | [string](#string) | | |
|
||||
| data | [bytes](#bytes) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user