I would like to ask if someone knows the difference between a "resource" and a "principal", when creating an aws_iam_policy_document in terraform.
The terraform documentation has the following information:
resource: A list of resource ARNs that this statement applies to. This is required by AWS if used for an IAM policy.
principals: A nested configuration block (described below) specifying a resource (or resource pattern) to which this statement applies.
From reading the above two sentences, it looks like they have the same effect, even thought they might do different things.
On further research, I came accross this article, which explains the differences between identity-based and resource-based policies.
It seams to me that this might be the answer to my question. If so, from what I understand, resource is a "resource-based" policy, while principal is a "identity-based" policy. Is that correct?
If this is the case, my follow-up question is: can I can use both type of policies together to further restrict the access?
For example, if i have a resource policy on an S3 bucket granting complete public access, but than I add a identity-based policy for a single user, does this user become the only one who can access the bucket?
I appreciate your help, and will try to clarify anything that might be unclear.
The Terraform documentation on this is a bit confusing. Prefer the AWS docs in this case. However, when TF refers to Principal, they do mean the same thing, i.e. who gets permissions. Who can be users, groups, roles and services.
However, a Principal isn't needed when you have a policy attached to an IAM user, group or role, because the user, group or role is the implied principal.
So why or when would you need a principal section? When the policy is attached to something that isn't inherently a user, group or role. For example, an S3 bucket policy.
HTH!
Related
Hi terraform mates out there
I want to automate the role assignments process for service accounts and users on the Google Cloud Platform. I am actually thinking of creating IAM custom roles to get fine-grained roles terraform resources for different services, and assign that role to the users or service account I want to.
Checking the way to associate which members will get what roles, I am actually wondering what is the difference between use google_project_iam_binding and use google_project_iam_member resources.
My current understanding could fall on in using google_project_iam_binding to grant roles to service accounts and google_project_iam_member to user accounts, but I am not sure since in the documentation they use both to associate user accounts.
I also found this interesting article https://binx.io/nl/2021/12/16/how-to-name-your-google-project-iam-resources-in-terraform/
As you know, Google IAM resources in Terraform come in three flavors:
google_project_iam_policy to define a complete policy for the project.
google_project_iam_binding to define all the members of a single role.
google_project_iam_member to define a single role binding for a single principal.
I didn't know the previous sentence and I would like to deep dive in the way I can use policies, and IAM roles in a better way for my purpose.
As the documentation states:
google_project_iam_binding: Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other
roles within the IAM policy for the project are preserved.
google_project_iam_member: Non-authoritative. Updates the IAM policy to grant a role to a new member. Other members for the role for
the project are preserved.
This means that google_project_iam_binding will grant a role to a list of members, and revokes it from any other member.
So if your project had two users e.g: jane#example.com and joe#example.com who both have roles/editor on the project. Running the following Terraform snippet will revoke roles/editor from joe#example.com as it's not present in the member list of google_project_iam_binding
resource "google_project_iam_binding" "project" {
project = "your-project-id"
role = "roles/editor"
members = [
"user:jane#example.com",
]
}
However, if you have for example jane#example.com and joe#example.com who both have roles/editor on the project. If you want to add a new editor (somone#example.com) without affecting the other roles/users, you can use google_project_iam_member
resource "google_project_iam_member" "project" {
project = "your-project-id"
role = "roles/editor"
member = "user:someone#example.com"
}
Notes from the documentation:
google_project_iam_policy cannot be used in conjunction with
google_project_iam_binding, google_project_iam_member, or
google_project_iam_audit_config or they will fight over what your
policy should be.
google_project_iam_binding resources can be used in conjunction with
google_project_iam_member resources only if they do not grant
privilege to the same role.
See:
Terraform google_project_iam_binding deletes GCP compute engine default service account from IAM principals
https://discuss.hashicorp.com/t/difference-between-google-project-iam-binding-and-google-project-iam-member/49645/2
https://github.com/hashicorp/terraform-provider-google/issues/8354
Is there a way I can fetch all users currently assigned permissions to each resource created under a subscription.
To put in other words, I want to traverse all the resources created under a subscription & get the list of all users, service principal names, SGs, AAD groups, along with their role who have access to each resource. This report would help me perform a periodic user access review .
Any leads/code would be appreciated.
You could simply get that with the powershell command Get-AzRoleAssignment.
Without any parameter, Get-AzRoleAssignment will get all the role assignments in the subscription, you can also leverage different parameters e.g. -ObjectId, -Scope to list assignments to a specific user/service principal/security group, or to list assignments on a specific resource group or resource.
For more details, see https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-list-powershell
Same thing also can be achieved by the REST API, Azure CLI, and SDK of different languages.
I am writing to ask your assistance regarding an important Azure topic.
Scenario 1:
I have 30 different resources in Azure in different resource groups in a subscription. There is a tag (owner) on all resources. If the value of owner tag is a username the only person who will be able to modify the owner tag is the user whose username is equal the owner tag's value. Of course if user1 modified the owner tag's value to another existing username (user2) user1 wouldn't be able to modify the owner tag's value. In this case the only person who could modify the owner tag's value is user2. Is it possible to restrict tag value modification at any Azure resources?
Scenario 2:
I have 30 different resources in Azure in different resource groups in a subscription. I create a custom role (ops-role) which has similar privileges in Azure than a Contributor except this role doesn't have privilege to modify the tags and tags' value. Then I create a another custom role (tagger-role) which has only (or almost only) tag modification privileges. Is it possible to create these roles in Azure?
I need a solution for the 1st or the 2nd scenario. I would like to restrict the tags modification on the Azure resources.
no, this is not possible, you have to create your own api on top of azure
if my memory servers me well, there is no separate role for tags, anyone with write permission over the resource can tag so this is essentially not achievable, you need a custom api on top of azure to do that
I have created a .NET Core 2.0 API and published it to Azure. I have an API Management (APIM) instance fronting that API and doing all the wonderful things that it does. However, there is one thing I cannot seem to wrap my head around or find any documentation for. Authorization on operations. (Not to be confused with authentication, which I have working very well).
My API is a simple RESTful service with CRUD actions. Let's take a read operation for example:
GET /api/owner/{ownerid}/thing/{thingid}
In this case, what I want to be able to do is to grant users permissions to READ THINGS within a specific OWNER. The same user may not have read permissions with a different owner. If the user has permissions, 200 OK; otherwise, 403 Forbidden.
Leaving this completely carte blanche, what are some suggestions for implementing this? I assume an inbound policy for each operation within APIM is where the action will take place? If so, how?
Update 1
I was informed of the possibility of using the same validate-jwt policy at the individual operation levels to append to the validate-jwt policy at the root. The idea is that the root policy validates that the user is authenticated while the operation policy checks for specific claims. This appears to work well, but is that the correct method, or just a hack?
Update 2
For the validate-jwt option to work, the permission model would need to align well with roles and groups; otherwise, it's just as much work as setting up your own custom database wherein at least you benefit from your own rules. In the end, I put the permissions in an Azure Storage Account table (any database will do) and used a send-request (with appropriate caching) to gather permissions based on the current operation and user. It works well, but "feels wrong". I am happy to share details to anyone who wants. In the meantime, I'll leave this open for now in case someone has a better idea.
Ultimately the only way to do so is by using policies at operation level. you can use validate-jwt to check for specific claims, you can check some other credentials that are passed to you as a part of request. Or you can use send-request to call some other service and ask for user permissions. In APIM itself there is no place to store any user related data besides some basic info, thus it is required for such authorization information to come from outside of APIM.
In the end it appears that there is no built-in solution. Rolling your own permission model and then validating it yourself is the way to go.
However...
This can still be done in APIM. As I mentioned in my second update, I was able to make a custom solution work. The way it was done was to use an inbound policy at the "all operations" level to retrieve permissions. (A caching mechanism was used so as not to retrieve the permissions on every single call.) Then, each operation determines if the user has permission to that specific operation based on the parameters that were passed in. (That is also cached.)
The result is that the root API has no authentication or authorization built-in, but APIM does and the appropriate behavior is observed.
Still, the preference would be an RBAC approach. For example, imagine the individual operations being seen as services as in this role definition:
{
"Name": "{rolename}",
"Id": "{roleid}",
"IsCustom": true,
"Description": "{roledescription}",
"Actions": [
"GET {myapi}/owner/{ownerid}/*",
"POST {myapi}/owner/{ownerid}/*",
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/{subscriptionid}"
]
}
If that were possible, we could create roles, assign them to users/groups at the subscription level, then have the claims automatically passed to APIM where they can be evaluated like any other claim.
How can I group the permissions using Picketlink[1] in such a way that I can assign one or more especific Groups of permissions to a Role ?
Thanks in advance.
Have you read the official documentation before asking?
If yes, showing us your efforts would make it easier to help you.
If not, please take a look at this.
I'm asking you this for a reason: I think you've misunderstood the concepts of Group, Role and Permission.
A Group is used to manage collections of identity types. For instance, Alice and Bob could be User identities which are member of "employees" group.
The Role is used in various relationship types to designate authority to another identity type to perform various operations within an application.
For example, Trent could be an User identity with the role of "moderator".
Permissions can be assigned to User, Groups and Roles.
It's up to you to choose in which way(s) to manage permissions in your application.
Access control can be based on Groups ("only employees can use this method"), Roles ("only moderators can delete posts") or even Users ("I am the only one who can eat bacon here!"). This can be done with the use of the Permission API, as explained in the documentation linked above.
Trust me, I know it could be not so simple at first - but please make an effort; then feel free to ask anything :)
Let us know!
Answer to comments
As you said, PicketLink's Permission API only lets you assign one permission at a time.
Anyways, note that even if you have to grant one permission at a time, this doesn't mean you can't grant multiple permissions to an instance:
permissionManager.grantPermission(adminRole, resource, myPermissions.CREATE)
permissionManager.grantPermission(adminRole, resource, myPermissions.DELETE)
permissionManager.grantPermission(adminRole, resource, myPermissions.UPDATE)
grants 3 permissions to every user that has adminRole and needs to invoke resource.