From cd22c5abdf0ab2d86f2b9491146307b96dc61038 Mon Sep 17 00:00:00 2001 From: Kenrick Date: Tue, 26 Dec 2023 10:21:45 +0800 Subject: [PATCH 1/3] added retrieve token function --- cmd/get.go | 2 -- cmd/retrieve-token.go | 35 +++++++++++++++++++++++++++++++++++ cmd/root.go | 25 ++++++++++--------------- example-config.yaml | 2 +- main.go | 18 ++++++++++++------ pkg/config/config.go | 18 +++++++++++------- 6 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 cmd/retrieve-token.go diff --git a/cmd/get.go b/cmd/get.go index 4297d8e..b395a06 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -21,8 +21,6 @@ func GetCommand(kcClient *keycloak.KeycloakClient) *cobra.Command { return GetCommand } - - // List Realm func GetRealmCommand(kcClient *keycloak.KeycloakClient) *cobra.Command { return &cobra.Command{ diff --git a/cmd/retrieve-token.go b/cmd/retrieve-token.go new file mode 100644 index 0000000..0928cf6 --- /dev/null +++ b/cmd/retrieve-token.go @@ -0,0 +1,35 @@ +package cmd + +import ( + "fmt" + "keycloak-api-cli/pkg/keycloak" + + "github.com/spf13/cobra" +) + + +// GetCommand creates and returns a new list command +func RetrieveCommand(kcClient *keycloak.KeycloakClient) *cobra.Command { + RetrieveCommand := &cobra.Command{ + Use: "retrieve [token]", + Short: "retrieve token in Keycloak", + } + RetrieveCommand.AddCommand(RetrieveTokenCommand(kcClient)) + + return RetrieveCommand +} + +// Retrieve Token Command +func RetrieveTokenCommand(kcClient *keycloak.KeycloakClient) *cobra.Command { + return &cobra.Command{ + Use: "token", + Short: "Retrieve token in Keycloak", + Run: func(cmd *cobra.Command, args []string) { + if kcClient.Token == "" { + fmt.Println("Error: Token doesn't exist") + return + } + fmt.Printf(kcClient.Token) + }, + } +} \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go index c072f14..6bad737 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -24,6 +24,7 @@ var rootCmd = &cobra.Command{ } func Execute(kcClient *keycloak.KeycloakClient) { + rootCmd.AddCommand(RetrieveCommand(kcClient)) rootCmd.AddCommand(GetCommand(kcClient)) rootCmd.AddCommand(CreateCommand(kcClient)) rootCmd.AddCommand(DeleteCommand(kcClient)) @@ -35,31 +36,25 @@ func Execute(kcClient *keycloak.KeycloakClient) { } func init() { - cobra.OnInitialize(initConfig) - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "./config.yaml", "config file (default is $HOME/.keycloak-api-cli.yaml)") - + cobra.OnInitialize(initConfig) + // Set the default to an empty string + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file") } func initConfig() { - if cfgFile != "" { - fmt.Println("Using config file:", cfgFile) + // Use the specified config file + fmt.Println("Using specified config file:", cfgFile) viper.SetConfigFile(cfgFile) } else { - home, err := os.UserHomeDir() - if err != nil { - fmt.Println("Unable to find home directory:", err) - os.Exit(1) - } - fmt.Println("Looking for config file in home directory:", home) - viper.AddConfigPath(home) - viper.SetConfigName("config.yaml") + defaultConfig := "config.yaml" + fmt.Println("Using default config file:", defaultConfig) + viper.SetConfigFile(defaultConfig) } viper.AutomaticEnv() - err := viper.ReadInConfig() - if err != nil { + if err := viper.ReadInConfig(); err != nil { fmt.Println("Failed to read config file:", err) os.Exit(1) } else { diff --git a/example-config.yaml b/example-config.yaml index 7e9830e..291a6cf 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -1,4 +1,4 @@ -url: http://localhost:8080/auth +url: http://localhost:8080 client_id: admin-cli client_secret: username: admin diff --git a/main.go b/main.go index 08b18f2..24cb1be 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "log" "keycloak-api-cli/cmd" "keycloak-api-cli/pkg/keycloak" @@ -8,18 +9,23 @@ import ( ) func main() { - // Load your configuration (modify as per your configuration logic) - cfg, err := config.LoadConfig() + // Define a command-line flag for the config file + var cfgFile string + flag.StringVar(&cfgFile, "config", "config.yaml", "path to config file") + flag.Parse() + + // Load your configuration using the specified config file + cfg, err := config.LoadConfig(cfgFile) if err != nil { log.Fatalf("Failed to load config: %v", err) } // Initialize Keycloak client kcClient := keycloak.NewClient(cfg) - err = kcClient.Authenticate(cfg) - if err != nil { - log.Fatalf("Failed to authenticate: %v", err) - } + err = kcClient.Authenticate(cfg) + if err != nil { + log.Fatalf("Failed to authenticate: %v", err) + } // Execute the root command with the Keycloak client cmd.Execute(kcClient) diff --git a/pkg/config/config.go b/pkg/config/config.go index f438efe..24bc5a1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "github.com/spf13/viper" ) @@ -15,17 +16,20 @@ type KeycloakConfig struct { } // LoadConfig loads configuration from config.yaml -func LoadConfig() (KeycloakConfig, error) { +func LoadConfig(configFile string) (KeycloakConfig, error) { var config KeycloakConfig - // Set default configurations - viper.SetConfigName("config") - viper.AddConfigPath(".") + viper.SetConfigFile(configFile) // Set the configuration file viper.AutomaticEnv() + if err := viper.ReadInConfig(); err != nil { - return config, err + return config, fmt.Errorf("failed to load config file '%s': %v", configFile, err) } err := viper.Unmarshal(&config) - return config, err -} + if err != nil { + return config, fmt.Errorf("error unmarshalling config: %v", err) + } + + return config, nil +} \ No newline at end of file From 7ae29ed5a29db7946a59210d053b26a3dda90e0f Mon Sep 17 00:00:00 2001 From: Kenrick Date: Tue, 26 Dec 2023 10:22:56 +0800 Subject: [PATCH 2/3] fix config path --- cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/root.go b/cmd/root.go index 6bad737..3977f39 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -47,7 +47,7 @@ func initConfig() { fmt.Println("Using specified config file:", cfgFile) viper.SetConfigFile(cfgFile) } else { - defaultConfig := "config.yaml" + defaultConfig := "./config.yaml" fmt.Println("Using default config file:", defaultConfig) viper.SetConfigFile(defaultConfig) } From bd2850fee251e568857f795131bf05b6eba53b14 Mon Sep 17 00:00:00 2001 From: Kenrick Date: Tue, 26 Dec 2023 10:26:42 +0800 Subject: [PATCH 3/3] updated readme file --- README.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4fbcd78..b60e2d2 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,63 @@ # Keycloak API CLI Application +The Keycloak API CLI is a command-line tool that allows you to interact with the Keycloak authentication and authorization server. It simplifies the management of Keycloak entities, making it efficient for tasks such as creating users, realms, resources, and roles. + +## Table of Contents + +- [Keycloak API CLI Application](#keycloak-api-cli-application) + - [Table of Contents](#table-of-contents) + - [Setup and Execution](#setup-and-execution) + - [Available Commands](#available-commands) + - [1. `create`](#1-create) + - [2. `delete`](#2-delete) + - [3. `get`](#3-get) + - [4. `retrieve token`](#4-retrieve-token) + - [5. Root Command](#5-root-command) + - [Additional Notes](#additional-notes) + - [General Overview of Cobra and Viper](#general-overview-of-cobra-and-viper) + - [Cobra and Viper in This Application](#cobra-and-viper-in-this-application) + - [Why This CLI is Useful](#why-this-cli-is-useful) + ## Setup and Execution -1. **Install Go** - Ensure Go (version 1.21.4 or higher) is installed. + +To get started with the Keycloak API CLI, follow these steps: + +1. **Install Go** - Ensure Go (version 1.21.4 or higher) is installed on your system. + 2. **Clone the Repository** - Clone the application repository to your local machine. -3. **Install Dependencies** - Run `go mod tidy` in the project directory to install necessary dependencies. -4. **Configuration** - Edit the `config.yaml` file with appropriate Keycloak server details and credentials. -5. **Build the Application** - Run `go build .` in the project directory to build the executable. -6. **Make the Build Executable** - Use `chmod +x keycloak-api-cli` (or the name of your built executable) to make it executable. -7. **Running the Application** - Execute the built application. Use `./keycloak-api-cli --config path/to/config.yaml` to specify the configuration file. + +3. **Install Dependencies** - Run the following command in the project directory to install the necessary dependencies: + + ```bash + go mod tidy + ``` + +4. **Configuration** - Edit the `config.yaml` file with the appropriate Keycloak server details and credentials. + +5. **Build the Application** - Run the following command in the project directory to build the executable: + + ```bash + go build . + ``` + +6. **Make the Build Executable** - Use the following command to make the executable file executable: + + ```bash + chmod +x keycloak-api-cli + ``` + +7. **Running the Application** - Execute the built application. You can specify the configuration file using the `--config` flag. Example usage: + + ```bash + ./keycloak-api-cli --config path/to/config.yaml + ``` ## Available Commands +The Keycloak API CLI provides several commands to interact with Keycloak entities. Here are the available commands: + ### 1. `create` + - **Usage**: `create [user, realm, resource, role]` - **Description**: Creates various entities in Keycloak. - **Subcommands**: @@ -22,6 +68,7 @@ - **Example**: `./keycloak-api-cli create realm --config path/to/config.yaml` ### 2. `delete` + - **Usage**: `delete [user, realm, resource, role]` - **Description**: Deletes entities in Keycloak. - **Subcommands**: @@ -32,6 +79,7 @@ - **Example**: `./keycloak-api-cli delete realm --config path/to/config.yaml` ### 3. `get` + - **Usage**: `get [users, realms, resources, roles]` - **Description**: Retrieves information about entities in Keycloak. - **Subcommands**: @@ -41,10 +89,23 @@ - `get realms`: Lists all realms. - **Example**: `./keycloak-api-cli get realms --config path/to/config.yaml` -### 4. Root Command +### 4. `retrieve token` + +- **Usage**: `retrieve token` +- **Description**: Retrieves an authentication token from Keycloak. +- **Flags**: + - `-c, --config`: Specifies the path to the configuration file (e.g., `path/to/config.yaml`). + +Example usage: + +```bash +./keycloak-api-cli retrieve token --config example-config.yaml +``` + +### 5. Root Command - **Usage**: `keycloak-api-cli` - **Description**: Base command for Keycloak API interactions. -- **Integrated Commands**: Includes `create`, `delete`, and `get`. +- **Integrated Commands**: Includes `create`, `delete`, `get` and `retrieve token`. - **Example**: `./keycloak-api-cli --help` ## Additional Notes