package handlers import ( "byom-infra-api/config" "encoding/json" "log" "net/http" "github.com/gorilla/mux" ) type SSHKey struct { KeyName string `json:"keyName"` Key string `json:"key"` } type SSHKeyHandler struct{} func NewSSHKeyHandler() *SSHKeyHandler { return &SSHKeyHandler{} } // GetSSHKeys handles the retrieval of all SSH keys func (h *SSHKeyHandler) GetSSHKeys(w http.ResponseWriter, r *http.Request) { log.Printf("Handling GET request for all SSH keys from %s", r.RemoteAddr) // First, get the list of SSH key IDs var keyIDs []string err := config.OVHClient.Get("/me/sshKey", &keyIDs) if err != nil { log.Printf("Error fetching SSH key IDs: %v", err) http.Error(w, "Failed to fetch SSH keys: "+err.Error(), http.StatusInternalServerError) return } // Then fetch details for each key var sshKeys []SSHKey for _, id := range keyIDs { var key SSHKey err := config.OVHClient.Get("/me/sshKey/"+id, &key) if err != nil { log.Printf("Error fetching details for SSH key %s: %v", id, err) continue } sshKeys = append(sshKeys, key) } log.Printf("Successfully retrieved %d SSH keys", len(sshKeys)) w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(sshKeys); err != nil { log.Printf("Error encoding SSH keys response: %v", err) http.Error(w, "Failed to encode response", http.StatusInternalServerError) return } } // GetSSHKeyByID handles the retrieval of a specific SSH key by ID func (h *SSHKeyHandler) GetSSHKeyByID(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) keyID := vars["id"] log.Printf("Handling GET request for SSH key ID: %s from %s", keyID, r.RemoteAddr) var sshKey SSHKey err := config.OVHClient.Get("/me/sshKey/"+keyID, &sshKey) if err != nil { log.Printf("Error fetching SSH key %s: %v", keyID, err) http.Error(w, "Failed to fetch SSH key: "+err.Error(), http.StatusInternalServerError) return } log.Printf("Successfully retrieved SSH key: %s", keyID) w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(sshKey); err != nil { log.Printf("Error encoding SSH key response: %v", err) http.Error(w, "Failed to encode response", http.StatusInternalServerError) return } } // CreateSSHKey handles the creation of a new SSH key func (h *SSHKeyHandler) CreateSSHKey(w http.ResponseWriter, r *http.Request) { log.Printf("Handling POST request for new SSH key from %s", r.RemoteAddr) // Parse request body var newKey struct { KeyName string `json:"keyName"` Key string `json:"key"` } if err := json.NewDecoder(r.Body).Decode(&newKey); err != nil { log.Printf("Error decoding request body: %v", err) http.Error(w, "Invalid request body", http.StatusBadRequest) return } // Validate input if newKey.KeyName == "" || newKey.Key == "" { log.Printf("Invalid input: keyName or key is empty") http.Error(w, "KeyName and Key are required", http.StatusBadRequest) return } // Prepare creation payload sshKey := SSHKey{ KeyName: newKey.KeyName, Key: newKey.Key, } // Create SSH key via OVH API err := config.OVHClient.Post("/me/sshKey", sshKey, &sshKey) if err != nil { log.Printf("Error creating SSH key: %v", err) http.Error(w, "Failed to create SSH key: "+err.Error(), http.StatusInternalServerError) return } log.Printf("Successfully created SSH key: %s", sshKey.KeyName) // Return created key details w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) if err := json.NewEncoder(w).Encode(sshKey); err != nil { log.Printf("Error encoding response: %v", err) http.Error(w, "Failed to encode response", http.StatusInternalServerError) return } } // // GenerateED25519Key generates a new ED25519 SSH key pair and returns public and private keys // func GenerateED25519Key(keyName string) (string, string, error) { // // Generate the key pair // pubKey, privKey, err := ed25519.GenerateKey(rand.Reader) // if err != nil { // return "", "", fmt.Errorf("failed to generate ED25519 key: %v", err) // } // // Convert to OpenSSH format // // ED25519 public key format: ssh-ed25519 // publicKeyStr := "ssh-ed25519 " + base64.StdEncoding.EncodeToString(pubKey) + " OVH_" + keyName // // Convert private key to base64 // privateKeyStr := base64.StdEncoding.EncodeToString(privKey) // return publicKeyStr, privateKeyStr, nil // } // // Example usage in CreateSSHKey: // func (h *SSHKeyHandler) CreateSSHKeyWithGeneration(w http.ResponseWriter, r *http.Request) { // var request struct { // KeyName string `json:"keyName"` // } // if err := json.NewDecoder(r.Body).Decode(&request); err != nil { // http.Error(w, "Invalid request body", http.StatusBadRequest) // return // } // publicKey, privateKey, err := GenerateED25519Key(request.KeyName) // if err != nil { // http.Error(w, err.Error(), http.StatusInternalServerError) // return // } // sshKey := SSHKey{ // KeyName: request.KeyName, // Key: publicKey, // } // // print private key to console // fmt.Printf("-----BEGIN OPENSSH PRIVATE KEY-----\n") // fmt.Printf("%s\n", privateKey) // fmt.Printf("-----END OPENSSH PRIVATE KEY-----\n") // // Create SSH key via OVH API // err = config.OVHClient.Post("/me/sshKey", sshKey, &sshKey) // if err != nil { // log.Printf("Error creating SSH key: %v", err) // http.Error(w, "Failed to create SSH key: "+err.Error(), http.StatusInternalServerError) // return // } // // Return created key details // w.Header().Set("Content-Type", "application/json") // w.WriteHeader(http.StatusCreated) // if err := json.NewEncoder(w).Encode(sshKey); err != nil { // log.Printf("Error encoding response: %v", err) // http.Error(w, "Failed to encode response", http.StatusInternalServerError) // return // } // } // DeleteSSHKey handles the deletion of an SSH key func (h *SSHKeyHandler) DeleteSSHKey(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) keyId := vars["id"] log.Printf("Handling DELETE request for SSH key: %s from %s", keyId, r.RemoteAddr) err := config.OVHClient.Delete("/me/sshKey/"+keyId, nil) if err != nil { log.Printf("Error deleting SSH key %s: %v", keyId, err) http.Error(w, "Failed to delete SSH key: "+err.Error(), http.StatusInternalServerError) return } log.Printf("Successfully deleted SSH key: %s", keyId) w.WriteHeader(http.StatusNoContent) }