09 3 security
Authorization Policy💣
Authorization is answering the access control portion of the question. Is an authenticated principal allowed to perform an action on an object? Can User A send a GET
request to path /hello
to Service A? Remember that certain actions may still be prohibited even if we authenticate a principal.
Your company ID card might be valid and authentic. However, you won’t be able to use it to enter the offices of a different company. If we continue with the customs officer metaphor from before, authorization is similar to a visa stamp in your passport.
It is essential to have both authentication and authorization. Without one or the other, it will not be beneficial. For proper access control, we need both.
For example: If we only authenticate the principals and don’t authorize them, they can do anything and perform any actions on any objects. Conversely, suppose we authorize a request but don’t authenticate it. In that case, we can pretend to be someone else and perform any actions on objects again.
Armed with an authenticated principal, we can now decide to restrict access based on that. To do that, we use an AuthorizationPolicy
. The AuthorizationPolicy
resource is where we can use the principle from the PeerAuthentication
policies and the RequestAuthentication
policy. Suppose we attempt to write policies based on peer or service identities. In that case, we can use the principals’ field, and if we are making decisions based on the users, we will use request principals.
This example applies the AuthorizationPolicy
to all workloads matching the app=prod
label. The second part of the resource is where we define the rules and say that we allow calls from a source with any requestPrincipal
set. We aren’t checking for any specific principal here, just that the principal is set. With this AuthorizationPolicy
and the RequestAuthentication
policy, we guarantee that only authenticated requests will reach the prod workloads.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: default
spec:
selector:
matchLabels:
app: prod
rules:
- from:
- source:
requestPrincipals: ["*"]
The previous example was simple, but we can write rules in the authorization policies in multiple ways. We have seen the from
field in the last example. With from
, you can define a list of source identities, namespaces, and principals allowed to call the services to which we’ve applied the policy.
This example will allow calls from services that use the workload service account, are coming from the prod namespace, and have the requesting principal set to tetrate.io/nauticalmike
.
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/workload"]
- source:
namespaces: ["prod"]
- source:
requestPrincipals: ["tetrate.io/nauticalmike"]
All these sources, principals, request principals, namespaces, and IP blocks also have negative matches, so we could write notPrincipals
or notNamespaces
to include a list of negative matches.
For example: If we want to apply the rules to all the namespaces except the prod
namespace, we could write notNamespaces: ["prod"]
.
The second field is the to
field. This field is where we can specify what paths, methods, ports, or hosts we use when making the calls to the service. This example shows that we can call DELETE
on the /logs
path, call GET
on the /data
path, and allow ports 3000
or 5000
for requests from request.host
:
rules:
- from:
- ...
to:
- operation:
methods: ["DELETE"]
paths: ["/logs*"]
- operation:
methods: ["GET"]
paths: ["/data"]
- operation:
hosts: ["request.host"]
ports: ["3000", "5000"]
Like with the from
field, we can also write negative matches.
For example: notMethods
, notPath
, and notHosts
.
The when
field permits us to specify various conditions depending on the attributes of the request, such as headers, source IP, remote IP, namespaces, principals, destination ports, and connection SNI.
This example shows that we can only make the calls from
and to
when the request has a valid JWT token that was issued by accounts.google.com
when the my-header
contains some-value
and the request is coming from the foo
namespace:
rules:
- from:
to:
when:
- key: request.auth.claims[iss]
values: ["https://accounts.google.com"]
- key: request.headers[my-header]
values: ["some-value"]
- key: source.namespace
value: ["foo"]
...
Once we’ve written the rules, we can configure the action. We can either ALLOW
or DENY
the requests matching those rules. Additional supported actions are CUSTOM
and AUDIT
.
The CUSTOM
action specifies our custom extension to handle the request. You must configure the custom extension in the MeshConfig
. An example of this would be if you wanted to integrate a custom external authorization system to delegate the auth decisions. The CUSTOM
action is experimental, which might break or change in future Istio versions.
The AUDIT
action audits a request that matches the rules. If the request matches the rules, the AUDIT
action will trigger logging that request. This action does not affect where the request is allowed or denied. Only DENY
, ALLOW
, and CUSTOM
actions can do that. A sample scenario for when you could use the AUDIT
action is when you are migrating your workloads from Permissive
to STRICT
mTLS mode.
spec:
action: DENY
rules:
- from:
to:
when:
...
In summary, services get their identity through x.509 certificates from service accounts in Kubernetes. To manage the communication between services, use the PeerAuthentication
resource. You can choose between Permissive
or STRICT
mutual TLS mode settings here.
The system saves specific metadata about the authenticated service, such as the principal name. It can later use to impose access control. Utilize the RequestAuthentication
resource to verify the identity of users using JWT tokens. Once users have verified their identity, the system uses the data in the JWT token to control their access.
After obtaining the authenticated principal, which can be a service or a user, we can utilize an AuthorizationPolicy
to determine which services have permission to access the workloads and establish restrictions for methods and paths.
Next💣
Next, we will focus on the security lab.