I want to set up a web service which will manage few resources on a user's behalf (on his own AWS account).
So basically, after a user logs in, he will provide my service with proper permission to access his account. I've noticed similar services (https://www.dashbird.io/), which instruct you on how to create a proper role, but I'm not sure on how to actually use the role. How to login on his behalf (there is no token nor password).
I'm using node.js, but other examples will help as well.
Thanks.
Your application will need valid credentials to access resources in your customer's AWS Account. Theses credentials can be provided in various ways, but they would most probably be either:
Credentials for an IAM User in your customer's account, or
An IAM Role in your customer's account, which they have configured to allow you to assume
IAM User
This is the simplest method. Your customer would create an IAM User and provide it with appropriate permissions. They would then supply your application with the Access Key and Secret Key associated with the User.
Your application would use those credentials when establishing a session with AWS services.
IAM Role
Your customer would create an IAM Role and provide it with appropriate permissions. Unlike an IAM User, an IAM Role does not have credentials. Rather, an AWS User assumes a Role. They are then provided with temporary credentials that can be used to use AWS services in that account.
Think of it like a Fire Warden -- if there is a fire in an office building, somebody temporarily assumes the role of Fire Warden, telling people what to do. When there's a fire, they have authority because they assumed the role. But when there's no fire, they have no authority to tell you what to do.
The customer would need to configure the Role to trust your Account, or a User in your account. They will then give you the ARN (Amazon Resource Name) of the Role. Your application then uses an IAM User in your own Account to call AssumeRole(). If that IAM User (or your whole account) is trusted, then you will receive back credentials for accessing your customer's account.
See:
Creating a Role to Delegate Permissions to an IAM User
AssumeRole
Related
I'm working with an app registration that has a secret defined. Via PowerShell I am able to get the credential, but not the secret value. Function used is Get-AzADAppCredential This is expected behavior, no issue here.
To renew the secret I run two functions Remove-AzADAppCredential and New-AzADAppCredential.
I run these PowerShell cmdlets via a DevOps pipeline and use a service connection with permissions in Azure portal.
I noticed that, when we create a service connection from DevOps to Azure, the service principal gets the role Cloud application administrator automatically assigned.
This role includes the permission "microsoft.directory/applications/credentials/update".
So the above (remove + new) should work, but it does not...
DevOps returns an error:
Az.MSGraph.internal\Remove-AzADApplicationPassword : Insufficient privileges to complete the operation.
Az.MSGraph.internal\Add-AzADApplicationPassword : Insufficient privileges to complete the operation.
PS. Using Az.Resources version 5.4.0 when working with the PowerShell functions.
Anyone got any idea what I'm missing?
Thanks.
Insufficient privileges to complete the operation.
The error comes when the user doesn't have sufficient privileges in AAD and doesn't have Write permission for the selected Azure Subscription.
Note: If you have Cloud application administrator privileges of the user, this role grants the ability to manage application credentials. Users assigned this role can add credentials to an application and use those credentials to impersonate the application’s identity. If the application’s identity has been granted access to a resource, such as the ability to create or update User or other objects, then a user assigned to this role could perform those actions while impersonating the application.
Make sure to check once if you have Global Administrator Access. If you have the access you can able to Modify the secret.
Users who are assigned to the Global administrator role can read and modify every administrative setting in your Azure AD organization.
The permission issue may happen due to
The user has only guest permission in the directory
The user is not authorized to the add applications in the directory
Refer here for detailed information
To be able to update a secret on an app registration, through DevOps, using a service principal, with minimal permissions, first make the service connection owner on that random app registration.
Next, add the Application.ReadWrite.OwnedBy application API permission on the app registration that's linked to the enterprise application. Not on the app registration where the service principal was made owner.
Than renewing the secret works fine.
It remains a question though why the role Cloud application administrator isn't sufficient because microsoft.directory/applications/credentials/update is included in that role, and that should also be enough.
I'm creating Node.js server that uses Google Oauth2 for authenticating users. I have my project in my organization created in Google Cloud Platform. And I've setup Oauth2, so only users of my organization can be authorized to use the service.
All users will be described as IAM members of project, and so everyone will have a specific role and permissions granted for their role. Users now can be authenticated and authorized in my app with Oauth2 (only users of my organization). The problem is I have no any clue how to retrieve their roles in my project from IAM. At first I used to think I only need to pass specific scopes in authorization methods (I am using Passport.js and GoogleStrategy). But then I realized that it only can be done after user have been authorized with next API request (is that even right?).
I've read IAM API documentation many times but only ended up with methods that allows me to retrieve arrays of presets of roles or policies or testable permissions or something created and used in my project. But I can't see any method allowing me to ask a service to retrieve a specific role and permissions for user (by email or google id) and send it back to me, so my Node server gets to know what this user is allowed to do. Maybe I need to dig somewhere else..
You can use CloudResourceManager service to retrieve a project's IAM policy. This will include project-specific (not inherited) role bindings: accounts (including user's) and their IAM roles:
https://cloud.google.com/resource-manager/reference/rest/v3/projects/getIamPolicy
We have an endpoint that needs to be queried for the pool Id for a given tenant before the user's login request can be sent. What is the best way to "secure" such an endpoint that is open for access by unauthenticated users?
We are using API gateway and lambda functions and serverless framework.
AWS Cognito Identity Pools have an option that may work for you. First, I'll quickly cover the differemt Cognito services, since it's something that confused me when I was first trying to understand Cognito.
At the risk of oversimplifying, AWS Cognito exists to answer two questions:
Who are you? (authentication)
What can you do? (authorization)
Cognito addresses these concerns with two distinct offerings: User Pools (authentication) and Identity Pools (authorization).
You can think of Cognito User Pools as your application's user directory. At a high level, User Pools let you handle user registration, authentication, account recovery, and supports authentication with third-party identity providers like Facebook, Google, etc.
Cognito Identity Pools provides a way to authorize users to use various AWS services. You can think of it as a vending machine for handing out AWS credentials. For example, if you needed to give your users access to upload a file to an S3 bucket or to invoke an endpoint in API Gateway, you could do so with an Identity Pool.
Here's a handy illustration to describe what I've outlined above.
Cognito lets you support unauthenticated users in your Identity Pool (instructions here).
So, how does this apply to your question?
You can use Cognito to enable IAM authorization across your entire API, which allows you to leverage the power of IAM to control access to your API. When you enable unauthenticated user access in Cognito, guest visitors to your site will be assigned to the unauthenticated IAM user role. Users that log in to your site will be assigned to the authenticated IAM user role. You can attach IAM policies to these roles that define what each role has access to.
For example, you might want to restrict unauthenticated users to certain API endpoints. On the other hand, authenticated users might get access to invoke all API endpoints in your application.
Here is a scenario. I have a SaaS product that needs to make api calls to customer's Azure cloud account. I understand a service principal can be created on the customer's AZ account, and if I have the credentials(app id, password, etc), I can make calls using that user/principal based on the permissions to that principal. One way is that customer creates it for my product, then comes to my product portal(web ui) and punches in this information which my SaaS product can then store securely in vault and use it.
Is there a better way to achieve the creation of the principal? For example via application manifest or something and then also be able to get a Event grid notification or something with the app/principal's creds to a webhook url endpoint?
Basically, I want this to be as automated as possible but cannot think of a way if it is even possible.
Normally if you are writing a multi-tenant application, you will set up your app registration as multi-tenant, and you will call the "common" endpoint for all users to log in.
when the admin from a different tenant logs into your application, if set up properly, a consent window will appear and when they consent, the Service principal will automatically be created in their tenant.
please see here: https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant#understand-user-and-admin-consent
I am trying to find security best practice on App permissions in the context of azure resource management.
Currently, there is only one permission listed for management.azure.com and it is
management.azure.com/user_impersonation (preview). This delegated user impersonation can be a serious problem and it can led to account takeover by malicious app.
Think about a scenario where a user with global administrator role consent and authorize an access token to the app. App can use the token and do whatever it wants with the azure tenant.
Another scenario where a privileged user assigned contributor role to multiple subscriptions. Token authorized by this user can be misused by app to modify resources in any of the subscriptions.
Unlike graph (graph.microsoft.com) api where you can handpick the permission (user.read), resource management api has only one option - user_impersonation!
You may argue why would a privileged user authorize the action but people make mistakes. Our job is to stop or minimize such risk by design. So, what's the best way to allow app to manage resources in azure and minimize the security risk?
Thanks to #juunas for outline and tips. Thanks to #Gaurav for attempting to address my question. I was able to modify azure resources on a subscription without having to grant user_impersonation on management.azure.com api. Here are the steps-
1) Register an app (TestPermissions in my case)
2) Add API Permissions (optional). You don't need to add management.azure.com.
3) Go the Azure resource (subscription, resource group or management group level based on your requirement) and add IAM/RBAC role to the registered app. I assigned Contributor role to TestPermissions app at the subscription level.
4) Request a oauth2 access token following client credential grant flow. You can provide client_id and client_secret in the body of the POST request or you can provide it as Authorization Basic base64 encoded header (that's what I did). Save the access token for future use (until it expires).
Note: I could not add multiple audience (scope) at the same time. If you would like to get a token for graph api, you can request a separate token by changing the scope to http://graph.microsoft.com/.default
5) Use the access token captured in the previous step to interact with azure resource manager. You will need to add the jwt bearer token in the Authorization header (not shown here) on every request to https://management.azure.com. In this example, I am creating a new resource group named TestCreateRG003 to one of my Pay-as-you-go subscription.
6) Let's validate/verify that the resource is created or updated in Azure. Bingo, there they are! App can read/modify (based on RBAC) azure resources w/o having to grant impersonation permission.
It is true that by granting that permission you are allowing the app to act as you, with all the permissions that brings.
The main way I've seen used when limitations are desired is that you:
Register an app in your Azure AD
Grant the service principal the necessary roles (e.g. Reader on specific resources)
Set the tenant id, client id, client secret etc. in the app
This of course requires that the app itself supports this approach.
If it only allows usage through impersonation, then you'll need to either trust or not use it.
Let me see if I can answer this question.
When a user requests a token for management.azure.com, all is done at that time is that the user has permission to execute Azure ARM API. That doesn't mean that they can do everything that's possible with Azure ARM API.
The things that they can do is controlled by Azure Role Based Access Control (RBAC). So if a user is in the Reader role, the token got on behalf of the user can only read information about resources in their Azure Subscription. They will not be allowed to create, update or delete resources in their Azure Subscription.
What you will need to do is grant users appropriate RBAC role to minimize the risks of misuse.