From a44bf0cb0c31bbea029a6b4cccd6e83054565766 Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Wed, 22 Jun 2016 23:29:17 +0000 Subject: [PATCH] Add a node for artifact signing jobs Create the signing01.ci.openstack.org job node and puppet the signing subkey onto it via pubring.gpg and secring.gpg files stored in private hiera. Also set up some basic configuration and packages on the management bastion to aid in key management/rotation, and add the beginnings of administrative documentation for this. Change-Id: Iecddb778994a38f7898e0c20e7f3f8e93f0a7f60 Depends-On: I70c3b82185681ee64791cda653360c26a93bd466 Story: #2000336 Signed-off-by: Jeremy Stanley --- doc/source/signing.rst | 87 +++++++++++++++++++ doc/source/systems.rst | 1 + hiera/group/zuul-merger.yaml | 4 + manifests/site.pp | 10 +++ .../files/puppetmaster/groups.txt | 1 + .../files/puppetmaster/signing.conf | 24 +++++ .../files/puppetmaster/sks-ca.pem | 32 +++++++ .../manifests/puppetmaster.pp | 30 +++++++ .../manifests/signing_node.pp | 60 +++++++++++++ 9 files changed, 249 insertions(+) create mode 100644 doc/source/signing.rst create mode 100644 modules/openstack_project/files/puppetmaster/signing.conf create mode 100644 modules/openstack_project/files/puppetmaster/sks-ca.pem create mode 100644 modules/openstack_project/manifests/signing_node.pp diff --git a/doc/source/signing.rst b/doc/source/signing.rst new file mode 100644 index 0000000000..a0209ddf25 --- /dev/null +++ b/doc/source/signing.rst @@ -0,0 +1,87 @@ +:title: Signing System + +.. _signing: + +Signing System +############## + +This machine corresponds to the ``signing`` node label in job +configuration, holding an unencrypted copy of the OpenPGP signing +subkey for ``OpenStack Infra (Some Cycle) +`` used to create detached signatures for +release artifacts (tarballs, wheels, et cetera) and to sign and push +Git tags as part of our managed release automation. It only runs CI +jobs for tasks which require access to this key, using only vetted +tools and scripts reviewed by the Infra team. + + +At a Glance +=========== + +:Hosts: + * signing*.ci.openstack.org +:Puppet: + * :file:`modules/openstack_project/manifests/signing_node.pp` + + +Key Management Overview +======================= + +The signing server is a fairly typical long-lived job node, +distinguished primarily by having the signing subkey pair installed +by Puppet into the job runner account's home directory from binary +blobs in hiera. These blobs correspond to the +``~/.gnupg/pubring.gpg`` and ``~/.gnupg/secring.gpg`` files of a +freshly initialized gpg config after importing a minimal unencrypted +export on the management bastion of only the desired signing subkey +from the ``/root/signing.gunpg`` directory. + + +Storage +------- + +While the signing subkey is present unencrypted on this system, the +corresponding master key is kept symmetrically encrypted in the root +home directory of the Infra systems management bastion instead. At +the time of key creation a revocation certificate is also generated, +for which Infra root sysadmins are encouraged to retrieve and keep +local copies in case control over or access to the original master +key is lost. In the future, the master key and revocation +certificate may be distributed across our root team rather than kept +in one place (for example using Shamir's secret sharing scheme +similar to what `the Debian Project does for its archive keys +`). + + +Rotation +-------- + +The master key is rotated at the start of each development cycle, +signed by a majority of Infra root sysadmins before being put into +service, and has an expiration date set for shortly after the end of +the targeted development cycle. As each new key is created and +brought into rotation, an announcement should be signed by both the +old and new keys and sent to the +openstack-announce@lists.openstack.org mailing list. The new key +should also be signed by the old, and this signature pushed to the +public keyserver network. New key fingerprints are also submitted to +the openstack/releases repository, for publication on the +releases.openstack.org Web site. + + +Revocation +---------- + +Under normal circumstances, keys should be allowed to expire +gracefully. If the key is compromised but still accessible, a +revocation certificate can be generated and published to the key +network at that time. If access to the private key is lost +completely, the revocation certificate generated at key creation +time should be used as a last resort. + + +Management +========== + +As process is solidified, this section will be updated with specific +commands and examples. diff --git a/doc/source/systems.rst b/doc/source/systems.rst index 185e22e607..52c0e194a2 100644 --- a/doc/source/systems.rst +++ b/doc/source/systems.rst @@ -37,6 +37,7 @@ Major Systems translate refstack codesearch + signing .. NOTE(dhellmann): These projects were not listed above, or in any other toctree, which breaks the build. It's not clear why they were diff --git a/hiera/group/zuul-merger.yaml b/hiera/group/zuul-merger.yaml index 27eeda8a3a..811b76a32a 100644 --- a/hiera/group/zuul-merger.yaml +++ b/hiera/group/zuul-merger.yaml @@ -42,6 +42,10 @@ zuul_nodes: host: 'release.slave.openstack.org' labels: 'release' + - name: 'signing01.ci.openstack.org' + host: 'signing01.ci.openstack.org' + labels: 'signing' + - name: 'wheel-mirror-centos-7-amd64.slave.openstack.org' host: 'wheel-mirror-centos-7-amd64.slave.openstack.org' labels: 'wheel-mirror-centos-7-amd64' diff --git a/manifests/site.pp b/manifests/site.pp index de85fc925b..bbadd22d8c 100644 --- a/manifests/site.pp +++ b/manifests/site.pp @@ -936,6 +936,16 @@ node 'release.slave.openstack.org' { } } +# Node-OS: trusty +node /^signing\d+\.ci\.openstack\.org$/ { + include openstack_project + class { 'openstack_project::signing_node': + jenkins_ssh_public_key => $openstack_project::jenkins_ssh_key, + pubring => hiera('pubring'), + secring => hiera('secring'), + } +} + # Node-OS: trusty node 'openstackid.org' { class { 'openstack_project::openstackid_prod': diff --git a/modules/openstack_project/files/puppetmaster/groups.txt b/modules/openstack_project/files/puppetmaster/groups.txt index b6e9c8d9df..5524ccd4b1 100644 --- a/modules/openstack_project/files/puppetmaster/groups.txt +++ b/modules/openstack_project/files/puppetmaster/groups.txt @@ -10,4 +10,5 @@ afsdb afsdb*.openstack.org afs afs*.*.openstack.org wheel-mirror *wheel-mirror-*.openstack.org afsadmin mirror-update.openstack.org:release.slave.openstack.org +signing signing*.ci.openstack.org disabled review-dev.openstack.org:ci-backup-rs-ord.openstack.org:ask-staging.openstack.org:db368fcd-e61a-4294-a5cb-851c16650f7a:wiki.openstack.org diff --git a/modules/openstack_project/files/puppetmaster/signing.conf b/modules/openstack_project/files/puppetmaster/signing.conf new file mode 100644 index 0000000000..436679d2f5 --- /dev/null +++ b/modules/openstack_project/files/puppetmaster/signing.conf @@ -0,0 +1,24 @@ +# A basic ~/.gnupg/gpg.conf using secure keyserver transport +# and some more verbose display options + +# Receive, send and search for keys in the SKS keyservers pool using +# HKPS (OpenPGP HTTP Keyserver Protocol via TLS/SSL). +keyserver hkps://hkps.pool.sks-keyservers.net + +# Set the path to the public certificate for the +# sks-keyservers.net CA used to verify connections to servers in +# the pool above. +keyserver-options ca-cert-file=/root/signing.gnupg/sks-keyservers.netCA.pem + +# Ignore keyserver URLs specified in retrieved/refreshed keys +# so they don't direct you to update from non-HKPS sources. +keyserver-options no-honor-keyserver-url + +# Display key IDs in a more accurate 16-digit hexidecimal format +# and add 0x at the beginning for clarity. +keyid-format 0xlong + +# Display the calculated validity of user IDs when listing keys or +# showing signatures. +list-options show-uid-validity +verify-options show-uid-validity diff --git a/modules/openstack_project/files/puppetmaster/sks-ca.pem b/modules/openstack_project/files/puppetmaster/sks-ca.pem new file mode 100644 index 0000000000..24a2ad2e8e --- /dev/null +++ b/modules/openstack_project/files/puppetmaster/sks-ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u +ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw +MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP +c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr +cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I +6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj +MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F +45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS +FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx +Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 +aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx +MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y +u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 +p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP +fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G +A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY +TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR +OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u +gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ +X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 +gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB +UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 +lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT +BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB +cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U +f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G +ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph +WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== +-----END CERTIFICATE----- diff --git a/modules/openstack_project/manifests/puppetmaster.pp b/modules/openstack_project/manifests/puppetmaster.pp index 824fc8250d..82c9a6a2fc 100644 --- a/modules/openstack_project/manifests/puppetmaster.pp +++ b/modules/openstack_project/manifests/puppetmaster.pp @@ -176,6 +176,36 @@ class openstack_project::puppetmaster ( ensure => absent, } + # For signing key management + package { 'gnupg': + ensure => present, + } + package { 'gnupg-curl': + ensure => present, + } + file { '/root/signing.gnupg': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0700', + } + file { '/root/signing.gnupg/gpg.conf': + ensure => present, + owner => 'root', + group => 'root', + mode => '0400', + source => 'puppet:///modules/openstack_project/puppetmaster/signing.conf', + require => File['/root/signing.gnupg'], + } + file { '/root/signing.gnupg/sks-keyservers.netCA.pem': + ensure => present, + owner => 'root', + group => 'root', + mode => '0400', + source => 'puppet:///modules/openstack_project/puppetmaster/sks-ca.pem', + require => File['/root/signing.gnupg'], + } + # Enable puppetdb if $puppetdb { diff --git a/modules/openstack_project/manifests/signing_node.pp b/modules/openstack_project/manifests/signing_node.pp new file mode 100644 index 0000000000..e723114847 --- /dev/null +++ b/modules/openstack_project/manifests/signing_node.pp @@ -0,0 +1,60 @@ +# Copyright 2016 OpenStack Foundation +# +# 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. +# +# Class to install dependencies for uploading releases to pypi, maven and +# similar external repositories +# +class openstack_project::signing_node ( + $jenkins_ssh_public_key, + $pubring, + $secring, + $project_config_repo = 'https://git.openstack.org/openstack-infra/project-config', +) { + class { 'openstack_project::slave': + thin => true, + ssh_key => $jenkins_ssh_public_key, + project_config_repo => $project_config_repo, + } + + package { 'gnupg': + ensure => present, + } + + file { '/home/jenkins/.gnupg': + ensure => directory, + owner => 'jenkins', + group => 'jenkins', + mode => '0700', + require => File['/home/jenkins'], + } + + file { '/home/jenkins/.gnupg/pubring.gpg': + ensure => present, + owner => 'jenkins', + group => 'jenkins', + mode => '0400', + content => $pubring, + require => File['/home/jenkins/.gnupg'], + } + + file { '/home/jenkins/.gnupg/secring.gpg': + ensure => present, + owner => 'jenkins', + group => 'jenkins', + mode => '0400', + content => $secring, + require => File['/home/jenkins/.gnupg'], + } + +}