Key | Value |
---|---|
Author(s) | David.Vader |
Date | May 11th, 2023 |
Status | Under Review |
Please provide a summary of the new feature, redesign or refactor:
This proposal is small piece to a larger effort to increase the overall security of the platform.
The problem being solved is that the Redis queue is currently a potential attack vector with direct regard to the information compiled in plaintext into the executable pipeline build object, namely the NETRC_PASSWORD
placed in the environment.
The feature proposed is a modification to what data the server places directly on the queue and to offload the potentially sensitive executable pipeline build to a table in the database that must be requested when the build is ready for execution. The server would enqueue only the build's ID, which the worker would pop from the queue. The worker would use a minted build token to retrieve the executable pipeline build, increasing the work required to compromise a repo owner's token in the event of a worker compromise. This should not impact the functionality of the platform, and is moreso a security-driven improvement to decrease Redis' potential as an attack vector.
The main advantage to this approach would be that the NETRC_PASSWORD
is no longer stored on the Redis queue at any point in the build execution workflow.
Please briefly answer the following questions:
- Why is this required?
- improves security by removing potentially sensitive pipeline information from the queue
- takes a greater "dumb worker" approach by giving them less direct-access to potentially sensitive data
- moves access to sensitive pipeline information behind the worker auth & build token process
- If this is a redesign or refactor, what issues exist in the current implementation?
The current queue implementation involves placing sensitive pipeline information like the user token in Redis, and the worker depends on this information being present to properly execute builds.
- Are there any other workarounds, and if so, what are the drawbacks?
It's possible to improve security around the queue in other ways, like using a READONLY replica, though it doesn't improve the sensitivity of the data that can be read.
We could also look into GitHub Apps to limit the blast radius if the queue were compromised as an attack vector.
- Are there any related issues? Please provide them below if any exist.
Indirect: #804
Please describe your solution to the proposal. This includes, but is not limited to:
- new database table to store interim executable builds
- new endpoint to retrieve a executable build from the server
- modification to the Item currently placed on the queue to only push build ID
- modification to webhook processing to push the executable build to a separate table
- added interaction between worker and server to request an executable build
For reference please review the following design diagram that explains the approach from a high level.
flowchart TD
A[GitHub] --> B[Vela Server]
B --> |compile\npush executable build| C[Redis Queue]
C --> |pop executable build| D[Vela Worker]
D --> E(execute build)
F[GitHub] --> G[Vela Server]
G --> |compile\npush executable build| H[Database]
G --> |push build_id| K[Redis Queue]
K --> |pop build_id| I[Vela Worker]
I --> |request executable build\nfrom server via build_token| G
I --> J(execute build)
New functionality that is absolutely required:
- GET
api/v1/<org>/<repo>/build/<number>/executable
orapi/v1/search/builds/<id>/executable
to retrieve an executable pipeline build using a build token database/executable-build
package and a new database tableexecutable_build
that will contain serialized executable pipeline builds in bytes, formerly stored directly on the Redis queue.- separate database row creation in addition to the Redis Item push
- should perform a GET
api/v1/<org>/<repo>/build/<number>/executable
orapi/v1/search/builds/<id>/executable
to retrieve an executable pipeline build using a build token
Removing the pipeline.Build
from the Item
published to the queue, which represents the "executable pipeline build" (aka "executable build").
// Item is the queue representation of an item to publish to the queue.
type Item struct {
Build *library.Build `json:"build"`
- Pipeline *pipeline.Build `json:"pipeline"`
Repo *library.Repo `json:"repo"`
User *library.User `json:"user"`
}
Please briefly answer the following questions:
- Is this something you plan to implement yourself?
Yes
- What's the estimated time to completion?
3-4 days
Please provide all tasks (gists, issues, pull requests, etc.) completed to implement the design:
Please list any questions you may have:
N/A