raw draft of policy-manager
This commit is contained in:
113
createpolicy.go
Normal file
113
createpolicy.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CreatePolicyRequest struct {
|
||||
PolicyName string `json:"policyname"`
|
||||
PolicyDocument Policy `json:"policy"`
|
||||
}
|
||||
|
||||
func CreatePolicy(w http.ResponseWriter, r *http.Request) {
|
||||
// Only allow POST method
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
// XXX Temporary Account Handler
|
||||
accountid := r.Header.Get("Account")
|
||||
if accountid == "" {
|
||||
http.Error(w, "Account header is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Optional: enforce content type
|
||||
if r.Header.Get("Content-Type") != "application/json" {
|
||||
http.Error(w, "Content-Type must be application/json", http.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
|
||||
// Read body with size limit (protect against huge requests)
|
||||
const maxBodyBytes = 1 << 20 // 1 MB
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxBodyBytes)
|
||||
|
||||
// Decode JSON into our struct
|
||||
var policydocumentrequest CreatePolicyRequest
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
decoder.DisallowUnknownFields() // strict mode - reject unknown fields
|
||||
|
||||
if err := decoder.Decode(&policydocumentrequest); err != nil {
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
http.Error(w, "Empty request body", http.StatusBadRequest)
|
||||
case err.Error() == "http: request body too large":
|
||||
http.Error(w, "Request body too large (max 1MB)", http.StatusRequestEntityTooLarge)
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Optional: basic validation
|
||||
if policydocumentrequest.PolicyDocument.Actions == nil || policydocumentrequest.PolicyDocument.Effect == "" || policydocumentrequest.PolicyDocument.Resources == nil {
|
||||
http.Error(w, "Missing required fields: id and title", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Process the results
|
||||
log.Printf("New Policy: Account:%s, PolicyIdentifier=%s, Actions=%q, Effect=%q, Resources=%q, Comment=%q",
|
||||
accountid, policydocumentrequest.PolicyDocument.PolicyIdentifier, policydocumentrequest.PolicyDocument.Actions,
|
||||
policydocumentrequest.PolicyDocument.Effect, policydocumentrequest.PolicyDocument.Resources, policydocumentrequest.PolicyDocument.Comment)
|
||||
|
||||
// Check if policy with the same name already exists for the account
|
||||
checkExisting := pool.QueryRow(context.Background(),
|
||||
"SELECT FROM policies WHERE accountid = $1 AND policyname = $2",
|
||||
accountid, policydocumentrequest.PolicyName)
|
||||
err := checkExisting.Scan()
|
||||
if err == nil {
|
||||
pri := "pri:iam::" + accountid + ":policy/" + policydocumentrequest.PolicyName
|
||||
response := map[string]interface{}{
|
||||
"status": "fail",
|
||||
"pri": pri,
|
||||
"message": "Policy " + policydocumentrequest.PolicyName + " already exists: " + pri,
|
||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()),
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(response)
|
||||
http.Error(w, "Policy with the same name already exists for this account", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = pool.Exec(context.Background(),
|
||||
"INSERT INTO policies (accountid, policyname, document) VALUES($1, $2, $3) ON CONFLICT DO NOTHING",
|
||||
accountid, policydocumentrequest.PolicyName, policydocumentrequest.PolicyDocument)
|
||||
if err != nil {
|
||||
log.Printf("Error inserting policy: %v", err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Success response
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
// arnservice:region:account-id:resource-type:resource-id
|
||||
pri := "pri:iam::" + accountid + ":policy/" + policydocumentrequest.PolicyName
|
||||
|
||||
response := map[string]interface{}{
|
||||
"status": "success",
|
||||
"pri": pri,
|
||||
"message": "Policy created",
|
||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()),
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
Reference in New Issue
Block a user