From e48f14003fba505d21b96f35fca5dec559d41a7b Mon Sep 17 00:00:00 2001 From: Arnaud GRESSE Date: Fri, 16 Dec 2022 17:51:39 +0100 Subject: [PATCH] Add role --- README.md | 50 +++++- roles/cfssl-server/defaults/main.yml | 24 +++ roles/cfssl-server/handlers/main.yml | 0 roles/cfssl-server/tasks/main.yml | 143 ++++++++++++++++++ roles/cfssl-server/tasks/pre_requisite.yml | 28 ++++ roles/cfssl-server/templates/cfssl.json.j2 | 50 ++++++ roles/cfssl-server/templates/cfssl.service.j2 | 16 ++ roles/cfssl-server/templates/csr.json.j2 | 6 + .../templates/csr_ROOT_CA.json.j2 | 6 + .../templates/csr_intermediate_CA.json.j2 | 6 + roles/cfssl-server/templates/db.json.j2 | 1 + roles/cfssl-server/templates/init.sql.j2 | 26 ++++ 12 files changed, 350 insertions(+), 6 deletions(-) create mode 100644 roles/cfssl-server/defaults/main.yml create mode 100644 roles/cfssl-server/handlers/main.yml create mode 100644 roles/cfssl-server/tasks/main.yml create mode 100644 roles/cfssl-server/tasks/pre_requisite.yml create mode 100644 roles/cfssl-server/templates/cfssl.json.j2 create mode 100644 roles/cfssl-server/templates/cfssl.service.j2 create mode 100644 roles/cfssl-server/templates/csr.json.j2 create mode 100644 roles/cfssl-server/templates/csr_ROOT_CA.json.j2 create mode 100644 roles/cfssl-server/templates/csr_intermediate_CA.json.j2 create mode 100644 roles/cfssl-server/templates/db.json.j2 create mode 100644 roles/cfssl-server/templates/init.sql.j2 diff --git a/README.md b/README.md index 0fbf63f..3a48f84 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,47 @@ -# CFSSL-SERVER +ansible-role-cfssl +================== -## Presentation +Installes CFSSL (CloudFlare's PKI toolkit) binaries and generate certificate : +- Self Signed Root CA +- CA Signed Client Certificates -## License -For open source projects, say how it is licensed. -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +Role Variables +-------------- + +``` +#Specifies the version of CFSSL toolkit we want to download and use +cfssl_version: "1.6.3" + +# The directory where CFSSL binaries will be installed +cfssl_bin_directory: /usr/bin + +# The CA directory where we will store CA, and Client certificates/keys. +pki_dir: /opt/cfssl + +# The Certificates Key Algos for both CA and Client certificates. +pki_key: + algo: rsa + size: 4096 + +# The CA Certificate Object and the default Client Certificate Object. +pki_names: + - C: FR + L: 'Paris' + O: 'Acme' + OU: IT + +pki_ca: + cname: My Internal Certification Authority + +# The properties of the CA +pki_ca: + cname: My Internal Certification Authority + expiry: 262800h (30 Years) + +# The properties of the Intermediate CA +pki_intermediate_ca: + cname: My Intermediate Internal Certification Authority + expiry: 262800h (30 Years) + +``` \ No newline at end of file diff --git a/roles/cfssl-server/defaults/main.yml b/roles/cfssl-server/defaults/main.yml new file mode 100644 index 0000000..128fd71 --- /dev/null +++ b/roles/cfssl-server/defaults/main.yml @@ -0,0 +1,24 @@ +--- +cfssl_version: 1.6.3 +cfssl_bin_directory: /usr/bin +cfssl_port: 8888 + +pki_dir: /opt/cfssl + +pki_key: + algo: rsa + size: 4096 + +pki_names: + - C: FR + L: 'Paris' + O: 'Acme' + OU: IT + +pki_ca: + cname: My Internal Certification Authority + expiry: 262800h + +pki_intermediate_ca: + cname: My Intermediate Internal Certification Authority + expirity: 262800h \ No newline at end of file diff --git a/roles/cfssl-server/handlers/main.yml b/roles/cfssl-server/handlers/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/roles/cfssl-server/tasks/main.yml b/roles/cfssl-server/tasks/main.yml new file mode 100644 index 0000000..a4c604b --- /dev/null +++ b/roles/cfssl-server/tasks/main.yml @@ -0,0 +1,143 @@ +- name: include pre_requisite.yml + import_tasks: pre_requisite.yml + +- name: Create cfssl user + ansible.builtin.user: + name: cfssl + shell: /usr/sbin/nologin + create_home: no + home: '{{pki_dir}}' + +- name: create pki dir + file: + path: '{{pki_dir}}' + state: directory + owner: cfssl + group: cfssl + mode: 0700 + +- name: create pki csr dir + file: + path: '{{pki_dir}}/csr' + state: directory + owner: cfssl + group: cfssl + mode: 0700 + +- name: create pki etc dir + file: + path: '{{pki_dir}}/etc' + state: directory + owner: cfssl + group: cfssl + mode: 0700 + +- name: create pki data dir + file: + path: '{{pki_dir}}/data' + state: directory + owner: cfssl + group: cfssl + mode: 0700 + +- name: create pki CA dir + file: + path: '{{pki_dir}}/CA' + state: directory + owner: cfssl + group: cfssl + mode: 0700 + +- name: creating CA CSR json + template: + src: csr_ROOT_CA.json.j2 + dest: '{{pki_dir}}/csr/csr_ROOT_CA.json' + owner: cfssl + group: cfssl + mode: 0600 + +- name: creating Intermediate CA CSR json + template: + src: csr_intermediate_CA.json.j2 + dest: '{{pki_dir}}/csr/csr_intermediate_CA.json' + owner: cfssl + group: cfssl + mode: 0600 + +- name: creating config file + template: + src: cfssl.json.j2 + dest: '{{pki_dir}}/etc/cfssl.json' + owner: cfssl + group: cfssl + mode: 0600 + +- name: creating db config file + template: + src: db.json.j2 + dest: '{{pki_dir}}/etc/db.json' + owner: cfssl + group: cfssl + mode: 0600 + +- name: creating init sql file + template: + src: init.sql.j2 + dest: '{{pki_dir}}/data/init.sql' + owner: cfssl + group: cfssl + mode: 0600 + +- name: create certificate authority key pair and CSR, autosign it + shell: '{{cfssl_bin_directory}}/cfssl gencert -initca {{pki_dir}}/csr/csr_ROOT_CA.json | {{cfssl_bin_directory}}/cfssljson -bare ca' + args: + chdir: '{{pki_dir}}/CA/' + +- name: create intermediate certificate authority key pair and CSR, autosign it + shell: '{{cfssl_bin_directory}}/cfssl gencert -ca {{pki_dir}}/CA/ca.pem -ca-key {{pki_dir}}/CA/ca-key.pem -config={{pki_dir}}/etc/cfssl.json -profile="intermediate_ca" {{pki_dir}}/csr/csr_intermediate_CA.json | {{cfssl_bin_directory}}/cfssljson -bare ca-server' + args: + chdir: '{{pki_dir}}/CA/' + +- name: create sqlite3 database + shell: 'cat {{pki_dir}}/data/init.sql | sqlite3 {{pki_dir}}/data/certdb.db' + args: + chdir: '{{pki_dir}}/CA/' + + +- name: Change owner of ca-server.pem by cfssl + ansible.builtin.file: + path: '{{pki_dir}}/CA/ca-server.pem' + owner: cfssl + group: cfssl + mode: 0600 + +- name: Change owner of ca-server.pem by cfssl + ansible.builtin.file: + path: '{{pki_dir}}/CA/ca-server-key.pem' + owner: cfssl + group: cfssl + mode: 0600 + +- name: Change owner of certdb.db by cfssl + ansible.builtin.file: + path: '{{pki_dir}}/data/certdb.db' + owner: cfssl + group: cfssl + mode: 0600 + +- name: Création du fichier de service /lib/systemd/system/cfssl.service + ansible.builtin.template: + src: cfssl.service.j2 + dest: /lib/systemd/system/cfssl.service + owner: root + group: root + mode: 0644 + +- name : Create firewall rules + ansible.builtin.shell: 'firewall-cmd --zone=public --permanent --add-port=8888/tcp && firewall-cmd --reload' + +- name: Démarrage et activation du service cfssl + ansible.builtin.service: + name: cfssl + state: started + enabled: true \ No newline at end of file diff --git a/roles/cfssl-server/tasks/pre_requisite.yml b/roles/cfssl-server/tasks/pre_requisite.yml new file mode 100644 index 0000000..0a03fd8 --- /dev/null +++ b/roles/cfssl-server/tasks/pre_requisite.yml @@ -0,0 +1,28 @@ +--- +- name: Check if cfssl is already available + stat: + path: '{{cfssl_bin_directory}}/cfssl' + register: cfssl_exist +- name: Download statically linked cfssl binary + get_url: + url: https://github.com/cloudflare/cfssl/releases/download/v{{cfssl_version}}/cfssl_{{cfssl_version}}_linux_amd64 + dest: '{{cfssl_bin_directory}}/cfssl' + mode: 0755 + when: cfssl_exist.stat.exists == false + +- name: Check if cfssljson is already available + stat: + path: '{{cfssl_bin_directory}}/cfssljson' + register: cfssljson_exist +- name: Download statically linked cfssljson binary + get_url: + url: https://github.com/cloudflare/cfssl/releases/download/v{{cfssl_version}}/cfssljson_{{cfssl_version}}_linux_amd64 + dest: '{{cfssl_bin_directory}}/cfssljson' + mode: 0755 + when: cfssljson_exist.stat.exists == false + +- name: Install sqlite3 + ansible.builtin.package: + name: sqlite3 + state: present + update_cache : true \ No newline at end of file diff --git a/roles/cfssl-server/templates/cfssl.json.j2 b/roles/cfssl-server/templates/cfssl.json.j2 new file mode 100644 index 0000000..0fdd001 --- /dev/null +++ b/roles/cfssl-server/templates/cfssl.json.j2 @@ -0,0 +1,50 @@ +{ + "signing": { + "default": { + "crl_url": "http://{{inventory_hostname_short}}.{{vm_domain_name}}:8888/crl", + "expiry": "26280h", + "usages": [ + "signing", + "key encipherment", + "client auth" + ] + }, + "profiles": { + "intermediate_ca": { + "usages": [ + "signing", + "digital signature", + "key encipherment", + "cert sign", + "crl sign", + "server auth", + "client auth" + ], + "expiry": "87600h", + "ca_constraint": { + "is_ca": true, + "max_path_len": 0, + "max_path_len_zero": true + } + }, + "server": { + "usages": [ + "signing", + "digital signing", + "key encipherment", + "server auth" + ], + "expiry": "8760h" + }, + "client": { + "usages": [ + "signing", + "digital signature", + "key encipherment", + "client auth" + ], + "expiry": "8760h" + } + } + } +} \ No newline at end of file diff --git a/roles/cfssl-server/templates/cfssl.service.j2 b/roles/cfssl-server/templates/cfssl.service.j2 new file mode 100644 index 0000000..fe024cf --- /dev/null +++ b/roles/cfssl-server/templates/cfssl.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=CFSSL PKI Server +After=syslog.target +After=network.target + +[Service] +RestartSec=2s +Type=simple +User=cfssl +Group=cfssl +WorkingDirectory={{pki_dir}} +ExecStart={{cfssl_bin_directory}}/cfssl serve -address 0.0.0.0 -db-config {{pki_dir}}/etc/db.json -config {{pki_dir}}/etc/cfssl.json -ca {{pki_dir}}/CA/ca-server.pem -ca-key {{pki_dir}}/CA/ca-server-key.pem -port {{cfssl_port}} +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/roles/cfssl-server/templates/csr.json.j2 b/roles/cfssl-server/templates/csr.json.j2 new file mode 100644 index 0000000..2419c3b --- /dev/null +++ b/roles/cfssl-server/templates/csr.json.j2 @@ -0,0 +1,6 @@ +{ + "CN": {{item.cname | to_json}}, + "hosts": {{ (item.sans|default([]) + item.altips|default([]) + item.cname.split(',')) | to_json}}, + "key" : {{item.key | default(pki_key) | to_json}}, + "names" : {{item.names | default(pki_names) | to_json}} +} diff --git a/roles/cfssl-server/templates/csr_ROOT_CA.json.j2 b/roles/cfssl-server/templates/csr_ROOT_CA.json.j2 new file mode 100644 index 0000000..597c403 --- /dev/null +++ b/roles/cfssl-server/templates/csr_ROOT_CA.json.j2 @@ -0,0 +1,6 @@ +{ + "CN": {{pki_ca.cname | to_json}}, + "key" : {{pki_key | to_json}}, + "names" : {{pki_names | to_json}}, + "ca": {"expiry": "{{pki_ca.expiry | to_json}}"} +} diff --git a/roles/cfssl-server/templates/csr_intermediate_CA.json.j2 b/roles/cfssl-server/templates/csr_intermediate_CA.json.j2 new file mode 100644 index 0000000..aab8cec --- /dev/null +++ b/roles/cfssl-server/templates/csr_intermediate_CA.json.j2 @@ -0,0 +1,6 @@ +{ + "CN": {{pki_intermediate_ca.cname | to_json}}, + "key" : {{pki_key | to_json}}, + "names" : {{pki_names | to_json}}, + "ca": {"expiry": "{{pki_intermediate_ca.expiry | to_json}}"} +} diff --git a/roles/cfssl-server/templates/db.json.j2 b/roles/cfssl-server/templates/db.json.j2 new file mode 100644 index 0000000..53610c9 --- /dev/null +++ b/roles/cfssl-server/templates/db.json.j2 @@ -0,0 +1 @@ +{"driver":"sqlite3","data_source":"{{pki_dir}}/data/certdb.db"} \ No newline at end of file diff --git a/roles/cfssl-server/templates/init.sql.j2 b/roles/cfssl-server/templates/init.sql.j2 new file mode 100644 index 0000000..98d2b7c --- /dev/null +++ b/roles/cfssl-server/templates/init.sql.j2 @@ -0,0 +1,26 @@ +CREATE TABLE certificates ( + serial_number blob NOT NULL, + authority_key_identifier blob NOT NULL, + ca_label blob, + status blob NOT NULL, + reason int, + expiry timestamp, + revoked_at timestamp, + pem blob NOT NULL, + PRIMARY KEY(serial_number, authority_key_identifier) +); + +CREATE TABLE ocsp_responses ( + serial_number blob NOT NULL, + authority_key_identifier blob NOT NULL, + body blob NOT NULL, + expiry timestamp, + PRIMARY KEY(serial_number, authority_key_identifier), + FOREIGN KEY(serial_number, authority_key_identifier) REFERENCES certificates(serial_number, authority_key_identifier) +); + +ALTER TABLE certificates ADD COLUMN "issued_at" timestamp; +ALTER TABLE certificates ADD COLUMN "not_before" timestamp; +ALTER TABLE certificates ADD COLUMN "metadata" text; +ALTER TABLE certificates ADD COLUMN "sans" text; +ALTER TABLE certificates ADD COLUMN "common_name" text; \ No newline at end of file