diff --git a/common/admin/nfs/export.go b/common/admin/nfs/export.go index 02e0d84..fd379ed 100644 --- a/common/admin/nfs/export.go +++ b/common/admin/nfs/export.go @@ -26,6 +26,18 @@ const ( Unspecifiedquash SquashMode = "" ) +// SecType indicates the kind of security/authentication to be used by an export. +type SecType string + +// src: https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/config_samples/export.txt +const ( + SysSec SecType = "sys" + NoneSec SecType = "none" + Krb5Sec SecType = "krb5" + Krb5iSec SecType = "krb5i" + Krb5pSec SecType = "krb5p" +) + // CephFSExportSpec is used to specify the parameters used to create a new // CephFS based export. type CephFSExportSpec struct { @@ -36,6 +48,7 @@ type CephFSExportSpec struct { ReadOnly bool `json:"readonly"` ClientAddr []string `json:"client_addr,omitempty"` Squash SquashMode `json:"squash,omitempty"` + SecType []SecType `json:"sectype,omitempty"` } // ExportResult is returned along with newly created exports. @@ -81,6 +94,7 @@ type ExportInfo struct { Transports []string `json:"transports"` FSAL FSALInfo `json:"fsal"` Clients []ClientInfo `json:"clients"` + SecType []SecType `json:"sectype"` } func parseExportResult(res commands.Response) (*ExportResult, error) { diff --git a/common/admin/nfs/export_sectype_test.go b/common/admin/nfs/export_sectype_test.go new file mode 100644 index 0000000..cc1d161 --- /dev/null +++ b/common/admin/nfs/export_sectype_test.go @@ -0,0 +1,87 @@ +//go:build ceph_preview && ceph_main + +package nfs + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ceph/go-ceph/internal/commands" +) + +func (suite *NFSAdminSuite) TestExportSecType() { + require := suite.Require() + ra := radosConnector.Get(suite.T()) + nfsa := NewFromConn(ra) + + _, err := nfsa.CreateCephFSExport(CephFSExportSpec{ + FileSystemName: suite.fileSystemName, + ClusterID: suite.clusterID, + PseudoPath: "/12", + Path: "/sept", + SecType: []SecType{Krb5pSec, Krb5iSec, SysSec}, + }) + require.NoError(err) + + defer func() { + err = nfsa.RemoveExport(suite.clusterID, "/12") + require.NoError(err) + }() + + e1, err := nfsa.ExportInfo(suite.clusterID, "/12") + require.NoError(err) + require.Equal(e1.PseudoPath, "/12") + require.Equal(e1.SecType, []SecType{Krb5pSec, Krb5iSec, SysSec}) +} + +// # ceph nfs export info --cluster-id foobar --pseudo-path /cheese +const exportInfo2 = ` +{ + "export_id": 2, + "path": "/", + "cluster_id": "goceph", + "pseudo": "/bar", + "access_type": "RW", + "squash": "none", + "security_label": true, + "protocols": [ + 4 + ], + "transports": [ + "TCP" + ], + "fsal": { + "name": "CEPH", + "user_id": "nfs.goceph.2", + "fs_name": "cephfs" + }, + "clients": [], + "sectype": [ + "krb5p", + "sys" + ] +} +` + +func TestParseExportInfoWithSecType(t *testing.T) { + t.Run("exportInfo1", func(t *testing.T) { + r := commands.NewResponse([]byte(exportInfo1), "", nil) + e, err := parseExportInfo(r) + assert.NoError(t, err) + assert.Equal(t, e.Path, "/") + assert.Equal(t, e.PseudoPath, "/cheese") + assert.Len(t, e.SecType, 0) + }) + t.Run("exportInfo2", func(t *testing.T) { + r := commands.NewResponse([]byte(exportInfo2), "", nil) + e, err := parseExportInfo(r) + assert.NoError(t, err) + assert.Equal(t, e.Path, "/") + assert.Equal(t, e.PseudoPath, "/bar") + if assert.Len(t, e.SecType, 2) { + assert.Equal(t, e.SecType[0], Krb5pSec) + assert.Equal(t, e.SecType[1], SysSec) + } + }) +}