From 274d6030f6b456b2e536d731505b3565ad1952a1 Mon Sep 17 00:00:00 2001 From: Joe Garcia Date: Mon, 14 Aug 2023 13:48:08 -0400 Subject: [PATCH] Fixes #189 add support for cyberark identity authentication (#202) * Initial commit * Implement Identity check for httpjson * Update GitHub Workflows for successful tests (#200) * Update action versions & add Conjur fetching (#195) * Update action versions & add Conjur fetching * flip Go install to after source checkout * update go-version * go-version to version * version set to latest * add debug step * switch from authn-jwt to authn due to iat issues * Update README.md * Identity StartAuthentication implemented * refactored StartAuth * Began implementation of Password AdvanceAuth * Identity auth-type tested successfully * Added color to terminal * Update /docs * Updated README * Use platform discovery instead of requiring TenantID * Derive PCloud URL from Platform Discovery * Derive PCloud URL from Platform Discovery * Updated docs to remove tenant ID requirement * Fix 7 code smells * remove duplicate tests on v* branch --- .github/workflows/ci.yml | 1 - README.md | 42 ++- cmd/logon.go | 352 ++++++++++++++---- docs/cybr.md | 2 +- docs/cybr_accounts.md | 2 +- docs/cybr_accounts_add.md | 2 +- docs/cybr_accounts_change.md | 2 +- docs/cybr_accounts_delete.md | 2 +- docs/cybr_accounts_get-password.md | 2 +- docs/cybr_accounts_get.md | 2 +- docs/cybr_accounts_list.md | 2 +- docs/cybr_accounts_move.md | 2 +- docs/cybr_accounts_reconcile.md | 2 +- docs/cybr_accounts_verify.md | 2 +- docs/cybr_applications.md | 2 +- docs/cybr_applications_add-authn.md | 2 +- docs/cybr_applications_add.md | 2 +- docs/cybr_applications_delete-authn.md | 2 +- docs/cybr_applications_delete.md | 2 +- docs/cybr_applications_list-authn.md | 2 +- docs/cybr_applications_list.md | 2 +- docs/cybr_ccp.md | 2 +- docs/cybr_ccp_get-account.md | 2 +- docs/cybr_cem.md | 2 +- docs/cybr_cem_accounts.md | 2 +- docs/cybr_cem_entities.md | 2 +- docs/cybr_cem_entity-details.md | 2 +- docs/cybr_cem_logon.md | 2 +- docs/cybr_cem_recommendations.md | 2 +- docs/cybr_cem_remediations.md | 2 +- docs/cybr_completion.md | 2 +- docs/cybr_conjur.md | 2 +- docs/cybr_conjur_append-policy.md | 2 +- docs/cybr_conjur_enable-authn.md | 2 +- docs/cybr_conjur_get-secret.md | 2 +- docs/cybr_conjur_info.md | 2 +- docs/cybr_conjur_list.md | 2 +- docs/cybr_conjur_logoff.md | 2 +- docs/cybr_conjur_logon-non-interactive.md | 2 +- docs/cybr_conjur_logon.md | 2 +- docs/cybr_conjur_replace-policy.md | 2 +- docs/cybr_conjur_rotate-api-key.md | 2 +- docs/cybr_conjur_set-secret.md | 2 +- docs/cybr_conjur_update-policy.md | 2 +- docs/cybr_conjur_whoami.md | 2 +- docs/cybr_logoff.md | 2 +- docs/cybr_logon.md | 4 +- docs/cybr_platforms.md | 2 +- docs/cybr_platforms_get.md | 2 +- docs/cybr_platforms_list.md | 2 +- docs/cybr_safes.md | 2 +- docs/cybr_safes_add-member.md | 2 +- docs/cybr_safes_add.md | 2 +- docs/cybr_safes_delete.md | 2 +- docs/cybr_safes_list-members.md | 2 +- docs/cybr_safes_list.md | 2 +- docs/cybr_safes_remove-member.md | 2 +- docs/cybr_safes_update.md | 2 +- docs/cybr_users.md | 2 +- docs/cybr_users_add.md | 2 +- docs/cybr_users_delete.md | 2 +- docs/cybr_users_list.md | 2 +- docs/cybr_users_unsuspend.md | 2 +- docs/cybr_version.md | 2 +- pkg/cybr/api/accounts.go | 22 +- pkg/cybr/api/applications.go | 12 +- pkg/cybr/api/auth.go | 4 +- pkg/cybr/api/client.go | 1 + pkg/cybr/api/platforms.go | 4 +- pkg/cybr/api/safes.go | 14 +- pkg/cybr/api/server.go | 2 +- pkg/cybr/api/users.go | 8 +- pkg/cybr/helpers/httpjson/httpjson.go | 81 +++- pkg/cybr/helpers/prettyprint/prettyprint.go | 29 ++ pkg/cybr/helpers/util/util.go | 45 +++ pkg/cybr/identity/advanceauth.go | 31 ++ pkg/cybr/identity/outofbox.go | 1 + pkg/cybr/identity/requests/advanceauth.go | 9 + pkg/cybr/identity/requests/startauth.go | 8 + pkg/cybr/identity/responses/auth.go | 18 + .../identity/responses/shared/challenge.go | 19 + .../identity/responses/shared/clienthint.go | 9 + pkg/cybr/identity/responses/shared/result.go | 27 ++ pkg/cybr/identity/startauth.go | 31 ++ pkg/cybr/ispss/platformdiscovery.go | 29 ++ pkg/cybr/ispss/responses/platformdiscovery.go | 27 ++ 86 files changed, 772 insertions(+), 178 deletions(-) create mode 100644 pkg/cybr/identity/advanceauth.go create mode 100644 pkg/cybr/identity/outofbox.go create mode 100644 pkg/cybr/identity/requests/advanceauth.go create mode 100644 pkg/cybr/identity/requests/startauth.go create mode 100644 pkg/cybr/identity/responses/auth.go create mode 100644 pkg/cybr/identity/responses/shared/challenge.go create mode 100644 pkg/cybr/identity/responses/shared/clienthint.go create mode 100644 pkg/cybr/identity/responses/shared/result.go create mode 100644 pkg/cybr/identity/startauth.go create mode 100644 pkg/cybr/ispss/platformdiscovery.go create mode 100644 pkg/cybr/ispss/responses/platformdiscovery.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6742ad6..775d6cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: pull_request: branches: - main - - v* push: branches-ignore: - main diff --git a/README.md b/README.md index 7fea61b..cd7b717 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,13 @@ # cybr-cli +![image](https://github.com/infamousjoeg/cybr-cli/assets/1924063/ff018174-2880-46f1-bd24-3262d1276b41) + A "Swiss Army Knife" command-line interface (CLI) for easy human and non-human interaction with CyberArk's suite of products. Current products supported: -* CyberArk Privileged Access Manager (PAM) +* CyberArk Identity Security Platform Shared Services (ISPSS) +* CyberArk Privilege Cloud SaaS +* CyberArk Self-Hosted Privileged Access Manager (PAM) * CyberArk Secrets Manager Central Credential Provider (CCP) * CyberArk Conjur Secrets Manager Enterprise & [Open Source](https://conjur.org) * CyberArk Cloud Entitlements Manager ([Free trial](https://www.cyberark.com/try-buy/cloud-entitlements-manager/)) @@ -21,6 +25,9 @@ Current products supported: - [Install from Source](#install-from-source) - [Usage](#usage) - [Authenticating with authn-iam (AWS IAM Role Authentication)](#authenticating-with-authn-iam-aws-iam-role-authentication) + - [Authenticating to Privilege Cloud via ISPSS (Identity)](#authenticating-to-privilege-cloud-via-ispss-identity) + - [Password Authentication](#password-authentication) + - [MFA Authentication](#mfa-authentication) - [Documentation](#documentation) - [Autocomplete](#autocomplete) - [Example Source Code](#example-source-code) @@ -87,6 +94,39 @@ Once environment variables are set, ensure no .conjurrc or .netrc exists in the Then run any command you wish to run within `cybr conjur`. Use the `--help` flag to see all available commands. +### Authenticating to Privilege Cloud via ISPSS (Identity) + +You will need to know the following information to authenticate to Privilege Cloud via ISPSS: + * `-b, --base-url` - The base URL of CyberArk Cloud (e.g. https://example.cyberark.cloud or https://example.privilegecloud.cyberark.cloud) + * `-u, --username` - The username of the Privilege Cloud user (e.g. joe.garcia@cyberark.cloud.1234) + +#### Password Authentication + +```shell +$ cybr logon -u joe.garcia@cyberark.cloud.1234 -a identity -b https://example.cyberark.cloud ++ Challenge #1 +Enter password: +``` + +After providing the password, if no other challenges are required, the CLI will handle the token exchange and a successful logon will be displayed. + +#### MFA Authentication + +If MFA is required, the CLI will prompt for the challenge method to use out of those available: + +```shell +$ cybr logon -u joe.garcia@cyberark.cloud.1234 -a identity -b https://example.cyberark.cloud ++ Challenge #1 +Enter password: ++ Challenge #2 +1. Email... @joe-garcia.com +2. SMS... XXX-1234 +> 2 +Enter code: 12341234 +``` + +After providing the MFA code, if no other challenges are required, the CLI will handle the token exchange and a successful logon will be displayed. + ### Documentation All commands are documentated [in the docs/ directory](docs/cybr.md). diff --git a/cmd/logon.go b/cmd/logon.go index 5446e99..be43339 100644 --- a/cmd/logon.go +++ b/cmd/logon.go @@ -5,31 +5,116 @@ import ( "log" "os" "strings" - "syscall" pasapi "github.com/infamousjoeg/cybr-cli/pkg/cybr/api" "github.com/infamousjoeg/cybr-cli/pkg/cybr/api/requests" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/prettyprint" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/util" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity" + identityrequests "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/requests" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/responses" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/ispss" + ispssresponses "github.com/infamousjoeg/cybr-cli/pkg/cybr/ispss/responses" "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" ) +// Constants for logon command +const ( + maxAttempts = 10 + identityUnsuccessfulResponse = "Identity returned unsuccessful response." + identityFailedAnswer = "Failed to answer challenge." + bearer = "Bearer " + sessionIDKey = "Session ID:" + mechanismIDKey = "Mechanism ID:" + actionKey = "Action:" + answerKey = "Answer:" + advanceResponseKey = "Advance Authentication Response:" +) + +// Global variables for logon command var ( - // Username to logon PAS REST API using - Username string - // AuthenticationType to be used to logon PAS REST API - AuthenticationType string - // InsecureTLS is a boolean value whether to verify TLS or not - InsecureTLS bool - // BaseURL to send PAS REST API logon request to - BaseURL string - // NonInteractive logon - NonInteractive bool - // Password to logon to the PAS REST API - Password string - // ConcurrentSession allow concurrent sessions - ConcurrentSession bool + Username string // Username to logon PAS REST API + AuthenticationType string // Authentication type for PAS REST API + TenantID string // Tenant ID for Identity authentication + InsecureTLS bool // Boolean to decide whether to verify TLS or not + BaseURL string // Base URL to send PAS REST API logon request + NonInteractive bool // Flag for non-interactive logon + Password string // Password for PAS REST API + ConcurrentSession bool // Flag to allow concurrent sessions + SelectedChallenges []int // Slice of selected challenges for Identity authentication + AnswerChallenge identityrequests.AdvanceAuthentication // Answer challenge struct + StartOobChallenge identityrequests.AdvanceAuthentication // Start Oob challenge struct + AnswerOOBChallenge identityrequests.AdvanceAuthentication // Answer Oob challenge struct + advanceResponse *responses.Authentication // Advance authentication response + platformDiscovery *ispssresponses.PlatformDiscovery // Platform discovery response ) +func logonToPAS(c pasapi.Client, username, password string, nonInteractive, concurrentSession bool) error { + var err error + // Check if non-interactive flag is not provided and password is not empty + if !nonInteractive && password != "" { + return fmt.Errorf("An error occured because --non-interactive must be provided when using --password flag") + } + // If the execution is not non-interactive, ask the user to input password + if !nonInteractive { + password, err = util.ReadPassword() + if err != nil { + return fmt.Errorf("An error occurred trying to read password from Stdin. Exiting") + } + } + // Check if password is empty + if password == "" { + return fmt.Errorf("Provided password is empty") + } + // Create credentials for logon + credentials := requests.Logon{ + Username: username, + Password: password, + ConcurrentSession: concurrentSession, + } + // Logon to the PAS REST API + err = c.Logon(credentials) + if err != nil && !strings.Contains(err.Error(), "ITATS542I") { + return fmt.Errorf("Failed to Logon to the PVWA. %s", err) + } + // Deal with OTPCode here if error contains challenge error code and redo client.Logon() + if err != nil { + // Get OTP code from Stdin + credentials, err = util.ReadOTPcode(credentials) + err = c.Logon(credentials) + if err != nil { + return fmt.Errorf("Failed to respond to challenge. Possible timeout occurred. %s", err) + } + } + // Set client config + err = c.SetConfig() + if err != nil { + return fmt.Errorf("Failed to create configuration file. %s", err) + } + return nil +} + +func startAuthIdentity(c pasapi.Client, username string) (*responses.Authentication, error) { + // Create credentials for logon + startAuth := identityrequests.StartAuthentication{ + User: username, + TenantID: c.TenantID, + Version: "1.0", + } + + // Start authentication + response, err := identity.StartAuthentication(c, startAuth) + if err != nil { + return nil, fmt.Errorf("Failed to start authentication. %s", err) + } + if response.Success != true { + return nil, fmt.Errorf("%s %s", identityUnsuccessfulResponse, *response.Message) + } + + return response, nil +} + +// logonCmd represents the 'logon' command for PAS REST API var logonCmd = &cobra.Command{ Use: "logon", Short: "Logon to PAS REST API", @@ -37,85 +122,215 @@ var logonCmd = &cobra.Command{ Example Usage: $ cybr logon -u $USERNAME -a $AUTH_TYPE -b https://pvwa.example.com + Logon to Privilege Cloud REST API: + $ cybr logon -u $USERNAME -a identity -b https://example.privilegecloud.cyberark.cloud To bypass TLS verification: $ cybr logon -u $USERNAME -a $AUTH_TYPE -b https://pvwa.example.com -i`, Aliases: []string{"login"}, Run: func(cmd *cobra.Command, args []string) { - password := os.Getenv("PAS_PASSWORD") - - if !NonInteractive && Password != "" { - log.Fatalf("An error occured because --non-interactive must be provided when using --password flag") + // Create new client for PAS REST API + c := pasapi.Client{ + BaseURL: BaseURL, + AuthType: AuthenticationType, + InsecureTLS: InsecureTLS, } - if !NonInteractive { - // Get secret value from STDIN - fmt.Print("Enter password: ") - byteSecretVal, err := terminal.ReadPassword(int(syscall.Stdin)) - fmt.Println() + // Check if auth type is "identity" and get TenantID if true + if c.AuthType == "identity" { + platformDiscovery, err := ispss.PlatformDiscovery(c.BaseURL) if err != nil { - log.Fatalln("An error occurred trying to read password from " + - "Stdin. Exiting...") + log.Fatalf("Failed to get platform discovery. %s", err) + } + c.TenantID, err = util.GetSubDomain(platformDiscovery.IdentityUserPortal.API) + c.BaseURL = platformDiscovery.Pcloud.API + if err != nil { + log.Fatalf("Failed to get tenant ID. %s", err) } - password = string(byteSecretVal) } - if Password != "" { - password = Password - } + // Get password from environment variable PAS_PASSWORD + Password := os.Getenv("PAS_PASSWORD") - if password == "" { - log.Fatalf("Provided password is empty") - } + // Handle authentication depending on auth type + if c.AuthType != "identity" { + err := logonToPAS(c, Username, Password, NonInteractive, ConcurrentSession) + if err != nil { + log.Fatalf("%s", err) + } + // Handle Identity authentication + } else { + // Start authentication + startResponse, err := startAuthIdentity(c, Username) + if err != nil { + log.Fatalf("%s", err) + } + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("Start Authentication Response: %+v", startResponse)) + } + if startResponse.Result.Token != "" { + c.SessionToken = fmt.Sprintf("%s %s", bearer, startResponse.Result.Token) + } - client := pasapi.Client{ - BaseURL: BaseURL, - AuthType: AuthenticationType, - InsecureTLS: InsecureTLS, - } + // Loop through challenges until c.SessionToken is set + for attempts := 0; c.SessionToken == "" && attempts < maxAttempts; attempts++ { + loop: + // Print challenge number + prettyprint.PrintColor("yellow", fmt.Sprintf("+ Challenge #%d", attempts+1)) - credentials := requests.Logon{ - Username: Username, - Password: password, - ConcurrentSession: ConcurrentSession, - } + if startResponse.Result.Challenges[0].Mechanisms[0].PromptSelectMech == "Password" && attempts == 0 { + // Get password from Stdin + Password, err = util.ReadPassword() + if err != nil { + log.Fatalf("An error occurred trying to read password from Stdin. Exiting") + } + // Create AdvanceAuthentication struct + AnswerChallenge.SessionID = startResponse.Result.SessionID + AnswerChallenge.MechanismID = startResponse.Result.Challenges[0].Mechanisms[0].MechanismID + AnswerChallenge.Action = "Answer" + AnswerChallenge.Answer = Password - err := client.Logon(credentials) - if err != nil && !strings.Contains(err.Error(), "ITATS542I") { - log.Fatalf("Failed to Logon to the PVWA. %s", err) - } + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", sessionIDKey, AnswerChallenge.SessionID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", mechanismIDKey, AnswerChallenge.MechanismID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", actionKey, AnswerChallenge.Action)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", answerKey, AnswerChallenge.Answer)) + } - // if error contains challenge error code, deal with OTPCode here instead and redo client.Logon() - if err != nil { - // Get secret value from STDIN - fmt.Print("Enter one-time passcode: ") - byteOTPCode, err := terminal.ReadPassword(int(syscall.Stdin)) - credentials.Password = string(byteOTPCode) - fmt.Println() - if err != nil { - log.Fatalln("An error occurred trying to read one-time passcode from " + - "Stdin. Exiting...") + // Answer challenge + advanceResponse, err = identity.AdvanceAuthentication(c, AnswerChallenge) + if err != nil { + log.Fatalf("%s %s", identityFailedAnswer, err) + } + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %+v", advanceResponseKey, advanceResponse)) + } + if advanceResponse.Result.Token != "" { + c.SessionToken = fmt.Sprintf("%s %s", bearer, advanceResponse.Result.Token) + break + } + if !advanceResponse.Success { + log.Fatalf("%s %s", identityUnsuccessfulResponse, *advanceResponse.Message) + } + + attempts++ + goto loop + } + + if advanceResponse.Result.Summary == "StartNextChallenge" { + // Ask for user input for challenges + for i, mechanism := range startResponse.Result.Challenges[1].Mechanisms { + prettyprint.PrintColor("green", fmt.Sprintf("%d. %s", i+1, mechanism.PromptSelectMech)) + } + + // Get user input + fmt.Printf("> ") + var input int + fmt.Scanln(&input) + // Keep asking for input until valid + for input < 1 || input > len(startResponse.Result.Challenges[1].Mechanisms) { + prettyprint.PrintColor("red", fmt.Sprintf("Please enter a valid number between 1 and %d", len(startResponse.Result.Challenges[1].Mechanisms))) + fmt.Scanln(&input) + } + // Add selected challenge to slice + SelectedChallenges = append(SelectedChallenges, input) + + // Print selected challenges' PromptSelectMech + for _, challenge := range SelectedChallenges { + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("Selected: %s", startResponse.Result.Challenges[1].Mechanisms[challenge-1].PromptSelectMech)) + } + selectedMechanismID := startResponse.Result.Challenges[1].Mechanisms[challenge-1].MechanismID + selectedAnswerType := startResponse.Result.Challenges[1].Mechanisms[challenge-1].AnswerType + + if strings.HasPrefix(selectedAnswerType, "Start") && strings.HasSuffix(selectedAnswerType, "Oob") { + StartOobChallenge.SessionID = startResponse.Result.SessionID + StartOobChallenge.MechanismID = selectedMechanismID + StartOobChallenge.Action = "StartOOB" + + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", sessionIDKey, StartOobChallenge.SessionID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", mechanismIDKey, StartOobChallenge.MechanismID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", actionKey, StartOobChallenge.Action)) + } + + // Answer challenge + challengeResponse, err := identity.AdvanceAuthentication(c, StartOobChallenge) + if err != nil { + log.Fatalf("%s %s", identityFailedAnswer, err) + } + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %+v", advanceResponseKey, challengeResponse)) + } + if challengeResponse.Result.Token != "" { + c.SessionToken = fmt.Sprintf("%s %s", bearer, challengeResponse.Result.Token) + break + } + if !challengeResponse.Success { + log.Fatalf("%s %s", identityUnsuccessfulResponse, *advanceResponse.Message) + } + + // Get OTP code from Stdin + fmt.Printf("Enter code: ") + var code string + fmt.Scanln(&code) + + AnswerOOBChallenge.SessionID = startResponse.Result.SessionID + AnswerOOBChallenge.MechanismID = selectedMechanismID + AnswerOOBChallenge.Action = "Answer" + AnswerOOBChallenge.Answer = code + + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", sessionIDKey, AnswerOOBChallenge.SessionID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", mechanismIDKey, AnswerOOBChallenge.MechanismID)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", actionKey, AnswerOOBChallenge.Action)) + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %s", answerKey, AnswerOOBChallenge.Answer)) + } + + // Answer challenge + answerOOBResponse, err := identity.AdvanceAuthentication(c, AnswerOOBChallenge) + if err != nil { + log.Fatalf("%s %s", identityFailedAnswer, err) + } + if Verbose { + prettyprint.PrintColor("cyan", fmt.Sprintf("%s %+v", advanceResponseKey, answerOOBResponse)) + } + if answerOOBResponse.Result.Token != "" { + c.SessionToken = fmt.Sprintf("%s %s", bearer, answerOOBResponse.Result.Token) + break + } + if advanceResponse.Message != nil { + log.Fatalf("%s %s", identityUnsuccessfulResponse, *advanceResponse.Message) + } else { + log.Fatalf("Identity returned unsuccessful response, but the message is unavailable.") + } + } + } + } } - err = client.Logon(credentials) - if err != nil { - log.Fatalf("Failed to respond to challenge. Possible timeout occurred. %s", err) + + // Maximum attempts reached + if c.SessionToken == "" { + log.Fatalf("Failed to get non-empty token after %d attempts. Exiting", maxAttempts) } - } - err = client.SetConfig() - if err != nil { - log.Fatalf("Failed to create configuration file. %s", err) - return + // Set client config + err = c.SetConfig() + if err != nil { + log.Fatalf("Failed to create configuration file. %s", err) + } } - fmt.Printf("Successfully logged onto PAS as user %s.\n", Username) + // Logon success message + prettyprint.PrintColor("green", fmt.Sprintf("Successfully logged onto PAS as user %s.", Username)) }, } +// init function to initialize flags for the 'logon' command func init() { logonCmd.Flags().StringVarP(&Username, "username", "u", "", "Username to logon to PAS REST API") logonCmd.MarkFlagRequired("username") logonCmd.Flags().StringVarP(&AuthenticationType, "auth-type", "a", "", "Authentication method to logon using [cyberark|ldap|radius]") - logonCmd.MarkFlagRequired("authType") + logonCmd.MarkFlagRequired("auth-type") logonCmd.Flags().BoolVarP(&InsecureTLS, "insecure-tls", "i", false, "If detected, TLS will not be verified") logonCmd.Flags().StringVarP(&BaseURL, "base-url", "b", "", "Base URL to send Logon request to [https://pvwa.example.com]") logonCmd.MarkFlagRequired("base-url") @@ -123,5 +338,6 @@ func init() { logonCmd.Flags().StringVarP(&Password, "password", "p", "", "Password to logon to PAS REST API, only supported when using --non-interactive flag") logonCmd.Flags().BoolVar(&ConcurrentSession, "concurrent", false, "If detected, will create a concurrent session to the PAS API") + // Add 'logon' command to root command rootCmd.AddCommand(logonCmd) } diff --git a/docs/cybr.md b/docs/cybr.md index e77a97e..d28797e 100644 --- a/docs/cybr.md +++ b/docs/cybr.md @@ -31,4 +31,4 @@ Security. * [cybr users](cybr_users.md) - User actions for PAS REST API * [cybr version](cybr_version.md) - Display current version -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts.md b/docs/cybr_accounts.md index 1d10e56..0c01d4b 100644 --- a/docs/cybr_accounts.md +++ b/docs/cybr_accounts.md @@ -35,4 +35,4 @@ All account actions that can be taken via PAS REST API. * [cybr accounts reconcile](cybr_accounts_reconcile.md) - Mark an account for reconciliation * [cybr accounts verify](cybr_accounts_verify.md) - Mark an account for verification -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_add.md b/docs/cybr_accounts_add.md index b3ae170..73cce00 100644 --- a/docs/cybr_accounts_add.md +++ b/docs/cybr_accounts_add.md @@ -39,4 +39,4 @@ cybr accounts add [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_change.md b/docs/cybr_accounts_change.md index 6fffc49..6137d00 100644 --- a/docs/cybr_accounts_change.md +++ b/docs/cybr_accounts_change.md @@ -31,4 +31,4 @@ cybr accounts change [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_delete.md b/docs/cybr_accounts_delete.md index f111b93..fd7d4a1 100644 --- a/docs/cybr_accounts_delete.md +++ b/docs/cybr_accounts_delete.md @@ -30,4 +30,4 @@ cybr accounts delete [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_get-password.md b/docs/cybr_accounts_get-password.md index 8ae0cc9..817ec0d 100644 --- a/docs/cybr_accounts_get-password.md +++ b/docs/cybr_accounts_get-password.md @@ -34,4 +34,4 @@ cybr accounts get-password [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_get.md b/docs/cybr_accounts_get.md index 72fd390..bc4e631 100644 --- a/docs/cybr_accounts_get.md +++ b/docs/cybr_accounts_get.md @@ -30,4 +30,4 @@ cybr accounts get [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_list.md b/docs/cybr_accounts_list.md index 3277004..a7b25e1 100644 --- a/docs/cybr_accounts_list.md +++ b/docs/cybr_accounts_list.md @@ -35,4 +35,4 @@ cybr accounts list [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_move.md b/docs/cybr_accounts_move.md index 214a056..a5a992c 100644 --- a/docs/cybr_accounts_move.md +++ b/docs/cybr_accounts_move.md @@ -31,4 +31,4 @@ cybr accounts move [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_reconcile.md b/docs/cybr_accounts_reconcile.md index 83d5a96..e3b78cb 100644 --- a/docs/cybr_accounts_reconcile.md +++ b/docs/cybr_accounts_reconcile.md @@ -30,4 +30,4 @@ cybr accounts reconcile [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_accounts_verify.md b/docs/cybr_accounts_verify.md index e33198e..4cc41c7 100644 --- a/docs/cybr_accounts_verify.md +++ b/docs/cybr_accounts_verify.md @@ -30,4 +30,4 @@ cybr accounts verify [flags] * [cybr accounts](cybr_accounts.md) - Account actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications.md b/docs/cybr_applications.md index 88c2b1e..2341af5 100644 --- a/docs/cybr_applications.md +++ b/docs/cybr_applications.md @@ -33,4 +33,4 @@ All applications actions that can be taken via PAS REST API. * [cybr applications list](cybr_applications_list.md) - List all applications * [cybr applications list-authn](cybr_applications_list-authn.md) - List all authn methods on a specific application -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_add-authn.md b/docs/cybr_applications_add-authn.md index 2054d8c..cbfeadd 100644 --- a/docs/cybr_applications_add-authn.md +++ b/docs/cybr_applications_add-authn.md @@ -34,4 +34,4 @@ cybr applications add-authn [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_add.md b/docs/cybr_applications_add.md index 98d8260..f3d5697 100644 --- a/docs/cybr_applications_add.md +++ b/docs/cybr_applications_add.md @@ -40,4 +40,4 @@ cybr applications add [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_delete-authn.md b/docs/cybr_applications_delete-authn.md index 87ba615..96198ed 100644 --- a/docs/cybr_applications_delete-authn.md +++ b/docs/cybr_applications_delete-authn.md @@ -31,4 +31,4 @@ cybr applications delete-authn [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_delete.md b/docs/cybr_applications_delete.md index 3878323..409b7b2 100644 --- a/docs/cybr_applications_delete.md +++ b/docs/cybr_applications_delete.md @@ -30,4 +30,4 @@ cybr applications delete [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_list-authn.md b/docs/cybr_applications_list-authn.md index 2bf4d9c..0bd873b 100644 --- a/docs/cybr_applications_list-authn.md +++ b/docs/cybr_applications_list-authn.md @@ -31,4 +31,4 @@ cybr applications list-authn [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_applications_list.md b/docs/cybr_applications_list.md index b6c3bcf..ba9d2d2 100644 --- a/docs/cybr_applications_list.md +++ b/docs/cybr_applications_list.md @@ -30,4 +30,4 @@ cybr applications list [flags] * [cybr applications](cybr_applications.md) - Applications actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_ccp.md b/docs/cybr_ccp.md index 8609fb2..b84970c 100644 --- a/docs/cybr_ccp.md +++ b/docs/cybr_ccp.md @@ -26,4 +26,4 @@ All actions that can be performed with the Central Credential Provider. * [cybr](cybr.md) - cybr is CyberArk's PAS command-line interface utility * [cybr ccp get-account](cybr_ccp_get-account.md) - Get account from CCP -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_ccp_get-account.md b/docs/cybr_ccp_get-account.md index b94845f..f303136 100644 --- a/docs/cybr_ccp_get-account.md +++ b/docs/cybr_ccp_get-account.md @@ -47,4 +47,4 @@ cybr ccp get-account [flags] * [cybr ccp](cybr_ccp.md) - CCP actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem.md b/docs/cybr_cem.md index 6c152d5..7907d0e 100644 --- a/docs/cybr_cem.md +++ b/docs/cybr_cem.md @@ -32,4 +32,4 @@ All actions that can be performed with the Cloud Entitlements Manager. * [cybr cem recommendations](cybr_cem_recommendations.md) - Get Entity Recommendations * [cybr cem remediations](cybr_cem_remediations.md) - Get Entity Remediations -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_accounts.md b/docs/cybr_cem_accounts.md index 58a9274..32d9a46 100644 --- a/docs/cybr_cem_accounts.md +++ b/docs/cybr_cem_accounts.md @@ -29,4 +29,4 @@ cybr cem accounts [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_entities.md b/docs/cybr_cem_entities.md index bca1981..b99f95a 100644 --- a/docs/cybr_cem_entities.md +++ b/docs/cybr_cem_entities.md @@ -36,4 +36,4 @@ cybr cem entities [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_entity-details.md b/docs/cybr_cem_entity-details.md index fb6557c..6370d68 100644 --- a/docs/cybr_cem_entity-details.md +++ b/docs/cybr_cem_entity-details.md @@ -32,4 +32,4 @@ cybr cem entity-details [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_logon.md b/docs/cybr_cem_logon.md index 9d5b13d..e12db7d 100644 --- a/docs/cybr_cem_logon.md +++ b/docs/cybr_cem_logon.md @@ -35,4 +35,4 @@ cybr cem logon [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_recommendations.md b/docs/cybr_cem_recommendations.md index 03a479b..b11a5b7 100644 --- a/docs/cybr_cem_recommendations.md +++ b/docs/cybr_cem_recommendations.md @@ -32,4 +32,4 @@ cybr cem recommendations [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_cem_remediations.md b/docs/cybr_cem_remediations.md index 19b16c4..9c5b23e 100644 --- a/docs/cybr_cem_remediations.md +++ b/docs/cybr_cem_remediations.md @@ -32,4 +32,4 @@ cybr cem remediations [flags] * [cybr cem](cybr_cem.md) - CEM actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_completion.md b/docs/cybr_completion.md index 7f556f1..aa286ba 100644 --- a/docs/cybr_completion.md +++ b/docs/cybr_completion.md @@ -64,4 +64,4 @@ cybr completion [bash|zsh|fish|powershell] * [cybr](cybr.md) - cybr is CyberArk's PAS command-line interface utility -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur.md b/docs/cybr_conjur.md index ac24418..7e5e3cd 100644 --- a/docs/cybr_conjur.md +++ b/docs/cybr_conjur.md @@ -35,4 +35,4 @@ Perform actions on conjur * [cybr conjur update-policy](cybr_conjur_update-policy.md) - Update policy to conjur * [cybr conjur whoami](cybr_conjur_whoami.md) - Get current user info logged into Conjur -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_append-policy.md b/docs/cybr_conjur_append-policy.md index 7f49cf1..a2ebc25 100644 --- a/docs/cybr_conjur_append-policy.md +++ b/docs/cybr_conjur_append-policy.md @@ -32,4 +32,4 @@ cybr conjur append-policy [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_enable-authn.md b/docs/cybr_conjur_enable-authn.md index 723a13e..d0afb64 100644 --- a/docs/cybr_conjur_enable-authn.md +++ b/docs/cybr_conjur_enable-authn.md @@ -30,4 +30,4 @@ cybr conjur enable-authn [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_get-secret.md b/docs/cybr_conjur_get-secret.md index 5a71981..8ff405c 100644 --- a/docs/cybr_conjur_get-secret.md +++ b/docs/cybr_conjur_get-secret.md @@ -33,4 +33,4 @@ cybr conjur get-secret [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_info.md b/docs/cybr_conjur_info.md index 680bf01..c32deec 100644 --- a/docs/cybr_conjur_info.md +++ b/docs/cybr_conjur_info.md @@ -29,4 +29,4 @@ cybr conjur info [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_list.md b/docs/cybr_conjur_list.md index 35a6338..59eccae 100644 --- a/docs/cybr_conjur_list.md +++ b/docs/cybr_conjur_list.md @@ -34,4 +34,4 @@ cybr conjur list [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_logoff.md b/docs/cybr_conjur_logoff.md index aa5f30c..d2110f1 100644 --- a/docs/cybr_conjur_logoff.md +++ b/docs/cybr_conjur_logoff.md @@ -29,4 +29,4 @@ cybr conjur logoff [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_logon-non-interactive.md b/docs/cybr_conjur_logon-non-interactive.md index 237a45b..14b2d5a 100644 --- a/docs/cybr_conjur_logon-non-interactive.md +++ b/docs/cybr_conjur_logon-non-interactive.md @@ -29,4 +29,4 @@ cybr conjur logon-non-interactive [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_logon.md b/docs/cybr_conjur_logon.md index 3c321df..56cd4d0 100644 --- a/docs/cybr_conjur_logon.md +++ b/docs/cybr_conjur_logon.md @@ -36,4 +36,4 @@ cybr conjur logon [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_replace-policy.md b/docs/cybr_conjur_replace-policy.md index 807fc33..6ebca15 100644 --- a/docs/cybr_conjur_replace-policy.md +++ b/docs/cybr_conjur_replace-policy.md @@ -32,4 +32,4 @@ cybr conjur replace-policy [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_rotate-api-key.md b/docs/cybr_conjur_rotate-api-key.md index 60d8aba..ea7a0b3 100644 --- a/docs/cybr_conjur_rotate-api-key.md +++ b/docs/cybr_conjur_rotate-api-key.md @@ -34,4 +34,4 @@ cybr conjur rotate-api-key [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_set-secret.md b/docs/cybr_conjur_set-secret.md index 16e9967..1a6378e 100644 --- a/docs/cybr_conjur_set-secret.md +++ b/docs/cybr_conjur_set-secret.md @@ -31,4 +31,4 @@ cybr conjur set-secret [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_update-policy.md b/docs/cybr_conjur_update-policy.md index 72327ab..918b683 100644 --- a/docs/cybr_conjur_update-policy.md +++ b/docs/cybr_conjur_update-policy.md @@ -32,4 +32,4 @@ cybr conjur update-policy [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_conjur_whoami.md b/docs/cybr_conjur_whoami.md index 3f8dec8..2678163 100644 --- a/docs/cybr_conjur_whoami.md +++ b/docs/cybr_conjur_whoami.md @@ -29,4 +29,4 @@ cybr conjur whoami [flags] * [cybr conjur](cybr_conjur.md) - Conjur actions -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_logoff.md b/docs/cybr_logoff.md index e4c8888..2100375 100644 --- a/docs/cybr_logoff.md +++ b/docs/cybr_logoff.md @@ -29,4 +29,4 @@ cybr logoff [flags] * [cybr](cybr.md) - cybr is CyberArk's PAS command-line interface utility -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_logon.md b/docs/cybr_logon.md index 523a450..8d1cfc7 100644 --- a/docs/cybr_logon.md +++ b/docs/cybr_logon.md @@ -8,6 +8,8 @@ Authenticate to PAS REST API using the provided authentication type. Example Usage: $ cybr logon -u $USERNAME -a $AUTH_TYPE -b https://pvwa.example.com + Logon to Privilege Cloud REST API: + $ cybr logon -u $USERNAME -a identity -b https://example.privilegecloud.cyberark.cloud To bypass TLS verification: $ cybr logon -u $USERNAME -a $AUTH_TYPE -b https://pvwa.example.com -i @@ -38,4 +40,4 @@ cybr logon [flags] * [cybr](cybr.md) - cybr is CyberArk's PAS command-line interface utility -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_platforms.md b/docs/cybr_platforms.md index 6afb44a..50045ac 100644 --- a/docs/cybr_platforms.md +++ b/docs/cybr_platforms.md @@ -28,4 +28,4 @@ All platform actions that can be taken via PAS REST API. * [cybr platforms get](cybr_platforms_get.md) - Get a specific platform * [cybr platforms list](cybr_platforms_list.md) - List all platforms -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_platforms_get.md b/docs/cybr_platforms_get.md index aa841de..b421c1f 100644 --- a/docs/cybr_platforms_get.md +++ b/docs/cybr_platforms_get.md @@ -30,4 +30,4 @@ cybr platforms get [flags] * [cybr platforms](cybr_platforms.md) - Platform actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_platforms_list.md b/docs/cybr_platforms_list.md index 3001904..c52dcf9 100644 --- a/docs/cybr_platforms_list.md +++ b/docs/cybr_platforms_list.md @@ -32,4 +32,4 @@ cybr platforms list [flags] * [cybr platforms](cybr_platforms.md) - Platform actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes.md b/docs/cybr_safes.md index 26b0d25..c416f0d 100644 --- a/docs/cybr_safes.md +++ b/docs/cybr_safes.md @@ -36,4 +36,4 @@ All safe actions that can be taken via PAS REST API. * [cybr safes remove-member](cybr_safes_remove-member.md) - Remove a member from a safe * [cybr safes update](cybr_safes_update.md) - Update a safe -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_add-member.md b/docs/cybr_safes_add-member.md index cca49de..90f8b5d 100644 --- a/docs/cybr_safes_add-member.md +++ b/docs/cybr_safes_add-member.md @@ -75,4 +75,4 @@ cybr safes add-member [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_add.md b/docs/cybr_safes_add.md index c9e6f93..60971b3 100644 --- a/docs/cybr_safes_add.md +++ b/docs/cybr_safes_add.md @@ -37,4 +37,4 @@ cybr safes add [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_delete.md b/docs/cybr_safes_delete.md index b562ec2..8f13454 100644 --- a/docs/cybr_safes_delete.md +++ b/docs/cybr_safes_delete.md @@ -32,4 +32,4 @@ cybr safes delete [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_list-members.md b/docs/cybr_safes_list-members.md index ef228bd..79909e8 100644 --- a/docs/cybr_safes_list-members.md +++ b/docs/cybr_safes_list-members.md @@ -38,4 +38,4 @@ cybr safes list-members [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_list.md b/docs/cybr_safes_list.md index 35d6fa4..c8b2989 100644 --- a/docs/cybr_safes_list.md +++ b/docs/cybr_safes_list.md @@ -33,4 +33,4 @@ cybr safes list [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_remove-member.md b/docs/cybr_safes_remove-member.md index 600f12f..6c7dfe5 100644 --- a/docs/cybr_safes_remove-member.md +++ b/docs/cybr_safes_remove-member.md @@ -32,4 +32,4 @@ cybr safes remove-member [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_safes_update.md b/docs/cybr_safes_update.md index 939d172..2e63436 100644 --- a/docs/cybr_safes_update.md +++ b/docs/cybr_safes_update.md @@ -34,4 +34,4 @@ cybr safes update [flags] * [cybr safes](cybr_safes.md) - Safe actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_users.md b/docs/cybr_users.md index 39ad5a3..541ef6a 100644 --- a/docs/cybr_users.md +++ b/docs/cybr_users.md @@ -29,4 +29,4 @@ All users actions that can be taken via PAS REST API. * [cybr users list](cybr_users_list.md) - List cyberark PAS users * [cybr users unsuspend](cybr_users_unsuspend.md) - Unsuspend a specific user -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_users_add.md b/docs/cybr_users_add.md index f33ef17..29902c2 100644 --- a/docs/cybr_users_add.md +++ b/docs/cybr_users_add.md @@ -59,4 +59,4 @@ cybr users add [flags] * [cybr users](cybr_users.md) - User actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_users_delete.md b/docs/cybr_users_delete.md index c08d28c..5710538 100644 --- a/docs/cybr_users_delete.md +++ b/docs/cybr_users_delete.md @@ -30,4 +30,4 @@ cybr users delete [flags] * [cybr users](cybr_users.md) - User actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_users_list.md b/docs/cybr_users_list.md index 431f0c4..9d2e30b 100644 --- a/docs/cybr_users_list.md +++ b/docs/cybr_users_list.md @@ -31,4 +31,4 @@ cybr users list [flags] * [cybr users](cybr_users.md) - User actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_users_unsuspend.md b/docs/cybr_users_unsuspend.md index 760fe92..8730fef 100644 --- a/docs/cybr_users_unsuspend.md +++ b/docs/cybr_users_unsuspend.md @@ -30,4 +30,4 @@ cybr users unsuspend [flags] * [cybr users](cybr_users.md) - User actions for PAS REST API -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/docs/cybr_version.md b/docs/cybr_version.md index 54d9178..aa0f309 100644 --- a/docs/cybr_version.md +++ b/docs/cybr_version.md @@ -29,4 +29,4 @@ cybr version [flags] * [cybr](cybr.md) - cybr is CyberArk's PAS command-line interface utility -###### Auto generated by spf13/cobra on 20-Jan-2023 +###### Auto generated by spf13/cobra on 14-Aug-2023 diff --git a/pkg/cybr/api/accounts.go b/pkg/cybr/api/accounts.go index a1fde50..f4f7b41 100644 --- a/pkg/cybr/api/accounts.go +++ b/pkg/cybr/api/accounts.go @@ -14,7 +14,7 @@ import ( // ListAccounts CyberArk user has access to func (c Client) ListAccounts(query *queries.ListAccounts) (*responses.ListAccount, error) { url := fmt.Sprintf("%s/passwordvault/api/Accounts%s", c.BaseURL, httpJson.GetURLQuery(query)) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListAccount{}, fmt.Errorf("Failed to list accounts. %s", err) } @@ -28,7 +28,7 @@ func (c Client) ListAccounts(query *queries.ListAccounts) (*responses.ListAccoun // GetAccount details for specific account func (c Client) GetAccount(accountID string) (*responses.GetAccount, error) { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s", c.BaseURL, accountID) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.GetAccount{}, fmt.Errorf("Failed to get account. %s", err) } @@ -43,7 +43,7 @@ func (c Client) GetAccount(accountID string) (*responses.GetAccount, error) { func (c Client) AddAccount(account requests.AddAccount) (*responses.GetAccount, error) { url := fmt.Sprintf("%s/passwordvault/api/Accounts", c.BaseURL) logger := c.GetLogger().AddSecret(account.Secret) - response, err := httpJson.Post(url, c.SessionToken, account, c.InsecureTLS, logger) + response, err := httpJson.Post(false, url, c.SessionToken, account, c.InsecureTLS, logger) logger = logger.ClearSecrets() if err != nil { @@ -60,7 +60,7 @@ func (c Client) AddAccount(account requests.AddAccount) (*responses.GetAccount, // DeleteAccount from cyberark func (c Client) DeleteAccount(accountID string) error { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s", c.BaseURL, accountID) - response, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to delete account '%s'. %s. %s", accountID, string(returnedError), err) @@ -72,7 +72,7 @@ func (c Client) DeleteAccount(accountID string) error { // GetJITAccess from a specific account func (c Client) GetJITAccess(accountID string) error { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s/grantAdministrativeAccess", c.BaseURL, accountID) - response, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to get JIT access for account '%s'. %s. %s", accountID, string(returnedError), err) @@ -84,7 +84,7 @@ func (c Client) GetJITAccess(accountID string) error { // RevokeJITAccess from a specific account func (c Client) RevokeJITAccess(accountID string) error { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s/RevokeAdministrativeAccess", c.BaseURL, accountID) - response, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to revoke JIT access for account '%s'. %s. %s", accountID, string(returnedError), err) @@ -97,7 +97,7 @@ func (c Client) RevokeJITAccess(accountID string) error { func (c Client) GetAccountPassword(accountID string, request requests.GetAccountPassword) (string, error) { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s/Password/Retrieve", c.BaseURL, accountID) - response, err := httpJson.SendRequestRaw(url, "POST", c.SessionToken, request, c.InsecureTLS, c.Logger) + response, err := httpJson.SendRequestRaw(false, url, "POST", c.SessionToken, request, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return "", fmt.Errorf("Failed to retrieve the account password '%s'. %s. %s", accountID, string(returnedError), err) @@ -110,7 +110,7 @@ func (c Client) GetAccountPassword(accountID string, request requests.GetAccount func (c Client) GetAccountSSHKey(accountID string, request requests.GetAccountPassword) (string, error) { url := fmt.Sprintf("%s/passwordvault/api/Accounts/%s/Secret/Retrieve", c.BaseURL, accountID) - response, err := httpJson.SendRequestRaw(url, "POST", c.SessionToken, request, c.InsecureTLS, c.Logger) + response, err := httpJson.SendRequestRaw(false, url, "POST", c.SessionToken, request, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return "", fmt.Errorf("Failed to retrieve the account SSH Key '%s'. %s. %s", accountID, string(returnedError), err) @@ -122,7 +122,7 @@ func (c Client) GetAccountSSHKey(accountID string, request requests.GetAccountPa // VerifyAccountCredentials marks an account for verification func (c Client) VerifyAccountCredentials(accountID string) error { url := fmt.Sprintf("%s/passwordvault/API/Accounts/%s/Verify", c.BaseURL, accountID) - response, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to verify account '%s'. %s. %s", accountID, string(returnedError), err) @@ -137,7 +137,7 @@ func (c Client) ChangeAccountCredentials(accountID string, changeEntireGroup boo body := requests.ChangeAccountCredential{ ChangeEntireGroup: changeEntireGroup, } - response, err := httpJson.Post(url, c.SessionToken, body, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, body, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to mark change on account '%s'. %s. %s", accountID, string(returnedError), err) @@ -149,7 +149,7 @@ func (c Client) ChangeAccountCredentials(accountID string, changeEntireGroup boo // ReconileAccountCredentials marks an account for reconciliation func (c Client) ReconileAccountCredentials(accountID string) error { url := fmt.Sprintf("%s/passwordvault/API/Accounts/%s/Reconcile", c.BaseURL, accountID) - response, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to mark reconcile on account '%s'. %s. %s", accountID, string(returnedError), err) diff --git a/pkg/cybr/api/applications.go b/pkg/cybr/api/applications.go index 6eda5a2..d3e9b3a 100644 --- a/pkg/cybr/api/applications.go +++ b/pkg/cybr/api/applications.go @@ -13,7 +13,7 @@ import ( // ListApplications returns all Application Identities setup in PAS func (c Client) ListApplications(location string) (*responses.ListApplications, error) { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications?Location=%s", c.BaseURL, location) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListApplications{}, fmt.Errorf("Error listing applications in location '%s'. %s", location, err) } @@ -26,7 +26,7 @@ func (c Client) ListApplications(location string) (*responses.ListApplications, // ListApplicationAuthenticationMethods returns all auth methods for a specific Application Identity func (c Client) ListApplicationAuthenticationMethods(appID string) (*responses.ListApplicationAuthenticationMethods, error) { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications/%s/Authentications", c.BaseURL, appID) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListApplicationAuthenticationMethods{}, fmt.Errorf("Error listing application's '%s' authentication methods. %s", appID, err) } @@ -39,7 +39,7 @@ func (c Client) ListApplicationAuthenticationMethods(appID string) (*responses.L // AddApplication add an applications to PAS func (c Client) AddApplication(application requests.AddApplication) error { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications", c.BaseURL) - response, err := httpJson.Post(url, c.SessionToken, application, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, application, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Error adding application '%s' authentication methods. %s. %s", application.Application.AppID, string(returnedError), err) @@ -50,7 +50,7 @@ func (c Client) AddApplication(application requests.AddApplication) error { // DeleteApplication delete an applications to PAS func (c Client) DeleteApplication(appID string) error { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications/%s", c.BaseURL, url.QueryEscape(appID)) - response, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Error deleting application '%s' authentication methods. %s. %s", appID, string(returnedError), err) @@ -61,7 +61,7 @@ func (c Client) DeleteApplication(appID string) error { // AddApplicationAuthenticationMethod add authentication method to an application func (c Client) AddApplicationAuthenticationMethod(appID string, authenticationMethod requests.AddApplicationAuthentication) error { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications/%s/Authentications/", c.BaseURL, url.QueryEscape(appID)) - response, err := httpJson.Post(url, c.SessionToken, authenticationMethod, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, authenticationMethod, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Error adding application authentication method to '%s'. %s. %s", appID, string(returnedError), err) @@ -72,7 +72,7 @@ func (c Client) AddApplicationAuthenticationMethod(appID string, authenticationM // DeleteApplicationAuthenticationMethod delete an applications authentication method func (c Client) DeleteApplicationAuthenticationMethod(appID string, authnMethodID string) error { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Applications/%s/Authentications/%s", c.BaseURL, url.QueryEscape(appID), url.QueryEscape(authnMethodID)) - response, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Error deleting application '%s' authentication methods. %s. %s", appID, string(returnedError), err) diff --git a/pkg/cybr/api/auth.go b/pkg/cybr/api/auth.go index b839d0d..654413f 100644 --- a/pkg/cybr/api/auth.go +++ b/pkg/cybr/api/auth.go @@ -19,7 +19,7 @@ func (c *Client) Logon(req requests.Logon) error { // Handle cyberark, ldap, and radius push, append & challenge/response authentication methods url := fmt.Sprintf("%s/passwordvault/api/auth/%s/logon", c.BaseURL, c.AuthType) - token, err := httpJson.SendRequestRaw(url, "POST", "", req, c.InsecureTLS, c.Logger) + token, err := httpJson.SendRequestRaw(false, url, "POST", "", req, c.InsecureTLS, c.Logger) if err != nil { return fmt.Errorf("Failed to authenticate to the PAS REST API. %s", err) } @@ -32,7 +32,7 @@ func (c *Client) Logon(req requests.Logon) error { func (c Client) Logoff() error { // Set URL for request url := fmt.Sprintf("%s/passwordvault/api/auth/logoff", c.BaseURL) - _, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + _, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { return fmt.Errorf("Unable to logoff PAS REST API Web Service. %s", err) } diff --git a/pkg/cybr/api/client.go b/pkg/cybr/api/client.go index 285d688..94b8060 100644 --- a/pkg/cybr/api/client.go +++ b/pkg/cybr/api/client.go @@ -13,6 +13,7 @@ import ( type Client struct { BaseURL string AuthType string + TenantID string InsecureTLS bool SessionToken string Logger logger.Logger diff --git a/pkg/cybr/api/platforms.go b/pkg/cybr/api/platforms.go index 42f3151..07a3384 100644 --- a/pkg/cybr/api/platforms.go +++ b/pkg/cybr/api/platforms.go @@ -12,7 +12,7 @@ import ( // ListPlatforms available in CyberArk func (c Client) ListPlatforms(query *queries.ListPlatforms) (*responses.ListPlatforms, error) { url := fmt.Sprintf("%s/passwordvault/api/platforms%s", c.BaseURL, httpJson.GetURLQuery(query)) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListPlatforms{}, fmt.Errorf("Failed to list platforms. %s", err) } @@ -25,7 +25,7 @@ func (c Client) ListPlatforms(query *queries.ListPlatforms) (*responses.ListPlat // GetPlatform details for specific platform func (c Client) GetPlatform(platformID string) (*responses.GetPlatform, error) { url := fmt.Sprintf("%s/passwordvault/api/platforms/%s", c.BaseURL, platformID) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.GetPlatform{}, fmt.Errorf("Failed to get platform. %s", err) } diff --git a/pkg/cybr/api/safes.go b/pkg/cybr/api/safes.go index 569cde9..3be21b5 100644 --- a/pkg/cybr/api/safes.go +++ b/pkg/cybr/api/safes.go @@ -14,7 +14,7 @@ import ( // ListSafes CyberArk user has access to func (c Client) ListSafes() (*responses.ListSafes, error) { url := fmt.Sprintf("%s/passwordvault/api/safes", c.BaseURL) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListSafes{}, fmt.Errorf("Failed to list safes. %s", err) } @@ -27,7 +27,7 @@ func (c Client) ListSafes() (*responses.ListSafes, error) { // ListSafeMembers List all members of a safe func (c Client) ListSafeMembers(safeName string, query *queries.ListSafeMembers) (*responses.ListSafeMembers, error) { url := fmt.Sprintf("%s/passwordvault/api/Safes/%s/Members%s", c.BaseURL, url.QueryEscape(safeName), httpJson.GetURLQuery(query)) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return &responses.ListSafeMembers{}, fmt.Errorf("Failed to list members of safe '%s'. %s", safeName, err) } @@ -40,7 +40,7 @@ func (c Client) ListSafeMembers(safeName string, query *queries.ListSafeMembers) // AddSafeMember Add a user or application as a member to a safe with specific permissions func (c Client) AddSafeMember(safeName string, addMember requests.AddSafeMember) error { url := fmt.Sprintf("%s/passwordvault/api/safes/%s/members", c.BaseURL, url.QueryEscape(safeName)) - response, err := httpJson.Post(url, c.SessionToken, addMember, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, addMember, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to add member '%s' to safe '%s'. %s. %s", addMember.MemberName, safeName, string(returnedError), err) @@ -51,7 +51,7 @@ func (c Client) AddSafeMember(safeName string, addMember requests.AddSafeMember) // RemoveSafeMember Remove a member from a specific safe func (c Client) RemoveSafeMember(safeName string, member string) error { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Safes/%s/Members/%s", c.BaseURL, url.QueryEscape(safeName), url.QueryEscape(member)) - response, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to remove member '%s' from safe '%s'. %s. %s", member, safeName, string(returnedError), err) @@ -63,7 +63,7 @@ func (c Client) RemoveSafeMember(safeName string, member string) error { func (c Client) AddSafe(body requests.AddSafe) error { // Set URL for request url := fmt.Sprintf("%s/passwordvault/api/safes", c.BaseURL) - _, err := httpJson.Post(url, c.SessionToken, body, c.InsecureTLS, c.Logger) + _, err := httpJson.Post(false, url, c.SessionToken, body, c.InsecureTLS, c.Logger) if err != nil { return fmt.Errorf("Unable to add the safe named %s. %s", body.SafeName, err) } @@ -74,7 +74,7 @@ func (c Client) AddSafe(body requests.AddSafe) error { func (c Client) DeleteSafe(safeName string) error { // Set URL for request url := fmt.Sprintf("%s/passwordvault/api/safes/%s", c.BaseURL, url.QueryEscape(safeName)) - _, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + _, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { return fmt.Errorf("Unable to delete the safe named %s. %s", safeName, err) } @@ -85,7 +85,7 @@ func (c Client) DeleteSafe(safeName string) error { func (c Client) UpdateSafe(targetSafeName string, body requests.UpdateSafe) (*responses.UpdateSafe, error) { // Set URL for request url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Safes/%s", c.BaseURL, targetSafeName) - response, err := httpJson.Put(url, c.SessionToken, body, c.InsecureTLS, c.Logger) + response, err := httpJson.Put(false, url, c.SessionToken, body, c.InsecureTLS, c.Logger) if err != nil { return nil, fmt.Errorf("Unable to update the safe named %s. %s", targetSafeName, err) } diff --git a/pkg/cybr/api/server.go b/pkg/cybr/api/server.go index 87873ba..5740dec 100644 --- a/pkg/cybr/api/server.go +++ b/pkg/cybr/api/server.go @@ -11,7 +11,7 @@ import ( // ServerVerify is an unauthenticated endpoint for testing Web Service availability func (c Client) ServerVerify() (*responses.ServerVerify, error) { url := fmt.Sprintf("%s/passwordvault/WebServices/PIMServices.svc/Verify", c.BaseURL) - response, err := httpJson.SendRequest(url, "GET", "", nil, c.InsecureTLS, c.Logger) + response, err := httpJson.SendRequest(false, url, "GET", "", nil, c.InsecureTLS, c.Logger) if err != nil { return &responses.ServerVerify{}, fmt.Errorf("Error verifying PAS REST API Web Service. %s", err) } diff --git a/pkg/cybr/api/users.go b/pkg/cybr/api/users.go index f96e41f..63a1073 100644 --- a/pkg/cybr/api/users.go +++ b/pkg/cybr/api/users.go @@ -14,7 +14,7 @@ import ( func (c Client) UnsuspendUser(userID int) error { url := fmt.Sprintf("%s/passwordvault/api/Users/%d/activate", c.BaseURL, userID) - response, err := httpJson.Post(url, c.SessionToken, nil, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, nil, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to unsuspend user with id '%d'. %s. %s", userID, string(returnedError), err) @@ -26,7 +26,7 @@ func (c Client) UnsuspendUser(userID int) error { func (c Client) ListUsers(query *queries.ListUsers) (responses.ListUsers, error) { url := fmt.Sprintf("%s/passwordvault/api/Users%s", c.BaseURL, httpJson.GetURLQuery(query)) - response, err := httpJson.Get(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Get(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return responses.ListUsers{}, fmt.Errorf("Failed to list users. %s. %s", string(returnedError), err) @@ -42,7 +42,7 @@ func (c Client) ListUsers(query *queries.ListUsers) (responses.ListUsers, error) func (c Client) DeleteUser(userID int) error { url := fmt.Sprintf("%s/passwordvault/api/Users/%d", c.BaseURL, userID) - response, err := httpJson.Delete(url, c.SessionToken, c.InsecureTLS, c.Logger) + response, err := httpJson.Delete(false, url, c.SessionToken, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return fmt.Errorf("Failed to delete user '%d'. %s. %s", userID, string(returnedError), err) @@ -55,7 +55,7 @@ func (c Client) DeleteUser(userID int) error { func (c Client) AddUser(user requests.AddUser) (responses.AddUser, error) { url := fmt.Sprintf("%s/passwordvault/api/Users", c.BaseURL) - response, err := httpJson.Post(url, c.SessionToken, user, c.InsecureTLS, c.Logger) + response, err := httpJson.Post(false, url, c.SessionToken, user, c.InsecureTLS, c.Logger) if err != nil { returnedError, _ := json.Marshal(response) return responses.AddUser{}, fmt.Errorf("Failed to add user '%s'. %s. %s", user.Username, string(returnedError), err) diff --git a/pkg/cybr/helpers/httpjson/httpjson.go b/pkg/cybr/helpers/httpjson/httpjson.go index b30584a..376e453 100644 --- a/pkg/cybr/helpers/httpjson/httpjson.go +++ b/pkg/cybr/helpers/httpjson/httpjson.go @@ -56,7 +56,7 @@ func logRequest(req *http.Request, logger logger.Logger) { req.Body = ioutil.NopCloser(bytes.NewReader([]byte(body))) } -func getResponse(url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (http.Response, error) { +func getResponse(identity bool, url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (http.Response, error) { if insecureTLS { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} } else { @@ -84,9 +84,16 @@ func getResponse(url string, method string, token string, body interface{}, inse // attach the header req.Header = make(http.Header) req.Header.Add("Content-Type", "application/json") + if identity { + req.Header.Add("X-IDAP-NATIVE-CLIENT", "true") + } // if token is provided, add header Authorization if token != "" { - req.Header.Add("Authorization", token) + if identity { + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) + } else { + req.Header.Add("Authorization", token) + } } logRequest(req, logger) @@ -104,8 +111,8 @@ func getResponse(url string, method string, token string, body interface{}, inse } // SendRequest is an http request and get response as serialized json map[string]interface{} -func SendRequest(url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { - res, err := getResponse(url, method, token, body, insecureTLS, logger) +func SendRequest(identity bool, url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { + res, err := getResponse(identity, url, method, token, body, insecureTLS, logger) if err != nil && strings.Contains(err.Error(), "Failed to send request") { return nil, err @@ -132,8 +139,8 @@ func SendRequest(url string, method string, token string, body interface{}, inse } // SendRequestRaw is an http request and get response as byte[] -func SendRequestRaw(url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) ([]byte, error) { - res, err := getResponse(url, method, token, body, insecureTLS, logger) +func SendRequestRaw(identity bool, url string, method string, token string, body interface{}, insecureTLS bool, logger logger.Logger) ([]byte, error) { + res, err := getResponse(identity, url, method, token, body, insecureTLS, logger) if err != nil { return nil, err } @@ -145,26 +152,72 @@ func SendRequestRaw(url string, method string, token string, body interface{}, i return content, err } +// SendRequestRawWithHeaders is an http request and get response as byte[] +func SendRequestRawWithHeaders(url, method string, headers http.Header, body interface{}, insecureTLS bool, logger logger.Logger) ([]byte, error) { + if insecureTLS { + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + } else { + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: false} + } + httpClient := http.Client{ + Timeout: time.Second * 30, // Maximum of 30 secs + } + + var res *http.Response + + content, err := bodyToBytes(body) + if err != nil { + return []byte(""), err + } + + // create the request + req, err := http.NewRequest(method, url, bytes.NewBuffer(content)) + if err != nil { + return []byte(""), fmt.Errorf("Failed to create new request. %s", err) + } + + // attach the header + req.Header = headers + + logRequest(req, logger) + + // send request + res, err = httpClient.Do(req) + if err != nil { + return []byte(""), fmt.Errorf("Failed to send request. %s", err) + } + + if res.StatusCode >= 300 { + return []byte(""), fmt.Errorf("Received non-200 status code '%d'", res.StatusCode) + } + + content, err = ioutil.ReadAll(res.Body) + if err != nil { + return []byte(""), fmt.Errorf("Failed to read body. %s", err) + } + return content, err +} + // Get a get request and get response as serialized json map[string]interface{} -func Get(url string, token string, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { - response, err := SendRequest(url, http.MethodGet, token, "", insecureTLS, logger) +func Get(identity bool, url string, token string, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { + response, err := SendRequest(identity, url, http.MethodGet, token, "", insecureTLS, logger) return response, err } // Post a post request and get response as serialized json map[string]interface{} -func Post(url string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { - response, err := SendRequest(url, http.MethodPost, token, body, insecureTLS, logger) +func Post(identity bool, url string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { + response, err := SendRequest(identity, url, http.MethodPost, token, body, insecureTLS, logger) return response, err } // Put a put request and get response as serialized json map[string]interface{} -func Put(url string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { - response, err := SendRequest(url, http.MethodPut, token, body, insecureTLS, logger) +func Put(identity bool, url string, token string, body interface{}, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { + response, err := SendRequest(identity, url, http.MethodPut, token, body, insecureTLS, logger) return response, err } // Delete a delete request and get response as serialized json map[string]interface{} -func Delete(url string, token string, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { - response, err := SendRequest(url, http.MethodDelete, token, "", insecureTLS, logger) +func Delete(identity bool, url string, token string, insecureTLS bool, logger logger.Logger) (map[string]interface{}, error) { + response, err := SendRequest(identity, url, http.MethodDelete, token, "", insecureTLS, logger) return response, err } diff --git a/pkg/cybr/helpers/prettyprint/prettyprint.go b/pkg/cybr/helpers/prettyprint/prettyprint.go index 14e3f36..162e184 100644 --- a/pkg/cybr/helpers/prettyprint/prettyprint.go +++ b/pkg/cybr/helpers/prettyprint/prettyprint.go @@ -3,8 +3,22 @@ package prettyprint import ( "encoding/json" "fmt" + "runtime" + "strings" ) +var colorMap = map[string]string{ + "reset": "\033[0m", + "red": "\033[31m", + "green": "\033[32m", + "yellow": "\033[33m", + "blue": "\033[34m", + "purple": "\033[35m", + "cyan": "\033[36m", + "gray": "\033[37m", + "white": "\033[97m", +} + // PrintJSON will pretty print any data structure to a JSON blob func PrintJSON(obj interface{}) error { json, err := json.MarshalIndent(obj, "", " ") @@ -16,3 +30,18 @@ func PrintJSON(obj interface{}) error { return nil } + +// PrintColor will print a message in a given color +func PrintColor(color string, message string) error { + if runtime.GOOS == "windows" { + fmt.Println(message) + return nil + } + if _, ok := colorMap[strings.ToLower(color)]; !ok { + return fmt.Errorf("invalid color: %s", color) + } + + fmt.Println(colorMap[strings.ToLower(color)] + message + colorMap["reset"]) + + return nil +} diff --git a/pkg/cybr/helpers/util/util.go b/pkg/cybr/helpers/util/util.go index 62f6121..c55d4fc 100644 --- a/pkg/cybr/helpers/util/util.go +++ b/pkg/cybr/helpers/util/util.go @@ -2,7 +2,13 @@ package util import ( "fmt" + "net/url" "os" + "strings" + "syscall" + + "github.com/infamousjoeg/cybr-cli/pkg/cybr/api/requests" + "golang.org/x/crypto/ssh/terminal" ) // GetUserHomeDir Get the Home directory of the current user @@ -14,3 +20,42 @@ func GetUserHomeDir() (string, error) { } return userHome, nil } + +// ReadPassword Read password from Stdin +func ReadPassword() (string, error) { + fmt.Print("Enter password: ") + byteSecretVal, err := terminal.ReadPassword(int(syscall.Stdin)) + fmt.Println() + if err != nil { + return "", fmt.Errorf("An error occurred trying to read password from Stdin. Exiting") + } + return string(byteSecretVal), nil +} + +// ReadOTPcode Read one-time passcode from Stdin +func ReadOTPcode(credentials requests.Logon) (requests.Logon, error) { + fmt.Print("Enter one-time passcode: ") + byteOTPCode, err := terminal.ReadPassword(int(syscall.Stdin)) + if err != nil { + return credentials, fmt.Errorf("An error occurred trying to read one-time passcode from Stdin. Exiting") + } + credentials.Password = string(byteOTPCode) + fmt.Println() + return credentials, nil +} + +// GetSubDomain Get the subdomain from the platform URL +func GetSubDomain(platformURL string) (string, error) { + // Get the subdomain from the platform URL https://.privilegecloud.cyberark.cloud + parsedURL, err := url.Parse(platformURL) + if err != nil { + return "", fmt.Errorf("Failed to parse URL. %s", err) + } + + parts := strings.Split(parsedURL.Hostname(), ".") + if len(parts) > 2 { + return parts[0], nil + } + + return "", fmt.Errorf("Failed to get subdomain from URL. %s", err) +} diff --git a/pkg/cybr/identity/advanceauth.go b/pkg/cybr/identity/advanceauth.go new file mode 100644 index 0000000..ed2b758 --- /dev/null +++ b/pkg/cybr/identity/advanceauth.go @@ -0,0 +1,31 @@ +package identity + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/infamousjoeg/cybr-cli/pkg/cybr/api" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/httpjson" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/requests" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/responses" +) + +// AdvanceAuthentication will answer challenges from CyberArk Identity +func AdvanceAuthentication(c api.Client, req requests.AdvanceAuthentication) (*responses.Authentication, error) { + identityTenant := fmt.Sprintf("https://%s.id.cyberark.cloud", c.TenantID) + url := fmt.Sprintf("%s/Security/AdvanceAuthentication", identityTenant) + + headers := http.Header{} + headers.Add("X-IDAP-NATIVE-CLIENT", "true") + headers.Add("Content-Type", "application/json") + + res, err := httpjson.SendRequestRawWithHeaders(url, "POST", headers, req, c.InsecureTLS, c.Logger) + if err != nil { + return &responses.Authentication{}, fmt.Errorf("Failed to start authentication. %s", err) + } + + AdvanceAuthResponse := &responses.Authentication{} + err = json.Unmarshal(res, AdvanceAuthResponse) + return AdvanceAuthResponse, err +} diff --git a/pkg/cybr/identity/outofbox.go b/pkg/cybr/identity/outofbox.go new file mode 100644 index 0000000..cca56a0 --- /dev/null +++ b/pkg/cybr/identity/outofbox.go @@ -0,0 +1 @@ +package identity diff --git a/pkg/cybr/identity/requests/advanceauth.go b/pkg/cybr/identity/requests/advanceauth.go new file mode 100644 index 0000000..3d0481c --- /dev/null +++ b/pkg/cybr/identity/requests/advanceauth.go @@ -0,0 +1,9 @@ +package requests + +// AdvanceAuthentication is the request body for the AdvanceAuthentication API call +type AdvanceAuthentication struct { + SessionID string `json:"SessionId"` + MechanismID string `json:"MechanismId"` + Action string `json:"Action"` + Answer string `json:"Answer,omitempty"` +} diff --git a/pkg/cybr/identity/requests/startauth.go b/pkg/cybr/identity/requests/startauth.go new file mode 100644 index 0000000..a8e26b7 --- /dev/null +++ b/pkg/cybr/identity/requests/startauth.go @@ -0,0 +1,8 @@ +package requests + +// StartAuthentication is the request to start authentication +type StartAuthentication struct { + TenantID string `json:"TenantId,omitempty"` + User string `json:"User"` + Version string `json:"Version"` +} diff --git a/pkg/cybr/identity/responses/auth.go b/pkg/cybr/identity/responses/auth.go new file mode 100644 index 0000000..0109046 --- /dev/null +++ b/pkg/cybr/identity/responses/auth.go @@ -0,0 +1,18 @@ +package responses + +import ( + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/responses/shared" +) + +// Authentication is the response from the start authentication request +type Authentication struct { + Success bool `json:"success"` + Result shared.Result `json:"Result"` + Message *string `json:"Message"` + MessageID *string `json:"MessageID"` + Exception *string `json:"Exception"` + ErrorID *string `json:"ErrorID"` + ErrorCode *string `json:"ErrorCode"` + IsSoftError bool `json:"IsSoftError"` + InnerExceptions *string `json:"InnerExceptions"` +} diff --git a/pkg/cybr/identity/responses/shared/challenge.go b/pkg/cybr/identity/responses/shared/challenge.go new file mode 100644 index 0000000..441fe76 --- /dev/null +++ b/pkg/cybr/identity/responses/shared/challenge.go @@ -0,0 +1,19 @@ +package shared + +// Challenge contains the challenge response including the mechanisms +type Challenge struct { + Mechanisms []Mechanism `json:"Mechanisms"` +} + +// Mechanism contains the mechanism response +type Mechanism struct { + AnswerType string `json:"AnswerType"` + Name string `json:"Name"` + PromptMechChosen string `json:"PromptMechChosen"` + PromptSelectMech string `json:"PromptSelectMech"` + MechanismID string `json:"MechanismId"` + Enrolled bool `json:"Enrolled"` + MaskedEmailAddress string `json:"MaskedEmailAddress,omitempty"` + PartialAddress string `json:"PartialAddress,omitempty"` + PartialDeviceAddress string `json:"PartialDeviceAddress,omitempty"` +} diff --git a/pkg/cybr/identity/responses/shared/clienthint.go b/pkg/cybr/identity/responses/shared/clienthint.go new file mode 100644 index 0000000..91795d1 --- /dev/null +++ b/pkg/cybr/identity/responses/shared/clienthint.go @@ -0,0 +1,9 @@ +package shared + +// ClientHint contains the client hint response +type ClientHint struct { + PersistDefault bool `json:"PersistDefault"` + AllowPersist bool `json:"AllowPersist"` + AllowForgotPassword bool `json:"AllowForgotPassword"` + EndpointAuthenticationEnabled bool `json:"EndpointAuthenticationEnabled"` +} diff --git a/pkg/cybr/identity/responses/shared/result.go b/pkg/cybr/identity/responses/shared/result.go new file mode 100644 index 0000000..ac76ebb --- /dev/null +++ b/pkg/cybr/identity/responses/shared/result.go @@ -0,0 +1,27 @@ +package shared + +// Result contains the result response +type Result struct { + ClientHints ClientHint `json:"ClientHints"` + Version string `json:"Version"` + SessionID string `json:"SessionId"` + EventDescription *string `json:"EventDescription"` + RetryWaitingTime int `json:"RetryWaitingTime"` + SecurityImageName *string `json:"SecurityImageName"` + AllowLoginMfaCache bool `json:"AllowLoginMfaCache"` + Challenges []Challenge `json:"Challenges"` + Summary string `json:"Summary"` + TenantID string `json:"TenantId"` + AuthLevel string `json:"AuthLevel"` + DisplayName string `json:"DisplayName"` + Token string `json:"Token"` + Auth string `json:"Auth"` + UserID string `json:"UserId"` + EmailAddress string `json:"EmailAddress"` + UserDirectory string `json:"UserDirectory"` + PodFqdn string `json:"PodFqdn"` + User string `json:"User"` + CustomerID string `json:"CustomerId"` + SystemID string `json:"SystemId"` + SourceDsType string `json:"SourceDsType"` +} diff --git a/pkg/cybr/identity/startauth.go b/pkg/cybr/identity/startauth.go new file mode 100644 index 0000000..5f34e28 --- /dev/null +++ b/pkg/cybr/identity/startauth.go @@ -0,0 +1,31 @@ +package identity + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/infamousjoeg/cybr-cli/pkg/cybr/api" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/httpjson" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/requests" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/identity/responses" +) + +// StartAuthentication starts the authentication process +func StartAuthentication(c api.Client, req requests.StartAuthentication) (*responses.Authentication, error) { + identityTenant := fmt.Sprintf("https://%s.id.cyberark.cloud", req.TenantID) + url := fmt.Sprintf("%s/Security/StartAuthentication", identityTenant) + + headers := http.Header{} + headers.Add("X-IDAP-NATIVE-CLIENT", "true") + headers.Add("Content-Type", "application/json") + + res, err := httpjson.SendRequestRawWithHeaders(url, "POST", headers, req, c.InsecureTLS, c.Logger) + if err != nil { + return &responses.Authentication{}, fmt.Errorf("Failed to start authentication. %s", err) + } + + StartAuthResponse := &responses.Authentication{} + err = json.Unmarshal(res, StartAuthResponse) + return StartAuthResponse, err +} diff --git a/pkg/cybr/ispss/platformdiscovery.go b/pkg/cybr/ispss/platformdiscovery.go new file mode 100644 index 0000000..38164cc --- /dev/null +++ b/pkg/cybr/ispss/platformdiscovery.go @@ -0,0 +1,29 @@ +package ispss + +import ( + "encoding/json" + "fmt" + + httpJson "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/httpjson" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/helpers/util" + "github.com/infamousjoeg/cybr-cli/pkg/cybr/ispss/responses" +) + +// PlatformDiscovery uses the ISPSS API to discover the platform URLs +func PlatformDiscovery(platformURL string) (*responses.PlatformDiscovery, error) { + subdomain, err := util.GetSubDomain(platformURL) + if err != nil { + return &responses.PlatformDiscovery{}, fmt.Errorf("Failed to get subdomain. %s", err) + } + + url := fmt.Sprintf("https://platform-discovery.cyberark.cloud/api/v2/services/subdomain/%s", subdomain) + response, err := httpJson.SendRequestRaw(false, url, "GET", "", nil, false, nil) + if err != nil { + return &responses.PlatformDiscovery{}, fmt.Errorf("Failed to get platform discovery. %s", err) + } + + PlatformDiscoveryResponse := &responses.PlatformDiscovery{} + err = json.Unmarshal(response, PlatformDiscoveryResponse) + + return PlatformDiscoveryResponse, err +} diff --git a/pkg/cybr/ispss/responses/platformdiscovery.go b/pkg/cybr/ispss/responses/platformdiscovery.go new file mode 100644 index 0000000..3020b93 --- /dev/null +++ b/pkg/cybr/ispss/responses/platformdiscovery.go @@ -0,0 +1,27 @@ +package responses + +// PlatformDiscovery is the response from the ISPSS API for the platform discovery endpoint +type PlatformDiscovery struct { + SecretsManager Data `json:"secrets_manager,omitempty"` + Pcloud Data `json:"pcloud,omitempty"` + SecretsHub Data `json:"secrets_hub,omitempty"` + IdaptiveRiskAnalytics Data `json:"idaptive_risk_analytics,omitempty"` + ComponentManager Data `json:"component_manager,omitempty"` + IdentityUserPortal Data `json:"identity_user_portal,omitempty"` + Cem Data `json:"cem,omitempty"` + IdentityAdministration Data `json:"identity_administration,omitempty"` + CloudOnboarding Data `json:"cloud_onboarding,omitempty"` + Analytics Data `json:"analytics,omitempty"` + Sca Data `json:"sca,omitempty"` + Jit Data `json:"jit,omitempty"` + SessionMonitoring Data `json:"session_monitoring,omitempty"` + Audit Data `json:"audit,omitempty"` +} + +// Data is the data for each platform +type Data struct { + UI string `json:"ui,omitempty"` + API string `json:"api,omitempty"` + Bootstrap string `json:"bootstrap,omitempty"` + Region string `json:"region,omitempty"` +}