github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/sentinel_apply.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/nomad/api"
    10  	"github.com/posener/complete"
    11  )
    12  
    13  type SentinelApplyCommand struct {
    14  	Meta
    15  }
    16  
    17  func (c *SentinelApplyCommand) Help() string {
    18  	helpText := `
    19  Usage: nomad sentinel apply [options] <name> <file>
    20  
    21    Apply is used to write a new Sentinel policy or update an existing one.
    22    The name of the policy and file must be specified. The file will be read
    23    from stdin by specifying "-".
    24  
    25    Sentinel commands are only available when ACLs are enabled. This command
    26    requires a management token.
    27  
    28  General Options:
    29  
    30    ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + `
    31  
    32  Apply Options:
    33  
    34    -description
    35      Sets a human readable description for the policy.
    36  
    37    -scope (default: submit-job)
    38      Sets the scope of the policy and when it should be enforced.
    39  
    40    -level (default: advisory)
    41      Sets the enforcement level of the policy. Must be one of advisory,
    42      soft-mandatory, hard-mandatory.
    43  
    44  `
    45  	return strings.TrimSpace(helpText)
    46  }
    47  
    48  func (c *SentinelApplyCommand) AutocompleteFlags() complete.Flags {
    49  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    50  		complete.Flags{
    51  			"-description": complete.PredictAnything,
    52  			"-scope":       complete.PredictAnything,
    53  			"-level":       complete.PredictAnything,
    54  		})
    55  }
    56  
    57  func (c *SentinelApplyCommand) AutocompleteArgs() complete.Predictor {
    58  	return complete.PredictNothing
    59  }
    60  
    61  func (c *SentinelApplyCommand) Synopsis() string {
    62  	return "Create a new or update existing Sentinel policies"
    63  }
    64  
    65  func (c *SentinelApplyCommand) Name() string { return "sentinel apply" }
    66  
    67  func (c *SentinelApplyCommand) Run(args []string) int {
    68  	var description, scope, enfLevel string
    69  	var err error
    70  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    71  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    72  	flags.StringVar(&description, "description", "", "")
    73  	flags.StringVar(&scope, "scope", "submit-job", "")
    74  	flags.StringVar(&enfLevel, "level", "advisory", "")
    75  	if err := flags.Parse(args); err != nil {
    76  		return 1
    77  	}
    78  
    79  	// Check that we got exactly two arguments
    80  	args = flags.Args()
    81  	if l := len(args); l != 2 {
    82  		c.Ui.Error("This command takes exactly two arguments: <name> <file>")
    83  		c.Ui.Error(commandErrorText(c))
    84  		return 1
    85  	}
    86  
    87  	// Get the name and file
    88  	policyName := args[0]
    89  
    90  	// Read the file contents
    91  	file := args[1]
    92  	var rawPolicy []byte
    93  	if file == "-" {
    94  		rawPolicy, err = ioutil.ReadAll(os.Stdin)
    95  		if err != nil {
    96  			c.Ui.Error(fmt.Sprintf("Failed to read stdin: %v", err))
    97  			return 1
    98  		}
    99  	} else {
   100  		rawPolicy, err = ioutil.ReadFile(file)
   101  		if err != nil {
   102  			c.Ui.Error(fmt.Sprintf("Failed to read file: %v", err))
   103  			return 1
   104  		}
   105  	}
   106  
   107  	// Construct the policy
   108  	sp := &api.SentinelPolicy{
   109  		Name:             policyName,
   110  		Description:      description,
   111  		Scope:            scope,
   112  		EnforcementLevel: enfLevel,
   113  		Policy:           string(rawPolicy),
   114  	}
   115  
   116  	// Get the HTTP client
   117  	client, err := c.Meta.Client()
   118  	if err != nil {
   119  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   120  		return 1
   121  	}
   122  
   123  	// Get the list of policies
   124  	_, err = client.SentinelPolicies().Upsert(sp, nil)
   125  	if err != nil {
   126  		c.Ui.Error(fmt.Sprintf("Error writing Sentinel policy: %s", err))
   127  		return 1
   128  	}
   129  
   130  	c.Ui.Output(fmt.Sprintf("Successfully wrote %q Sentinel policy!",
   131  		policyName))
   132  	return 0
   133  }