Skip to content

Commit

Permalink
support file attack (#123)
Browse files Browse the repository at this point in the history
* add dile

Signed-off-by: xiang <xiang13225080@163.com>

* add command

Signed-off-by: xiang <xiang13225080@163.com>

* upadte comment

Signed-off-by: xiang <xiang13225080@163.com>

* fix recover

Signed-off-by: xiang <xiang13225080@163.com>

* add file tools

Signed-off-by: xiang <xiang13225080@163.com>

* update file attack 1

Signed-off-by: xiang <xiang13225080@163.com>

* update file attack 2

Signed-off-by: xiang <xiang13225080@163.com>

* add integration test

Signed-off-by: xiang <xiang13225080@163.com>

* add missed file

Signed-off-by: xiang <xiang13225080@163.com>

* minor update on env

Signed-off-by: xiang <xiang13225080@163.com>

* add missed file

Signed-off-by: xiang <xiang13225080@163.com>

* update year in license

Signed-off-by: xiang <xiang13225080@163.com>

* add json label

Signed-off-by: xiang <xiang13225080@163.com>

* minor update

Signed-off-by: xiang <xiang13225080@163.com>

* replace data in file by sed

Signed-off-by: xiang <xiang13225080@163.com>

* add recover for replace

Signed-off-by: xiang <xiang13225080@163.com>

* add missed file

Signed-off-by: xiang <xiang13225080@163.com>

* format

Signed-off-by: xiang <xiang13225080@163.com>

Co-authored-by: Ti Chi Robot <ti-community-prow-bot@tidb.io>
  • Loading branch information
WangXiangUSTC and ti-chi-bot committed Apr 20, 2022
1 parent 2d07a77 commit 84daf15
Show file tree
Hide file tree
Showing 20 changed files with 2,131 additions and 5 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ chaosd:

chaos-tools:
$(CGOENV) go build -o bin/tools/PortOccupyTool tools/PortOccupyTool.go
$(CGOENV) go build -o bin/tools/FileTool tools/file/*.go
ifeq (,$(wildcard bin/tools/stress-ng))
curl -fsSL -o ./bin/tools/stress-ng https://mirrors.chaos-mesh.org/latest/stress-ng
chmod +x ./bin/tools/stress-ng
Expand Down
1 change: 1 addition & 0 deletions cmd/attack/attack.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func NewAttackCommand() *cobra.Command {
NewHostAttackCommand(&uid),
NewJVMAttackCommand(&uid),
NewClockAttackCommand(&uid),
NewFileAttackCommand(&uid),
)

return cmd
Expand Down
172 changes: 172 additions & 0 deletions cmd/attack/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright 2022 Chaos Mesh Authors.
//
// Licensed 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package attack

import (
"fmt"

"github.com/spf13/cobra"
"go.uber.org/fx"

"github.com/chaos-mesh/chaosd/cmd/server"
"github.com/chaos-mesh/chaosd/pkg/core"
"github.com/chaos-mesh/chaosd/pkg/server/chaosd"
"github.com/chaos-mesh/chaosd/pkg/utils"
)

func NewFileAttackCommand(uid *string) *cobra.Command {
options := core.NewFileCommand()
dep := fx.Options(
server.Module,
fx.Provide(func() *core.FileCommand {
options.UID = *uid
return options
}),
)

cmd := &cobra.Command{
Use: "file <subcommand>",
Short: "File attack related commands",
}

cmd.AddCommand(
NewFileCreateCommand(dep, options),
NewFileModifyPrivilegeCommand(dep, options),
NewFileDeleteCommand(dep, options),
NewFileRenameCommand(dep, options),
NewFileAppendCommand(dep, options),
NewFileReplaceCommand(dep, options),
)

return cmd
}

func NewFileCreateCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "create file",

Run: func(*cobra.Command, []string) {
options.Action = core.FileCreateAction
options.CompleteDefaults()
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.FileName, "file-name", "f", "", "the name of file to be created")
cmd.Flags().StringVarP(&options.DirName, "dir-name", "d", "", "the name of directory to be created")

return cmd
}

func NewFileModifyPrivilegeCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "modify",
Short: "modify file privilege",
Run: func(cmd *cobra.Command, args []string) {
options.Action = core.FileModifyPrivilegeAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.FileName, "file-name", "f", "", "file to be change privilege")
cmd.Flags().Uint32VarP(&options.Privilege, "privilege", "p", 0, "privilege to be update")

return cmd
}

func NewFileDeleteCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "delete",
Short: "delete file",

Run: func(cmd *cobra.Command, args []string) {
options.Action = core.FileDeleteAction
options.CompleteDefaults()
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.FileName, "file-name", "f", "", "the file to be deleted")
cmd.Flags().StringVarP(&options.DirName, "dir-name", "d", "", "the directory to be deleted")

return cmd
}

func NewFileRenameCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "rename",
Short: "rename file",

Run: func(cmd *cobra.Command, args []string) {
options.Action = core.FileRenameAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.SourceFile, "source-file", "s", "", "the source file/dir of rename")
cmd.Flags().StringVarP(&options.DestFile, "dest-file", "d", "", "the destination file/dir of rename")

return cmd
}

func NewFileAppendCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "append",
Short: "append file",

Run: func(cmd *cobra.Command, args []string) {
options.Action = core.FileAppendAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.FileName, "file-name", "f", "", "append data to the file")
cmd.Flags().StringVarP(&options.Data, "data", "d", "", "append data")
cmd.Flags().IntVarP(&options.Count, "count", "c", 1, "append count with default value is 1")

return cmd
}

func NewFileReplaceCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "replace",
Short: "replace data in file",

Run: func(cmd *cobra.Command, args []string) {
options.Action = core.FileReplaceAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
},
}

cmd.Flags().StringVarP(&options.FileName, "file-name", "f", "", "replace data in the file")
cmd.Flags().StringVarP(&options.OriginStr, "origin-string", "o", "", "the origin string to be replaced")
cmd.Flags().StringVarP(&options.DestStr, "dest-string", "d", "", "the destination string to replace the origin string")
cmd.Flags().IntVarP(&options.Line, "line", "l", 0, "the line number to replace, default is 0, means replace all lines")

return cmd
}

func commonFileAttackFunc(options *core.FileCommand, chaos *chaosd.Server) {
if err := options.Validate(); err != nil {
utils.ExitWithError(utils.ExitBadArgs, err)
}

uid, err := chaos.ExecuteAttack(chaosd.FileAttack, options, core.CommandMode)
if err != nil {
utils.ExitWithError(utils.ExitError, err)
}

utils.NormalExit(fmt.Sprintf("Attack file successfully, uid: %s", uid))
}
3 changes: 3 additions & 0 deletions pkg/core/experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
ClockAttack = "clock"
HostAttack = "host"
JVMAttack = "jvm"
FileAttack = "file"
)

const (
Expand Down Expand Up @@ -107,6 +108,8 @@ func GetAttackByKind(kind string) *AttackConfig {
attackConfig = &JVMCommand{}
case ClockAttack:
attackConfig = &ClockOption{}
case FileAttack:
attackConfig = &FileCommand{}
default:
return nil
}
Expand Down
167 changes: 167 additions & 0 deletions pkg/core/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2022 Chaos Mesh Authors.
//
// Licensed 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
"encoding/json"

"github.com/pingcap/errors"
)

type FileCommand struct {
CommonAttackConfig

// FileName is the name of the file to be created, modified, deleted, renamed, or appended.
FileName string `json:"file-name,omitempty"`
// DirName is the directory name to create or delete.
DirName string `json:"dir-name,omitempty"`
// Privilege is the file privilege to be set.
Privilege uint32 `json:"privilege,omitempty"`
// SourceFile is the name need to be renamed.
SourceFile string `json:"source-file,omitempty"`
// DestFile is the name to be renamed.
DestFile string `json:"dest-file,omitempty"`
// Data is the data for append.
Data string `json:"data,omitempty"`
// Count is the number of times to append the data.
Count int `json:"count,omitempty"`
// OriginPrivilege used to save the file's origin privilege.
OriginPrivilege int `json:"origin-privilege,omitempty"`

// OriginStr is the origin string of the file.
OriginStr string `json:"origin-string,omitempty"`
// DestStr is the destination string of the file.
DestStr string `json:"dest-string,omitempty"`
// Line is the line number of the file to be replaced.
Line int `json:"line,omitempty"`
}

var _ AttackConfig = &FileCommand{}

const (
FileCreateAction = "create"
FileModifyPrivilegeAction = "modify"
FileDeleteAction = "delete"
FileRenameAction = "rename"
FileAppendAction = "append"
FileReplaceAction = "replace"
)

func (n *FileCommand) Validate() error {
if err := n.CommonAttackConfig.Validate(); err != nil {
return err
}
switch n.Action {
case FileCreateAction:
return n.validFileCreate()
case FileModifyPrivilegeAction:
return n.validFileModify()
case FileDeleteAction:
return n.validFileDelete()
case FileRenameAction:
return n.validFileRename()
case FileAppendAction:
return n.validFileAppend()
case FileReplaceAction:
return n.validFileReplace()
default:
return errors.Errorf("file action %s not supported", n.Action)
}
}

func (n *FileCommand) validFileCreate() error {
if len(n.FileName) == 0 && len(n.DirName) == 0 {
return errors.New("one of file-name and dir-name is required")
}

return nil
}

func (n *FileCommand) validFileModify() error {
if len(n.FileName) == 0 {
return errors.New("file name is required")
}

if n.Privilege == 0 {
return errors.New("file privilege is required")
}

return nil
}

func (n *FileCommand) validFileDelete() error {
if len(n.FileName) == 0 && len(n.DirName) == 0 {
return errors.New("one of file-name and dir-name is required")
}

return nil
}

func (n *FileCommand) validFileRename() error {
if len(n.SourceFile) == 0 || len(n.DestFile) == 0 {
return errors.New("both source file and destination file are required")
}

return nil
}

func (n *FileCommand) validFileAppend() error {
if len(n.FileName) == 0 {
return errors.New("file-name is required")
}

if len(n.Data) == 0 {
return errors.New("append data is required")
}

return nil
}

func (n *FileCommand) validFileReplace() error {
if len(n.FileName) == 0 {
return errors.New("file-name is required")
}

if len(n.OriginStr) == 0 || len(n.DestStr) == 0 {
return errors.New("both origin and destination string are required")
}

return nil
}

func (n *FileCommand) CompleteDefaults() {
switch n.Action {
case FileAppendAction:
n.setDefaultForFileAppend()
}
}

func (n *FileCommand) setDefaultForFileAppend() {
if n.Count == 0 {
n.Count = 1
}
}

func (n FileCommand) RecoverData() string {
data, _ := json.Marshal(n)
return string(data)
}

func NewFileCommand() *FileCommand {
return &FileCommand{
CommonAttackConfig: CommonAttackConfig{
Kind: FileAttack,
},
}
}
Loading

0 comments on commit 84daf15

Please sign in to comment.