<!--
  ~ Copyright 2010 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<chapter id='signing_plugin'>
    <title>The Signing Plugin</title>

    <para>
        The signing plugin adds the ability to digitally sign built files and artifacts.
        These digital signatures can then be used to prove who built the artifact the signature is attached to
        as well as other information such as when the signature was generated.
    </para>
    <para>
        The signing plugin currently only provides support for generating <ulink url='https://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP'>OpenPGP signatures</ulink>
        (which is the signature format <ulink url="http://central.sonatype.org/pages/requirements.html#sign-files-with-gpgpgp">required for
        publication to the Maven Central Repository</ulink>).
    </para>

    <section id="sec:signing_usage">
        <title>Usage</title>
        <para>To use the Signing plugin, include the following in your build script:</para>
        <sample id="useSigningPlugin" dir="signing/maven" title="Using the Signing plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
    </section>

    <section id="sec:signatory_credentials">
        <title>Signatory credentials</title>
        <para>
            In order to create OpenPGP signatures, you will need a key pair (instructions on creating a key pair using the <ulink url="https://www.gnupg.org/">GnuPG tools</ulink>
            can be found in the <ulink url="https://www.gnupg.org/documentation/howtos.html">GnuPG HOWTOs</ulink>). You need to provide the signing plugin
            with your key information, which means three things:
        </para>
        <itemizedlist>
            <listitem><para>The public key ID (an 8 character hexadecimal string).</para></listitem>
            <listitem><para>The absolute path to the secret key ring file containing your private key.</para></listitem>
            <listitem><para>The passphrase used to protect your private key.</para></listitem>
        </itemizedlist>
        <para>
            These items must be supplied as the values of properties <literal>signing.keyId</literal>,
            <literal>signing.secretKeyRingFile</literal>, and <literal>signing.password</literal> respectively. Given the personal and private nature of these values, a good practice
            is to store them in the user <literal>gradle.properties</literal> file (described in <xref linkend="sec:gradle_properties_and_system_properties"/>).
        </para>
        <programlisting>
signing.keyId=24875D73
signing.password=secret
signing.secretKeyRingFile=/Users/me/.gnupg/secring.gpg
        </programlisting>
        <para>
            If specifying this information (especially <literal>signing.password</literal>) in the user <literal>gradle.properties</literal> file is not feasible for your environment, you can source the information
            however you need to and set the project properties manually.
        </para>
        <!--
            Unsure how to go about automatically testing this little snippet.
        -->
        <programlisting>
import org.gradle.plugins.signing.Sign

gradle.taskGraph.whenReady { taskGraph ->
    if (taskGraph.allTasks.any { it instanceof Sign }) {
        // Use Java 6's console to read from the console (no good for
        // a CI environment)
        Console console = System.console()
        console.printf "\n\nWe have to sign some things in this build." +
                       "\n\nPlease enter your signing details.\n\n"

        def id = console.readLine("PGP Key Id: ")
        def file = console.readLine("PGP Secret Key Ring File (absolute path): ")
        def password = console.readPassword("PGP Private Key Password: ")

        allprojects { ext."signing.keyId" = id }
        allprojects { ext."signing.secretKeyRingFile" = file }
        allprojects { ext."signing.password" = password }

        console.printf "\nThanks.\n\n"
    }
}
        </programlisting>
        <section id="sec:subkeys">
            <title>Using OpenPGP subkeys</title>
            <para>
                OpenPGP supports subkeys, which are like the normal keys, except they're bound to a master key pair.
                One feature of OpenPGP subkeys is that they can be revoked independently of the master keys which makes key management easier.
                A practical case study of how subkeys can be leveraged in software development can be read on the <ulink url="https://wiki.debian.org/Subkeys">Debian wiki</ulink>.
            </para>
            <para>
                The signing plugin supports OpenPGP subkeys out of the box. Just specify a subkey ID as the value in the <literal>signing.keyId</literal> property.
            </para>
        </section>
    </section>

    <section id="sec:specifying_what_to_sign">
        <title>Specifying what to sign</title>
        <para>
            As well as configuring how things are to be signed (i.e. the signatory configuration), you must also specify what is to be signed.
            The Signing plugin provides a DSL that allows you to specify the tasks and/or configurations that should be signed.
        </para>
        <section id="sec:signing_configurations">
            <title>Signing Configurations</title>
            <para>
                It is common to want to sign the artifacts of a configuration. For example, the <link linkend="java_plugin">Java plugin</link>
                configures a jar to build and this jar artifact is added to the <literal>archives</literal> configuration.
                Using the Signing DSL, you can specify that all of the artifacts of this configuration should be signed.
            </para>
            <sample id="signingArchives" dir="signing/maven" title="Signing a configuration">
                <sourcefile file="build.gradle" snippet="sign-archives"/>
            </sample>
            <para>
                This will create a task (of type <apilink class="org.gradle.plugins.signing.Sign"/>) in your project named “<literal>signArchives</literal>”,
                that will build any <literal>archives</literal> artifacts (if needed) and then generate signatures for them. The signature files will be placed
                alongside the artifacts being signed.
            </para>
            <sample id="signingArchivesOutput" dir="signing/maven" title="Signing a configuration output">
                <output args="signArchives"/>
            </sample>
        </section>
        <section id="sec:signing_tasks">
            <title>Signing Tasks</title>
            <para>
                In some cases the artifact that you need to sign may not be part of a configuration. In this case you can directly sign the task that
                produces the artifact to sign.
            </para>
            <sample id="signingTasks" dir="signing/tasks" title="Signing a task">
                <sourcefile file="build.gradle" snippet="sign-task"/>
            </sample>
            <para>
                This will create a task (of type <apilink class="org.gradle.plugins.signing.Sign"/>) in your project named “<literal>signStuffZip</literal>”,
                that will build the input task's archive (if needed) and then sign it. The signature file will be placed
                alongside the artifact being signed.
            </para>
            <sample id="signingTaskOutput" dir="signing/tasks" title="Signing a task output">
                <output args="signStuffZip"/>
            </sample>
            <para>
                For a task to be “signable”, it must produce an archive of some type. Tasks that do this are the <apilink class="org.gradle.api.tasks.bundling.Tar"/>,
                <apilink class="org.gradle.api.tasks.bundling.Zip"/>, <apilink class="org.gradle.api.tasks.bundling.Jar"/>,
                <apilink class="org.gradle.api.tasks.bundling.War"/> and <apilink class="org.gradle.plugins.ear.Ear"/> tasks.
            </para>
        </section>
        <section id="sec:conditional_signing">
            <title>Conditional Signing</title>
            <para>
                A common usage pattern is to only sign build artifacts under certain conditions. For example, you may not wish to sign artifacts for non release versions.
                To achieve this, you can specify that signing is only required under certain conditions.
            </para>
            <sample id="conditionalSigning" dir="signing/conditional" title="Conditional signing">
                <sourcefile file="build.gradle" snippet="conditional-signing" />
            </sample>
            <para>
                In this example, we only want to require signing if we are building a release version and we are going to publish it. Because we are inspecting the task
                graph to determine if we are going to be publishing, we must set the <literal>signing.required</literal> property to a closure to defer the evaluation. See
                <apilink class="org.gradle.plugins.signing.SigningExtension" method="setRequired" /> for more information.
            </para>
        </section>
    </section>

    <section id="sec:publishing_the_signatures">
        <title>Publishing the signatures</title>
        <para>
            When specifying what is to be signed via the Signing DSL, the resultant signature artifacts are automatically added to the <literal>signatures</literal> and
            <literal>archives</literal> dependency configurations. This means that if you want to upload your signatures to your distribution repository along
            with the artifacts you simply execute the <literal>uploadArchives</literal> task as normal.
        </para>
    </section>

    <section id="sec:signing_pom_files">
        <title>Signing POM files</title>
        <para>
            When deploying signatures for your artifacts to a Maven repository, you will also want to sign the published POM file. The signing plugin adds a
            <literal>signing.signPom()</literal> (see: <apilink class="org.gradle.plugins.signing.SigningExtension" method="signPom(org.gradle.api.artifacts.maven.MavenDeployment, groovy.lang.Closure)" />) method that can be used in the
            <literal>beforeDeployment()</literal> block in your upload task configuration.
        </para>
        <sample id="signingMavenPom" dir="signing/maven" title="Signing a POM for deployment">
            <sourcefile file="build.gradle" snippet="sign-pom"/>
        </sample>
        <para>
            When signing is not required and the POM cannot be signed due to insufficient configuration (i.e. no credentials for signing) then the
            <literal>signPom()</literal> method will silently do nothing.
        </para>
    </section>

</chapter>
