Security is of course a very important aspect of the application. It will be necessary to identify users for billing purposes, but also to avoid exposing sensitive information to parties that should not see it.
Ideally, we could use existing infrastructure so that we would not have to re-invent the wheel, but also because then we could use tried-and-true software. This reduces the risk of vulnerabilities.
For now, we do not manage account information of our own. Instead, we
delegate this functionality to existing platforms. In this case this is
Github and Bitbucket, which already offer user management and provide Oauth2
authentication. MonkeyCI only keeps track of the user type (which provider)
and the type-specific ID. In case of Github, the type is github
and the
type id is the numerical Github user id. For Bitbucket, the type is bitbucket
and the id is the Bitbucket user uuid.
Sensitive data includes ssh keys and build parameters. We keep these encrypted in the database, but at one point they will need to be decrypted to be passed to the jobs, either as parameters (in action jobs) or environment variables (for container jobs).
We do not want to transmit sensitive information unencrypted, e.g. in events. Therefore, we need to encrypt this data but we also have to allow the event receivers to decrypt it when necessary. To this end we use Data Encryption Keys (DEKs). The cloud provider offers a key service, which both allows us to generate new DEKs as needed, but also encrypts them. The original encryption key is not known to MonkeyCI, it remains in the key service.
Whenever a new build is started, a build-specific DEK is generated, and
added to the build/initialized
event in encrypted form. The build controller
is then able to ask the API to decrypt the key. This way, we have a double
protection layer: should the event be intercepted, the key is still useless
because it's encrypted. The attacker would also need to have a token to call
the API to decrypt the key.
Whenever a build adds sensitive data to events, e.g. when starting a container job that has environment variables, the build DEK is used to encrypt this information. The job controller in turn is also aware of the build DEK and can also contact the API to decrypt it. It will then use the DEK to decrypt environment variables before passing them to the container itself.
When using ssh keys to check out a private repository, the ssh keys are fetched directly from the database using the API, which is using TLS so it's already secure. Similarly, the build script retrieves the parameters using an API call. But when a container job is started, the environment variables are included in the event, so they should be re-encrypted at this point, only to be decrypted when they are passed to the container.
Similarly, we do not store sensitive data unencrypted in the database. Here we also have a double security layer. For each organization, MonkeyCI generates a new DEK, which is encrypted using the cloud key platform. The encrypted DEK is stored along with other organization information in the database. This DEK is in turn used to encrypt any newly generated build-specific DEKs. Whenever a client uses the API to decrypt a DEK, it needs to specify the organization id, which is then used to retrieve the correct DEK for decryption.
In order to store ssh keys and parameters in the database, each parameter or ssh key set has its own DEK, which is again encrypted using the organization DEK. This is an additional security layer: it becomes impossible to compare encrypted values because they are all encrypted using their own DEK.
All the above security measures combined should be a pretty secure defense against any attackers and should guarantee that the user's sensitive information is not exposed. It is of course up to the user to limit this information as much as possible and not expose it him/herself, e.g. by printing it in the logs or something like that.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close