diff --git a/service/README.md b/service/README.md index 3a2da2d982..87e97ce1c6 100644 --- a/service/README.md +++ b/service/README.md @@ -72,7 +72,7 @@ For convenience, the `make toolcheck` script checks if you have the necessary de ### Provisioning Custom Keycloak and Policy Data -To provision a custom Keycloak setup, create a yaml following the format of [the sample Keycloak config](service/cmd/keycloak_data.yaml). You can create different realms with separate users, clients, roles, and groups. Run the provisioning with `go run ./service provision keycloak-from-config -f `. +To provision a custom Keycloak setup, create a yaml following the format of [the sample Keycloak config](service/cmd/keycloak_data.yaml). You can create different realms with separate users, clients, roles, and groups. Run the provisioning with `go run ./service provision keycloak -f `. ### Develop a new service diff --git a/service/cmd/provisionKeycloak.go b/service/cmd/provisionKeycloak.go index 909fbad24b..194be731d1 100644 --- a/service/cmd/provisionKeycloak.go +++ b/service/cmd/provisionKeycloak.go @@ -2,10 +2,15 @@ package cmd import ( "context" + "encoding/json" + "fmt" + "io" + "log/slog" + "os" "github.com/opentdf/platform/lib/fixtures" - "github.com/opentdf/platform/service/internal/config" "github.com/spf13/cobra" + "gopkg.in/yaml.v2" ) const ( @@ -13,59 +18,117 @@ const ( provKcUsernameFlag = "username" provKcPasswordFlag = "password" provKcRealmFlag = "realm" + provKcFilenameFlag = "file" provKcInsecure = "insecure" ) var ( - provisionKeycloakCmd = &cobra.Command{ - Use: "keycloak", - Short: "Run local provision of keycloak data", - Long: ` - ** Local Development and Testing Only ** - This command will create the following Keyclaok resource: - - Realm - - Roles - - Client - - Users - - This command is intended for local development and testing purposes only. - `, - RunE: func(cmd *cobra.Command, _ []string) error { - kcEndpoint, _ := cmd.Flags().GetString(provKcEndpointFlag) - realmName, _ := cmd.Flags().GetString(provKcRealmFlag) - kcUsername, _ := cmd.Flags().GetString(provKcUsernameFlag) - kcPassword, _ := cmd.Flags().GetString(provKcPasswordFlag) - configFile, _ := cmd.Flags().GetString(configFileFlag) - configKey, _ := cmd.Flags().GetString(configKeyFlag) - insecure, _ := cmd.Flags().GetBool(provKcInsecure) - - config, err := config.LoadConfig(configKey, configFile) - if err != nil { - return err - } - - kcConnectParams := fixtures.KeycloakConnectParams{ - BasePath: kcEndpoint, - Username: kcUsername, - Password: kcPassword, - Realm: realmName, - Audience: config.Server.Auth.Audience, - AllowInsecureTLS: insecure, - } - - return fixtures.SetupKeycloak(context.Background(), kcConnectParams) - }, - } + provKeycloakFilename = "./service/cmd/keycloak_data.yaml" + keycloakData fixtures.KeycloakData ) +var provisionKeycloakCmd = &cobra.Command{ + Use: "keycloak", + Short: "Run local provision of keycloak data", + Long: ` + ** Local Development and Testing Only ** + This command will create the following Keyclaok resource: + - Realm + - Roles + - Client + - Users + + This command is intended for local development and testing purposes only. + `, + RunE: func(cmd *cobra.Command, _ []string) error { + kcEndpoint, _ := cmd.Flags().GetString(provKcEndpointFlag) + kcUsername, _ := cmd.Flags().GetString(provKcUsernameFlag) + kcPassword, _ := cmd.Flags().GetString(provKcPasswordFlag) + keycloakFilename, _ := cmd.Flags().GetString(provKcFilenameFlag) + + LoadKeycloakData(keycloakFilename) + ctx := context.Background() + + kcParams := fixtures.KeycloakConnectParams{ + BasePath: kcEndpoint, + Username: kcUsername, + Password: kcPassword, + Realm: "", + AllowInsecureTLS: true, + } + + err := fixtures.SetupCustomKeycloak(ctx, kcParams, keycloakData) + if err != nil { + return err + } + + return nil + }, +} + +var provisionKeycloakFromConfigCmd = &cobra.Command{ + Use: "keycloak-from-config", + RunE: func(_ *cobra.Command, _ []string) error { + slog.Info("Command keycloak-from-config has been deprecated. Please use command 'keycloak' instead.") + return nil + }, +} + +func convert(i interface{}) interface{} { + switch x := i.(type) { + case map[interface{}]interface{}: + m2 := map[string]interface{}{} + for k, v := range x { + m2[k.(string)] = convert(v) //nolint:forcetypeassert // allow type assert + } + return m2 + case []interface{}: + for i, v := range x { + x[i] = convert(v) + } + } + return i +} + +func LoadKeycloakData(file string) { + yamlData := make(map[interface{}]interface{}) + + f, err := os.Open(file) + if err != nil { + panic(fmt.Errorf("error when opening YAML file: %s", err.Error())) + } + + fileData, err := io.ReadAll(f) + if err != nil { + panic(fmt.Errorf("error reading YAML file: %s", err.Error())) + } + + err = yaml.Unmarshal(fileData, &yamlData) + if err != nil { + panic(fmt.Errorf("error unmarshaling yaml file %s", err.Error())) + } + + cleanedYaml := convert(yamlData) + + kcData, err := json.Marshal(cleanedYaml) + if err != nil { + panic(fmt.Errorf("error converting yaml to json: %s", err.Error())) + } + + if err := json.Unmarshal(kcData, &keycloakData); err != nil { + slog.Error("could not unmarshal json into data object", slog.String("error", err.Error())) + panic(err) + } +} + func init() { provisionKeycloakCmd.Flags().StringP(provKcEndpointFlag, "e", "http://localhost:8888/auth", "Keycloak endpoint") provisionKeycloakCmd.Flags().StringP(provKcUsernameFlag, "u", "admin", "Keycloak username") provisionKeycloakCmd.Flags().StringP(provKcPasswordFlag, "p", "changeme", "Keycloak password") - provisionKeycloakCmd.Flags().StringP(provKcRealmFlag, "r", "opentdf", "OpenTDF Keycloak Realm name") - provisionKeycloakCmd.Flags().BoolP(provKcInsecure, "", false, "Ignore tls verification when connecting to keycloak. --insecure to disable.") + provisionKeycloakCmd.Flags().StringP(provKcFilenameFlag, "f", provKeycloakFilename, "Keycloak config file") provisionCmd.AddCommand(provisionKeycloakCmd) - rootCmd.AddCommand(provisionKeycloakCmd) + // Deprecated command + provisionCmd.AddCommand(provisionKeycloakFromConfigCmd) } diff --git a/service/cmd/provisionKeycloakFromConfig.go b/service/cmd/provisionKeycloakFromConfig.go deleted file mode 100644 index f93996c53b..0000000000 --- a/service/cmd/provisionKeycloakFromConfig.go +++ /dev/null @@ -1,124 +0,0 @@ -package cmd - -import ( - "context" - "encoding/json" - "fmt" - "io" - "log/slog" - "os" - - "github.com/opentdf/platform/lib/fixtures" - "github.com/spf13/cobra" - "gopkg.in/yaml.v2" -) - -var ( - provKeycloakFilename = "./cmd/keycloak_data.yaml" - keycloakData fixtures.KeycloakData -) - -var ( - provisionKeycloakFromConfigCmd = &cobra.Command{ - Use: "keycloak-from-config", - Short: "Run local provision of keycloak data", - Long: ` - ** Local Development and Testing Only ** - This command will create the following Keyclaok resource: - - Realm - - Roles - - Client - - Users - - This command is intended for local development and testing purposes only. - `, - RunE: func(cmd *cobra.Command, _ []string) error { - kcEndpoint, _ := cmd.Flags().GetString(provKcEndpointFlag) - kcUsername, _ := cmd.Flags().GetString(provKcUsernameFlag) - kcPassword, _ := cmd.Flags().GetString(provKcPasswordFlag) - keycloakFilename, _ := cmd.Flags().GetString(provKeycloakFilename) - - // config, err := config.LoadConfig("") - LoadKeycloakData(keycloakFilename) - ctx := context.Background() - - kcParams := fixtures.KeycloakConnectParams{ - BasePath: kcEndpoint, - Username: kcUsername, - Password: kcPassword, - Realm: "", - AllowInsecureTLS: true, - } - - err := fixtures.SetupCustomKeycloak(ctx, kcParams, keycloakData) - if err != nil { - return err - } - - return nil - }, - } -) - -func convert(i interface{}) interface{} { - switch x := i.(type) { - case map[interface{}]interface{}: - m2 := map[string]interface{}{} - for k, v := range x { - m2[k.(string)] = convert(v) //nolint:forcetypeassert // allow type assert - } - return m2 - case []interface{}: - for i, v := range x { - x[i] = convert(v) - } - } - return i -} - -func LoadKeycloakData(file string) { - var yamlData = make(map[interface{}]interface{}) - - f, err := os.Open(file) - if err != nil { - panic(fmt.Errorf("error when opening YAML file: %s", err.Error())) - } - - fileData, err := io.ReadAll(f) - if err != nil { - panic(fmt.Errorf("error reading YAML file: %s", err.Error())) - } - - err = yaml.Unmarshal(fileData, &yamlData) - if err != nil { - panic(fmt.Errorf("error unmarshaling yaml file %s", err.Error())) - } - - cleanedYaml := convert(yamlData) - - kcData, err := json.Marshal(cleanedYaml) - if err != nil { - panic(fmt.Errorf("error converting yaml to json: %s", err.Error())) - } - // slog.Info("", slog.Any("kcData", kcData)) - - if err := json.Unmarshal(kcData, &keycloakData); err != nil { - slog.Error("could not unmarshal json into data object", slog.String("error", err.Error())) - panic(err) - } - - // slog.Info("Fully loaded keycloak data", slog.Any("keycloakData", keycloakData)) - // panic("hi") -} - -func init() { - provisionKeycloakFromConfigCmd.Flags().StringP(provKcEndpointFlag, "e", "http://localhost:8888/auth", "Keycloak endpoint") - provisionKeycloakFromConfigCmd.Flags().StringP(provKcUsernameFlag, "u", "admin", "Keycloak username") - provisionKeycloakFromConfigCmd.Flags().StringP(provKcPasswordFlag, "p", "changeme", "Keycloak password") - provisionKeycloakFromConfigCmd.Flags().StringP(provKeycloakFilename, "f", "./cmd/keycloak_data.yaml", "Keycloak config file") - // provisionKeycloakFromConfigCmd.Flags().StringP(provKcRealm, "r", "opentdf", "OpenTDF Keycloak Realm name") - - provisionCmd.AddCommand(provisionKeycloakFromConfigCmd) - - rootCmd.AddCommand(provisionKeycloakFromConfigCmd) -}