github.com/bigcommerce/nomad@v0.9.3-bc/command/agent/acl_endpoint.go (about)

     1  package agent
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/nomad/structs"
     8  )
     9  
    10  func (s *HTTPServer) ACLPoliciesRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    11  	if req.Method != "GET" {
    12  		return nil, CodedError(405, ErrInvalidMethod)
    13  	}
    14  
    15  	args := structs.ACLPolicyListRequest{}
    16  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
    17  		return nil, nil
    18  	}
    19  
    20  	var out structs.ACLPolicyListResponse
    21  	if err := s.agent.RPC("ACL.ListPolicies", &args, &out); err != nil {
    22  		return nil, err
    23  	}
    24  
    25  	setMeta(resp, &out.QueryMeta)
    26  	if out.Policies == nil {
    27  		out.Policies = make([]*structs.ACLPolicyListStub, 0)
    28  	}
    29  	return out.Policies, nil
    30  }
    31  
    32  func (s *HTTPServer) ACLPolicySpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    33  	name := strings.TrimPrefix(req.URL.Path, "/v1/acl/policy/")
    34  	if len(name) == 0 {
    35  		return nil, CodedError(400, "Missing Policy Name")
    36  	}
    37  	switch req.Method {
    38  	case "GET":
    39  		return s.aclPolicyQuery(resp, req, name)
    40  	case "PUT", "POST":
    41  		return s.aclPolicyUpdate(resp, req, name)
    42  	case "DELETE":
    43  		return s.aclPolicyDelete(resp, req, name)
    44  	default:
    45  		return nil, CodedError(405, ErrInvalidMethod)
    46  	}
    47  }
    48  
    49  func (s *HTTPServer) aclPolicyQuery(resp http.ResponseWriter, req *http.Request,
    50  	policyName string) (interface{}, error) {
    51  	args := structs.ACLPolicySpecificRequest{
    52  		Name: policyName,
    53  	}
    54  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
    55  		return nil, nil
    56  	}
    57  
    58  	var out structs.SingleACLPolicyResponse
    59  	if err := s.agent.RPC("ACL.GetPolicy", &args, &out); err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	setMeta(resp, &out.QueryMeta)
    64  	if out.Policy == nil {
    65  		return nil, CodedError(404, "ACL policy not found")
    66  	}
    67  	return out.Policy, nil
    68  }
    69  
    70  func (s *HTTPServer) aclPolicyUpdate(resp http.ResponseWriter, req *http.Request,
    71  	policyName string) (interface{}, error) {
    72  	// Parse the policy
    73  	var policy structs.ACLPolicy
    74  	if err := decodeBody(req, &policy); err != nil {
    75  		return nil, CodedError(500, err.Error())
    76  	}
    77  
    78  	// Ensure the policy name matches
    79  	if policy.Name != policyName {
    80  		return nil, CodedError(400, "ACL policy name does not match request path")
    81  	}
    82  
    83  	// Format the request
    84  	args := structs.ACLPolicyUpsertRequest{
    85  		Policies: []*structs.ACLPolicy{&policy},
    86  	}
    87  	s.parseWriteRequest(req, &args.WriteRequest)
    88  
    89  	var out structs.GenericResponse
    90  	if err := s.agent.RPC("ACL.UpsertPolicies", &args, &out); err != nil {
    91  		return nil, err
    92  	}
    93  	setIndex(resp, out.Index)
    94  	return nil, nil
    95  }
    96  
    97  func (s *HTTPServer) aclPolicyDelete(resp http.ResponseWriter, req *http.Request,
    98  	policyName string) (interface{}, error) {
    99  
   100  	args := structs.ACLPolicyDeleteRequest{
   101  		Names: []string{policyName},
   102  	}
   103  	s.parseWriteRequest(req, &args.WriteRequest)
   104  
   105  	var out structs.GenericResponse
   106  	if err := s.agent.RPC("ACL.DeletePolicies", &args, &out); err != nil {
   107  		return nil, err
   108  	}
   109  	setIndex(resp, out.Index)
   110  	return nil, nil
   111  }
   112  
   113  func (s *HTTPServer) ACLTokensRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
   114  	if req.Method != "GET" {
   115  		return nil, CodedError(405, ErrInvalidMethod)
   116  	}
   117  
   118  	args := structs.ACLTokenListRequest{}
   119  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   120  		return nil, nil
   121  	}
   122  
   123  	var out structs.ACLTokenListResponse
   124  	if err := s.agent.RPC("ACL.ListTokens", &args, &out); err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	setMeta(resp, &out.QueryMeta)
   129  	if out.Tokens == nil {
   130  		out.Tokens = make([]*structs.ACLTokenListStub, 0)
   131  	}
   132  	return out.Tokens, nil
   133  }
   134  
   135  func (s *HTTPServer) ACLTokenBootstrap(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
   136  	// Ensure this is a PUT or POST
   137  	if !(req.Method == "PUT" || req.Method == "POST") {
   138  		return nil, CodedError(405, ErrInvalidMethod)
   139  	}
   140  
   141  	// Format the request
   142  	args := structs.ACLTokenBootstrapRequest{}
   143  	s.parseWriteRequest(req, &args.WriteRequest)
   144  
   145  	var out structs.ACLTokenUpsertResponse
   146  	if err := s.agent.RPC("ACL.Bootstrap", &args, &out); err != nil {
   147  		return nil, err
   148  	}
   149  	setIndex(resp, out.Index)
   150  	if len(out.Tokens) > 0 {
   151  		return out.Tokens[0], nil
   152  	}
   153  	return nil, nil
   154  }
   155  
   156  func (s *HTTPServer) ACLTokenSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
   157  	path := req.URL.Path
   158  
   159  	switch path {
   160  	case "/v1/acl/token":
   161  		if !(req.Method == "PUT" || req.Method == "POST") {
   162  			return nil, CodedError(405, ErrInvalidMethod)
   163  		}
   164  		return s.aclTokenUpdate(resp, req, "")
   165  	case "/v1/acl/token/self":
   166  		return s.aclTokenSelf(resp, req)
   167  	}
   168  
   169  	accessor := strings.TrimPrefix(path, "/v1/acl/token/")
   170  	return s.aclTokenCrud(resp, req, accessor)
   171  }
   172  
   173  func (s *HTTPServer) aclTokenCrud(resp http.ResponseWriter, req *http.Request,
   174  	tokenAccessor string) (interface{}, error) {
   175  	if tokenAccessor == "" {
   176  		return nil, CodedError(400, "Missing Token Accessor")
   177  	}
   178  
   179  	switch req.Method {
   180  	case "GET":
   181  		return s.aclTokenQuery(resp, req, tokenAccessor)
   182  	case "PUT", "POST":
   183  		return s.aclTokenUpdate(resp, req, tokenAccessor)
   184  	case "DELETE":
   185  		return s.aclTokenDelete(resp, req, tokenAccessor)
   186  	default:
   187  		return nil, CodedError(405, ErrInvalidMethod)
   188  	}
   189  }
   190  
   191  func (s *HTTPServer) aclTokenQuery(resp http.ResponseWriter, req *http.Request,
   192  	tokenAccessor string) (interface{}, error) {
   193  	args := structs.ACLTokenSpecificRequest{
   194  		AccessorID: tokenAccessor,
   195  	}
   196  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   197  		return nil, nil
   198  	}
   199  
   200  	var out structs.SingleACLTokenResponse
   201  	if err := s.agent.RPC("ACL.GetToken", &args, &out); err != nil {
   202  		return nil, err
   203  	}
   204  
   205  	setMeta(resp, &out.QueryMeta)
   206  	if out.Token == nil {
   207  		return nil, CodedError(404, "ACL token not found")
   208  	}
   209  	return out.Token, nil
   210  }
   211  
   212  func (s *HTTPServer) aclTokenSelf(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
   213  	if req.Method != "GET" {
   214  		return nil, CodedError(405, ErrInvalidMethod)
   215  	}
   216  	args := structs.ResolveACLTokenRequest{}
   217  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   218  		return nil, nil
   219  	}
   220  
   221  	args.SecretID = args.AuthToken
   222  
   223  	var out structs.ResolveACLTokenResponse
   224  	if err := s.agent.RPC("ACL.ResolveToken", &args, &out); err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	setMeta(resp, &out.QueryMeta)
   229  	if out.Token == nil {
   230  		return nil, CodedError(404, "ACL token not found")
   231  	}
   232  	return out.Token, nil
   233  }
   234  
   235  func (s *HTTPServer) aclTokenUpdate(resp http.ResponseWriter, req *http.Request,
   236  	tokenAccessor string) (interface{}, error) {
   237  	// Parse the token
   238  	var token structs.ACLToken
   239  	if err := decodeBody(req, &token); err != nil {
   240  		return nil, CodedError(500, err.Error())
   241  	}
   242  
   243  	// Ensure the token accessor matches
   244  	if tokenAccessor != "" && (token.AccessorID != tokenAccessor) {
   245  		return nil, CodedError(400, "ACL token accessor does not match request path")
   246  	}
   247  
   248  	// Format the request
   249  	args := structs.ACLTokenUpsertRequest{
   250  		Tokens: []*structs.ACLToken{&token},
   251  	}
   252  	s.parseWriteRequest(req, &args.WriteRequest)
   253  
   254  	var out structs.ACLTokenUpsertResponse
   255  	if err := s.agent.RPC("ACL.UpsertTokens", &args, &out); err != nil {
   256  		return nil, err
   257  	}
   258  	setIndex(resp, out.Index)
   259  	if len(out.Tokens) > 0 {
   260  		return out.Tokens[0], nil
   261  	}
   262  	return nil, nil
   263  }
   264  
   265  func (s *HTTPServer) aclTokenDelete(resp http.ResponseWriter, req *http.Request,
   266  	tokenAccessor string) (interface{}, error) {
   267  
   268  	args := structs.ACLTokenDeleteRequest{
   269  		AccessorIDs: []string{tokenAccessor},
   270  	}
   271  	s.parseWriteRequest(req, &args.WriteRequest)
   272  
   273  	var out structs.GenericResponse
   274  	if err := s.agent.RPC("ACL.DeleteTokens", &args, &out); err != nil {
   275  		return nil, err
   276  	}
   277  	setIndex(resp, out.Index)
   278  	return nil, nil
   279  }