150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var (
|
|
dbUsername string
|
|
dbToken string
|
|
)
|
|
|
|
type DatabaseCredentials struct {
|
|
Host string `json:"host"`
|
|
Port int `json:"port"`
|
|
Name string `json:"name"`
|
|
User string `json:"user"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
type ErrorResponse struct {
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
var databaseCmd = &cobra.Command{
|
|
Use: "database",
|
|
Short: "Manage database credentials",
|
|
Long: `Commands for managing database credentials in the MCIAS system.`,
|
|
}
|
|
|
|
var addDBUserCmd = &cobra.Command{
|
|
Use: "add-user [database-id] [user-id]",
|
|
Short: "Associate a user with a database",
|
|
Long: `Associate a user with a database, allowing them to read its credentials.`,
|
|
Args: cobra.ExactArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
addUserToDatabase(args[0], args[1])
|
|
},
|
|
}
|
|
|
|
var removeDBUserCmd = &cobra.Command{
|
|
Use: "remove-user [database-id] [user-id]",
|
|
Short: "Remove a user's association with a database",
|
|
Long: `Remove a user's association with a database, preventing them from reading its credentials.`,
|
|
Args: cobra.ExactArgs(2),
|
|
Run: func(_ *cobra.Command, args []string) {
|
|
removeUserFromDatabase(args[0], args[1])
|
|
},
|
|
}
|
|
|
|
var listDBUsersCmd = &cobra.Command{
|
|
Use: "list-users [database-id]",
|
|
Short: "List users associated with a database",
|
|
Long: `List all users who have access to read the credentials of a specific database.`,
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(_ *cobra.Command, args []string) {
|
|
listDatabaseUsers(args[0])
|
|
},
|
|
}
|
|
|
|
var getCredentialsCmd = &cobra.Command{
|
|
Use: "credentials",
|
|
Short: "Get database credentials",
|
|
Long: `Retrieve database credentials from the MCIAS system.
|
|
This command requires authentication with a username and token.`,
|
|
Run: func(_ *cobra.Command, args []string) {
|
|
getCredentials()
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(databaseCmd)
|
|
databaseCmd.AddCommand(getCredentialsCmd)
|
|
databaseCmd.AddCommand(addDBUserCmd)
|
|
databaseCmd.AddCommand(removeDBUserCmd)
|
|
databaseCmd.AddCommand(listDBUsersCmd)
|
|
|
|
getCredentialsCmd.Flags().StringVarP(&dbUsername, "username", "u", "", "Username for authentication")
|
|
getCredentialsCmd.Flags().StringVarP(&dbToken, "token", "t", "", "Authentication token")
|
|
if err := getCredentialsCmd.MarkFlagRequired("username"); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error marking username flag as required: %v\n", err)
|
|
}
|
|
if err := getCredentialsCmd.MarkFlagRequired("token"); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error marking token flag as required: %v\n", err)
|
|
}
|
|
}
|
|
|
|
func getCredentials() {
|
|
logger := log.New(os.Stdout, "MCIAS: ", log.LstdFlags)
|
|
|
|
serverAddr := viper.GetString("server")
|
|
if serverAddr == "" {
|
|
serverAddr = "http://localhost:8080"
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/v1/database/credentials?username=%s", serverAddr, dbUsername)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
if err != nil {
|
|
logger.Fatalf("Failed to create request: %v", err)
|
|
}
|
|
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", dbToken))
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
logger.Fatalf("Failed to send request: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
logger.Fatalf("Failed to read response: %v", err)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
var errResp ErrorResponse
|
|
if unmarshalErr := json.Unmarshal(body, &errResp); unmarshalErr == nil {
|
|
logger.Fatalf("Error: %s", errResp.Error)
|
|
} else {
|
|
logger.Fatalf("Error: %s", resp.Status)
|
|
}
|
|
}
|
|
|
|
var creds DatabaseCredentials
|
|
if unmarshalErr := json.Unmarshal(body, &creds); unmarshalErr != nil {
|
|
logger.Fatalf("Failed to parse response: %v", unmarshalErr)
|
|
}
|
|
|
|
fmt.Println("Database Credentials:")
|
|
fmt.Printf("Host: %s\n", creds.Host)
|
|
fmt.Printf("Port: %d\n", creds.Port)
|
|
fmt.Printf("Name: %s\n", creds.Name)
|
|
fmt.Printf("User: %s\n", creds.User)
|
|
fmt.Printf("Password: %s\n", creds.Password)
|
|
}
|