-
Notifications
You must be signed in to change notification settings - Fork 36
RFC: OPA integration proposal. #41
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
07a087c
Add RFC#41: OPA integration proposal.
evanchaoli 9dbfb9d
Addressed review comments: removed audit related statements.
evanchaoli 8660cce
Addressed the review comments.
evanchaoli a36bccd
addressed review comments.
evanchaoli 030d5ae
changed `UsingImage` to `UseImage`, and add a note for image_source r…
evanchaoli 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| # Summary | ||
|
|
||
| This proposal outlines the beginnings of support for policy enforcement. OPA | ||
| (Open Policy Agent) will be used as the first policy manager to integrate with. | ||
|
|
||
|
|
||
| # Motivation | ||
|
|
||
| Generally speaking, anything that exposes an HTTP API (whether an individual | ||
| micro-service or an application as a whole) needs to control who can run those | ||
| APIs and when. | ||
|
|
||
| Concourse, as a CI platform, also needs to control who can do something and when, | ||
| which can be done by integrating with a policy manager. Before any action, send | ||
| a policy check request, with data that describes the action, to the policy manager, | ||
| and only continue if the policy manager replies a "pass". | ||
|
|
||
| Possible policies to apply could be: | ||
|
|
||
| * Steps, e.g. code security scan, by certain resource types must be done. | ||
| * Some team's tasks must be run with certain tag. | ||
| * Some docker image registries are not allowed. | ||
| * Some docker images are not not allowed. | ||
| * and so on ... | ||
|
|
||
|
|
||
| # Proposal | ||
|
|
||
| ## Support multiple policy managers | ||
|
|
||
| Like how multiple credential managers are supported, Concourse should allow other | ||
| policy managers than OPA. Thus an interface of `PolicyCheck` should be defined, and | ||
| OPA is one of the implementations. | ||
|
|
||
| ## Policy check points | ||
|
|
||
| * All API calls, for example `set-pipeline`, will also go through policy checks. If | ||
| the check doesn't pass, API should return HTTP code 403 (forbidden). | ||
| * `UseImage` action will be sent to OPA before Concourse launches a container in | ||
| `check/get/put/task` steps. If the check doesn't pass, the step should return an error | ||
| indicating policy check not pass. | ||
|
|
||
| ## OPA configuration | ||
|
|
||
| * CONCOURSE_OPA_URL - URL of OPA service including path | ||
|
|
||
| For example, OPA_URL is `http://opa.mycompany.com/v1/data/concourse/policy`, a OPA | ||
| policy check request will look like: | ||
|
|
||
| ``` | ||
| POST http://opa.mycompany.com/v1/data/concourse/policy | ||
| { | ||
| "input": { | ||
| ... | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Policy check input data | ||
|
|
||
| Policy check input data should include common metadata and action specific data. | ||
| In principle, Concourse should send as much data as possible to the policy engine. | ||
|
|
||
| Common metadata include: | ||
|
|
||
| * `service`: should be always "concourse". This will allow Concourse specific | ||
| policies to to configured in the policy engine. | ||
| * `cluster_name`: cluster name. | ||
| * `cluster_version`: Concourse version | ||
| * `action`: Action name. This follows same action names used in RBAC, plus an extra | ||
| action `UseImage`. | ||
| * `http_method`: HTTP method of the action, for `UseImage`, this field absents. | ||
| * `user`: username who invokes the action. | ||
| * `team`: team name. | ||
| * `pipeline`: pipeline name. Some action is not against a pipeline, then this field | ||
| can be omitted. | ||
| * `data`: For API actions, `data` should carry data from the API call; for `UseImage` | ||
| action, data is the image configuration. | ||
|
|
||
| For example, a policy check request against `set_pipeline` looks like: | ||
|
|
||
| ```json | ||
| { | ||
| "input": { | ||
| "service": "concourse", | ||
| "cluster_name": "some-cluster", | ||
| "cluster_version": "5.7.0", | ||
| "user": "some-user", | ||
| "team": "some-team", | ||
| "pipeline": "some-pipeline", | ||
| "action": "SetPipeline", | ||
| "data": { | ||
| "groups": [ ], | ||
| "resource_types": [ ], | ||
| "resources": [ ], | ||
| "jobs": [ ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| A policy check request of action `UseImage` looks like: | ||
|
|
||
| ```json | ||
| { | ||
| "input": { | ||
| "service": "concourse", | ||
| "cluster_name": "some-cluster", | ||
| "cluster_version": "5.7.0", | ||
| "team": "some-team", | ||
| "pipeline": "some-pipeline", | ||
| "action": "UseImage", | ||
| "data": { | ||
| "image_type": "registry-image", | ||
| "image_source": { | ||
| "repository": "busybox", | ||
| "tag": "latest", | ||
| "username": "someone", | ||
| "password": "(redacted)" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| _NOTE: any secret appearing in `image_source` that is fetched from credential | ||
| manager or var_sources should be redacted._ | ||
|
|
||
|
|
||
| ## Policy check switches | ||
|
|
||
| If no policy manager is configured, then policy check is switched off. | ||
|
|
||
| When a policy manager is configured, Concourse intends to use "explicit" strategy | ||
| to decide which actions should run policy checks, meaning that, without defining | ||
| policy check filters, no action will run policy check. | ||
|
|
||
| Users may not want to run policy check against all actions. For example, Concourse | ||
| generate a large amount of `ListAllPipelines`, and it makes not much sense to check | ||
| it. | ||
|
|
||
| Users will tend to check with the policy manager for write actions rather than | ||
| read-only actions. As all actions except `UseImage` are invoked from HTTP, we | ||
| can provide a filter, `policy-check-filter-http-method`, to specify HTTP | ||
| methods via which actions are invoked. To skip read-only action for policy | ||
| check, users may set `POST,PUT,DELETE` to the filter `policy-check-filter-http- | ||
| method`, so that `GET` actions will not go through policy check. | ||
|
|
||
| User also may specifically want to or don't want to do run policy check against | ||
| certain actions. For example, a cluster will want to check policy against only | ||
| `SetPipeline`, or the other cluster don't want to check policy against `UseImage`, | ||
| for which two more filters, `policy-check-filter-action` and `policy-check- | ||
| filter-action-skip` are supported. If an action is defined in action list, then | ||
| the action will always go through policy check, vice versa for action-skip list. | ||
|
|
||
| In summary, where are three policy check filters: | ||
|
|
||
| * `policy-check-filter-http-method`: defines HTTP methods of actions that | ||
| should go through policy checks. Default to empty list. | ||
| * `policy-check-filter-action`: defines action names that should always go | ||
| through policy checks. Default to empty list. | ||
| * `policy-check-filter-action-skip`: defines action names that should never | ||
| go through policy checks. Default to empty list. | ||
|
|
||
|
|
||
| # Open Questions | ||
|
|
||
| * What else policy points? | ||
|
|
||
| * What else policy engines than OPA folks are using? | ||
|
|
||
| * Does it make sense to share Audit's switches to control policy checks? | ||
|
|
||
|
|
||
|
|
||
| # Answered Questions | ||
|
|
||
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.
Do you see this as something that should only be configured cluster-wide? Or would it make sense to you to have this configured on a per-team basis?
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.
For our use cases, we don't need per-team OPA. If a team/pipeline wants to use their own OPA, an OPA resource type can be used.