How can I get UserId for AWS SSO Users using Boto3.
I wanted to use it to assign permissions to a user for a specific aws account using below code, however, this requires PrincipalId which is some 16-20 digit number associated with each user and is called User ID in the AWS console.
You can read about it - here
response = client.create_account_assignment(
InstanceArn='string',
TargetId='string',
TargetType='AWS_ACCOUNT',
PermissionSetArn='string',
PrincipalType='USER'|'GROUP',
PrincipalId='string'
)
If you have the UserName for the user you'd like to assign permissions for, you can programmatically use IAM to determine that user's UserId:
import boto3
# Get the UserId.
user_name = 'the user name here'
iam_client = boto3.client('iam')
result = iam_client.get_user(UserName=user_name)
user_id = result['User']['UserId']
# Assign permissions to the UserId.
sso_admin_client = boto3.client('sso-admin')
response = sso_admin_client.create_account_assignment(
InstanceArn='string',
TargetId='string',
TargetType='AWS_ACCOUNT',
PermissionSetArn='string',
PrincipalType='USER',
PrincipalId=user_id
)
You'll also need to use the 'identitystore' to get user or group IDs. Try this from the docs -
import boto3
client = boto3.client('identitystore')
response = client.get_user_id(
IdentityStoreId='string',
AlternateIdentifier={
'ExternalId': {
'Issuer': 'string',
'Id': 'string'
},
'UniqueAttribute': {
'AttributePath': 'string',
'AttributeValue': {...}|[...]|123|123.4|'string'|True|None
}
}
)
Although I personally found that the above method didn't work for me due to it not being available in my installed version of Boto3, so I did this instead which worked perfectly -
import boto3
client = boto3.client('identitystore')
response = client.list_users(
IdentityStoreId='string',
Filters=[
{
'AttributePath': 'UserName',
'AttributeValue': 'string'
},
]
)
print(response["Users"][0]["UserId"])
Sources:
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/identitystore.html#id24
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/identitystore.html#IdentityStore.Client.get_user_id
https://botocore.amazonaws.com/v1/documentation/api/latest/reference/services/identitystore.html#IdentityStore.Client.list_users
Related
**I need to get Public IPv4 address and decrypted key pair on response of newly created instance by boto3 Lambda Function?
I am creating a instance using boto3 and i want to print the public ip Address and decrypted key (password) on response. please assist to complete this code
import boto3
import json
AMI = 'AMI'
INSTANCE_TYPE = 'INSTANCE_TYPE'
KEY_NAME = 'KEY_NAME'
REGION = 'REGION'
SUBNET_ID = 'SUBNET_ID'
SECURITYGROUP_ID = 'SECURITYGROUP_ID'
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=event['REGION'])
instance = ec2.run_instances(
ImageId=event['AMI'],
InstanceType=event['INSTANCE_TYPE'],
KeyName=event['KEY_NAME'],
SubnetId=event['SUBNET_ID'],
SecurityGroupIds = ['my.sg'],
MaxCount=1,
MinCount=1,
InstanceInitiatedShutdownBehavior="terminate",
TagSpecifications=[
{
'ResourceType': 'instance',
'Tags': [
{
'Key': 'Name',
'Value': 'myserver'
},
]
},
],
)
print ("New instance created:")
instance_id = instance['Instances'][0]['InstanceId']
print (instance_id)
return instance_id
please correct the code
ip = new_instance[0].private_ip_address
public_ip = new_instance[0].public_ip_address
It takes a little bit of time after an instance has been launched for a Public IP address to be assigned to the instance.
It takes a LONG time for a Windows password to be available on a newly launched instance.
Thus, your function will need to wait until that information is available. It can either keep calling describe_instances() and check the values, or can use a waiter. However, the instance status is not necessarily an indication of whether the Windows password is avilable.
Note that waiting for data to be available is not ideal for an AWS Lambda function because you are charged for the duration that the function runs.
I have a Lambda function written in python that is triggered by the API Gateway with proxy integration and a Cognito user pool authorizer. I am trying to access the "sub" UUID that Cognito gives every user, but nothing I try works. I have just about exhausted google of all related search results and nothing that I have found seems valid. They either return a null or they crash. My function (with every attempted UUID access line commented out) is below:
import json
def lambda_handler(event, context):
#UniqueUser = context.identity.cognito_identity_id
#UniqueUser = context.authorizer.claims.sub
#UniqueUser = event.requestContext.authorizer.claims.sub
#UniqueUser = event.request.userAttributes.sub
#UniqueUser = event.queryStringParameters.sub
try:
# Something that gets sub from cognito
except:
UniqueUser = "not valid code"
if not UniqueUser:
UniqueUser = "UniqueUser is null"
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps('Hello from Lambda ' + UniqueUser + "!")
};
Does anyone know any possible sources of this behavior or solution to this problem?
If you need to access the UUID of a Cognito user who is calling a Lambda function through the API Gateway with proxy integration, use the code below.
UniqueUser = event['requestContext']['authorizer']['claims']['sub']
I'm working with Python 3.x
Previously, I had a function to create tickets that looks like this
def jira_incident(jira_subject, jira_description):
user = "username"
apikey = 'apikey'
server = 'https://serverName.atlassian.net'
options = {
'server': server,
'verify': False
}
issue_dict = {
'project': {'key': 'project_name'},
'summary': str(jira_subject),
'description': str(jira_description),
'issuetype': {'name': 'Incident'},
'assignee': {'name': my_username},
'priority': {'name': 'Low'},
'customfield_10125':
{'value': 'Application Ops'}
}
jira = JIRA(options, basic_auth=(user, apikey))
new_issue = jira.create_issue(fields=issue_dict)
return new_issue
my_username is a global variable that's used for other things as well.
Anyway, the assignee is no longer working as of about 2 days ago. I did some googling and found that it now needs the accountId instead of the name, I can get this via the web UI by leaving a comment as #'ing someone in a comment. As a temporary solution I've populated a dictionary to reference (and that works), however I'd like to make this more dynamic for future proofing the script.
'assignee': {'accountId': jira_dict[my_username]},
I can't seem to really find any documentation on looking up the accountId from the name, and I figured I'd go ahead and ask the community to see if anyone else has run into/solved this issue.
I was thinking about just writing a new function that performs this query for me, then returns the accountId.
EDIT
I did find this:
import requests
from requests.auth import HTTPBasicAuth
import json
url = "/rest/api/3/user/bulk/migration"
auth = HTTPBasicAuth("email#example.com", "<api_token>")
headers = {
"Accept": "application/json"
}
response = requests.request(
"GET",
url,
headers=headers,
auth=auth
)
print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
However it 404's on me, I add the server address to the beginning of the url, and replace user, with the username in question.
Okay, I found a solution, it's not an elegant solution, but it does exactly what I need it to. So here is the new function:
def jira_account_id_from_username(username):
r = requests.get('https://serverName.atlassian.net/rest/api/3/user?username=' + username, auth=("username",api_key), verify=False)
value = re.search('"accountId":"(.*?)",', str(r.text)).group(1)
return value
I strongly encourage you to not rely on the username anymore. The endpoint you are using is deprecated, see also https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/.
The "new" or probably better way is to use the /user/search endpoint as described here: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-user-search-get There you can define a query that is matching against certain properties of a user (displayName or emailAddress), or search for the accountId if you already have it. Therefore, if you are linking users from the cloud to some other "user directory" (or just a scripts where you have stored some usernames), replace it by using either email address or accountId so you can properly link your users.
I'm using keycloak python API to assign user roles. Here is the code:
from keycloak import KeycloakAdmin
# make connection
admin = KeycloakAdmin(server_url = "https://xxx.xx.xx/auth/",
username = 'xx',
password = 'xxx',
realm_name = "xxx-xxx",
verify = True)
# get an user id via user name
userID = admin.get_user_id(self.userName)
# assign user role
admin.assign_client_role(client_id = "client_id",
user_id = userID,
#role_id = "role_id",
role_name = "test")
The make connection and get user id via user name part is successful. But assign_client_role() gives me an error:
TypeError: assign_client_role() got an unexpected keyword argument 'role_name'
It seems that the arguments are not corrsponding to those defined in the function. My code refers to the example from this website.
Could anyone tell me how to make it right?
Had the same problem. It turns out that the documentation for python-keycloak is not correct. Here's how I managed to fix the issue
First, make sure you're using client_id from url not the client id from keycloak interface (see picture):
client_id picture
Second, make sure your admin user has manage-users and manage-clients roles assigned to it:
roles picture
Third, assign_client_role() accepts argument role_name as an array, not string
Here's my code:
keycloak_admin = KeycloakAdmin(server_url="http://localhost:8088/auth/",
username='azat_admin',
password='some_password',
realm_name="realm_name",
verify=True)
new_user = keycloak_admin.create_user({"email": "some_email",
"username": "some_username",
"enabled": True,
"firstName": "some_firstname",
"lastName": "some_lastname",
"credentials": [{"value": "some_password","type": "password",}]})
roles = keycloak_admin.get_client_roles(client_id="2b50a8e3-dc91-4658-a552-83fb768badc8")
keycloak_admin.assign_client_role(client_id = "2b50a8e3-dc91-4658-a552-83fb768badc8",
user_id = new_user,
roles=[roles[0]])
Wang.
Another option is this:
from keycloak import KeycloakAdmin
# make connection
admin = KeycloakAdmin(server_url = "https://xxx.xx.xx/auth/",
username = 'xx',
password = 'xxx',
realm_name = "xxx-xxx",
verify = True)
# get an user id via user name
user_id = admin.get_user_id("username")
role = admin.get_client_roles(client_id="client_id", role_name="test")
# assign user client role
admin.assign_client_role(client_id = "client_id",
user_id = user_id,
roles=[role])
I will fixe de documentation about that.
The new oficial repository is "python-keycloak".
As stated in example documentation. You should certainly try first:
# Get client role id from name
role_id = keycloak_admin.get_client_role_id(client_id=client_id, role_name="test")
then
# Assign client role to user. Note that BOTH role_name and role_id appear to be required.
keycloak_admin.assign_client_role(client_id=client_id, user_id=user_id, role_id=role_id, role_name="test")
Or can you share more of your code and explain why you commented the 'role_id' argument?
It turns out that the documentation is wrong, I check the source code of keycloak_admin.py found the definition of function assign_client_role():
def assign_client_role(self, user_id, client_id, roles):
"""
Assign a client role to a user
:param client_id: id of client (not client-id)
:param user_id: id of user
:param client_id: id of client containing role,
:param roles: roles list or role (use RoleRepresentation)
:return Keycloak server response
"""
payload = roles if isinstance(roles, list) else [roles]
params_path = {"realm-name": self.realm_name, "id": user_id, "client-id":client_id}
data_raw = self.connection.raw_post(URL_ADMIN_USER_CLIENT_ROLES.format(**params_path),
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
The URL_ADMIN_USER_CLIENT_ROLES is defined in urls_patterns.py:
URL_ADMIN_USER_CLIENT_ROLES = "admin/realms/{realm-name}/users/{id}/role-mappings/clients/{client-id}"
As you can see, the realm-name, userid and client-id is used to form the url, if one of these parameters goes wrong, there will be 404 error because of the incorrect url. Content of parameter roles is warpped into post data, so if the format of roles parameter is wrong, there will probably be 500 error.
In order to get the right url example and the correct roles data structure, I used browser to manually assign a role, and check the url and post json data sent by the browser. Then change the code to produce the correct url and json data. Below is the final code that works:
from keycloak import KeycloakAdmin
# make connection
admin = KeycloakAdmin(server_url = "https://xxx.xx.xx/auth/",
username = 'xx',
password = 'xxx',
realm_name = "xxx-xxx",
verify = True)
# get user id
userID = admin.get_user_id('one user's name')
# make sure you have the right realm name
realmName = 'xxx-xxx'
clientID = admin.get_client_id(realmName)
admin.assign_client_role(user_id = userID,
client_id = clientID,
roles = [{"id":"34a02t60-2435-40da-v911-a3ee1xm58921",
"name":"USER",
"description":"xxxxx",
"composite":False,
"clientRole":True,
"containerId":"aa102d71-4jk1-4u2a-a8w4-a6cv5j7626i1"}])
I'm new on Facebook marketing API.
1) they let me open only a sandbox account and I want to create a real one and get a real report.
2) after generating the example code and working with Python SDK and getting this error -
Unsupported get request. Object with ID '[number_of_ad_account_id]' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api
please help me solve this issues.
thanks.
EDIT: CODE (take from Facebook sample code)
from facebookads.adobjects.adaccount import AdAccount
from facebookads.adobjects.adsinsights import AdsInsights
from facebookads.api import FacebookAdsApi
access_token = '{secret}'
ad_account_id = '{secret}'
app_secret = '{secret}'
FacebookAdsApi.init(access_token=access_token)
fields = [
'account_id',
'adgroup_id',
'campaign_group_id',
'campaign_id',
]
params = {
'time_range': {'since':'2017-07-10','until':'2017-07-10'},
'filtering': [],
'level': 'account',
'breakdowns': [],
}
print AdAccount(ad_account_id).get_insights(
fields=fields,
params=params,
)
I had the same problem. The SAMPLE_CODE.py auto-generated from Marketing API's quickstart doesn't prefix ad_account_id with act_ by default; it puts the Sandbox Account ID directly, while the Ad Insights API expects:
act_<AD_ACCOUNT_ID>/insights
Just prefix you ad_account_id with act_ and it will work.