Applying ServiceAccount specific OPA policies through Gatekeeper in kubernetes - security

We are trying to replace our existing PSPs in kubernetes with OPA policies using Gatekeeper. I'm using the default templates provided by Gatekeeper https://github.com/open-policy-agent/gatekeeper-library/tree/master/library/pod-security-policy and defined corresponding constraints.
However, I can't figure out how I can apply a policy to a specific ServiceAccount.
For eg. how to define allow-privilege-escalation policy only to a ServiceAccount named awsnode?
In PSPs I create a Role/ClusterRole for required podsecuritypolicies and create a RoleBinding to allow awsnode ServiceAccount to use required PSP. I'm struggling to understand how to achieve the same using Gatekeeper OPA policies?
Thank you.

Apparently PSPs and Gatekeeper OPA policies are designed to achieve pod security at different levels. Here is the response from AWS support on the above question.
Gatekeeper constraint templates (and the corresponding constraint CRDs defined from the templates) apply to a larger scope of Kubernetes resources than just pods. Gatekeeper extends additional functionality that RBAC cannot provide at this stage.
Gatekeeper itself cannot be managed by RBAC (by means of using verbs to restrict access to Gatekeeper constraints), because no RBAC resource keyword exists for Gatekeeper policy constraints (at least, at the time of writing this).
PodSecurity Admission Controller might be an option for someone looking for a replacement for PSPs which needs to be controlled by RBAC if the cluster is on 1.22 version or above.

I think a possible solution to applying an OPA Gatekeeper policy (a ConstraintTemplate) to a specific ServiceAccount, is to make the OPA/Rego policy code reflect that filter / selection logic. Since you said you're using pre-existing policies from the gatekeeper-library, maybe changing the policy code isn't an option for you. But if changing it is an option, I think your OPA/Rego policy can take into account the pod's serviceAccount field. Keep in mind with OPA Gatekeeper, the input to the Rego policy code is the entire admission request, including the spec of the pod (assuming it's pod creations that you're trying to check).
So part of the input to the Rego policy code might be like
"spec": {
"volumes": [... ],
"containers": [
{
"name": "apache",
"image": "docker.io/apache:latest",
"ports": [... ],
"env": [... ],
"resources": {},
"volumeMounts": [... ],
"imagePullPolicy": "IfNotPresent",
"securityContext": {... }
}
],
"restartPolicy": "Always",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "apache-service-account",
"serviceAccount": "apache-service-account",
So gatekeeper-library's allow-privilege-escalation references input.review.object.spec.containers and finds an array of containers like "apache". Similarly, you could modify the policy code to reference input.review.object.spec.serviceAccount and find "apache-service-account". From there, it's a matter of using that information to make sure the rule "violation" only matches if the service account is one you want to apply to.
Beyond that, it's possible to then take the expected service account name and make it a ConstraintTemplate parameter, to make your new policy more flexible/useable.
Hope this helps!

Related

How to assign Access Policies to an Azure Key Vault using Blueprints

I am creating a key vault through an Azure Blueprint: it gets created with no problem.
The thing is that, in order to access the Key Vault (Listing it, putting or getting values) Access Policies must be configured.
With ARM templates, I could insert a section like :
"accessPolicies": [
{
"tenantId": "22222222-3333-4444-aaaa-eeeeeeeeeeee",
"objectId": "77777777-6666-4444-8888-111111111111",
"permissions": {
"keys": [
"Get",
...
"Restore"
],
"secrets": [
"Get",
...
"Restore"
],
"certificates": []
}
},
but I'd need to have a TenantId and an ObjectId to hardcode, or to get as parameter, which is not the right way to do it.
Unfortunately I could not find a way to assign these access policies to the Key Vault, without which the key vault itself just can't be used, unless making those settings manual (and deleting them each time the blueprint is upgraded).
Is there a guideline or a best practice to do this in the proper way ?
The tenantId you can get dynamically using "[subscription().tenantId]". See official documentation.
Regarding the objectId, using a parameter is usually the right way as stated in this answer. ObjectIDs are not on the same layer as ARM components and therefore there aren't real way to get those dynamically using ARM.
Starting from the answer from #jul_DW, I realized that ARM could not set in an easy way users, so I should have used to something in the Blueprint.
And infact, one of the key features for Blueprint is Role Assignment.
To use this approach we need to enable the RBAC for the Key Vault, but that is done easily in the ARM template itself:
...
"type": "Microsoft.KeyVault/vaults",
"properties": {
...
"enableRbacAuthorization": true,
...
}
Once the RBAC is enabled, the ARM template should stay away from assigning permissions, and the Role Assignment feature from Blueprints should be used.
In my case, I assigned a Key Vault Administrator role to the needed user group, that can be indicated as a parameter. In this way the ARM template is kept as simple as possible, and at the same time we have a great flexibility in assigning roles to different users in the various environments.

Azure policy - prevent the creation of app services without authentication

I wish to create a policy that will prevent the creation of app services without authentication enabled (just auditing them is not enough).
The following policy can correctly identify existing resources that do not have authentication enabled:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "Microsoft.Web/sites/config/siteAuthEnabled",
"equals": "false"
}
]
},
"then": {
"effect": "deny"
}
}
}
however it does not prevent them being created in the first place (either via ARM template or through the portal).
I suspect this is because the Microsoft.Web/sites/config resource isn't being explicitly created.
Does anyone know if this is possible?
Apparently, the Microsoft.Web/sites/config/* resource type (except Microsoft.Web/sites/config/web) is not supported by Azure Policy at this point.
Quoting #camillemarie from this similar GitHub issue:
authSettings cannot be managed via policy at this time. In the interest of hiding secrets from users in the default Reader role, this resource provider doesn't expose secrets via GET calls (hence the null in /config/web, and lack of GET support for /config/authSettings).
This means that the existing Microsoft.Web/sites/config/siteAuthSettings.* aliases are invalid. We'll look into removing these, but we don't have a good deprecation story at the moment.
Reference:
Microsoft.Web/sites/config/siteAuthSettings.* aliases are not valid #264
Azure Policy - Known Issues
You can try using the Microsoft.Web/sites/siteConfig alias.

Having trouble understanding Azure's Roles JSON

Its just a concept im having trouble understanding with the wildcard * and what that means, so here we have two roles Owner and contributor.
"Name": "Contributor",
"Id": "b24988ac-6180-42a0-ab88-20f7382dd24c",
"IsCustom": false,
"Description": "Lets you manage everything except access to resources.",
"Actions": ["*"],
"NotActions": [
"Microsoft.Authorization/*/Delete",
"Microsoft.Authorization/*/Write",
"Microsoft.Authorization/elevateAccess/Action'],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [],
"/"
Name : Owner
Id : 8e3af657-a8ff-443c-a75c-2fe8c4bcb635
IsCustom : False
Description : Grants full access to manage all resources, including the ability to assign roles in Azure RBAC.
Actions : {*}
NotActions : {}
DataActions : {}
NotDataActions : {}
AssignableScopes : {/}
So my hang up is use of the astrisk, i know * under Owner means everything but with contributor, why is it used under the NotActions permissions? Why is it "Microsoft.Authorization/*/Delete" instead of Microsoft.Authorization/Delete". The permission in question stops the contributor from deleting users. So i know how these roles and permissions work, im just really struggling with the syntax. I have read the documentation on microsoft learn but there is something i clearly dont understand about the *. Does anyone with any knowledge know of a way of explaining this to help clear it up or maybe someone could point me to some better documentation? Any help would be greatly appreciated.
Why is it "Microsoft.Authorization/*/Delete" instead of
Microsoft.Authorization/Delete".
To understand this, please see this link especially Operations format section.
Essentially each operation is specified in {Company}.{ProviderName}/{resourceType}/{action} format.
So when you specify the operation as Microsoft.Authorization/*/Delete, you're essentially allowing delete operation on all the resources under Microsoft.Authorization resource provider.
This format also enables you to specify actions granularly at each resource level under a resource provider.

Terraform - how to remove ability to edit via console?

I have looked in the terraform documentation for a solution to this issue but have not found anything. I have a problem where my AWS account has 1000s of EC2s, SQS queues, SNS topics, dynamo tables and tons of other stuff. Some of this stuff is managed by terraform and some of it is not. I want to be able to make it so a given terraform resource is not able to be edited via the console. A simple example of an ideal conguration is as follows:
resource "aws_sns_topic" "my_topic" {
name = "my_topic_name"
is_console_configurable = false
}
Is something like the above possible to do? Or what is the best way to go about solving this issue?
Thanks in advance
Terraform itself can't directly control what the AWS console allows or does not allow.
I think in order to get an effect like this you'd need to use very granular IAM policies so that the credentials that your team is using to log in to the AWS Console do not have access to make changes to the objects managed by Terraform. You'd then use different credentials to run Terraform which do have the necessary access.
Coordinating policies at such a fine level of detail will be complicated, though. I think the closest approximation of what you showed in your example would be an IAM policy containing "Deny" statements, which you would then associate with all of the principals associated with users who have AWS Console access.
resource "aws_sns_topic" "my_topic" {
name = "my_topic_name"
}
resource "aws_iam_policy" "disable_sns_console" {
name = "SNS Topic Disable Console"
# ...
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Resource": aws_sns_topic.my_topic.arn,
},
]
})
}
You'd need to find some suitable IAM user, role, or group object to attach this policy to and ensure that every credential used for console access is associated with whatever object confers this policy.
This sort of "default allow, deny specific objects" policy is tricky because it will "fail open" if you don't set it up correctly. However, if your goal is more to inspire good behavior than to implement an infallible security layer then perhaps this compromise is reasonable.

Azure custom role: authorize role assignment for a specific set of roles

I am trying to create a custom role in Azure that would allow Subscriptions "owners" to do quite everything but cancelling/renaming their own subscriptions or moving into another management group.
I would also like them to be able to grant right access to who they want (especially built-in "Contributor" role) but without allowing them to grant "Owner" right, otherwise my custom role could be tricked easily.
I ended up with the following custom role definition which is so far nice and working, apart from the role assignment of course:
{
"Name": "MyCustomRole",
"IsCustom": true,
"Description": "Role designed for Azure subscriptions ownership limitations",
"Actions": [
"*"
],
"NotActions": [
"Microsoft.Management/managementGroups/subscriptions/write",
"Microsoft.Subscription/cancel/action",
"Microsoft.Subscription/rename/action"
],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/providers/Microsoft.Management/managementGroups/root.mg"
]
}
In the Azure documentation, the only operation I found for role assignment is Microsoft.Authorization/roleAssignments/write.
Is there any way to restrict that - to Contributor role assignment for instance - directly in the custom role?
Azure Policy might technically do the trick (not even sure), but since some operational/experts/whatever guys might end up as Owner, I do not want the policy engine to display "non-compliant" resources. It would lead customers to misunderstandings that I would like to avoid.
You might want to try Azure Policy, which you can apply on top of your IAM model. You can assign a policy on the Subscription or Management Group level, based on your governance structure.
Policy definition below will block EVERY request trying to assign "Owner" role with no exception. Built-in Owner role is represented by "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", same GUID across all Azure tenants.
However Role assignments of other RBAC roles would still be possible. This should fullfill your use case.
https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
{
"policyType": "Custom",
"mode": "All",
"displayName": "DenyOwnerAssisgnment",
"policyRule": {
"if": {
"allOf": [
{
"field": "Microsoft.Authorization/roleAssignments/roleDefinitionId",
"contains": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
},
{
"field": "type",
"equals": "Microsoft.Authorization/roleAssignments"
}
]
},
"then": {
"effect": "deny"
}
},
"type": "Microsoft.Authorization/policyDefinitions"
}
To my knowledge - no, you cannot be granular. you can only restrict a specific action.
ps. technically this is correct. but the policy usage above is really clever ;)
Yes it should be possible when you assign a policy, so it's not part of the definition but assignment. You can assign policy on the subscription-level scope, and exclude resource groups. You can do that via "notScopes".
Please see Azure Policy docs for how to do this (chapter Excluded scopes)
The scope of the assignment includes all child resource containers and
child resources. If a child resource container or child resource
shouldn't have the definition applied, each can be excluded from
evaluation by setting notScopes. This property is an array to enable
excluding one or more resource containers or resources from
evaluation. notScopes can be added or updated after creation of the
initial assignment.
https://learn.microsoft.com/en-us/azure/governance/policy/concepts/assignment-structure
You can include excluded scopes in the portal when assigning Policy or through PowerShell by including -NotScope parameter.

Resources