Approve/Revoke API Keys in Apigee Through PS

on Monday, April 2, 2018

The Apigee API Gateway grants access using API Keys (in this example). And, those keys are provisioned for each application that will use an API. This can be a bit confusing, because when you first sign up to use an API, you think that you’re going to get an API Key. But, that’s not the case. It’s your application that gets the key. This grants finer grained control of what applications have access to what, and allows for malicious activity to have a narrower impact. It does make the REST API Management backend a little confusing, as you always need to specify a developers email address when updating an application. The application’s are owned by a developer, so you have to know the developer before updating the application.

There’s a little more confusion because Applications don’t have direct access to APIs. Applications are given approval to use API Products. And, those API Products grant access to different API Proxies. This layer of abstraction is helpful when you want to make a very custom made API Product for an individual customer. And that can happen more often than you might expect.

image

So, in order to approve or revoke an API key on an Application you will actually need:

  • The developers email address
  • The application name
  • The API product name
  • And, either to approve or revoke the status

This script will use the developer email address and application name to look up the status of the application. If no specific API product name is given then the status of Approve or Revoke will be applied to the Application and all associated API Products. If a specific API product name is given, then only that API Products' status will be updated.

$global:ApigeeModule = @{}
$global:ApigeeModule.ApiUrl = "https://api.enterprise.apigee.com/v1/organizations/{org-name}"
$global:ApigeeModule.AuthHeader = @{ Authorization = "Basic {base64-encoded-credentials}" }

<#
.SYNOPSIS
	Makes a call to the Apigee Management API. It sets the approved/revoked status on
    an individual API Product for an Appliation. If not individual API Product is specified
    then the status will change for the Application and all associated API Products.

.PARAMETER Email
	The developer email address that owns the Application

.PARAMETER AppName
    The application to updated

.PARAMETER ApiProductName
    The individual API product to update (optional).

.PARAMETER Status
    Either 'approved' or 'revoked'

.EXAMPLE
	$appInfo = Set-ApigeeDeveloperAppStatus -Email it@company.org -AppName someapp -ApiProductName calendard_api -Status approved
#>
Function Set-ApigeeDeveloperAppStatus {
[CmdletBinding()]
Param (
    [Parameter(Mandatory = $true)]
    [string] $Email,
    [Parameter(Mandatory = $true)]
    [string] $AppName,
    [Parameter(Mandatory = $false)]
    [string] $ApiProductName = [String]::Empty,
    [Parameter(Mandatory = $true)]
    [ValidateSet("approved","revoked")]
    [string] $Status
)

    $action = "approve"
    if($Status -eq "revoked") { $action = "revoke" }


    # check the app exists (maybe use error handling here?)
    $appPath = "/developers/$Email/apps/$AppName"
    $app = Invoke-ApigeeRest -ApiPath $appPath


    # api key/oauth key are stored in the first credentials
    # (all api products are stored within this credential)
    $creds = $app.credentials[0]

    $keysPath = "$appPath/keys"
    $keyPath = "$keysPath/$($creds.consumerKey)"


    # if no api product is selected, approve or deny the entire developer app
    # (the api products are going to be approved/revoked as well)
    if($ApiProductName -eq [String]::Empty) {

        # it's very rare that the App will have it's status changed, but just in case ...
        if($app.status -ne $Status) { 
            $path = $appPath + "?action=$action"
            Write-Verbose "Setting app '$AppName' ($Email) to status '$Status'"
            Invoke-ApigeeRest -ApiPath $path -Method Post -ContentType "application/octet-stream"
        }
    

        # if no api product is selected,
        # then approve or deny the entire set of api products
        foreach($apiProduct in $creds.apiProducts) {
            if($apiProduct.status -ne $Status) {
                $path ="$keyPath/apiproducts/$($apiproduct.apiproduct)?action=$action"
                Write-Verbose "Setting api product '$($apiproduct.apiproduct)' on app '$AppName' ($Email) to status '$Status'"
                Invoke-ApigeeRest -ApiPath $path -Method Post -ContentType "application/octet-stream"
            }
        }

    } else {
    # if an api product name is given, then only update that product

        # check the api product exists
        $apiProduct = $creds.apiProducts |? apiproduct -eq $ApiProductName
        if(-not $apiProduct) {

            Write-Verbose "Could not find api product '$ApiProductName' for app '$AppName' ($Email)"

        } else {
            
            $path = "$keyPath/apiproducts/$($ApiProductName)?action=$action"
            Write-Verbose "Setting api product '$ApiProductName' on app '$AppName' ($Email) to status '$Status'"
            Invoke-ApigeeRest -ApiPath $path -Method Post -ContentType "application/octet-stream"

        }
    }
    

    $app = Invoke-ApigeeRest -ApiPath $appPath
    return $app
}



<#
.SYNOPSIS
	Makes a call to the Apigee Management API. It adds the authorization header and
	uses the root url for our organizations management api endpoint ($global:ApigeeModule.ApiUrl).
	This returns the body of the response as a string.

.PARAMETER ApiPath
	The sub path that will be added onto $global:ApigeeModule.ApiUrl.

.EXAMPLE
	$developers = Invoke-ApigeeMethod -ApiPath "/developers"
#>
Function Invoke-ApigeeRest {
[CmdletBinding()]
Param (
	[Parameter(Mandatory = $true)]
	[string] $ApiPath,
	[ValidateSet("Default","Delete","Get","Head","Merge","Options","Patch","Post","Put","Trace")]
	[string] $Method = "Default",
	[object] $Body = $null,
	[string] $ContentType = "application/json",
    [string] $OutFile = $null
)

	if($ApiPath.StartsWith("/") -eq $false) {
		$ApiPath = "/$ApiPath"
	}
	$Uri = $global:ApigeeModule.ApiUrl + $ApiPath

	if($Body -eq $null) {
		$result = Invoke-RestMethod `
                    -Uri $Uri `
                    -Method $Method `
                    -Headers $global:ApigeeModule.AuthHeader `
                    -ContentType $ContentType `
                    -OutFile $OutFile
	} else {
		$result = Invoke-RestMethod `
                    -Uri $Uri `
                    -Method $Method `
                    -Headers $global:ApigeeModule.AuthHeader `
                    -Body $Body `
                    -ContentType $ContentType `
                    -OutFile $OutFile
	}
	
	return $result
}

0 comments:

Post a Comment


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.