Skip to content

Commit

Permalink
Fixes to HTTPS support (#55)
Browse files Browse the repository at this point in the history
* Improvements to README

- Re-order sections so that important stuff comes first
- Replace sample Jenkins config.xml with something more minimal (the
  old one had EC2 plugin configuration stuff, etc)
- Fix indentation in example playbook, improve example vars used there
- Improve documentation for HTTPS
- Various cleanups and minor improvements

Sorry for the large diff!

* Copy SSL certificates to secrets dir, not home

They are much safer here, since that directory is mode 0700.

* Copy CA certificate private key to server

Should have been done in c2652e6.

* Fix HTTPS option strings for config file

- Use the ">-" multi-line operator to trim newlines
- Fix the destination path by using the basename filter

* Merge configure-config.yml -> configure-jenkins.yml

Sorry, it was not really necessary to introduce a new task file here.
The configure-jenkins.yml file should handle the main Jenkins-related
configuration, which also includes SSL stuff.

* Cleanup: improve task names, sort attributes

* Always create secrets dir

Even if copying a local secrets directory is not desired, we need to
ensure that the secrets dir exists and is owned by the Jenkins user.
We'll potentially copy SSL secrets here.

* Set HTTP*_PORT variables in config file

Previous to this change, we were using lineinfile to set HTTP_PORT,
but just ignoring that value in JENKINS_ARGS. This change fixes that,
and also adds another variable for HTTPS_PORT, which is not defined by
default in some package distribution versions of this file.

* Add a molecule scenario for HTTPS
  • Loading branch information
nre-ableton authored and emmetog committed Nov 19, 2019
1 parent d0e55de commit 510104b
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 256 deletions.
350 changes: 162 additions & 188 deletions README.md

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions molecule/https/Dockerfile.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Molecule managed

{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}

RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 648ACFD622F3D138 && \
apt-get update && \
apt-get install -y apt-transport-https aptitude bash ca-certificates sudo python \
python-apt && \
apt-get clean

RUN useradd -G sudo molecule
43 changes: 43 additions & 0 deletions molecule/https/jenkins-configs/config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version='1.1' encoding='UTF-8'?>
<hudson>
<disabledAdministrativeMonitors/>
<version>2.190.2</version>
<installStateName>RESTART</installStateName>
<numExecutors>1</numExecutors>
<mode>EXCLUSIVE</mode>
<useSecurity>true</useSecurity>
<authorizationStrategy class="hudson.security.AuthorizationStrategy$Unsecured"/>
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
<disableSignup>false</disableSignup>
<enableCaptcha>false</enableCaptcha>
</securityRealm>
<disableRememberMe>false</disableRememberMe>
<projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
<workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULLNAME}</workspaceDir>
<buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
<markupFormatter class="hudson.markup.EscapedMarkupFormatter"/>
<jdks/>
<viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
<myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
<clouds/>
<quietPeriod>0</quietPeriod>
<scmCheckoutRetryCount>0</scmCheckoutRetryCount>
<views>
<hudson.model.AllView>
<owner class="hudson" reference="../../.."/>
<name>all</name>
<filterExecutors>false</filterExecutors>
<filterQueue>false</filterQueue>
<properties class="hudson.model.View$PropertyList"/>
</hudson.model.AllView>
</views>
<primaryView>all</primaryView>
<slaveAgentPort>0</slaveAgentPort>
<disabledAgentProtocols>
<string>JNLP-connect</string>
<string>JNLP2-connect</string>
</disabledAgentProtocols>
<label>master</label>
<nodeProperties/>
<globalNodeProperties/>
</hudson>
35 changes: 35 additions & 0 deletions molecule/https/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: instance
image: ubuntu:16.04
privileged: true
exposed_ports:
- 8080/tcp
published_ports:
- 0.0.0.0:8080:8080/tcp
env:
JENKINS_HOME: /jenkins
provisioner:
name: ansible
log: true
lint:
name: ansible-lint
options:
# E602: Don't compare to empty string
# All workarounds for this are uglier than just comparing to empty strings. See:
# https://github.com/ansible/ansible-lint/issues/457
x: ['602']
verifier:
name: testinfra
env:
# Instruct the python-jenkins library to ignore SSL verification errors, which are
# caused by the self-signed certificate.
PYTHONHTTPSVERIFY: "0"
lint:
name: flake8
19 changes: 19 additions & 0 deletions molecule/https/playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
- name: Converge
hosts: all
vars:
jenkins_auth: "none"
jenkins_config_owner: "jenkins"
jenkins_config_group: "jenkins"
jenkins_home: "/jenkins"
jenkins_https_keystore: "{{ playbook_dir }}/ssl/test-cert.jks"
# NOTE: For testing purposes, we are using a self-signed certificate with the password
# of "password". You are of course advised to store such data in an Ansible vault.
jenkins_https_keystore_password: "password"
jenkins_https_validate_certs: false
jenkins_install_via: "apt"
jenkins_port: "-1"
jenkins_port_https: "8080"
jenkins_version: "2.190.2"
roles:
- ansible-jenkins
Binary file added molecule/https/ssl/test-cert.jks
Binary file not shown.
1 change: 1 addition & 0 deletions molecule/https/tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__/
30 changes: 30 additions & 0 deletions molecule/https/tests/test_default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os

import testinfra.utils.ansible_runner

from jenkins import Jenkins


testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')


def test_jenkins_installed(host):
package = host.package('jenkins')

assert package.is_installed


def test_jenkins_version():
master = Jenkins('https://127.0.0.1:8080')
version = master.get_version()

assert version == '2.190.2'


def test_jenkins_java_process(host):
process = host.process.get(command='/usr/bin/java')

assert '-Djenkins.install.runSetupWizard=false' in process.args
assert '--httpsKeyStore=/jenkins/secrets/test-cert.jks' in process.args
assert '--httpsKeyStorePassword=password' in process.args
57 changes: 0 additions & 57 deletions tasks/configure-config.yml

This file was deleted.

103 changes: 95 additions & 8 deletions tasks/configure-jenkins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,37 @@
# otherwise some data might be overwritten when it restarts.
- include_tasks: "{{ jenkins_install_via }}/stop.yml"

- name: Set JENKINS_HOME
lineinfile:
create: true
dest: "/etc/default/jenkins"
line: "JENKINS_HOME={{ jenkins_home }}"
regexp: '^JENKINS_HOME='
state: present
when: jenkins_install_via != "docker"

- name: Set Jenkins port for HTTP
lineinfile:
dest: /etc/default/jenkins
regexp: '^HTTP_PORT='
line: "HTTP_PORT={{ jenkins_port }}"
when: jenkins_install_via != "docker"

- name: Set Jenkins port for HTTPS
lineinfile:
dest: /etc/default/jenkins
regexp: '^HTTPS_PORT='
insertafter: '^HTTP_PORT='
line: "HTTPS_PORT={{ jenkins_port_https }}"
when: jenkins_install_via != "docker"

- name: Set Jenkins Java command line options
lineinfile:
dest: /etc/default/jenkins
regexp: '^JAVA_ARGS='
line: "JAVA_ARGS=\"{{ jenkins_java_opts }}\""
when: jenkins_install_via != "docker"

- name: Ensure correct ownership of JENKINS_HOME directory
file:
path: "{{ jenkins_home }}"
Expand All @@ -11,32 +42,88 @@
mode: 0755
state: directory

- name: Configuration file is up to date (config.xml)
- name: Ensure main configuration file is up to date
template:
src: "{{ jenkins_source_config_xml }}"
dest: "{{ jenkins_home }}/config.xml"
mode: 0644
owner: "{{ jenkins_config_owner }}"
group: "{{ jenkins_config_group }}"
mode: 0644

- name: Configure Jenkins location
template:
src: files/jenkins.model.JenkinsLocationConfiguration.xml.j2
dest: "{{ jenkins_home }}/jenkins.model.JenkinsLocationConfiguration.xml"
mode: 0644
owner: "{{ jenkins_config_owner }}"
group: "{{ jenkins_config_group }}"
mode: 0644

- name: Initialize Jenkins secrets dir fact
set_fact:
jenkins_secrets: "{{ jenkins_home }}/secrets"

- name: secrets dir is up to date
- name: Copy secrets
copy:
src: "{{ jenkins_source_secrets }}"
dest: "{{ jenkins_home }}/secrets"
dest: "{{ jenkins_secrets }}"
owner: "{{ jenkins_config_owner }}"
group: "{{ jenkins_config_group }}"
when: jenkins_include_secrets

- name: set permissions on secrets dir
- name: Ensure correct ownership of secrets directory
file:
path: "{{ jenkins_home }}/secrets"
path: "{{ jenkins_secrets }}"
owner: "{{ jenkins_config_owner }}"
group: "{{ jenkins_config_group }}"
mode: 0700
when: jenkins_include_secrets
state: directory

- name: Copy JKS keystore credentials
copy:
src: "{{ jenkins_https_keystore }}"
dest: "{{ jenkins_secrets }}/"
when: jenkins_https_keystore and jenkins_https_keystore_password

- name: Copy CA signed certificate
copy:
src: "{{ jenkins_https_certificate }}"
dest: "{{ jenkins_secrets }}/"
when: jenkins_https_certificate and jenkins_https_private_key

- name: Copy CA certificate private key
copy:
src: "{{ jenkins_https_private_key }}"
dest: "{{ jenkins_secrets }}/"
when: jenkins_https_certificate and jenkins_https_private_key

- name: Initialize HTTPS credentials fact
set_fact:
jenkins_https_creds: ""

- name: Set JKS keystore credentials
set_fact:
jenkins_https_creds: >-
--httpsKeyStore='{{ jenkins_secrets }}/{{ jenkins_https_keystore | basename }}'
--httpsKeyStorePassword='{{ jenkins_https_keystore_password }}'
when: jenkins_https_keystore and jenkins_https_keystore_password

# This fact prevents the next task from going over >90 chars
- name: Set fact for HTTPS certificate file
set_fact:
jenkins_https_certificate_file: >-
{{ jenkins_secrets }}/{{ jenkins_https_certificate | basename }}
when: jenkins_https_certificate and jenkins_https_private_key

- name: Set CA signed certificate credentials
set_fact:
jenkins_https_creds: >-
--httpsCertificate='{{ jenkins_https_certificate_file }}'
--httpsPrivateKey='{{ jenkins_secrets }}/{{ jenkins_https_private_key | basename }}'
when: jenkins_https_certificate and jenkins_https_private_key

- name: Set Jenkins command line options
lineinfile:
dest: /etc/default/jenkins
regexp: '^JENKINS_ARGS='
line: "JENKINS_ARGS=\"--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT \
--httpsPort=$HTTPS_PORT {{ jenkins_https_creds }}\""
3 changes: 0 additions & 3 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@

- include: "{{ jenkins_install_via }}/install.yml"

- include: "configure-config.yml"
when: jenkins_install_via != "docker"

- include: "configure-jenkins.yml"

- include: "configure-files.yml"
Expand Down

0 comments on commit 510104b

Please sign in to comment.