Skip to content

Commit

Permalink
Merge pull request #4 from redhatrises/provtoken
Browse files Browse the repository at this point in the history
Add ability to retrieve the provisioning token from the API
  • Loading branch information
redhatrises authored Aug 26, 2024
2 parents b54a50e + c7ba695 commit 717a8d4
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ API clients are granted one or more API scopes. Scopes allow access to specific

Ensure the following API scopes are enabled:

- **Sensor Download** [read]
- (optional) **Sensor update policies** [read]
> Use this scope when configuring the `-sensor-update-policy` cli flag or the`FALCON_SENSOR_UPDATE_POLICY_NAME` environment variable.
> [!IMPORTANT]
> - **Sensor Download** [read]
> - (optional) **Installation Tokens** [read]
> > This scope allows the installer to retrieve a provisioning token from the API, but only if installation tokens are required in your environment.
> - (optional) **Sensor update policies** [read]
> > Use this scope when configuring the `FALCON_SENSOR_UPDATE_POLICY_NAME` environment variable.
## Usage

Expand Down
6 changes: 3 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ func main() {

// Falcon sensor flags
falconCID := flag.String("cid", os.Getenv("FALCON_CID"), "Falcon Customer ID")
falconToken := flag.String("provisioning-token", os.Getenv("FALCON_PROVISIONING_TOKEN"), "The provisioning token to use for installing the sensor")
falconTags := flag.String("tags", os.Getenv("FALCON_TAGS"), "A comma seperated list of tags for sensor grouping.")
falconAPD := flag.String("apd", os.Getenv("FALCON_APD"), "Configures if the proxy should be enabled or disabled, By default, the proxy is enabled.")
falconToken := flag.String("provisioning-token", os.Getenv("FALCON_PROVISIONING_TOKEN"), "The provisioning token to use for installing the sensor. If not provided, the API will attempt to retrieve a token")
falconTags := flag.String("tags", os.Getenv("FALCON_TAGS"), "A comma seperated list of tags for sensor grouping")
falconAPD := flag.String("apd", os.Getenv("FALCON_APD"), "Configures if the proxy should be enabled or disabled. By default, the proxy is enabled")
falconAPH := flag.String("aph", os.Getenv("FALCON_APH"), "The proxy host for the sensor to use when communicating with CrowdStrike")
falconAPP := flag.String("app", os.Getenv("FALCON_APP"), "The proxy port for the sensor to use when communicating with CrowdStrike")
updatePolicyName := flag.String("sensor-update-policy", os.Getenv("FALCON_SENSOR_UPDATE_POLICY_NAME"), "The sensor update policy name to use for sensor installation")
Expand Down
87 changes: 87 additions & 0 deletions pkg/installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/crowdstrike/falcon-installer/pkg/utils/osutils"
"github.com/crowdstrike/gofalcon/falcon"
"github.com/crowdstrike/gofalcon/falcon/client"
"github.com/crowdstrike/gofalcon/falcon/client/installation_tokens"
"github.com/crowdstrike/gofalcon/falcon/client/sensor_download"
"github.com/crowdstrike/gofalcon/falcon/client/sensor_update_policies"
"github.com/crowdstrike/gofalcon/falcon/models"
Expand Down Expand Up @@ -81,6 +82,13 @@ func Run(fc FalconInstaller) {

falconArgs := fc.falconArgs()

if fc.SensorConfig.ProvisioningToken == "" {
fc.SensorConfig.ProvisioningToken = fc.getSensorProvisioningToken(client)
if fc.SensorConfig.ProvisioningToken != "" {
falconArgs = append(falconArgs, fc.osArgHandler("provisioning-token", fc.SensorConfig.ProvisioningToken))
}
}

if !falconInstalled {
if rpm.IsRpmInstalled() {
slog.Info("Installing CrowdStrike Falcon GPG key")
Expand Down Expand Up @@ -201,6 +209,85 @@ func (fi FalconInstaller) osArgHandler(arg, val string) string {
}
}

// getSensorProvisioningToken queries the CrowdStrike API for the sensor provisioning token
func (fi FalconInstaller) getSensorProvisioningToken(client *client.CrowdStrikeAPISpecification) string {
res, err := client.InstallationTokens.CustomerSettingsRead(
&installation_tokens.CustomerSettingsReadParams{
Context: context.Background(),
},
)
if err != nil {
errPayload := falcon.ErrorExtractPayload(err)
if errPayload == nil {
log.Fatal(falcon.ErrorExplain(err))
}

bytes, err := errPayload.MarshalBinary()
if err != nil {
log.Fatal(err)
}

if strings.Contains(string(bytes), "\"code\":403,\"message\":\"access denied, authorization failed\"") {
slog.Warn("Skipping getting installation tokens because the OAuth scope does not have permission to read installation tokens. If you are using provisioning tokens, please provide the token via CLI or update the OAuth2 client with the `Installation Tokens: Read` scope.")
return ""
} else {
log.Fatal(falcon.ErrorExplain(err))
}
}

payload := res.GetPayload()
if err = falcon.AssertNoError(payload.Errors); err != nil {
log.Fatal(err)
}

token := ""
if payload.Resources[0].TokensRequired != nil && *payload.Resources[0].TokensRequired {
token = fi.getToken(client, fi.getTokenList(client))
slog.Debug("Found suitable Falcon installation token", "Token", token)
}

return token
}

// getTokenList queries the CrowdStrike API for the installation tokens
func (fi FalconInstaller) getTokenList(client *client.CrowdStrikeAPISpecification) []string {
res, err := client.InstallationTokens.TokensQuery(
&installation_tokens.TokensQueryParams{
Context: context.Background(),
},
)
if err != nil {
log.Fatal(falcon.ErrorExplain(err))
}

payload := res.GetPayload()
if err = falcon.AssertNoError(payload.Errors); err != nil {
log.Fatal(err)
}

return payload.Resources
}

// getToken queries the CrowdStrike API for the installation token using the token ID
func (fi FalconInstaller) getToken(client *client.CrowdStrikeAPISpecification, tokenList []string) string {
res, err := client.InstallationTokens.TokensRead(
&installation_tokens.TokensReadParams{
Context: context.Background(),
Ids: tokenList,
},
)
if err != nil {
log.Fatal(falcon.ErrorExplain(err))
}

payload := res.GetPayload()
if err = falcon.AssertNoError(payload.Errors); err != nil {
log.Fatal(err)
}

return *payload.Resources[0].Value
}

// getSensorUpdatePolicies queries the CrowdStrike API for sensor update policies that match the provided policy name and architecture
func (fi FalconInstaller) getSensorUpdatePolicies(client *client.CrowdStrikeAPISpecification) string {
var filter *string
Expand Down

0 comments on commit 717a8d4

Please sign in to comment.