-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat: OPA Authorizer #777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
labrenbe
wants to merge
21
commits into
main
Choose a base branch
from
feat/opa-authorizer
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: OPA Authorizer #777
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
88944a6
add support for authorization with OPA
labrenbe 142f867
add docs on authorization with OPA
labrenbe e603d7d
update helm chart
labrenbe 39caff2
Merge remote-tracking branch 'origin/main' into feat/opa-authorizer
labrenbe 032ab37
rename input.user to input.identity
labrenbe 4470e83
Merge remote-tracking branch 'origin/main' into feat/opa-authorizer
labrenbe 6bd4831
add opa cm watch
labrenbe b87430b
remove unused test
labrenbe 3c9c7c1
update rego with new opa response schema
labrenbe 7dd6e38
update docs
labrenbe 47f1ab5
improve docs
labrenbe 150dfdd
update docs
labrenbe 9b3e0d3
Merge remote-tracking branch 'origin/main' into feat/opa-authorizer
labrenbe 031820b
fix docs
labrenbe 13e60bc
refactor references_config_map function
labrenbe cfa6783
fix docs
labrenbe f9bcd44
wip: add integration test
labrenbe 46fc511
add retries to nifi calls during test
labrenbe 8f0a02f
simplify rego rules
labrenbe ca61f92
move nifi flow copying into init container
labrenbe 6e66627
remove oidc test and fix oidc-opa test with tls disabled
labrenbe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,9 +1,14 @@ | ||||||
= Security | ||||||
:description: Secure Apache NiFi on Kubernetes with TLS, authentication, and authorization using the Stackable operator. Configure LDAP, OIDC, and sensitive data encryption. | ||||||
:nifi-docs-authorization: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#multi-tenant-authorization | ||||||
:nifi-docs-access-policies: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#access-policies | ||||||
:nifi-docs-component-level-access-policies: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#component-level-access-policies | ||||||
:nifi-docs-access-policy-inheritance: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#access-policy-inheritance | ||||||
:nifi-docs-fileusergroupprovider: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#fileusergroupprovider | ||||||
:nifi-docs-fileaccesspolicyprovider: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#fileaccesspolicyprovider | ||||||
:nifi-docs-sensitive-properties-key: https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#nifi_sensitive_props_key | ||||||
:nifi-opa-plugin: https://github.com/DavidGitter/nifi-opa-plugin/ | ||||||
:opa-rego-docs: https://www.openpolicyagent.org/docs/latest/#rego | ||||||
|
||||||
== TLS | ||||||
|
||||||
|
@@ -168,7 +173,7 @@ stringData: | |||||
|
||||||
NiFi supports {nifi-docs-authorization}[multiple authorization methods], the available authorization methods depend on the chosen authentication method. | ||||||
|
||||||
Authorization is not fully implemented by the Stackable Operator for Apache NiFi. | ||||||
The Stackable Operator for Apache NiFi supports a default authorization methods for each authentication method and authorization with Open Policy Agent. | ||||||
|
||||||
[#authorization-single-user] | ||||||
=== Single user | ||||||
|
@@ -190,6 +195,171 @@ With this authorization method, all authenticated users have administrator capab | |||||
An admin user with an auto-generated password is created that can access the NiFi API. | ||||||
The password for this user is stored in a Kubernetes Secret called `<nifi-name>-oidc-admin-password`. | ||||||
|
||||||
[#authorization-opa] | ||||||
=== Open Policy Agent (OPA) | ||||||
|
||||||
NiFi can be configured to delegate authorization decisions to an Open Policy Agent (OPA) instance. More information on the setup and configuration of OPA can be found in the xref:opa:index.adoc[OPA Operator documentation]. | ||||||
|
||||||
A NiFi cluster can be configured with OPA authorization by adding this section to the configuration: | ||||||
|
||||||
[source,yaml] | ||||||
---- | ||||||
spec: | ||||||
clusterConfig: | ||||||
authorization: | ||||||
opa: | ||||||
configMapName: simple-opa # <1> | ||||||
package: my-nifi-rules # <2> | ||||||
cache: | ||||||
entryTimeToLive: 5s # <3> | ||||||
maxEntries: 10 # <4> | ||||||
---- | ||||||
<1> The name of your OPA Stacklet (`simple-opa` in this case) | ||||||
<2> The rego rule package to use for policy decisions. | ||||||
The package needs to contain an `allow` rule. | ||||||
This is optional and defaults to the name of the NiFi Stacklet. | ||||||
<3> TTL for items in the cache in NiFi. | ||||||
<4> Maximum number of concurrent entries in the cache in NiFi | ||||||
|
||||||
[#defining-rego-rules] | ||||||
=== Defining rego rules | ||||||
|
||||||
For a general explanation of how rules are written, please refer to the {opa-rego-docs}[OPA documentation]. Authorization with OPA is done using a {nifi-opa-plugin}[custom authorizer provided by a plugin for NiFi]. | ||||||
|
||||||
[#opa-inputs] | ||||||
==== OPA Inputs | ||||||
The payload sent by NiFi with each request to OPA, that is accessible within the rego rules, has the following structure: | ||||||
|
||||||
[cols="1,2,1"] | ||||||
|=== | ||||||
| Payload Field| Description| Possible Values | ||||||
| action.name | ||||||
| The action taken against the resource. | ||||||
|`read`, `write` | ||||||
| resource.id | ||||||
| The unique identifier of the resource that is being authorized. | ||||||
| | ||||||
| resource.name | ||||||
| The name of the resource that is being authorized. | ||||||
| | ||||||
| resource.safeDescription | ||||||
| The description of the resource that is being authorized. | ||||||
| | ||||||
| requestedResource.id | ||||||
| The unique identifier of the original resource that was requested (see <<component-level-access-policies>>). | ||||||
| | ||||||
| requestedResource.name | ||||||
| The name of the original resource that is being authorized on (see <<component-level-access-policies>>). | ||||||
| | ||||||
| requestedResource.safeDescription | ||||||
| The description of the resource that is being authorized on (see <<component-level-access-policies>>). | ||||||
| | ||||||
| identity.name | ||||||
| The name of the identity/user accessing the resource. | ||||||
| | ||||||
| identity.groups | ||||||
| Comma-separated list of groups that the identity/user accessing the resource belongs to. | ||||||
| | ||||||
| properties.isAccessAttempt | ||||||
| Whether this is a direct access attempt of the resource or if it's being checked as part of another response. | ||||||
| `true`, `false` (String) | ||||||
| isAnonymous | ||||||
| Whether the entity accessing the resource is anonymous. | ||||||
| `true`, `false` (String) | ||||||
| resourceContext | ||||||
| Object containing the event attributes to make additional access decisions for provenance events. | ||||||
| ```{"": ""}``` if empty | ||||||
| userContext | ||||||
| Additional context for the user to make additional access decisions. | ||||||
| ```{"": ""}``` if empty | ||||||
|=== | ||||||
|
||||||
[#opa-result] | ||||||
==== OPA Result | ||||||
|
||||||
The OPA authorizer plugin expects relo rules to be named `allow` and to return a result following this schema: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
[source,json] | ||||||
---- | ||||||
{ | ||||||
"allowed": <Boolean>, # <1> | ||||||
"resourceNotFound": <Boolean>, # <2> | ||||||
"dumpCache": <Boolean>, # <3> | ||||||
"message": <String>, # <4> | ||||||
} | ||||||
---- | ||||||
<1> Whether the action against the resource is allowed. Optional, defaults to false. | ||||||
<2> Whether no rule was found for the authorization request. This should only be set to true in the default rule. If set to true the value of the "allowed" field will be ignored. Optional, defaults to false. | ||||||
<3> Whether the whole local cache in the OPA authorizer plugin in NiFi should be invalidated. Optional, defaults to false. | ||||||
<4> An optional error message that is shown to the user when access is denied. | ||||||
|
||||||
[#access-policies] | ||||||
==== Access Policies | ||||||
NiFi uses {nifi-docs-access-policies}[access policies] to manage access to system-wide resources like the user interface. | ||||||
|
||||||
[#component-level-access-policies] | ||||||
==== Component Level Access Policies and Access Policy Inheritance | ||||||
|
||||||
{nifi-docs-component-level-access-policies}[Component Level Access Policies] allow managing granular access to components like process-groups and processors. Components can {nifi-docs-access-policy-inheritance}[inherite access policies] defined for parent components, e.g. a process group is the parent component for a processor component. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
The payload field `requestedResource` contains the id, name and description of the original resource that was requested. In cases with inherited policies, this will be an ancestor resource of the current resource. For the initial request, and cases without inheritance, the requested resource will be the same as the current resource. | ||||||
|
||||||
When an authorizer returns "resourceNotFound" as result instead of an authorization decision, NiFi will send an authorization request for the parent component. Access policy inheritance can be recursive up to the root component. If "resourceNotFound" is returned for an authorization request and the component doesn't have a parent component, NiFi will deny access to the component. | ||||||
|
||||||
To manage access for all process groups in the NiFi instance a rule has to be defined for the root process group which is identified by the resource name "NiFi Flow" and a resource id generated at random ("/process-groups/<uuid>"). | ||||||
|
||||||
[source,rego] | ||||||
---- | ||||||
default allow := { | ||||||
"resourceNotFound": true | ||||||
} <1> | ||||||
|
||||||
allow := { | ||||||
"allowed": true | ||||||
} if { | ||||||
input.resource.name == "NiFi Flow" | ||||||
startswith(input.resource.id, "/process-groups") | ||||||
} <2> | ||||||
|
||||||
allow := { | ||||||
"allowed": false | ||||||
} if { | ||||||
input.resource.id == "/process-groups/a10c311e-0196-1000-2856-dc0606d3c5d7" | ||||||
input.identity.name == "alice" | ||||||
} <3> | ||||||
---- | ||||||
<1> Default rule returns should `"resourceNotFound": true`. If this is not set NiFi's access policy inheritance won't work. Any values for the `allowed` field in the response will be ignored. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
<2> A rule that grants all users access to the root process group and thus to all components in the NiFi instance. | ||||||
<3> A rule that denies access to a specific process group for the user "alice". For this process group the default rego rule will not be applied and NiFi's component inhertiance will not be used. All child components of this process group will also be authorized based on this rule unless a more granular rule overrides it. | ||||||
|
||||||
[#communication-between-nifi-nodes] | ||||||
==== Communication between NiFi nodes | ||||||
To allow communication between NiFi nodes an additional rego rule is required: | ||||||
[source,rego] | ||||||
---- | ||||||
allow := { | ||||||
"allowed": true | ||||||
} if { | ||||||
input.identity.name == "CN=generated certificate for pod" # <1> | ||||||
input.resource.id == "/proxy" # <2> | ||||||
} | ||||||
---- | ||||||
<1> The identity of NiFi nodes authenticated with TLS certificates provided by the secrets operator. | ||||||
<2> Only access to the `/proxy` API is required. | ||||||
|
||||||
[#caching] | ||||||
==== Caching | ||||||
|
||||||
The OPA authorizer has a mechanism to cache results from OPA which can be configured in the NifCluster spec (see above). To delete the whole cache add `"dumpCache": true` to the result. | ||||||
[source,rego] | ||||||
---- | ||||||
allow := { | ||||||
"allowed": false | ||||||
"dumpCache": true | ||||||
} if { | ||||||
... | ||||||
} | ||||||
---- | ||||||
|
||||||
[#encrypting-sensitive-properties] | ||||||
== Encrypting sensitive properties on disk | ||||||
|
||||||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont understand that sentence at all. Would you mind reformulating or explaining it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea is that there are different default authorization methods depending on the authentication method and OPA authorization which works with every authentication method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel then this can be merged with the sentence above?