The annotation processing to deliver BigFatSecuritySwitch (or deferring to another method) is basically what I'd do.
Provided the build fails, I guess it doesn't really matter whether it's a method-not-found, or an enforcer-style rule (e.g: No calling @deprecated). Basically I *know* I'm lazy, and unless the toolchain basically forces me to fix something, I know I never will. My indolence then means it's hard to remove old, crufty things. As to whether using annotations to both provide the machinery for API manipulation *and* the documentation / 'end-user API' for it I guess is a judgement call. Personally I rather prefer in my IDE if I type JenkinsThing<dot> it doesn't provide me with the history of the universe of methods with annotations my IDE won't understand. But I also appreciate that there are platform constraints (e.g: you can't tell which java interface a method was called through, meaning interface-versioning is quite hard) that mean it's hard to satisfy everyone. I'll prepare the barricades before someone suggests OSGi or other similar self-abuse toolkits :-) On Wed, Sep 16, 2015 at 12:27 PM, Stephen Connolly < [email protected]> wrote: > Well @Restricted(DoNotUse.class) should give you a build time failure > if you are using the Maven toolchain... if you are using the groovy > toolchain I presume you can add the same checks... > > What I think you are thus asking for is something like > > @SecureAlternative(name="getFooSecure") > public Foo getFoo(...) { > ... > } > > public Foo getFooSecure(...) { > ... > } > > So that when the annotation is processed the annotated method gets the > equivalent injected: > > if (BigFatSecuritySwitch.isActive()) { > return getFooSecure(...); > } > > at the start > > If we design the BigFatSecuritySwitch.isActive() method correctly, the > JVM should be able to inline all the way and remove the cost of the > branch point. > > The downside that I see is that we end up in the nightmare of the > getInstance() -> getActiveInstance() transition (which should really > have been adding @NonNull to getInstance() and adding a > getInstanceUnchecked() method) > > So perhaps an even better way would be > > @UnsecureAlternative(name="getFooUnsafe", until="1.650") > public Foo getFoo(...) { > ... > } > > private Foo getFooUnsafe(...) { > ... > } > > With the above you inject (as long as Jenkins' pom.xml's version < > 1.650) the following into getFoo() > > if (!BigFatSecuritySwitch.isActive()) { > return getFooUnsafe(...); > } > > We could then add an Admin monitor that looks at the until fields on > Jenkins and tells you if any of your plugins were compiled against a > version of Jenkins older than the until... similarly the plugin > manager could alert you for plugins that are compiled against an older > jenkins than your oldest until... (we could expose the same logic for > plugin dependencies so that plugins could use the @UnsecureAlternative > annotation also) > > The advantage of @UnsecureAlternative is that we get to move the API > contracts while allowing people to flick the switch if they don't care > > WDYT? > > On 16 September 2015 at 11:58, Nigel Magnay <[email protected]> > wrote: > > From the perspective of a plugin developer and Jenkins Instance owner, > who > > often goes months at a time between re-visiting plugin code, I'd like the > > following (ymmv, of course!): > > > > 1) I'd like the interfaces I build to, to not have at all interface > methods > > and fields that are no longer secure / broken. I.E: If I upgrade my POM > to > > point to a 'new' version of Jenkins 1.629, I'd like the compile to fail > if > > I'm using something that is broken, security or otherwise. > > > > Having @Restricted and @Deprecated annotations all over the place just > means > > I'm likely never to even notice, let alone actually get around to doing > the > > work to update it. Looking at the API becomes a total mess of ancient > cruft. > > Every time I see "@deprecated" I just think "oh yeah.. when?" > > > > 2) I don't want to have to touch plugins when updating an LTS version, > and I > > don't want LTS versions to break 'just because of security'. I'm > firewalled, > > and frankly couldn't care less about security - it's just a gigantic ache > > for me that I'd like a big red button marked 'OFF'. > > > > Thus: > > > > Could we have a mechanism where Jenkins maintains all the old APIs in the > > binary (I.E: allows plugins build against older versions of Jenkins to > > continue to function without change) - but you build against a 'stripped' > > version of the current, "correct" API? > > > > In the example where the signature doesn't change, but the contract > > potentially does - if it's not reasonable to be able to turn off the > > security change (big-red-off), then I think the signature should change. > The > > interface has been versioned. > > > > At least this way you could probably have tight security on installs that > > need it (If jenkins is Version X, all plugins must be built to that > version > > or later, and @Restricted methods can safely fail closing the back door). > > You could also use the jenkins version the plugin built against to > control > > whether your API - by default - applies new semantics or old ones. > > > > > > > > On Tue, Sep 15, 2015 at 11:39 AM, Stephen Connolly > > <[email protected]> wrote: > >> > >> Those of us who are on the jenkins-cert list have probably seen my > >> comments about how there needs to be some guidance from the community > >> on how far SECURITY issue fixes can go. > >> > >> I am starting this thread to try and start compiling that guidance. > >> > >> The general problem (as I cannot share the specifics outside of the > >> jenkins-cert list) is as follows: > >> > >> * User raises a SECURITY issue from noticing some implicitly defined > >> API of Jenkins has a hole of some sort > >> * We have to fix the issue, but fixing it will involve changing the > >> implicitly defined API and thus risking breaking existing "users" of > >> the implicitly defined API > >> * Much heated debate around should we leave the old API present and > >> try and redirect to the new one (thereby leaving the hole open) or > >> break existing plugins and close the hole. > >> > >> In some cases it is possible to use a system property to re-enable the > >> hole for those users who are accepting of the risk... but other cases > >> require changing class structures (this can range from encapsulating > >> fields to completely reworking the java class that gets returned) > >> > >> My view is that a hole is a hole until it is fully plugged, and if > >> plugging the hole means that some plugins break, well sorry but > >> SECURITY... now by all means we should seek to minimize that breakage > >> *while closing the hole*... and where possible we should provide a > >> System property based switch to re-open the hole for those users who > >> upgrade and are ok with the risk. > >> > >> Let's take a semi-concrete example: > >> > >> In order to fix SECURITY-144 we had to change the interface of > >> h.r.Callable to include the role checking... being pre-java 8 we > >> cannot use default methods, so this was a backwards incompatible > >> change... any plugin that does not implement the role checking method > >> would potentially be broken... as a result - and after much debate - > >> it was decided that a majority of people implicitly trust their slaves > >> as much as the master and so the role checking is likely not required > >> for maybe 60-70% of installations. Thus the role checking ships off by > >> default and we implemented a way to whitelist plugins that are > >> compiled without role-checking support. Thus if you have slaves that > >> are less trusted than the master you can opt-in to the higher security > >> requirements... if there are plugins that you need that get broken, > >> you can white-list those specific plugins if you absolutely need to. > >> > >> The point here is that we closed the hole. We felt the risk of plugins > >> being broken was sufficiently high that the hole would not be closed > >> by default (The plan is to measure the plugins with support for roles > >> and once above a threshold then turn on secure by default) but when > >> the security is turned on it is on. > >> > >> So what kind of things do we need guidance on: > >> > >> * Some methods of some objects allow you to discover information about > >> other objects that you do not have permission to discover. > >> - Do we just protect the ways that we know about and leave the > >> original method present with a @Restricted(DoNotUse.class) so that > >> when plugins upgrade their core version they are forced to switch to > >> the new method; or > >> - Do we change the contract of the current method (so it now > >> returns maybe a null or throws an exception or omits entries from a > >> collection) so that the method does what it was originally supposed to > >> do but didn't... this may break existing plugins in fun and exciting > >> ways > >> > >> * Some objects have public fields that are either mutable or of a type > >> that needs to be changed in order to remove the hole. > >> - Do we leave the field as is and just introduce the new accessor > >> methods - leaves the hole as is... so we have to rely on adding a > >> stapler action method (since they are higher priority than public > >> fields) to mask that route to discovery via Web and hope that there > >> are no other routes to that field... > >> - Do we say kill that field, you shouldn't have been using it (oh > >> and let's hire a hitman to find the lazy developer who made a public > >> field rather than use their IDE to generate getters and setters) and > >> risk breaking any plugins that actually use the field. > >> > >> * Some HTTP requests can be used for more than their original intended > >> purpose. Jenkins Admins may well have discovered this and - rather > >> than thinking oh look a security issue - used such back doors to do > >> important things for their instance > >> - Do we try and make such back-door usage as safe as possible - > >> which in a sense makes this side-usage officially part of the API of > >> that HTTP request > >> - Do we lock the HTTP request down to its original intended > >> purpose and break any side-effect usage that Jenkins Admins were > >> hijacking? > >> > >> There are probably other classes of guidance required, but my brain is > >> melted trying to derive the classes from the issues I am aware of so I > >> cannot think of any others at the moment. > >> > >> It all boils down to the question: > >> > >> Which is more important, maintaining backwards compatibility or fixing > >> the security hole. > >> > >> My view is that fixing the security hole trumps backwards > >> compatibility, if we have to break a few plugins or a Jenkins admin > >> has to find a different way to solve their problem... well sorry but > >> SECURITY... that doesn't mean we should start by breaking backwards > >> compatibility, rather we should do everything we can to close the hole > >> while maintaining backwards compatibility... but when that isn't > >> enough to close the hole (and usually it is not enough BTW)... well we > >> need to close the hole. > >> > >> Over to you! > >> > >> -- > >> You received this message because you are subscribed to the Google > Groups > >> "Jenkins Developers" group. > >> To unsubscribe from this group and stop receiving emails from it, send > an > >> email to [email protected]. > >> To view this discussion on the web visit > >> > https://groups.google.com/d/msgid/jenkinsci-dev/CA%2BnPnMw6rhFBDP-jjqaaNN8YZoxT1kqGUXR1F9hvDT6s%2B01_Bw%40mail.gmail.com > . > >> For more options, visit https://groups.google.com/d/optout. > > > > > > -- > > You received this message because you are subscribed to the Google Groups > > "Jenkins Developers" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to [email protected]. > > To view this discussion on the web visit > > > https://groups.google.com/d/msgid/jenkinsci-dev/CAPYP83R8yd%3DD%3D%2BeQdoGVCgsOk4_YyuXn7K4ePqZe4DLdQhL%2Bxg%40mail.gmail.com > . > > > > For more options, visit https://groups.google.com/d/optout. > > -- > You received this message because you are subscribed to the Google Groups > "Jenkins Developers" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/jenkinsci-dev/CA%2BnPnMyxdOjQyRZ2QUBqOrW791nzQPuP%3DK5CmEWszhJTzynC6A%40mail.gmail.com > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Jenkins Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-dev/CAPYP83R3k8W5Hxq7FdKjpdA0VBMoLyV%3D5ehX%2BNHbGH4uVmcnyQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
