From c92454d2396400cfe94fa67f69cf985e28fad769 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 21 Mar 2017 21:13:24 -0400 Subject: [PATCH] Implement crontab to perform Fernet keys rotations This crontab is useful to run keystone-manage fernet_rotate command in a scheduled way. It doesn't take care of the distribution of keys when deploying Keystone on multinode environment but it's still useful to use it on single-node keystone deployments or when we have an external system to distribute the keys after running this command. Change-Id: I125e81d8cd130fadb8271f1b7bcdcf9794c79f47 --- manifests/cron/fernet_rotate.pp | 81 ++++++++++++++ ...ernet_rotate_crontab-aad7ddda61d8ee31.yaml | 7 ++ .../keystone_cron_fernet_rotate_spec.rb | 105 ++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 manifests/cron/fernet_rotate.pp create mode 100644 releasenotes/notes/fernet_rotate_crontab-aad7ddda61d8ee31.yaml create mode 100644 spec/classes/keystone_cron_fernet_rotate_spec.rb diff --git a/manifests/cron/fernet_rotate.pp b/manifests/cron/fernet_rotate.pp new file mode 100644 index 000000000..20b93d187 --- /dev/null +++ b/manifests/cron/fernet_rotate.pp @@ -0,0 +1,81 @@ +# Copyright 2017 Red Hat, Inc. +# All Rights Reserved. +# +# 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: keystone::cron::fernet_rotate +# +# Installs a cron job that rotates fernet keys. +# +# === Parameters +# +# [*ensure*] +# (optional) Defaults to present. +# Valid values are present, absent. +# +# [*minute*] +# (optional) Defaults to '1'. +# +# [*hour*] +# (optional) Defaults to '0'. +# +# [*monthday*] +# (optional) Defaults to '*'. +# +# [*month*] +# (optional) Defaults to '*'. +# +# [*weekday*] +# (optional) Defaults to '*'. +# +# [*maxdelay*] +# (optional) Seconds. Defaults to 0. Should be a positive integer. +# Induces a random delay before running the cronjob to avoid running all +# cron jobs at the same time on all hosts this job is configured. +# +# [*user*] +# (optional) Defaults to 'keystone'. +# Allow to run the crontab on behalf any user. +# +class keystone::cron::fernet_rotate ( + $ensure = present, + $minute = 1, + $hour = 0, + $monthday = '*', + $month = '*', + $weekday = '*', + $maxdelay = 0, + $user = 'keystone', +) { + + include ::keystone::deps + + if $maxdelay == 0 { + $sleep = '' + } else { + $sleep = "sleep `expr \${RANDOM} \\% ${maxdelay}`; " + } + + cron { 'keystone-manage fernet_rotate': + ensure => $ensure, + command => "${sleep}keystone-manage fernet_rotate", + environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + user => $user, + minute => $minute, + hour => $hour, + monthday => $monthday, + month => $month, + weekday => $weekday, + require => Anchor['keystone::service::end'], + } +} diff --git a/releasenotes/notes/fernet_rotate_crontab-aad7ddda61d8ee31.yaml b/releasenotes/notes/fernet_rotate_crontab-aad7ddda61d8ee31.yaml new file mode 100644 index 000000000..94e1027c1 --- /dev/null +++ b/releasenotes/notes/fernet_rotate_crontab-aad7ddda61d8ee31.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Implement a basic crontab that does fernet keys rotations with + keystone::cron::fernet_rotate class. This crontab won't take + care of the key distribution but just run `keystone-manage fernet_rotate` + command in a scheduled way. diff --git a/spec/classes/keystone_cron_fernet_rotate_spec.rb b/spec/classes/keystone_cron_fernet_rotate_spec.rb new file mode 100644 index 000000000..91a96c9b2 --- /dev/null +++ b/spec/classes/keystone_cron_fernet_rotate_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' + +describe 'keystone::cron::fernet_rotate' do + + let :facts do + OSDefaults.get_facts({ :osfamily => 'Debian' }) + end + + let :params do + { :ensure => 'present', + :minute => 1, + :hour => 0, + :monthday => '*', + :month => '*', + :weekday => '*', + :maxdelay => 0, + } + end + + describe 'with default parameters' do + it 'configures a cron' do + is_expected.to contain_cron('keystone-manage fernet_rotate').with( + :ensure => params[:ensure], + :command => "keystone-manage fernet_rotate", + :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + :user => 'keystone', + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday], + :require => 'Anchor[keystone::service::end]', + ) + end + end + + describe 'when specifying a maxdelay param' do + before :each do + params.merge!( + :maxdelay => 600 + ) + end + + it 'configures a cron with delay' do + is_expected.to contain_cron('keystone-manage fernet_rotate').with( + :ensure => params[:ensure], + :command => "sleep `expr ${RANDOM} \\% #{params[:maxdelay]}`; keystone-manage fernet_rotate", + :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + :user => 'keystone', + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday], + :require => 'Anchor[keystone::service::end]', + ) + end + end + + describe 'when specifying a user param' do + let :params do + { + :user => 'keystonecustom' + } + end + + it 'configures a cron with delay' do + is_expected.to contain_cron('keystone-manage fernet_rotate').with( + :ensure => 'present', + :command => 'keystone-manage fernet_rotate', + :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + :user => 'keystonecustom', + :minute => 1, + :hour => 0, + :monthday => '*', + :month => '*', + :weekday => '*', + :require => 'Anchor[keystone::service::end]', + ) + end + end + + describe 'when disabling cron job' do + before :each do + params.merge!( + :ensure => 'absent' + ) + end + + it 'configures a cron with delay' do + is_expected.to contain_cron('keystone-manage fernet_rotate').with( + :ensure => params[:ensure], + :command => "keystone-manage fernet_rotate", + :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + :user => 'keystone', + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday], + :require => 'Anchor[keystone::service::end]', + ) + end + end +end