def grant_access(access_list): client = strongdm.Client(access_key, secret_key) # Get Datasource(s) resources = list(client.resources.list('name:{}'.format(DATASOURCE)) ) resourceID = resources[0].id # Cycle through the output from PagerDuty for item in access_list: # Use the PD email address to get the user from SDM print('Current PD user is: ' + item["email"]) users = list(client.accounts.list('email:{}'.format(item["email"]))) if len(users) > 0: print('SDM user found!') myUserID = users[0].id # Convert the date strings from PD into a datetime object s = datetime.datetime.strptime(item["from"], '%Y-%m-%dT%H:%M:%SZ') e = datetime.datetime.strptime(item["to"], '%Y-%m-%dT%H:%M:%SZ') # Make both objects 'aware' (with TZ) as required by the strongDM SDK start = s.replace(tzinfo=timezone.utc) end = e.replace(tzinfo=timezone.utc) # Create the grant object myGrant = strongdm.AccountGrant(resource_id='{}'.format(resourceID),account_id='{}'.format(myUserID), start_from=start, valid_until=end) # Perform the grant try: respGrant = client.account_grants.create(myGrant) except Exception as ex: print("\nSkipping user " + item["email"] + " on account of error: " + str(ex)) else: print("\nGrant succeeded for user " + item["email"] + " to resource " + DATASOURCE + " from {} to {}".format(start,end)) print('---\n')
def main(): client = strongdm.Client(os.getenv("SDM_API_ACCESS_KEY"), os.getenv("SDM_API_SECRET_KEY")) users = client.accounts.list('') for user in users: print(user)
def main(): client = strongdm.Client(os.getenv("SDM_API_ACCESS_KEY"), os.getenv("SDM_API_SECRET_KEY")) # The RoleGrants API has been deprecated in favor of Access Rules. # When using Access Rules, the best practice is to grant Resources access based on type and tags. # If it is _necessary_ to grant access to specific Resources in the same way as Role Grants did, # you can use Resource IDs directly in Access Rules as shown in the following examples. create_role_grant_via_access_rules(client) delete_role_grant_via_access_rules(client) list_role_grants_via_access_rules(client)
# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import os import strongdm # Load the SDM API keys from the environment. # If these values are not set in your environment, # please follow the documentation here: # https://www.strongdm.com/docs/admin-guide/api-credentials/ api_access_key = os.getenv("SDM_API_ACCESS_KEY") api_secret_key = os.getenv("SDM_API_SECRET_KEY") client = strongdm.Client(api_access_key, api_secret_key) service = strongdm.Service(name="example service account") response = client.accounts.create(service, timeout=30) print("Successfully created service.") print("\tName:", response.account.name) print("\tID:", response.account.id) print("\tToken:", response.token)
def main(): access_key = os.getenv("SDM_API_ACCESS_KEY") secret_key = os.getenv("SDM_API_SECRET_KEY") if access_key is None or secret_key is None: print("SDM_API_ACCESS_KEY and SDM_API_SECRET_KEY must be provided") return 1 client = strongdm.Client(access_key, secret_key) if len(sys.argv) == 2 and sys.argv[1] == "revert": with open('state.json', 'r') as infile: state = json.load(infile) reinstated_count = 0 users = client.accounts.list('') for user in users: if not user.suspended: continue reinstated_count += 1 user.suspended = False client.accounts.update(user) for attachment in state['attachments']: try: client.account_attachments.create( strongdm.AccountAttachment( account_id=attachment["account_id"], role_id=attachment["role_id"])) except strongdm.errors.AlreadyExistsError: pass except Exception as ex: print("skipping creation of attachment due to error: ", str(ex)) for grant in state['grants']: try: client.account_grants.create( strongdm.AccountGrant( account_id=grant["account_id"], resource_id=grant["resource_id"])) except strongdm.errors.AlreadyExistsError: pass except Exception as ex: print("skipping creation of grant due to error: ", str(ex)) print("reinstated " + str(reinstated_count) + " users") print("recreated " + str(len(state['attachments'])) + " account attachments") print("recreated " + str(len(state['grants'])) + " account grants") return admin_email = "" if len(sys.argv) == 2: admin_email = sys.argv[1] else: print("please provide an admin email to preserve") return 1 admin_user_id = "" users = client.accounts.list('email:?', admin_email) for user in users: admin_user_id = user.id account_attachments = client.account_attachments.list('') account_grants = client.account_grants.list('') state = { 'attachments': [{ "account_id": x.account_id, "role_id": x.role_id } for x in account_attachments if x.account_id != admin_user_id], 'grants': [{ "account_id": x.account_id, "resource_id": x.resource_id } for x in account_grants if x.account_id != admin_user_id and x.valid_until is None], } print("storing " + str(len(state['attachments'])) + " account attachments in state") print("storing " + str(len(state['grants'])) + " account grants in state") with open('state.json', 'w') as outfile: json.dump(state, outfile) suspended_count = 0 users = client.accounts.list('') for user in users: if isinstance(user, strongdm.User) and user.email == admin_email: continue user.suspended = True try: client.accounts.update(user) suspended_count += 1 except Exception as ex: print("skipping user " + user.id + " on account of error: " + str(ex)) print("suspended " + str(suspended_count) + " users ")
def create_sdm_service(api_access_key, api_secret_key, log): client = strongdm.Client(api_access_key, api_secret_key) return SdmService(client, log)
import logging import os import strongdm import model client = strongdm.Client(os.getenv("SDM_API_ACCESS_KEY"), os.getenv("SDM_API_SECRET_KEY")) def save_user_resources(users: [model.User]): for user in users: sdm_user = get_or_create_user(user) logging.info("User details %s", sdm_user) for resource in user.resources_to_grant: sdm_resource = grant_resource(sdm_user, resource) if sdm_resource: logging.info("Resource = %s granted to user = %s", sdm_resource, sdm_user) for resource in user.resources_to_revoke: sdm_resource = revoke_resource(sdm_user, resource) if sdm_resource: logging.info("Resource = %s revoked from user = %s", sdm_resource, sdm_user) def get_or_create_user(user: model.User): sdm_user = next(client.accounts.list(f'email:{user.email}'), None) if not sdm_user:
def okta_sync(plan, verbose): SDM_API_ACCESS_KEY = os.getenv('SDM_API_ACCESS_KEY') SDM_API_SECRET_KEY = os.getenv('SDM_API_SECRET_KEY') OKTA_CLIENT_TOKEN = os.getenv('OKTA_CLIENT_TOKEN') OKTA_CLIENT_ORGURL = os.getenv('OKTA_CLIENT_ORGURL') if SDM_API_ACCESS_KEY is None or SDM_API_SECRET_KEY is None \ or OKTA_CLIENT_TOKEN is None or OKTA_CLIENT_ORGURL is None: print( "SDM_API_ACCESS_KEY, SDM_API_SECRET_KEY, OKTA_CLIENT_TOKEN, and OKTA_CLIENT_ORGURL must be set" ) return report = { 'start': str(datetime.datetime.now()), 'oktaUsersCount': 0, 'oktaUsers': [], 'sdmUsersCount': 0, 'sdmUsers': [], 'bothUsersCount': 0, 'sdmResourcesCount': 0, 'sdmResources': {}, 'permissionsGranted': 0, 'permissionsRevoked': 0, 'grants': [], 'revocations': [], 'matchers': {}, } matchers = load_matchers() okta_users = load_okta_users() report['matchers'] = matchers report['oktaUsers'] = [x.to_dict() for x in okta_users] report['oktaUsersCount'] = len(okta_users) client = strongdm.Client(SDM_API_ACCESS_KEY, SDM_API_SECRET_KEY) accounts = {o.email: o for o in client.accounts.list('type:user')} permissions = [v for v in client.account_grants.list('')] report['sdmUsers'] = {k: v.to_dict() for (k, v) in accounts.items()} report['sdmUsersCount'] = len(accounts) # define current state current = {} for p in permissions: if p.account_id not in current: current[p.account_id] = set() current[p.account_id].add((p.resource_id, p.id)) # define desired state desired = {} overlapping = 0 for group in matchers["groups"]: for resourceQuery in group["resources"]: for res in client.resources.list(resourceQuery): report['sdmResources'] = res for u in okta_users: if group["name"] in u.groups: if u.login not in accounts: continue overlapping += 1 aid = accounts[u.login].id if aid not in desired: desired[aid] = set() desired[aid].add(res.id) report['bothUsersCount'] = overlapping report['sdmResourcesCount'] = len(report['sdmResources']) # revoke things revocations = 0 for aid, curRes in current.items(): desRes = desired.get(aid, set()) for rid in curRes: if rid[0] not in desRes: if plan: print('Plan: revoke {} from user {}'.format(rid[1], aid)) else: client.account_grants.delete(rid[1]) report['revocations'].append(rid[1]) revocations += 1 report['permissionsRevoked'] = revocations # grant things grants = 0 for aid, desRes in desired.items(): curRes = current.get(aid, set()) for rid in desRes: for cr in curRes: if rid != cr[0]: ag = strongdm.AccountGrant(resource_id=rid, account_id=aid) if plan: print('Plan: grant {} to user {}'.format(rid, aid)) else: ag = client.account_grants.create(ag) report['grants'].append(ag) grants += 1 report['permissionsGranted'] = grants report['complete'] = str(datetime.datetime.now()) if verbose: print(json.dumps(report, indent=4, sort_keys=True)) else: print("{} Okta users, {} strongDM users, {} overlapping users, {} grants, {} revocations".format(\ len(okta_users),len(accounts), overlapping, grants, revocations))