Skip to content

Commit

Permalink
Move github.com/elastic/beats/v7/libbeat/keystore and `github.com/e…
Browse files Browse the repository at this point in the history
…lastic/beats/v7/libbeat/common/file.FileInfo` (elastic#20)
  • Loading branch information
kvch authored Mar 3, 2022
1 parent 9d07e6f commit 5b4e674
Show file tree
Hide file tree
Showing 14 changed files with 1,407 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Provided packages:
* `github.com/elastic/elastic-agent-libs/cloudid` is used for parsing `cloud.id` and `cloud.auth` when connecting to the Elastic stack.
* `github.com/elastic/elastic-agent-libs/config` the previous `config.go` file from `github.com/elastic/beats/v7/libbeat/common`. A minimal wrapper around `github.com/elastic/go-ucfg`. It contains helpers for merging and accessing configuration objects and flags.
* `github.com/elastic/elastic-agent-libs/file` is responsible for rotating and writing input and output files.
* `github.com/elastic/elastic-agent-libs/keystore` interface for keystores and file keystore implementation.
* `github.com/elastic/elastic-agent-libs/logp` is the well known logger from libbeat.
* `github.com/elastic/elastic-agent-libs/logp/cfgwarn` provides logging utilities for warning users about deprecated settings.
* `github.com/elastic/elastic-agent-libs/mapstr` is the old `github.com/elastic/beats/v7/libbeat/common.MapStr`. It is an extra layer on top of `map[string]interface{}`.
Expand Down
72 changes: 72 additions & 0 deletions file/fileinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package file

import (
"errors"
"os"
)

// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
os.FileInfo
UID() (int, error) // UID of the file owner. Returns an error on non-POSIX file systems.
GID() (int, error) // GID of the file owner. Returns an error on non-POSIX file systems.
}

// Stat returns a FileInfo describing the named file.
// If there is an error, it will be of type *PathError.
func Stat(name string) (FileInfo, error) {
return stat(name, os.Stat)
}

// Lstat returns a FileInfo describing the named file.
// If the file is a symbolic link, the returned FileInfo
// describes the symbolic link. Lstat makes no attempt to follow the link.
// If there is an error, it will be of type *PathError.
func Lstat(name string) (FileInfo, error) {
return stat(name, os.Lstat)
}

// Wrap wraps the given os.FileInfo and returns a FileInfo in order to expose
// the UID and GID in a uniform manner across operating systems.
func Wrap(info os.FileInfo) (FileInfo, error) {
return wrap(info)
}

type fileInfo struct {
os.FileInfo
uid *int
gid *int
}

func (f fileInfo) UID() (int, error) {
if f.uid == nil {
return -1, errors.New("uid not implemented")
}

return *f.uid, nil
}

func (f fileInfo) GID() (int, error) {
if f.gid == nil {
return -1, errors.New("gid not implemented")
}

return *f.gid, nil
}
96 changes: 96 additions & 0 deletions file/fileinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//go:build !windows && !openbsd
// +build !windows,!openbsd

// Test for openbsd are excluded here as info.GID() returns 0 instead of the actual value
// As the code does not seem to be used in any of the beats, this should be ok
// Still it would be interesting to know why it returns 0.

package file_test

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"

"github.com/elastic/elastic-agent-libs/file"
)

func TestStat(t *testing.T) {
f, err := ioutil.TempFile("", "teststat")
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name())

link := filepath.Join(os.TempDir(), "teststat-link")
if err := os.Symlink(f.Name(), link); err != nil {
t.Fatal(err)
}
defer os.Remove(link)

info, err := file.Stat(link)
if err != nil {
t.Fatal(err)
}

require.True(t, info.Mode().IsRegular())

uid, err := info.UID()
if err != nil {
t.Fatal(err)
}
require.EqualValues(t, os.Geteuid(), uid)

gid, err := info.GID()
if err != nil {
t.Fatal(err)
}
require.EqualValues(t, os.Getegid(), gid)
}

func TestLstat(t *testing.T) {
link := filepath.Join(os.TempDir(), "link")
if err := os.Symlink("dummy", link); err != nil {
t.Fatal(err)
}
defer os.Remove(link)

info, err := file.Lstat(link)
if err != nil {
t.Fatal(err)
}

require.True(t, info.Mode()&os.ModeSymlink > 0)

uid, err := info.UID()
if err != nil {
t.Fatal(err)
}
require.EqualValues(t, os.Geteuid(), uid)

gid, err := info.GID()
if err != nil {
t.Fatal(err)
}
require.EqualValues(t, os.Getegid(), gid)
}
47 changes: 47 additions & 0 deletions file/fileinfo_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

//go:build !windows
// +build !windows

package file

import (
"errors"
"os"
"syscall"
)

func stat(name string, statFunc func(name string) (os.FileInfo, error)) (FileInfo, error) {
info, err := statFunc(name)
if err != nil {
return nil, err
}

return wrap(info)
}

func wrap(info os.FileInfo) (FileInfo, error) {
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return nil, errors.New("failed to get uid/gid")
}

uid := int(stat.Uid)
gid := int(stat.Gid)
return fileInfo{FileInfo: info, uid: &uid, gid: &gid}, nil
}
35 changes: 35 additions & 0 deletions file/fileinfo_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package file

import (
"os"
)

func stat(name string, statFunc func(name string) (os.FileInfo, error)) (FileInfo, error) {
info, err := statFunc(name)
if err != nil {
return nil, err
}

return wrap(info)
}

func wrap(info os.FileInfo) (FileInfo, error) {
return fileInfo{FileInfo: info}, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/stretchr/testify v1.7.0
go.elastic.co/ecszap v1.0.0
go.uber.org/zap v1.21.0
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
)

Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down
29 changes: 29 additions & 0 deletions keystore/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package keystore

// Config Define keystore configurable options
type Config struct {
Path string `config:"path"`
}

func defaultConfig() Config {
return Config{
Path: "",
}
}
Loading

0 comments on commit 5b4e674

Please sign in to comment.