Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accounts API examples for interacting with child accounts via parent account APIs #253

Merged
merged 5 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions examples/Accounts/create_integration_in_child_account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Example of creating an integration in a child account using parent account credentials

The key to successfully interacting with child accounts via the parent account APIs is
pairing the parent account API IKEY/SKEY combination with the api-host of the child account.
Once that connection is established, the child account ID must be passed along with all API interactions.
The duo_client SDK makes that easy by allowing the setting of the child account ID as an instance variable.
"""

import sys
import getpass
import duo_client

# Create an interator to be used by the interactive terminal prompt
argv_iter = iter(sys.argv[1:])


def _get_next_arg(prompt, secure=False):
"""Read information from STDIN, using getpass when sensitive information should not be echoed to tty"""
try:
return next(argv_iter)
except StopIteration:
if secure is True:
return getpass.getpass(prompt)
else:
return input(prompt)


def prompt_for_credentials() -> dict:
"""Collect required API credentials from command line prompts

:return: dictionary containing Duo Accounts API ikey, skey and hostname strings
"""
answers = {'ikey': _get_next_arg('Duo Accounts API integration key ("DI..."): '),
'skey': _get_next_arg('Duo Accounts API integration secret key: ', secure=True),
'host': _get_next_arg('Duo API hostname of child account ("api-....duosecurity.com"): '),
'account_id': _get_next_arg('Child account ID: '),
'app_name': _get_next_arg('New application name: '),
'app_type': _get_next_arg('New application type: ')}
return answers


def create_child_integration(inputs: dict):
"""Create new application integration in child account via the parent account API"""

# First create a duo_client.Admin instance using the parent account ikey/sky along with the child account api-host
account_client = duo_client.Admin(ikey=inputs['ikey'], skey=inputs['skey'], host=inputs['host'])
# Next assign the child account ID to the duo_client.Admin instance variable.
account_client.account_id = inputs['account_id']
# Now all API calls made via this instance will contain all of the minimum requirements to interact with the
# child account.

# Here only the two required arguments (name and type) are passed.
# Normally, much more information would be provided. The type of additional information
# varies by the type of application integration.
try:
new_app = account_client.create_integration(
name=inputs['app_name'],
integration_type=inputs['app_type'],
)
print(f"New application {inputs['app_name']} (ID: {new_app['integration_key']}) was created successfully.")
except RuntimeError as e_str:
# Any failure of the API call results in a generic Runtime Error
print(f"An error occurred while creating the new application: {e_str}")


def main():
"""Main program entry point"""
inputs = prompt_for_credentials()
create_child_integration(inputs)


if __name__ == '__main__':
main()
53 changes: 53 additions & 0 deletions examples/Accounts/retrieve_integrations_from_child_account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""
Example of creating an integration in a child account using parent account credentials
"""

import argparse
import duo_client


parser = argparse.ArgumentParser()
duo_arg_group = parser.add_argument_group('Duo Accounts API Credentials')
duo_arg_group.add_argument('--ikey',
help='Duo Accounts API IKEY',
required=True
)
duo_arg_group.add_argument('--skey',
help='Duo Accounts API Secret Key',
required=True,
)
duo_arg_group.add_argument('--host',
help='Duo child account API apihost',
required=True
)
parser.add_argument('--child_account_id',
help='The Duo account ID of the child account to query.',
required=True
)
args = parser.parse_args()

# It is important to note that we are using the IKEY/SKEY combination for an Accounts API integration in the
# parent account along with the api-hostname of a child account to create a new duo_client.Admin instance
account_client = duo_client.Admin(
ikey=args.ikey,
skey=args.skey,
host=args.host,
)

# Once the duo_client.Admin instance is created, the child account_id is assigned. This is necessary to ensure
# queries made with this Admin API instance are directed to the proper child account that matches the api-hostname
# used to create the instance.
account_client.account_id = args.child_account_id


def main():
"""Main program entry point"""

print(f"Retrieving integrations for child account {args.child_account_id}")
child_account_integrations = account_client.get_integrations_generator()
for integration in child_account_integrations:
print(f"{integration['name']=}")


if __name__ == '__main__':
main()
Loading