Drone "Protected" Build Workaround

#1

My team and I have been experimenting with Drone. We need a way to prevent changes to the .drone.yml file by unauthorized users. We noticed that if the branch was protected, and I made a change to the YAML file, that the build would hold until someone who had the rights could deny/approve the build. However, the following workaround seemed to defeat this:

  1. Change the .drone.yml file
  2. Go to the Drone UI and cancel the build (I cannot approve or deny it at this stage)
  3. Restart the same build manually

The manually restarted build finishes with no issues and uses the new YAML file, going around the protection. I took a bit of a dive into the code to see if I could find the cause of this, and it appears the IsGated check is only being run on the Pull Request event, and I assume a manual restart of a build does not match this check.

#2

Protected builds attempts to mitigate an attack vector where an individual with read access to your public github repository submits a malicious pull request that alters the yaml configuration file, in an attempt to expose secrets.

In this case it sounds like someone with admin declined and then manually re-started the build. This seems outside the scope of what protected mode tries to solve for, but perhaps I’m not fully understanding the issue.

#3

That is correct, we are trying to solve the use case where we want individual developers who have write access contributing to the codebase but not necessarily allowing them to alter the build pipeline itself (at least not without approval from some admin).

In our test case, I was given just write permissions to the codebase, then I altered the .drone.yml and committed. A build was triggered which I could not approve nor deny as I did not have sufficient permissions. I then cancelled the build and restarted it. The restarted version went through without an approve/deny. My assumption was that, since I did not have permission to approve the initial build, I shouldn’t be able to just cancel and rebuild and have the build go through.

#4

as a user with write access you have the ability to generate a new signature, which means if you push code and the build is blocked, you would generate a new signature, and then push new code to run you build.

I think changing the backend logic in Drone to prevent declined builds from being restarted makes sense, and will make this change. However, I’m not sure this is going to sufficiently solve for your use case since a user with write access can re-sign the yaml. There may be other workarounds possible since this was not part of the initial design goals (not trying to be difficult, just making a disclaimer :slight_smile:)

#5

Thanks for the quick responses! We have been poking around with various CI tools to see which ones fit our needs (including security in this case) and we have really been liking Drone. I guess on a similar note to this, is there any sort of option for a middleware that can be configured on the Drone server itself which would intercept build requests and, before they are run, go through a set of pre-defined actions? I am imagining the following scenario:

  1. User with write access makes a change to the drone.yml
  2. Request gets fired off via a git webhook to the Drone Server
  3. Server-configured middleware intercepts request and, prior to kicking off build, runs through a command which (in this case) has been written to check if the user is making a change to the drone.yml and, if so, are they in some list (stored somewhere - S3/Azure Blob/Redis/etc.) of users which are allowed to change the YAML file.
  4. If it fails the middleware, the build fails.

Such a middleware of course would not be configured inside the .drone.yml (because someone could just change it) but in the Drone Server itself. I saw there was a concept of plugins inside Drone, but it appears that they were to be configured inside the YAML itself.

#6

We have been adding middleware to Drone, which we call plugins, although perhaps middleware is a better name :slight_smile: . I think in this case our configuration plugin could be interesting for you [1]. A configuration plugin simply overrides the process of fetching and returning the yaml configuration file to Drone. It can enable some really cool use cases, such shared and global configuration, support for alternate formats such as jsonnet, and more [2].

You could create a configuration plugin that fetches the yaml, checks if the yaml was changed, and by who. If changed by an unauthorized user you could return an error, thus preventing the build from running.

The documentation is sparse because this is all very new, but we do have a few example plugins and a starter project on github [3] that you can use to get started.

[1] https://docs.drone.io/extend/config/
[2] https://github.com/drone/drone/issues/1021#issuecomment-417819643
[3] https://github.com/drone/drone-config-plugin-starter

#7

check if the user is making a change to the drone.yml and, if so, are they in some list (stored somewhere - S3/Azure Blob/Redis/etc.)

It might be cool if you use GitHub team membership to determine if the user is authorized to modify the yaml configuration file. It makes managing the list relatively simple and less technology specific (in the sense that everyone uses GitHub these days, but not everyone uses S3, Redis, etc), and I could see this being adopted by other teams using Drone should you choose to make it public. Just my 2 cents :slight_smile:

#8

Coincidentally we were just looking at Github Teams for security, so I think that is a great idea :slight_smile: We will take a look at the extensions documentation; it sounds like they are built to solve our use case. Thanks very much!

#9

Hello Everyone

I am facing a similar problem as @Lucretius and here is a suggestion: In project settings, we add a restriction on git branch(es) on which Drone will start new pipelines. Since most teams already have checks in place to merge new code into master, we know that pipeline configs in the master branch are good to run.

Of course this won’t solve all the possible cases where build triggers can be misused along with malicious pipeline configs, but seems like a good check to have anyway.

#10

Since most teams already have checks in place to merge new code into master, we know that pipeline configs in the master branch are good to run.

@stingerpk this is possible using configuration plugins. You can create a configuration plugin that sources the Yaml file from the master branch for a subset (or all) of your repositories. Note that plugins are the preferred method of customization vs building such logic into Drone core.

Starter project / example for creating configuration plugins: https://github.com/drone/drone-config-plugin-starter

#11

Just a crazy idea on the topic of securing the .drone.yml file from being altered…

It seems to me that a [git] project repo, where the user has rw access, could have a very basic pipeline performs a submodule checkout on a ro repo that contains a .drone.yml that runs a drone container that clones the original project and builds it within itself.

It’s ugly (and probably dumb) but I don’t see a reason why this wouldn’t work. :confused:

#12

Since this functionality will be delegated to plugins, anyone will have the ability to create a plugin and try out new and innovative ways of validating yaml configuration files.

1 Like
#13

Ah! ok I get it. Yes! And, in fact, I’ve just made my first drone (hellow world) plugin as of 10 minutes ago.

You guys are awesome -where can I get a 'I :heart: drone" t-shirt?! I’ve been mucking with drone for all of three days -it is really a refreshing system to work with.