boto3 get available actions per service - python

I want to programatically get all the actions a user is allowed to do across aws services.
I've tried to fiddle with simulate_principal_policy but it seems this method expects a list of all actions, and I don't want to maintain a hard-coded list.
I also tried to call it with iam:* for example and got a generic 'implicitDeny' response so I know the user is not permitted all the actions but I require a higher granularity of actions.
Any ideas as to how do I get the action list dynamically?
Thanks!

To start with, there is no programmatic way to retrieve all possible actions (regardless of whether they are permitted to use an action).
You would need to construct a list of possible actions before checking the security. As an example, the boto3 SDK for Python contains an internal list of commands that it uses to validate commands before sending them to AWS.
Once you have a particular action, you could use Access the Policy Simulator API to validate whether a given user would be allowed to make a particular API call. This is much easier than attempting to parse the various Allow and Deny permissions associated with a given user.
However, a call might be denied based upon the specific parameters of the call. For example, a user might have permissions to terminate any Amazon EC2 instance that has a particular tag, but cannot terminate all instances. To correctly test this, an InstanceId would need to be provided to the simulation.
Also, permissions might be restricted by IP Address and even Time of Day. Thus, while a user would have permission to call an Action, where and when they do it will have an impact on whether the Action is permitted.
Bottom line: It ain't easy! AWS will validate permissions at the time of the call. Use the Policy Simulator to obtain similar validation results.

I am surprised no one has answered this question correctly. Here is code that uses boto3 that addresses the OP's question directly:
import boto3
session = boto3.Session('us-east-1')
for service in session.get_available_services ():
service_client = session.client (service)
print (service)
print (service_client.meta.service_model.operation_names)
IAM, however, is a special case as it won't be listed in the get_available_services() call above:
IAM = session.client ('iam')
print ('iam')
print (IAM.meta.service_model.operation_names)

Related

Excluding default IP in Mixpanel track event (Python SDK)

I am sending some events to mixpanel from within a cloud function, using the Python SDK. I don't want the users' location to be set to the location of the cloud server. I have read the Mixpanel article referencing this, but the documentation only shows how to ignore IP for a people_set call, using the meta argument. I assumed the same logic would translate to the track call, as it also has the meta argument in its documentation.
After testing, the people_set call is not taking the server location, but the track call is still taking the server location. Does anyone have any ideas why this might be, or how to correctly go about this task for a track() call? Below are the code snippets for the two calls:
mp_eu.people_set(user_id, user_data,
meta={'$ignore_time': True, '$ip': 0})
mp_eu.track(user_id, 'event_name', event_data,
meta={'$ignore_time': True, '$ip': 0})
You should add "ip" to "properties".
properties["ip"] = ip
mp_eu.track(user_id, 'event_name', properties)
check this.
https://help.mixpanel.com/hc/en-us/articles/115004499343

boto3: getting the list of access-levels in a policy

is there a way in boto3 to get the access level of a service in a policy (Full access, List, Tagging, Read, Write)? The allowed actions are too much, I just need the access levels.
For example I have the "IAMUserChangePassword"-Policy.
The allowed service in that policy is "IAM" and the access levels are "Read, Write". Now I want to write some python code to return a list of all access levels. I do not need the actions "iam:GetAccountPasswordPolicy, iam:ChangePassword", I just need the access levels.
No, this is not possible.
While the IAM console does provide a 'user-friendly' version of policies by showing checkboxes with Read, Write, List, etc, this level of information is not available through an API. The console must have some additional logic that parses the policies to extract this information.

AWS API unable to validate query string (specifically - "VpcId=vpc-1738886c")

I am trying to send a API query for Subnet Creation. Please note that the authentication code is working the problem is just with the parameter string:
request_parameters = 'Action=CreateSubnet&**VpcId=vpc-1738886c**&CidrBlock=20.20.3.0%2F28&Version=2016-11-15'
When I send this, I get: AWS was not able to validate the provided access credentials
For the exact same code, when I send:
"request_parameters = 'Action=CreateVpc&CidrBlock=20.20.3.0%2F24&Version=2016-11-15'" # It works!!
I am guessing there is something wrong with: VpcId=vpc-1738886c
Being same user, I am able to create a subnet in that VPC with same CIDR block in the console so permission doesn't seem to be an issue.
Please can you advise? Thanks in advance.
"AWS was not able to validate the provided access credentials" should mean you have an issue in the signing code -- not in the actual parameters.
Initially, it's hard to see why that might be the case, here... but it is.
The problem lies in the fact that you need to be signing the canonical representation of the query string... which means the parameters must be sorted lexically when signing:
# canonical representation
Action=CreateSubnet&CidrBlock=20.20.3.0%2F28&Version=2016-11-15&VpcId=vpc-1738886c
There can be no safe assumptions about the order in which a query string's parameters may change end-to-end on the Internet, so the AWS signing algorithms require them to be sorted for signing. The order in the actual HTTP request doesn't matter, but the order when signing does.

AWS lambda to renew sts role at each invocation is time consuming

I would like to know about a more efficient way than renewing sts role for a cross account role when it run on lambda. By definition those roles last for 1h per default, but so far i'm doing it this way:
def aws_session(role_arn, session_name):
_ = boto3.client('sts')
resp = _.assume_role(RoleArn=role_arn, RoleSessionName=session_name)
session = boto3.Session(
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken'],
region_name='us-east-1')
return session
def lambda_handler(event, context):
session = aws_session(role_arn=ARN, session_name='CrossAccountLambdaRole')
s3_sts = session.resource('s3')
But it terribly inefficient because instead of ~300ms, renewing credentials take more than ~1500 ms each time and as we all know, we are charged on the duration execution. Anyone could help me on how to refresh this only when the token expire ? Coz between execution, we are not sure to endup using the same "container", so how to make global variable?
Thx a lot
Remove AssumeRole
I think your problem stems from the fact that your code is picking the role it needs on each run. Your assume role code should indeed be generating a new token on each call. I'm not familiar with the Python Boto library but in Node I only call AssumeRole when I'm testing locally and want to pull down new credentials, I save those credentials and never call assume role again until I want new creds. Every time I call assume role, I get new credentials as expected. You don't need STS directly to run your lambda functions.
An Alternate Approach:
For the production application my Lambda code does not pick its role. The automation scripts that build the Lambda function assign it a role and the lambda function will use that role for ever, with AWS managing the refresh of credentials on the back-end as they expire. You can do this by building your Lambda function in CloudFormation specifying what role you want it to use.
Lambda via CloudFormation
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html
If you then want to view what credentials your function is operating with you can print out environment variables. Lambda will pass in temporary credentials to your function and the credentials will be associated with the role you've defined.
Simpler Approach
If you don't want to deal with CloudFormation deploy your function manually into the AWS console and in the console specify the role it should run with. But the bottom line is you don't need to use STS inside your lambda code. Assign the role externally.
Since your going across accounts, you obviously can't follow the advice many people say of attaching directly to the lambda.
Your best option is parameter store which is covered in detail here:
https://aws.amazon.com/blogs/compute/sharing-secrets-with-aws-lambda-using-aws-systems-manager-parameter-store/
Simply have lambda request the credentials from there instead.
That said, it's probably not going to save much time compared to STS requests... But I've not timed either process.
A perhaps less-good way, that's fairly simple, is to store the credentials in /TMP and build a process around enduring the credentials remain valid -- perhaps assume role with 65 minute duration, and save to a time stamped file with the minutes/seconds dropped. If the file exists, read it in by file I/O.
Keep in mind your saving credentials in a way that can be compromised if your code allows access to read the file in some way... Though as a lambda and with shared responsibility security, it's reasonably secure compared to doing this strategy on a persistent server.
Always use least privilege roles. Only allow your trusted account to assume this role... I think your can even lock trust policies down to a specific incoming lambda role as allowed to assume role in. This way leaked credentials by somehow reading/outputting the file require a malicious user to compromise some other aspect of your account (if locked down by account number only), or execute remote code execution inside your lambda itself (if locked to lambda).... Though, at that point, your credentials are already available to the malicious user to use anyways.

Retrieve a Softlayer user's permission via API

I'd like to retrieve a user's current permissions via Softlayer's Python API, ideally a list containing permissions as they'd be seen on the user portal.
I've tried the method under User_Customer service, which reports back with the following error:
SoftLayer.exceptions.SoftLayerAPIError: SoftLayerAPIError(SoftLayer_Exception): Object does not exist to execute method on. (SoftLayer_User_Customer::getPermissions)
I'm aware that a header may need to be set for that particular API call, but I couldn't find a source that explains how to set the headers in the Python API.
I've also tried calling this Account service method. Which succeeds, but returns a list of users under the account and not the information I expect.
Here you can see examples about the use of the python client:
https://softlayer.github.io/python/
particulary about the permissions associated to an user you can see this example:
https://softlayer.github.io/python/set_permission/
permissions = self.client['User_Customer'].getPermissions(id=user_id)
print("=== OLD PERMISSIONS ===")
self.printPermissions(permissions)
Regards

Categories

Resources