Update to 2021-12-01 19:13

This commit is contained in:
Daniel Berteaud
2021-12-01 19:13:34 +01:00
commit 4c4556c660
2153 changed files with 60999 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
---
pki_version: '3.16.0'
pki_archive_url: https://github.com/openxpki/openxpki/archive/v{{ pki_version }}.tar.gz
pki_archive_sha1: 9bba585de36b81f70a7a315f8a591e388c516b38
pki_config_version: '3.16'
pki_config_archive_url: https://github.com/openxpki/openxpki-config/archive/v{{ pki_config_version }}.tar.gz
pki_config_archive_sha1: f4673cf976d8d76032bbea14371d63d5e69cbb42
# Should ansible handle updates or only initial install
pki_manage_upgrade: True
pki_root_dir: /opt/openxpki
pki_user: openxpki
# Database settings
pki_db_server: "{{ mysql_server | default('localhost') }}"
pki_db_port: 3306
pki_db_name: openxpki
pki_db_user: openxpki
# If not defined, a random pass will be generated and stored in the meta directory
# pki_db_pass:
# For sessions, use a distinct user, with only access to the frontend_session table
pki_db_session_user: openxpki_session
# pki_db_session_pass
# Base URL of the PKI
#pki_base_url: https://pki.domain.tld/openxpki
# Just a shortcut to get only the path of the url
pki_web_alias: "{{ pki_base_url | urlsplit('path') }}"
# You may restrict access to the web interface by IP
pki_src_ip:
- 0.0.0.0/0
# This is to restrict access to the public endpoints. Eg downloads of CRL
pki_pub_src_ip: "{{ pki_src_ip }}"
# Optional prefix and suffix to append to the Root CA, vault and scep certificates
pki_cn_prefix: ''
pki_cn_suffix: ''
pki_root_ca_cn: "{{ pki_cn_prefix }}Root CA{{ pki_cn_suffix }}"
pki_vault_cn: "{{ pki_cn_prefix }}Vault Certificate{{ pki_cn_suffix }}"
pki_scep_cn: "{{ pki_cn_prefix }}SCEP Certificate{{ pki_cn_suffix }}"
pki_default_realm:
subj_c: FR
subj_st: Aquitaine
subj_l: Bordeaux
subj_o: Firewall Services
subj_ou: Security
validity: 7300 # Root CA will use the double of this value
keysize: 4096 # Root CA will use the double of this value
subj_suffix: DC=PKI,DC=Firewall Services,DC=com
scep:
enabled: True
iprange: 0.0.0.0/0
# hmac: SecretHMAC
# challenge: SecretChallenge
profile: I18N_OPENXPKI_PROFILE_TLS_SERVER
notif:
admin_email: "{{ system_admin_email }}"
expiry_send_requestor: False # Should requestor be notified about expiry
auth:
ldap_uri: "{{ ad_auth | default(False) | ternary('ldap://' + ad_realm | default(samba_realm) | default(ansible_domain) | lower, ldap_uri) }}"
ldap_base: "{{ ad_auth | default(False) | ternary('DC=' + ad_realm | default(samba_realm) | default(ansible_domain) | regex_replace('\\.',',DC='), ldap_base) }}"
ldap_start_tls: True
ldap_user_attr: "{{ ad_auth | default(False) | ternary('samaccountname','uid') }}"
#ldap_bind_dn:
#ldap_bind_pass:
role_map:
- priority: 10
filter: "{{ ad_auth | default(False) | ternary('|(memberOf=CN=Domain Admins,CN=Users,DC=' + ad_realm | default(samba_realm) | default(ansible_domain) | regex_replace('\\.',',DC=') + ')(memberOf=CN=Domain Admins,OU=Groups,DC=' + ad_realm | default(samba_realm) | default(ansible_domain) | regex_replace('\\.',',DC=') + ')', 'posixMemberOf=admins') }}"
role: 'RA Operator'
- priority: 20
filter: "{{ ad_auth | default(False) | ternary('memberOf=CN=Equipe,OU=Groups,DC=' + ad_realm | default(samba_realm) | default(ansible_domain) | regex_replace('\\.',',DC='), 'posixMemberOf=equipe') }}"
role: 'User'
- priority: 30
filter: 'cn=*'
role: 'Anonymous'
passwd_quality: normal
# passwd_quality can either be string none, normal or strong.
# pki_extra_realm just lets you override some of the defaults, without
# redefining the whole dict
pki_extra_realm: {}
pki_realm_conf: "{{ pki_default_realm | combine(pki_extra_realm, recursive=True) }}"
# Auto-generated if not defined
# those will be used as default HMAC and challenge for realms
# which doesn't have them defined
# pki_scep_hmac:
# pki_scep_challenge:
pki_realms:
- name: vpn
description: VPN CA
- name: users
description: Users CA
pki_email_footer_txt: ''
pki_email_footer_html: ''

View File

@@ -0,0 +1,765 @@
#! /usr/bin/perl
# Copyright (C) 2014 by P. Tomulik <ptomulik@meil.pw.edu.pl>
#
# 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.
# Dependencies:
# perl-base
# libnet-ldap-perl
# libdata-dump-perl
use Net::LDAP;
use Data::Dump;
use Getopt::Long;
use String::Escape qw( unbackslash );
my $attrs;
my $base;
my $binddn;
my $binddn_env;
my $bindpw;
my $bindpw_env;
my $debug = 0;
my $deref;
my $extra_filter;
my $filter;
my $group;
my $ldapuri;
my $multiple;
my $starttls;
my $passwd;
my $passwd_env;
my $print;
my $rebind;
my $scope;
my $user;
my $user_attr = 'uid';
my $user_env;
my $user_filter;
my $verbose;
my $separator = '\n';
my $value_map;
my $tag = 'openxpki-auth-ldap';
Getopt::Long::Configure('no_auto_abbrev', 'no_ignore_case', 'auto_help');
Getopt::Long::GetOptions(
'attrs|a=s' => \$attrs,
'base|b=s' => \$base,
'binddn|d=s' => \$binddn,
'binddn-env|D=s' => \$binddn_env,
'bindpw|w=s' => \$bindpw,
'bindpw-env|W=s' => \$bindpw_env,
'debug|g' => \$debug,
'deref=s' => \$deref,
'extra-filter=s' => \$extra_filter,
'filter|f=s' => \$filter,
'group|G=s' => \$group,
'ldapuri|H=s' => \$ldapuri,
'multiple|m' => \$multiple,
'starttls|t' => \$starttls,
'passwd|p=s' => \$passwd,
'passwd-env|P=s' => \$passwd_env,
'print=s' => \$print,
'rebind|r' => \$rebind,
'scope|s=s' => \$scope,
'user|u=s' => \$user,
'user-attr=s' => \$user_attr,
'user-env|U=s' => \$user_env,
'user-filter=s' => \$user_filter,
'verbose|V' => \$verbose,
'separator=s' => \$separator,
'value-map|k=s%' => \$value_map
) or exit(1);
if($debug) {
print STDERR "$tag: debug: initial values: \n";
print STDERR "$tag: debug: attrs: " . Data::Dump::dump($attrs) ."\n" if(defined($attrs));
print STDERR "$tag: debug: base: '$base'\n" if(defined($base));
print STDERR "$tag: debug: binddn: '$binddn'\n" if(defined($binddn));
print STDERR "$tag: debug: binddn_env: \$$binddn_env\n" if(defined($binddn_env));
print STDERR "$tag: debug: bindpw: '$bindpw'\n" if(defined($bindpw));
print STDERR "$tag: debug: bindpw_env: \$$bindpw_env\n" if(defined($bindpw_env));
print STDERR "$tag: debug: debug: $debug\n";
print STDERR "$tag: debug: deref: '$deref'\n" if(defined($deref));
print STDERR "$tag: debug: extra_filter: '$extra_filter'\n" if(defined($extra_filter));
print STDERR "$tag: debug: filter: '$filter'\n" if(defined($filter));
print STDERR "$tag: debug: group: '$group'\n" if(defined($group));
print STDERR "$tag: debug: ldapuri: '$ldapuri'\n" if(defined($ldapuri));
print STDERR "$tag: debug: multiple: '$multiple'\n" if(defined($multiple));
print STDERR "$tag: debug: starttls: '$starttls'\n" if(defined($starttls));
print STDERR "$tag: debug: passwd: '$passwd'\n" if(defined($passwd));
print STDERR "$tag: debug: passwd_env: \$$passwd_env\n" if(defined($passwd_env));
print STDERR "$tag: debug: print: '$print'\n" if(defined($print));
print STDERR "$tag: debug: rebind: $rebind\n" if(defined($rebind));
print STDERR "$tag: debug: scope: '$scope'\n" if(defined($scope));
print STDERR "$tag: debug: user: '$user'\n" if(defined($user));
print STDERR "$tag: debug: user_attr: '$user_attr'\n" if(defined($user));
print STDERR "$tag: debug: user_env: \$$user_env\n" if(defined($user_env));
print STDERR "$tag: debug: user_filter: '$user_filter'\n" if(defined($user_filter));
print STDERR "$tag: debug: verbose: $verbose\n" if(defined($verbose));
print STDERR "$tag: debug: separator: $separator\n" if(defined($separator));
print STDERR "$tag: debug: value_map: " . Data::Dump::dump($value_map) . "\n" if(defined($value_map));
}
if(!defined($ldapuri)) {
print STDERR "$tag: error: missing LDAP URI, you MUST specify it with -H or --ldapuri\n";
exit(1);
}
if(defined($binddn) && defined($binddn_env)) {
print STDERR "$tag: error: --binddn and --binddn-env can't be specified at the same time\n";
exit(1);
}
if(defined($bindpw) && defined($bindpw_env)) {
print STDERR "$tag: error: --bindpw and --bindpw-env can't be specified at the same time\n";
exit(1);
}
if(defined($binddn_env) && !exists($ENV{$binddn_env})) {
print STDERR "$tag: error: expected environment variable \$$binddn_env to contain bind DN but it's not set\n";
exit(1);
}
if(defined($bindpw_env) && !exists($ENV{$bindpw_env})) {
print STDERR "$tag: error: expected environment variable \$$bindpw_env to contain bind DN password but it's not set\n";
exit(1);
}
if(defined($user) && defined($user_env)) {
print STDERR "$tag: error: --user and --user-env can't be specified at the same time\n";
exit(1);
}
if(defined($user) && defined($user_filter)) {
print STDERR "$tag: error: --user and --user-filter can't be used at the same time\n";
exit(1);
}
if(defined($user) && defined($filter)) {
print STDERR "$tag: error: --user and --filter can't be used at the same time\n";
exit(1);
}
if(defined($user_filter) && defined($filter)) {
print STDERR "$tag: error: --user-filter and --filter can't be used at the same time\n";
exit(1);
}
if(defined($extra_filter) && defined($filter)) {
print STDERR "$tag: error: --extra-filter and --filter can't be used at the same time\n";
exit(1);
}
if(defined($passwd) && defined($passwd_env)) {
print STDERR "$tag: error: --passwd and --passwd-env can't be specified at the same time\n";
exit(1);
}
if(defined($user_env) && !exists($ENV{$user_env})) {
print STDERR "$tag: error: expected environment variable \$$user_env to contain user user but it's not set\n";
exit(1);
}
if(defined($passwd_env) && !exists($ENV{$passwd_env})) {
print STDERR "$tag: error: expected environment variable \$$passwd_env to contain user password but it's not set\n";
exit(1);
}
# Retrieve credentials from environment
#
$binddn = $ENV{$binddn_env} if(defined($binddn_env));
$bindpw = $ENV{$bindpw_env} if(defined($bindpw_env));
$user = $ENV{$user_env} if(defined($user_env));
$passwd = $ENV{$passwd_env} if(defined($passwd_env));
if(defined($user) && !defined($user_attr)) {
print STDERR "--user or --user-env given but --user-attr is empty\n";
exit(1);
}
if(defined($user_attr) && defined($user)) {
print STDERR "$tag: info: authenticating user '$user'\n" if($verbose);
$user =~ s/\\/\\5C/g;
$user =~ s/\*/\\2A/g;
$user_filter = "$user_attr=$user";
}
if(defined($user_filter)) {
if(defined($extra_filter)) {
$filter = "(&($user_filter)($extra_filter))";
} else {
$filter = "($user_filter)";
}
print STDERR "$tag: info: search filter set to '$filter'\n" if($verbose);
}
if(defined($attrs)) {
my @tmp = split(/,/,$attrs);
$attrs = undef;
@$attrs = @tmp;
}
my $groupattr;
my $groupdn;
if(defined($group)) {
my ($p1, $p2) = split(/\//,$group,2);
if(!$p2) {
$groupdn = $p1;
} else {
$groupattr = $p1;
$groupdn = $p2;
}
$groupattr = 'member' if(!$groupattr);
if($debug) {
print STDERR "$tag: debug: \$groupdn='$groupdn'\n";
print STDERR "$tag: debug: \$groupattr='$groupattr'\n";
}
if(!$groupdn) {
print STDERR "$tag: error: group DN not provided for -G option\n";
exit(1);
}
}
if($debug) {
print STDERR "$tag: debug: final values: \n";
print STDERR "$tag: debug: attrs: " . Data::Dump::dump($attrs) ."\n" if(defined($attrs));
print STDERR "$tag: debug: base: '$base'\n" if(defined($base));
print STDERR "$tag: debug: binddn: '$binddn'\n" if(defined($binddn));
print STDERR "$tag: debug: binddn_env: \$$binddn_env\n" if(defined($binddn_env));
print STDERR "$tag: debug: bindpw: '$bindpw'\n" if(defined($bindpw));
print STDERR "$tag: debug: bindpw_env: \$$bindpw_env\n" if(defined($bindpw_env));
print STDERR "$tag: debug: debug: $debug\n";
print STDERR "$tag: debug: deref: '$deref'\n" if(defined($deref));
print STDERR "$tag: debug: extra_filter: '$extra_filter'\n" if(defined($extra_filter));
print STDERR "$tag: debug: filter: '$filter'\n" if(defined($filter));
print STDERR "$tag: debug: group: '$group'\n" if(defined($group));
print STDERR "$tag: debug: groupdn: '$groupdn'\n" if(defined($groupdn));
print STDERR "$tag: debug: groupattr: '$groupattr'\n" if(defined($groupattr));
print STDERR "$tag: debug: ldapuri: '$ldapuri'\n" if(defined($ldapuri));
print STDERR "$tag: debug: multiple: '$multiple'\n" if(defined($multiple));
print STDERR "$tag: debug: starttls:: '$starttls'\n" if(defined($starttls));
print STDERR "$tag: debug: passwd: '$passwd'\n" if(defined($passwd));
print STDERR "$tag: debug: passwd_env: \$$passwd_env\n" if(defined($passwd_env));
print STDERR "$tag: debug: print: '$print'\n" if(defined($print));
print STDERR "$tag: debug: rebind: $rebind\n" if(defined($rebind));
print STDERR "$tag: debug: scope: '$scope'\n" if(defined($scope));
print STDERR "$tag: debug: user: '$user'\n" if(defined($user));
print STDERR "$tag: debug: user_attr: '$user_attr'\n" if(defined($user));
print STDERR "$tag: debug: user_env: \$$user_env\n" if(defined($user_env));
print STDERR "$tag: debug: user_filter: '$user_filter'\n" if(defined($user_filter));
print STDERR "$tag: debug: verbose: $verbose\n" if(defined($verbose));
print STDERR "$tag: debug: separator: $separator\n" if(defined($separator));
print STDERR "$tag: debug: value_map: " . Data::Dump::dump($value_map) . "\n" if(defined($value_map));
}
if($debug) {
print STDERR "$tag: debug: connecting to $ldapuri\n";
print STDERR "$tag: debug: \$ldap = Net::LDAP->new('$ldapuri', verify => require)\n";
}
my $ldap = Net::LDAP->new($ldapuri, verify => 'require') or die "$tag: error: $@";
if($starttls) {
if($debug) {
print STDERR "$tag: debug: Asking for Start TLS\n";
print STDERR "$tag: debug: \$ldap->start_tls( verify => 'require' )\n";
}
$ldap->start_tls( verify => 'require' ) or die "$tag: error: $@";
}
if($binddn && $bindpw) {
print STDERR "$tag: debug: \$bind = \$ldap->bind('$binddn', password => '$bindpw')\n" if($debug);;
$bind = $ldap->bind($binddn, password => $bindpw);
} else {
$bind = $ldap->bind();
}
if($debug) {
print STDERR "$tag: debug: \$bind->is_error() == ".$bind->is_error()."\n";
print STDERR "$tag: debug: \$bind->code == ".$bind->code."\n";
}
if($bind->is_error()) {
print STDERR "$tag: error: ".$bind->error()."\n" if($verbose);
exit($bind->code);
}
my $userdn;
if(defined($filter)) {
print STDERR "$tag: debug: search filter given - will search LDAP database to find user\n" if($debug);
my $args = {};
$args->{'attrs'} = []; # we're just searching for user DN
$args->{'base'} = $base if(defined($base));
$args->{'scope'} = $base if(defined($scope));
$args->{'deref'} = $base if(defined($deref));
$args->{'filter'} = $filter;
print STDERR "$tag: debug: \$result = \$ldap->search(". Data::Dump::dump($args) .")\n" if($debug);
$result = $ldap->search(%$args);
if($result->is_error()) {
print STDERR "$tag: error: ".$result->error()."\n" if($verbose);
exit($result->code);
}
print STDERR "$tag: debug: \$result->count == ". $result->count ."\n" if($debug);;
if($result->count == 0) {
print STDERR "$tag: error: user not found in database\n" if($verbose);
exit(1);
} elsif(!$multiple && $result->count > 1) {
print STDERR "$tag: error: ambiguous search result (found ".$result->count."entries)\n" if($verbose);
exit(1);
}
my @entries = $result->entries();
# Try all entries to bind to their DNs
my $i = 0;
foreach(@entries) {
my $entry = $_;
my $dn = $entry->dn();
if($debug) {
print STDERR "$tag: debug: [$i] trying " .$dn. "\n" if($debug);
print STDERR "$tag: debug: [$i] \$bind = \$ldap->bind('$dn', password => '$passwd')\n";
}
# Try to bind as user
my $bind = $ldap->bind($dn, password => $passwd);
print STDERR "$tag: debug: [$i] \$bind->is_error() == ". $bind->is_error() ."\n" if($debug);
if($bind->is_error()) {
print STDERR "$tag: debug: [$i] ".$bind->error()."\n" if($debug);
} else {
print STDERR "$tag: debug: [$i] bind successful\n" if($debug);
$userdn = $dn;
}
# Bind back to the original bind DN
if($binddn && $bindpw) {
if($debug) {
print STDERR "$tag: debug: [$i] binding back to $binddn\n";
print STDERR "$tag: debug: [$i] \$bind = \$ldap->bind('$binddn', password => '$bindpw')\n";
}
$bind = $ldap->bind($binddn, password => $bindpw);
} else {
$bind = $ldap->bind;
}
if($debug) {
print STDERR "$tag: debug: [$i] \$bind->is_error() == ".$bind->is_error()."\n";
print STDERR "$tag: debug: [$i] \$bind->code == ".$bind->code."\n";
}
if($bind->is_error()) {
print STDERR "$tag: error: ".$bind->error()."\n" if($verbose);
exit($bind->code);
}
# User initially authenticated, it's done unless we have to check its
# group participation.
if(defined($userdn)) {
if(defined($groupdn) && defined($groupattr)) {
# Group check
if($debug) {
print STDERR "$tag: debug: [$i] group check requested by user\n";
print STDERR "$tag: debug: [$i] \$result = \$ldap->compare('$groupdn', attr => '$groupattr', value => '$userdn')\n";
}
my $result = $ldap->compare($groupdn, attr => $groupattr, value => $userdn);
print STDERR "$tag: debug: [$i] \$result->is_error() == " . $result->is_error() . "\n" if($debug);
if($result->is_error()) {
print STDERR "$tag: error: ".$bind->error()."\n" if($verbose);
exit($result->code);
}
print STDERR "$tag: debug: [$i] \$result->code == " . $result->code . "\n" if($debug);
if($result->code == 6) { # compareTrue(6)
print STDERR "$tag: debug: [$i] user belongs to the group $group\n" if($debug);
last;
} else {
print STDERR "$tag: debug: [$i] user does not belong to the group $group\n" if($debug);
$userdn = undef;
}
} else {
last;
}
}
$i += 1;
}
if(!defined($userdn)) {
print STDERR "$tag: error: authentication failed\n" if($verbose);
exit(1);
}
} elsif($binddn && $bindpw) {
$userdn = $binddn;
} else {
print STDERR "$tag: debug: no binddn, username nor search filter specified\n" if($debug);
print STDERR "$tag: error: authentication failed\n" if($verbose);
exit(1);
}
#
# Success! Do postprocessing.
#
print STDERR "$tag: info: successfully authenticated as '$userdn'\n" if($verbose);
if(defined($print)) {
print STDERR "$tag: debug: print was requested by user\n" if($debug);
if($print =~ /%\{[a-zA-Z0-9_]+\}/) {
print STDERR "$tag: debug: print template contains placeholders -- will retrieve user attributes\n" if($debug);
if($rebind) {
if($debug) {
print STDERR "$tag: debug: rebind requested by user\n";
print STDERR "$tag: debug: \$bind = \$ldap->bind('$userdn', password => '$passwd')\n";
}
my $bind = $ldap->bind($userdn, password => $passwd);
print STDERR "$tag: debug: \$bind->is_error() == ". $bind->is_error() ."\n" if($debug);
if($bind->is_error()) {
print STDERR "$tag: debug: ".$bind->error()."\n" if($debug);
} else {
print STDERR "$tag: debug: bind successful\n" if($debug);
}
}
my $args = {
'base' => $userdn,
'scope' => 'base',
'filter' => "objectClass=*"
};
$args->{'attrs'} = $attrs if(defined($attrs));
print STDERR "$tag: debug: \$result = \$ldap->search(" .Data::Dump::dump($args). ");\n" if($debug);
my $result = $ldap->search(%$args);
print STDERR "$tag: debug: \$result->is_error() == " . $result->is_error() . "\n" if($debug);
if($result->is_error()) {
print STDERR "$tag: error: ".$result->error()."\n" if($verbose);
exit($result->code);
}
print STDERR "$tag: debug: \$result->count() == " . $result->count() . "\n" if($debug);
if($result->count > 1) {
# Here we expect unique result, no matter what ..
print STDERR "$tag: error: ambiguous search result for dn: $userdn\n" if($verbose);
exit(1);
} elsif($result->count == 0) {
print STDERR "$tag: error: dn: $userdn not found in database\n" if($verbose);
exit(1);
}
my @entries = $result->entries();
my $userentry = @entries[0];
print STDERR "$tag: debug: substituting s/%{dn}/$userdn/gi\n" if($debug);
$print =~ s/%\{dn\}/$userdn/gi;
foreach my $attr ($userentry->attributes) {
my @values = $userentry->get_value($attr);
if($print =~ /%\{$attr\}/) {
if($debug) {
print STDERR "$tag: debug: substituting s/%{$attr}/$_/gi\n" foreach (@values);
}
# Map raw attr values with the attribute mapping
print STDERR "$tag: debug: Applying value mapping\n" if($debug);
@values = map { defined $value_map->{$_} ? $value_map->{$_} : $_ } @values;
$print =~ s/%{$attr}/join(unbackslash($separator),@values)/egi
}
}
}
print STDERR "$tag: debug: printing the requested string to stdout\n" if($debug);
print "$print\n";
}
exit(0);
__END__
=head1 NAME
openxpki-auth-ldap - Authenticate user against LDAP server.
=head1 SYNOPSIS
openxpki-auth-ldap B<-H> URI [options]
Options:
--attrs,-a attrs user attributes to retrieve from LDAP
--base,-b searchbase base DN for user search
--binddn,-d binddn bind DN used to bind to LDAP directory
--binddn-env,-D name name of environment variable providing the binddn
--bindpw,-w passwd use this password for bind DN authentication
--bindpw-env,-W name name of environment variable providint bindpw
--debug,-g run in debug mode
--deref type specify how aliases dereferencing is done
--extra-filter filter extra filter used when searching LDAP
--filter filter hard-coded filter used to find the user
--group,-G group ensure that the user belongs to a group
--help print this help and exit
--ldapuri,-H ldapuri URI referring to LDAP server
--multiple,-m accept ambiguous search results
--passwd,-p passwd password to be checked
--passwd-env,-P name name of environment variable providing passwd
--print template print a string specified by template
--scope,-s scope ldap search scope: base, one, sub, children
--user,-u username user name of the user to be authenticated
--user-attr attr name of LDAP username attribute (default: uid)
--user-env,-U name name of environment variable providing username
--user-filter,-u filter hard-coded ldap filter to find user in database
--verbose,-V print errors/warnings to stderr
--separator used with --print, set the separator for multi-valued attributes
--value-map,-k map attribute values with another value
=head1 OPTIONS
=over 8
=item B<--attrs,-a> I<attr1>[,I<attr2>[,...]]
List of user attributes to retrieve from LDAP when B<--print> is requested.
The attributes are only retrieved when B<--print> option is used and the print
template contains placeholders (see B<--print>). By default all attributes are
retrieved from LDAP. The B<--attrs> option may be used to limit the list of
attributes being queried. The value is a comma-separated list of attribute
names.
Example:
openxpki-auth-ldap --attrs cn,gidNumber,telephoneNumber ...
=item B<--base,-b> I<searchbase>
Use I<searchbase> as starting point for user search. This is only used when
B<--user>, B<--user-filter>, or B<--filter> is specified (otherwise the user
DN is specified directly by B<--binddn> and the search step is not performed).
=item B<--binddn,-d> I<binddn>
Use Distinguished Name I<binddn> to bind to the LDAP directory. This option is
provided for troubleshooting purposes only. You should avoid passing bind
credentials via command line. In production use B<--binddn-env> instead.
=item B<--binddn-env,-D> I<binddn_env>
Use environment variable I<binddn_env> to pass bind DN to the script.
Example:
(export BINDDN='cn=admin,dc=example,dc=com'; openxpki-auth-ldap -D BINDDN ...)
=item B<--bindpw,-w> I<passwd>
Use I<passwd> as the password for simple authentication (for binding as
binddn). This option is provided for troubleshooting purposes only. You should
NEVER PASS PASSWORDS VIA COMMAND LINE. In production use B<--bindpw-env>
instead.
=item B<--bindpw-env,-W> I<bindpw_env>
Use environment variable I<bindpw_env> to provide a password to be used for
binding with binddn.
Example:
(export BINDPW='secret'; openxpki-auth-ldap -W BINDPW ...)
=item B<--debug,-g>
Print debugging information to stderr.
=item B<--deref> I<type>
Specify how aliases dereferencing is done. The I<type> should be one of never,
always, search, or find to specify that aliases are never dereferenced, always
dereferenced, dereferenced when searching, or dereferenced only when locating
the base object for the search. The default is to never dereference aliases.
=item B<--extra-filter> I<filter>
For use with --user or --user-filter. When constructing a search filter for
user search it may be composed of two elements. The first is user_filter, which
by assumption only places restrictions on user identifiers (e.g. uid). The
second part called extra_filter may be arbitrary and provides additional,
custom restrictions. The two parts: the B<--user-filter> and B<--extra-filter>
are combined by the B<and> operator. This flag conflicts with B<--filter>.
Example:
The flags:
--user-filter 'uid=jsmith' --extra-filter 'accountStatus=active'"
will result with the search filter:
'(&(uid=jsmith)(accountStatus=active))'
=item B<--filter,-f> I<filter>
Hard-coded filter for user search. This flag conflicts with --user,
--user-filter, and --extra-filter.
=item B<--group,-G> I<group>
Ensure that user belongs to a given group. The I<group> parameter specifies an
entry containing Distinguished Names of users belonging to the group. The
format of I<group> argument is:
[attr/]dn
where C<attr> is the name of attribute collecting DNs of the group participants
and C<dn> is a Distinguished Name of the group entry. If C<attr> is not
provided, the default attribute C<'member'> is assumed.
Example:
# Let's say, we have the following group definition in LDAP:
#
# dn: cn=vip,dc=example,dc=org
# cn: pm-users
# objecClass: top
# objecClass: organizationalRole
# roleOccupant: uid=jsmith,ou=people,dc=example,dc=org
# roleOccupant: uid=pbrown,ou=people,dc=example,dc=org
#
# Then we may restrict authentication to this group participants only
# by using the following syntax:
openxpki-auth-ldap -G "roleOccupant/cn=vip,dc=example,dc=org" ...
=item B<--help>
Print this help message.
=item B<--ldapuri,-H> I<ldapuri>
Specify URI referring to the ldap server; only the protocol/host/port fields
are allowed.
=item B<--multiple,-m>
Accept ambiguous search results. If the user search results with multiple
entries, the script will try to bind to each of them (in order) untill first
successful bind. By default ambiguous search results are discarded, that is
they're reported as error.
=item B<--starttls,-t>
Upgrade the connection using Start TLS. If set, Start TLS is ran just after the
connection is established, before any bind or search operation.
=item B<--passwd,-p> I<passwd>
Provide password for user (specified with B<--user>, B<--user-env>,
B<--user-filter> or B<--filter>). This option is provided for troubleshooting
purposes only. You should NEVER PASS PASSWORDS VIA COMMANDLINE in production.
Instead, you should use B<--passwd-env>.
=item B<--passwd-env,-P> I<passwd_env>
Specify name of an environment variable carrying password for the user being
authenticated (specified with either --user or --user-env).
Example:
(export PASSWD=secret; openxpki-auth-ldap --passwd-env PASSWD ...)
=item B<--print> I<template>
Print a string specified by I<template>. On successful authentication a string
specified by I<template> will be printed to stdout. The template may contain
placeholders in form C<%{attrName}>, where the C<attrName> is the name of LDAP
attribute. The C<attrName> should be a name of attribute returned by user
search (it should be included in B<--attrs> list, if B<--attrs> option is
specified).
=item B<--scope,-s> {base|one|sub|children}
Specify the scope of the search to be one of base, one, sub, or children to
specify a base object, one-level, subtree, or children search. The default is
sub. Note: children scope requires LDAPv3 subordinate feature extension.
=item B<--user,-u> I<username>
Specify the user to be authenticated. This is usually a login/uid of the user
to be found in LDAP and authenticated. This option is provided for
troubleshooting purposes only. You should avoid passing user names via command
line. In production you should use B<--user-env> instead.
=item B<--user-atttr> I<attr>
Name of LDAP attribute used for user name (default is: uid). The I<attr> is
used together with the value of B<--user> I<username> option. When searching
the LDAP directory for I<username>, the I<username> is compared to the values
of I<attr> by the LDAP server.
=item B<--user-env,-U> I<user_env>
Specify name of an environment variable carrying username of the user that is
to be authenticated.
Example:
(export LOGIN=jsmith; openxpki-auth-ldap --passwd-env LOGIN ...)
=item B<--user-filter> I<filter>
Hard-code filter used to search users in LDAP database. Note, that
B<--extra-filter>, if specified, will be appended to this user filter.
Example:
openxpki-auth-ldap --user-filter 'uid=jsmi*'
=item B<--verbose,-V>
Print errors to stderr. Normally the script runs in quiet mode and only returns
success/failure status to shell without printing anything anywhere. With
B<--verbose> it outputs error/warning messages to stderr.
=item B<--separator>
Used with --print. If --print contains an attribute wich has multiple values,
separates them with this string. Default is \n
=item B<--value-map,-k>
Used with --print. Lets you map raw attribute values with other values. Can be
specified several times
=back
=head1 DESCRIPTION
Authenticate users against LDAP server. The script is intended to be used in
other scripts as an external authentication source.
Currently it allows for simple authentication (LDAP bind, SASL is not supported
yet). The user to be authenticated may be specified by its Distinguished Name
or the LDAP directory may be searched for the user.
All the options necessary to establish connection, find the user and perform
the authentication are provided via command line and environment variables.
Sensitive data (logins, passwords) should be passed via (temporary) environment
variables (command line may be easilly disclosed by users having access to the
operating system running the script).
=head1 EXAMPLES
# Aanonymous bind. This always fails, even if the bind itself is successful.
openxpki-auth-ldap -g -V -H ldap://ldap.example.org
# Try to bind to uid=jsmith,ou=people,dc=example,dc=org using "secret" as
# the password.
(
export BINDDN="cn=jsmith,ou=people,dc=example,dc=org";
export BINDPW="secret";
openxpki-auth-ldap -g -V -H ldaps://ldap.example.org -D BINDDN -W BINDPW;
)
# Try to authenticate user 'jsmith' with password 'secret'.
# This will try to anonymously bind to LDAP directory and then search for
# 'uid=jsmith' starting from base "ou=people,dc=example,dc=org".
# If 'jsmith' is found, the script will try to bind to its entry using
# the provided password.
(
export LOGIN="jsmith";
export PASSWD="secret";
openxpki-auth-ldap -g -V -H ldap://ldap.example.org -U LOGIN -P PASSWD \
-b "ou=people,dc=example,dc=org";
)
# Try to authenticate user 'jsmith' with password 'secret'.
# This will try to bind as "cn=admin,dc=example,dc=org" to LDAP directory
# and then search for 'uid=jsmith' starting from default base. If 'jsmith'
# is found, the script will try to bind to its entry using the provided
# password.
(
export BINDDN="cn=jsmith,ou=people,dc=example,dc=org";
export BINDPW="secret";
export LOGIN="jsmith";
export PASSWD="secret";
openxpki-auth-ldap -g -V -H ldap://ldap.example.org -D BINDDN -W BINDPW \
-U LOGIN -P PASSWD -b "ou=people,dc=example,dc=org";
)
=cut

View File

@@ -0,0 +1,10 @@
module openxpki 1.0;
require {
type httpd_sys_script_t;
type httpd_var_run_t;
class sock_file write;
}
#============= httpd_sys_script_t ==============
allow httpd_sys_script_t httpd_var_run_t:sock_file write;

View File

@@ -0,0 +1,29 @@
From 7938c0f6977196bc0c074ff5c5f0fe11018dc111 Mon Sep 17 00:00:00 2001
From: Daniel Berteaud <daniel@firewall-services.com>
Date: Fri, 7 Sep 2018 08:52:15 +0200
Subject: [PATCH] Render templates for reply and cc fields for SMTP
notifications Just as the to field is rendered. BTW the reply is needed even
with the sample config in notification.smtp.message.csr_created.raop
---
core/server/OpenXPKI/Server/Notification/SMTP.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/core/server/OpenXPKI/Server/Notification/SMTP.pm b/core/server/OpenXPKI/Server/Notification/SMTP.pm
index 28658e07f..7f8a27135 100644
--- a/core/server/OpenXPKI/Server/Notification/SMTP.pm
+++ b/core/server/OpenXPKI/Server/Notification/SMTP.pm
@@ -592,8 +592,8 @@ sub _send_html {
Charset => 'UTF-8',
);
- push @args, (Cc => join(",", @{$vars->{cc}})) if ($vars->{cc});
- push @args, ("Reply-To" => $cfg->{reply}) if ($cfg->{reply});
+ push @args, (Cc => $self->_render_template(join(",", @{$vars->{cc}}),$vars)) if ($vars->{cc});
+ push @args, ("Reply-To" => $self->_render_template($cfg->{reply},$vars)) if ($cfg->{reply});
##! 16: 'Building with args: ' . Dumper @args
--
2.17.1

View File

@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS `frontend_session` (
`session_id` varchar(255) NOT NULL PRIMARY KEY,
`data` longtext,
`created` int(10) unsigned NOT NULL,
`modified` int(10) unsigned NOT NULL,
`ip_address` varchar(45) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@@ -0,0 +1,9 @@
ALTER TABLE `certificate`
DROP KEY `pki_realm_2`,
ADD KEY `pki_realm_req_key` (`pki_realm`,`req_key`),
ADD KEY `req_key` (`req_key`);
ALTER TABLE `csr_attributes`
ADD KEY `pki_realm_req_key` (`pki_realm`,`req_key`);

View File

@@ -0,0 +1,13 @@
ALTER TABLE `certificate`
ADD COLUMN `revocation_id` INT NULL DEFAULT NULL
AFTER `hold_instruction_code`;
ALTER TABLE `crl`
ADD COLUMN `max_revocation_id` INT NULL DEFAULT NULL
AFTER `items`;
ALTER TABLE `certificate`
ADD UNIQUE `revocation_id` (`revocation_id`);
ALTER TABLE `crl`
ADD KEY `revocation_id` (`max_revocation_id`);

View File

@@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS `users` (
`username` varchar(255) NOT NULL,
`password` varchar(255) DEFAULT NULL,
`pki_realm` varchar(255) DEFAULT NULL,
`mail` varchar(255) NOT NULL,
`realname` varchar(255) DEFAULT NULL,
`role` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@@ -0,0 +1,22 @@
ALTER TABLE `application_log`
MODIFY COLUMN `logtimestamp` decimal(20,5) unsigned DEFAULT NULL;
ALTER TABLE `audittrail`
MODIFY COLUMN `logtimestamp` decimal(20,5) unsigned DEFAULT NULL;
ALTER TABLE `crl`
ADD COLUMN `profile` varchar(64) DEFAULT NULL
AFTER `issuer_identifier`;
ALTER TABLE `crl`
ADD KEY `profile` (`profile`);
ALTER TABLE `datapool`
ADD COLUMN `access_key` varchar(255) NULL DEFAULT NULL
AFTER `encryption_key`;
ALTER TABLE `workflow`
ADD COLUMN `workflow_archive_at` int(10) unsigned DEFAULT NULL
AFTER `workflow_reap_at`;
ALTER TABLE `workflow`
ADD KEY `watchdog_archive_at` (`workflow_archive_at`, `watchdog_key`, `workflow_proc_state`);

View File

@@ -0,0 +1,12 @@
---
- name: restart openxpki
service: name=openxpki state=restarted
when: not pki_started.changed
- name: reload openxpki
service: name=openxpki state=reloaded
- name: restart openxpki fcgi
shell: kill $(pgrep -f '(webui|scep.*|sc|est|rpc|download|soap).fcgi')
failed_when: False

View File

@@ -0,0 +1,6 @@
---
dependencies:
- role: httpd_common
- role: mkdir
- role: mysql_server
when: pki_db_server in ['localhost', '127.0.0.1']

View File

@@ -0,0 +1,8 @@
---
- import_tasks: ../includes/webapps_compress_archive.yml
vars:
- root_dir: "{{ pki_root_dir }}"
- version: "{{ pki_current_version }}"
tags: pki

View File

@@ -0,0 +1,30 @@
---
- name: Create archive dir
file: path={{ pki_root_dir }}/archives/{{ pki_current_version }} state=directory mode=700
tags: pki
- name: Archive previous version
synchronize:
src: "{{ pki_root_dir }}"
dest: "{{ pki_root_dir }}/archives/{{ pki_current_version }}/"
delete: True
compress: False
rsync_opts:
- '--exclude=archives/'
- '--exclude=run/'
delegate_to: "{{ inventory_hostname }}"
tags: pki
- name: Dump the database
mysql_db:
state: dump
name: "{{ pki_db_name }}"
target: "{{ pki_root_dir }}/archives/{{ pki_current_version }}/{{ pki_db_name }}.sql"
login_host: "{{ pki_db_server | default(mysql_server) }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
quick: True
single_transaction: True
tags: pki

View File

@@ -0,0 +1,24 @@
---
- name: List sources
shell: find {{ pki_root_dir }}/src -maxdepth 1 -mindepth 1 -exec basename "{}" \;
register: pki_sources
changed_when: False
tags: pki
# Note : we keep sources and tgz for the currently installed version
- name: Remove previous sources
file: path={{ pki_root_dir }}/src/{{ item }} state=absent
loop: "{{ pki_sources.stdout_lines }}"
when:
- item != 'openxpki-' ~ pki_version
- item != 'openxpki-' ~ pki_version ~ '.tar.gz'
- item != 'openxpki-config-' ~ pki_config_version
- item != 'openxpki-config-' ~ pki_config_version ~ '.tar.gz'
tags: pki
- name: Remove obsolete and temp files and directories
file: path={{ item }} state=absent
loop:
- "{{ pki_root_dir }}/db_dumps"
tags: pki

View File

@@ -0,0 +1,118 @@
---
- name: Deploy JS config
template: src=localconfig.js.j2 dest={{ pki_root_dir }}/web/htdocs/localconfig.js
tags: pki
- name: Check if notification is a link or a dir
stat: path={{ pki_root_dir }}/etc/notification
register: pki_notif_config
tags: pki
- name: Remove notification dir from the config
file: path={{ pki_root_dir }}/etc/notification state=absent
when:
- pki_notif_config.stat.isdir is defined
- pki_notif_config.stat.isdir
tags: pki
- name: Copy default configuration
synchronize:
src: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/"
dest: "{{ pki_root_dir }}/etc/"
compress: False
rsync_opts:
- '--exclude=config.d/realm/democa'
delegate_to: "{{ inventory_hostname }}"
when: pki_install_mode != 'none' # or pki_patches.changed
tags: pki
- name: Create realm config directories
file: path={{ pki_root_dir }}/etc/config.d/realm/{{ item.name }} state=directory
with_items: "{{ pki_realms }}"
register: pki_new_realms
tags: pki
- name: Populate realm config
synchronize:
src: "{{ pki_root_dir }}/etc/config.d/realm.tpl/"
dest: "{{ pki_root_dir }}/etc/config.d/realm/{{ item.item.name }}/"
compress: False
delete: True
delegate_to: "{{ inventory_hostname }}"
when: item.changed or pki_install_mode != 'none'
with_items: "{{ pki_new_realms.results }}"
tags: pki
- name: Create per realm links to the scep script handler
file: src=scep.fcgi dest={{ pki_root_dir }}/web/cgi-bin/scep_{{ item.name }}.fcgi state=link
when: item.scep.enabled
with_items: "{{ pki_realms }}"
tags: pki
- name: Remove scep for realms who has disabled it
file: path={{ pki_root_dir }}/web/cgi-bin/scep_{{ item.name }}.fcgi state=absent
when: not item.scep.enabled
with_items: "{{ pki_realms }}"
tags: pki
- name: Deploy system configuration
template: src={{ item }}.j2 dest={{ pki_root_dir }}/etc/{{ item }}
with_items:
- config.d/system/crypto.yaml
- config.d/system/database.yaml
- config.d/system/realms.yaml
- config.d/system/server.yaml
- config.d/system/watchdog.yaml
- notification/email/_footer.txt
- notification/email/_footer.html
notify: restart openxpki
tags: pki
- name: Deploy realm configuration
template: src=config.d/realm/{{ item.1 }}.j2 dest={{ pki_root_dir }}/etc/config.d/realm/{{ item.0.name }}/{{ item.1 }}
with_nested:
- "{{ pki_realms }}"
- - crypto.yaml
- nice.yaml
- notification/smtp.yaml
- publishing.yaml
- profile/default.yaml
- profile/signer.yaml
- profile/tls_client.yaml
- profile/tls_server.yaml
- profile/user_auth_enc.yaml
- auth/stack.yaml
- auth/handler.yaml
- workflow/global/validator/password_quality.yaml
- scep/scep-server.yaml
notify: restart openxpki
tags: pki
- name: Deploy per realm scep configuration
template: src=scep/default.conf.j2 dest={{ pki_root_dir }}/etc/scep/{{ item.name }}.conf
with_items: "{{ pki_realms }}"
notify: restart openxpki fcgi
tags: pki
- name: Deploy general configuration
template: src={{ item }}.j2 dest={{ pki_root_dir }}/etc/{{ item }}
with_items:
- log.conf
- openssl.cnf
- scep/log.conf
tags: pki
- name: Deploy webui configuration
template: src={{ item }}.j2 dest={{ pki_root_dir }}/etc/{{ item }}
with_items:
- webui/default.conf
- webui/log.conf
notify: restart openxpki fcgi
tags: pki
- name: Deploy httpd config
template: src=httpd.conf.j2 dest=/etc/httpd/ansible_conf.d/10-openxpki.conf
notify: reload httpd
tags: pki

View File

@@ -0,0 +1,52 @@
---
- name: Create directories
file: path={{ pki_root_dir }}/{{ item.path }} state=directory owner={{ item.owner | default(omit) }} group={{ item.group | default(omit) }} mode={{ item.mode | default(omit) }}
with_items:
- path: /
group: apache
mode: 750
- path: etc/config.d/realm
owner: "{{ pki_user }}"
group: apache
mode: 750
- path: etc/ssl/root
owner: "{{ pki_user }}"
group: "{{ pki_user }}"
mode: 700
- path: log
owner: "{{ pki_user }}"
mode: 700
- path: data
owner: "{{ pki_user }}"
group: apache
mode: 750
- path: run
owner: "{{ pki_user }}"
group: apache
mode: 750
- path: tmp
owner: "{{ pki_user }}"
group: apache
mode: 770
- path: meta
mode: 700
- path: locale
- path: web
- path: backup
mode: 700
- path: src
- path: archives
mode: 700
tags: pki
- name: Create data directories for realms
file: path={{ pki_root_dir }}/data/{{ item.name }} state=directory owner={{ pki_user }} group=apache mode=750
with_items: "{{ pki_realms }}"
tags: pki
- name: Create CA's directory
file: path={{ pki_root_dir }}/etc/ssl/{{ item.name }} state=directory
with_items: "{{ pki_realms }}"
tags: pki

View File

@@ -0,0 +1,83 @@
---
- include_vars: "{{ item }}"
with_first_found:
- vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml
- vars/{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml
- vars/{{ ansible_distribution }}.yml
- vars/{{ ansible_os_family }}.yml
tags: pki
# Merge realm config
- name: Build PKI realm config
set_fact: pki_realms_conf={{ pki_realms_conf | default([]) + [ pki_realm_conf | combine(item, recursive=True) ] }}
with_items: "{{ pki_realms }}"
tags: pki
- set_fact: pki_realms={{ pki_realms_conf | default([]) }}
tags: pki
# Detect if its an initial install, an upgrade, or none
- import_tasks: ../includes/webapps_set_install_mode.yml
vars:
- root_dir: "{{ pki_root_dir }}"
- version: "{{ pki_version }}"
tags: pki
- set_fact: pki_install_mode={{ (install_mode == 'upgrade' and not pki_manage_upgrade) | ternary('none',install_mode) }}
tags: pki
- set_fact: pki_current_version={{ current_version | default('') }}
tags: pki
# Generate various password and secrets, if they are not defined
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_secret_cookie"
tags: pki
- set_fact: pki_secret_cookie={{ rand_pass }}
tags: pki
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_secret"
when: pki_secret is not defined
tags: pki
- set_fact: pki_secret={{ rand_pass }}
when: pki_secret is not defined
tags: pki
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_scep_hmac"
when: pki_scep_hmac is not defined
tags: pki
- set_fact: pki_scep_hmac={{ rand_pass }}
when: pki_scep_hmac is not defined
tags: pki
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_scep_challenge"
when: pki_scep_challenge is not defined
tags: pki
- set_fact: pki_scep_challenge={{ rand_pass }}
when: pki_scep_challenge is not defined
tags: pki
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_dbpass"
when: pki_db_pass is not defined
tags: pki
- set_fact: pki_db_pass={{ rand_pass }}
when: pki_db_pass is not defined
tags: pki
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ pki_root_dir }}/meta/ansible_session_dbpass"
when: pki_db_session_pass is not defined
tags: pki
- set_fact: pki_db_session_pass={{ rand_pass }}
when: pki_db_session_pass is not defined
tags: pki

View File

@@ -0,0 +1,284 @@
---
- name: Install dependencies
yum: name={{ pki_packages }}
tags: pki
- name: Download OpenXPKI
get_url:
url: "{{ pki_archive_url }}"
dest: "{{ pki_root_dir }}/src"
checksum: "sha1:{{ pki_archive_sha1 }}"
register: pki_download
tags: pki
- name: Download OpenXPKI config
get_url:
url: "{{ pki_config_archive_url }}"
dest: "{{ pki_root_dir }}/src"
checksum: "sha1:{{ pki_config_archive_sha1 }}"
register: pki_config_download
tags: pki
- name: Extract OpenXPKI
unarchive:
src: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}.tar.gz"
dest: "{{ pki_root_dir }}/src"
remote_src: True
when: pki_download.changed
tags: pki
- name: Extract OpenXPKI config
unarchive:
src: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}.tar.gz"
dest: "{{ pki_root_dir }}/src"
remote_src: True
when: pki_config_download.changed
tags: pki
# This is needed or make will fail
- name: Write version in source dir
copy: content={{ pki_version }} dest={{ pki_root_dir }}/src/openxpki-{{ pki_version }}/VERSION
tags: pki
- name: Stop openxpki during upgrade
service: name=openxpki state=stopped
when: pki_install_mode == 'upgrade'
tags: pki
# With this, we ensure we update all perl modules each time we update OpenXPKI
- name: Wipe local lib dir
file: path={{ pki_root_dir }}/lib/perl5 state=absent
when: pki_install_mode == 'upgrade'
tags: pki
- when: pki_install_mode != 'none'
block:
- name: Install perl module without tests
cpanm:
name: "{{ item }}"
locallib: "{{ pki_root_dir }}"
notest: True
with_items:
- Git::PurePerl
- Connector # This module tries to fetch web content without checking proxy from env
- Net::Server # 2 tests are failing on el8 t/SSL_test.t and t/SSLEAY_test.t
- name: Install OpenXPKI dependencies
cpanm:
locallib: "{{ pki_root_dir }}"
installdeps: True
from_path: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/server"
environment:
PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
PATH: "{{ pki_root_dir }}/bin:{{ ansible_env.PATH }}"
- name: Install additional perl modules
cpanm:
name: "{{ item }}"
locallib: "{{ pki_root_dir }}"
with_items:
- Devel::CheckLib # Needed to build BDB::mysql >= 4.047
- DBD::mysql
- Log::Log4perl::Appender::Screen # Log::Log4perl::Appender::Journald is broken on systemd > 209
- Data::Dump # Needed for the external ldap auth script
- String::Escape # Needed for the external ldap auth script
- TINITA/YAML-1.30.tar.gz
- name: Build OpenXPKI
cpanm:
locallib: "{{ pki_root_dir }}"
from_path: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/server"
notest: True
environment:
PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
PATH: "{{ pki_root_dir }}/bin:{{ ansible_env.PATH }}"
- name: Install OpenXPKI
command: make install
args:
chdir: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/server"
notify: restart openxpki
# This is needed so the build-pot.pl script finds msg labels in config
# during the make scan step in next task
- name: Copy default conf in server source directory
synchronize:
src: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/"
dest: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/config/"
delete: True
compress: False
delegate_to: "{{ inventory_hostname }}"
- name: Scan, build and install translations
shell: make scan && make && make install LOCALE_DIR={{ pki_root_dir }}/locale
args:
chdir: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/i18n"
- name: Install the web UI
synchronize:
src: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/server/{{ item }}"
dest: "{{ pki_root_dir }}/web/"
compress: False
delegate_to: "{{ inventory_hostname }}"
with_items:
- cgi-bin
- htdocs
tags: pki
- name: Install OpenXPKI CGI::Session driver
copy:
src: "{{ pki_root_dir }}/src/openxpki-{{ pki_version }}/core/server/CGI_Session_Driver/openxpki.pm"
dest: "{{ pki_root_dir }}/lib/perl5/CGI/Session/Driver/openxpki.pm"
remote_src: True
tags: pki
- name: Fix relative URL in the index page
command: sed -i -e 's|/openxpki/|{{ pki_web_alias }}|g' {{ pki_root_dir }}/web/htdocs/default.html
changed_when: False
tags: pki
- name: Install wrapper scripts
template: src=bin/{{ item }}.j2 dest=/usr/local/bin/{{ item }} mode=755
with_items:
- openxpkiadm
- openxpkicmd
tags: pki
- name: Deploy cron scripts
template: src=bin/{{ item }}.j2 dest={{ pki_root_dir }}/bin/{{ item }} mode=755
with_items:
- crl_update
- notify_expiry
tags: pki
- name: Setup cronjobs
cron:
name: "{{ item.script }}"
cron_file: openxpki
user: "{{ pki_user }}"
job: /bin/systemd-cat {{ pki_root_dir }}/bin/{{ item.script }}
special_time: "{{ item.freq }}"
with_items:
- script: crl_update
freq: hourly
- script: notify_expiry
freq: weekly
tags: pki
- import_tasks: ../includes/webapps_create_mysql_db.yml
vars:
- db_name: "{{ pki_db_name }}"
- db_user: "{{ pki_db_user }}"
- db_server: "{{ pki_db_server }}"
- db_pass: "{{ pki_db_pass }}"
tags: pki
- name: Inject MySQL schema
mysql_db:
name: "{{ pki_db_name }}"
state: import
target: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/schema-mysql.sql"
login_host: "{{ pki_db_server }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
when:
- pki_install_mode == 'install'
- db_created.changed
tags: pki
- name: Copy additional sql scripts
copy: src={{ item }} dest={{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/{{ item }}
loop:
- session_table.sql
- upgrade_to_v3.sql
tags: pki
- name: Create session table
mysql_db:
name: "{{ pki_db_name }}"
state: import
target: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/session_table.sql"
login_host: "{{ pki_db_server }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
when:
- pki_install_mode != 'none'
tags: pki
- name: Create user for session table
mysql_user:
name: "{{ pki_db_session_user }}"
password: "{{ pki_db_session_pass }}"
priv: "{{ pki_db_name }}.frontend_session:SELECT,INSERT,UPDATE,DELETE"
append_privs: "{{ append_privs | default(False) }}"
host: "{{ ( pki_db_server == 'localhost' ) | ternary('localhost', item ) }}"
login_host: "{{ pki_db_server }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
state: present
with_items: "{{ ansible_all_ipv4_addresses }}"
tags: pki
- name: Upgrade database from v2 to v3
mysql_db:
name: "{{ pki_db_name }}"
state: import
target: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/upgrade_to_v3.sql"
login_host: "{{ pki_db_server }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
when:
- pki_install_mode == 'upgrade'
- pki_current_version is match('^2')
tags: pki
- name: Copy DB upgrades scripts
copy: src=upgrade_to_v{{ item }}.sql dest={{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/
loop:
- '3.4'
- '3.8'
- '3.14'
tags: pki
- name: Apply db upgrades
mysql_db:
name: "{{ pki_db_name }}"
state: import
target: "{{ pki_root_dir }}/src/openxpki-config-{{ pki_config_version }}/contrib/sql/upgrade_to_v{{ item }}.sql"
login_host: "{{ pki_db_server }}"
login_user: sqladmin
login_password: "{{ mysql_admin_pass }}"
loop:
- '3.4'
- '3.8'
- '3.14'
when:
- pki_install_mode == 'upgrade'
- pki_current_version is version(item, '<')
tags: pki
- name: Deploy systemd unit
template: src=openxpki.service.j2 dest=/etc/systemd/system/openxpki.service
register: pki_unit
tags: pki
- name: Reload systemd
systemd: daemon_reload=True
when: pki_unit.changed
tags: pki
- name: Deploy authentication script helpers
copy: src={{ item }} dest={{ pki_root_dir }}/bin/{{ item }} mode=755
with_items:
- openxpki-auth-ldap
tags: pki
- name: Install pre and post backup scripts
template: src={{ item }}-backup.j2 dest=/etc/backup/{{ item }}.d/openxpki mode=750
loop:
- pre
- post
tags: pki

View File

@@ -0,0 +1,23 @@
---
- include: user.yml
- include: directories.yml
- include: facts.yml
- include: archive_pre.yml
when: pki_install_mode == 'upgrade'
- include: install.yml
- include: conf.yml
- include: selinux.yml
when: ansible_selinux.status == 'enabled'
- include: pki.yml
- include: service.yml
- include: write_version.yml
- include: archive_post.yml
when: pki_install_mode == 'upgrade'
- include: cleanup.yml
#### TODO #####
# * Cron to renew at least issuing CA (and maybe Root CA later)
# * Add/Modify workflow to allow passwordless certs to be stored
# * Profile for OCSP signing
# * OCSP responder

View File

@@ -0,0 +1,211 @@
---
- name: Create global certificates
command: >
openssl req
-config {{ pki_root_dir }}/etc/openssl.cnf
-extensions v3_ca
-x509
-newkey rsa:{{ pki_realm_conf.keysize * 2 }}
-keyout {{ pki_root_dir }}/etc/ssl/root/{{ item.name }}-key-1.pem
-out {{ pki_root_dir }}/etc/ssl/root/{{ item.name }}-cert-1.pem
-sha256
-days {{ pki_realm_conf.validity * 2 }}
-subj '/C={{ pki_realm_conf.subj_c }}/ST={{ pki_realm_conf.subj_st }}/L={{ pki_realm_conf.subj_l }}/O={{ pki_realm_conf.subj_o }}/OU={{ pki_realm_conf.subj_ou }}/CN={{ item.cn }}'
-passout stdin
args:
creates: "{{ pki_root_dir }}/etc/ssl/root/{{ item.name }}-cert-1.pem"
stdin: "{{ pki_secret }}"
with_items:
- name: signer
cn: "{{ pki_root_ca_cn }}"
- name: vault
cn: "{{ pki_vault_cn }}"
- name: scep
cn: "{{ pki_scep_cn }}"
register: pki_root_created
tags: pki
- name: Check if the index file for the root CA exists
stat: path={{ pki_root_dir }}/etc/ssl/root/index.txt
register: pki_root_ca_index
tags: pki
- name: Create the index file
file: path={{ pki_root_dir }}/etc/ssl/root/index.txt state=touch
when: not pki_root_ca_index.stat.exists
tags: pki
- name: Create the serial file
shell: echo 1000 > {{ pki_root_dir }}/etc/ssl/root/serial
args:
creates: "{{ pki_root_dir }}/etc/ssl/root/serial"
tags: pki
- name: Import the certificates in the global namespace of OpenXPKI DB
command: >
{{ pki_root_dir }}/bin/openxpkiadm certificate import
--file {{ pki_root_dir }}/etc/ssl/root/{{ item.item.name }}-cert-1.pem
--config={{ pki_root_dir }}/etc/config.d/
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
with_items: "{{ pki_root_created.results }}"
#no_log: True
when: item.changed
tags: pki
# Vault and SCEP certificates are global, so just link them from the root dir in every realm dir
- name: Link vault and SCEP keys from the root to the realms
file: src=../root/{{ item.1 }}-key-1.pem dest={{ pki_root_dir }}/etc/ssl/{{ item.0.name }}/{{ item.1 }}-key-1.pem state=link
with_nested:
- "{{ pki_realms }}"
- [vault,scep]
tags: pki
# For each realm, we create only the signer CA. Vault and SCEP will use the global ones
- name: Create issuing CA's private keys
command: >
openssl genrsa
-out {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-key-1.pem
-aes256
-passout stdin
{{ item.keysize }}
args:
creates: "{{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-key-1.pem"
stdin: "{{ pki_secret }}"
with_items: "{{ pki_realms }}"
#no_log: True
tags: pki
- name: Create issuing CA's CSR
command: >
openssl req
-config {{ pki_root_dir }}/etc/openssl.cnf
-new
-sha256
-key {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-key-1.pem
-out {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-csr-1.pem
-subj '/C={{ item.subj_c | default(pki_realm_conf.subj_c) }}/ST={{ item.subj_st | default(pki_realm_conf.subj_st) }}/L={{ item.subj_l | default(pki_realm_conf.subj_l) }}/O={{ item.subj_o | default(pki_realm_conf.subj_o) }}/OU={{ item.subj_ou | default(pki_realm_conf.subj_ou) }}/CN={{ item.name }}'
-extensions v3_intermediate_ca
-passin stdin
args:
creates: "{{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-csr-1.pem"
stdin: "{{ pki_secret }}"
with_items: "{{ pki_realms }}"
#no_log: True
tags: pki
# Now we create issuing CA. First, iterate over those who do not have a parent defined. Which means they are a child of the root CA
- name: Sign intermediate CA with the Root CA
command: >
openssl ca
-config {{ pki_root_dir }}/etc/openssl.cnf
-keyfile {{ pki_root_dir }}/etc/ssl/root/signer-key-1.pem
-cert {{ pki_root_dir }}/etc/ssl/root/signer-cert-1.pem
-in {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-csr-1.pem
-out {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-cert-1.pem
-passin stdin
-extensions v3_intermediate_ca
-days {{ item.validity | default('3650') }}
-notext
-batch
args:
creates: "{{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-cert-1.pem"
stdin: "{{ pki_secret }}"
when: item.parent is not defined
register: pki_ca_issuing_created
with_items: "{{ pki_realms }}"
#no_log: True
tags: pki
- name: Import certificates for CA signed by the Root CA in OpenXPKI DB
command: >
{{ pki_root_dir }}/bin/openxpkiadm certificate import
--file {{ pki_root_dir }}/etc/ssl/{{ item.item.name }}/signer-cert-1.pem
--realm {{ item.item.name }}
--token certsign
--config={{ pki_root_dir }}/etc/config.d/
when: item.changed
with_items: "{{ pki_ca_issuing_created.results }}"
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
#no_log: True
tags: pki
# And now the same with intermediate CA
- name: Sign intermediate CA with their parent CA
command: >
openssl ca
-config {{ pki_root_dir }}/etc/openssl.cnf
-keyfile {{ pki_root_dir }}/etc/ssl/{{ item.parent }}/signer-key-1.pem
-cert {{ pki_root_dir }}/etc/ssl/{{ item.parent }}/signer-cert-1.pem
-in {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-csr-1.pem
-out {{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-cert-1.pem
-passin stdin
-extensions v3_intermediate_ca
-days {{ item.validity | default('3650') }}
-notext
-batch
args:
creates: "{{ pki_root_dir }}/etc/ssl/{{ item.name }}/signer-cert-1.pem"
stdin: "{{ pki_secret }}"
when: item.parent is defined
register: pki_ca_intermediate_created
with_items: "{{ pki_realms }}"
tags: pki
# Once added in the DB, each certs gets an ID. We need to get this ID for
# the two global certs (vault and scep) so we can create an alias for each realm
- name: Get ID of the global vault certificate
command: >
{{ pki_root_dir }}/bin/openxpkiadm certificate id
--file {{ pki_root_dir }}/etc/ssl/root/vault-cert-1.pem
--config={{ pki_root_dir }}/etc/config.d/
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
register: pki_global_vault_id
changed_when: False
tags: pki
- name: Get ID of the global scep certificate
command: >
{{ pki_root_dir }}/bin/openxpkiadm certificate id
--file {{ pki_root_dir }}/etc/ssl/root/scep-cert-1.pem
--config={{ pki_root_dir }}/etc/config.d/
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
register: pki_global_scep_id
changed_when: False
tags: pki
- name: Create an alias for the vault
command: >
{{ pki_root_dir }}/bin/openxpkiadm alias --realm {{ item.item.name }}
--token datasafe --identifier {{ pki_global_vault_id.stdout }}
--config {{ pki_root_dir }}/etc/config.d/
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
with_items: "{{ pki_ca_issuing_created.results + pki_ca_intermediate_created.results }}"
when: item.changed
tags: pki
- name: Create an alias for the scep certificate
command: >
{{ pki_root_dir }}/bin/openxpkiadm alias --realm {{ item.item.name }}
--token scep --identifier {{ pki_global_scep_id.stdout }}
--config {{ pki_root_dir }}/etc/config.d/
environment:
- PERL5LIB: "{{ pki_root_dir }}/lib/perl5"
with_items: "{{ pki_ca_issuing_created.results + pki_ca_intermediate_created.results }}"
#no_log: True
when: item.changed
tags: pki
- name: Deploy permission script
template: src=perms.sh.j2 dest={{ pki_root_dir }}/bin/perms.sh mode=755
tags: pki
- name: Fix permissions on key files
command: "{{ pki_root_dir }}/bin/perms.sh }}"
changed_when: False
tags: pki

View File

@@ -0,0 +1,37 @@
---
- name: Set correct SELinux labels
sefcontext:
target: "{{ pki_root_dir }}/{{ item.path }}(/.*)?"
setype: "{{ item.type }}"
state: present
loop:
- path: run
type: httpd_var_run_t
- path: web/cgi-bin
type: httpd_sys_script_exec_t
- path: web/htdocs
type: httpd_sys_content_t
- path: data
type: httpd_sys_content_t
tags: pki
- name: Restore SElinux contexts
command: restorecon -R {{ pki_root_dir }}
changed_when: False
tags: pki
- name: Copy SElinux policy file
copy: src=openxpki.te dest=/etc/selinux/targeted/local/
register: pki_selinux_policy
tags: pki
- name: Add local policy
shell: |
cd /etc/selinux/targeted/local/
checkmodule -M -m -o openxpki.mod openxpki.te
semodule_package -o openxpki.pp -m openxpki.mod
semodule -i /etc/selinux/targeted/local/openxpki.pp
when: pki_selinux_policy.changed
tags: pki

View File

@@ -0,0 +1,7 @@
---
- name: Start and enable the daemon
service: name=openxpki state=started enabled=True
register: pki_started
tags: pki

View File

@@ -0,0 +1,10 @@
---
- name: Create openxpki system user
user:
name: "{{ pki_user }}"
system: True
shell: /sbin/nologin
home: "{{ pki_root_dir }}"
tags: pki

View File

@@ -0,0 +1,6 @@
---
- name: Write version
copy: content={{ pki_version }} dest={{ pki_root_dir }}/meta/ansible_version
tags: pki

View File

@@ -0,0 +1,8 @@
#!/bin/sh
export PERL5LIB={{ pki_root_dir }}/lib/perl5
export OPENXPKI_CONF_PATH={{ pki_root_dir }}/etc/config.d
{% for realm in pki_realms %}
{{ pki_root_dir }}/bin/openxpkicmd --socketfile={{ pki_root_dir }}/run/openxpki.socket --realm {{ realm.name }} crl_issuance
{{ pki_root_dir }}/bin/openxpkicmd --socketfile={{ pki_root_dir }}/run/openxpki.socket --realm {{ realm.name }} ca_publish
{% endfor %}

View File

@@ -0,0 +1,8 @@
#!/bin/sh
export PERL5LIB={{ pki_root_dir }}/lib/perl5
export OPENXPKI_CONF_PATH={{ pki_root_dir }}/etc/config.d
{% for realm in pki_realms %}
{{ pki_root_dir }}/bin/openxpkicmd --socketfile={{ pki_root_dir }}/run/openxpki.socket --realm {{ realm.name }} notify_expiry
{% endfor %}

View File

@@ -0,0 +1,5 @@
#!/bin/sh
export PERL5LIB={{ pki_root_dir }}/lib/perl5
export OPENXPKI_CONF_PATH={{ pki_root_dir }}/etc/config.d
exec {{ pki_root_dir }}/bin/openxpkiadm "$@"

View File

@@ -0,0 +1,5 @@
#!/bin/sh
export PERL5LIB={{ pki_root_dir }}/lib/perl5
export OPENXPKI_CONF_PATH={{ pki_root_dir }}/etc/config.d
exec {{ pki_root_dir }}/bin/openxpkicmd --socketfile={{ pki_root_dir }}/run/openxpki.socket "$@"

View File

@@ -0,0 +1,22 @@
{% for map in item.0.auth.role_map | sort(attribute='priority') %}
LDAP Auth {{ map.role }}:
type: Command
label: LDAP Authentication {{ map.role }}
description: Authenticate {{ map.role }} against an LDAP server
role: {{ map.role }}
command: [ '{{ pki_root_dir }}/bin/openxpki-auth-ldap', '-H', '{{ item.0.auth.ldap_uri }}', '-b', '{{ item.0.auth.ldap_base }}', '{{ item.0.auth.ldap_start_tls | ternary('--starttls','') }}', '-U', 'LOGIN', '-P', 'PASSWD', '--extra-filter={{ map.filter }}', '--user-attr={{ item.0.auth.ldap_user_attr }}'{% if item.0.auth.ldap_bind_dn is defined and item.0.auth.ldap_bind_pass is defined %}, '-D', 'BIND_DN', '-W', 'BIND_PASS'{% endif %} ]
env:
PERL5LIB: {{ pki_root_dir }}/lib/perl5
LOGIN: "[% username %]"
PASSWD: "[% password %]"
{% if item.0.auth.ldap_bind_dn is defined and item.0.auth.ldap_bind_pass is defined %}
BIND_DN: {{ item.0.auth.ldap_bind_dn }}
BIND_PASS: '{{ item.0.auth.ldap_bind_pass }}'
{% endif %}
{% endfor %}
System:
type: Anonymous
label: System
role: System

View File

@@ -0,0 +1,9 @@
User:
description: I18N_OPENXPKI_CONFIG_AUTH_STACK_DESCRIPTION_USER
handler:
{% for map in item.0.auth.role_map | sort(attribute='priority') %}
- LDAP Auth {{ map.role }}
{% endfor %}
_System:
handler: System

View File

@@ -0,0 +1,37 @@
type:
certsign: signer-key
datasafe: vault-key
scep: scep-key
token:
default:
backend: OpenXPKI::Crypto::Backend::OpenSSL
key: {{ pki_root_dir }}/etc/ssl/[% PKI_REALM %]/[% ALIAS %].pem
engine: OpenSSL
engine_section: ''
engine_usage: ''
key_store: OPENXPKI
shell: /usr/bin/openssl
wrapper: ''
randfile: {{ pki_root_dir }}/data/rand
secret: default
signer-key:
inherit: default
vault-key:
inherit: default
scep-key:
inherit: default
backend: OpenXPKI::Crypto::Tool::SCEP
shell: /usr/bin/openca-scep
secret:
default:
label: Default secret group of this realm
export: 0
method: literal
value: '{{ pki_secret }}'
cache: daemon

View File

@@ -0,0 +1,5 @@
backend: Local
api:
use_revocation_id: 1

View File

@@ -0,0 +1,118 @@
backend:
class: OpenXPKI::Server::Notification::SMTP
host: localhost
port: 25
debug: 0
use_html: 1
# No SMIME for now
default:
to: "[% cert_info.requestor_email %]"
from: no-reply@{{ ansible_domain }}
reply: {{ item.0.notif.admin_email }}
cc: {{ item.0.notif.admin_email }}
prefix: PKI [% meta_wf_id %]
images:
banner: head.png
# template settings
template:
dir: {{ pki_root_dir }}/etc/notification/email/
message:
testmail:
default:
template: testmail
subject: SMTP Notification Test
to: "[% data.rcpt %]"
from: no-reply@{{ ansible_domain }}
reply: ''
cc: ''
prefix: ''
csr_created:
default:
template: csr_created_user
subject: CSR for [% cert_subject %]
raop:
template: csr_created_raop
to: {{ item.0.notif.admin_email }}
cc: ''
reply: "[% cert_info.requestor_email %]"
subject: CSR for [% cert_subject %]
csr_rejected:
default:
template: csr_rejected
subject: CSR rejected for [% cert_subject %]
cert_issued:
default:
template: cert_issued
subject: certificate issued for [% cert_subject %]
cert_expiry:
default:
to: {{ item.0.notif.admin_email }}
{% if item.0.notif.expiry_send_requestor %}
cc: "[% data.notify_to %]
{% endif %}
template: cert_expiry
subject: Certificate Expiry Warning
scpu_notify:
default:
template: scpu_notify_user
subject: Smartcard Enrollment Verification Notice
to: "[% data.requestor_mail %]"
auth1:
template: scpu_notify_authcontact
to: "[% data.auth1_mail %]"
reply: "[% data.requestor_mail %]"
subject: Smartcard Enrollment Verification Request for [% data.requestor_name %]
auth2:
template: scpu_notify_authcontact
to: "[% data.auth2_mail %]"
reply: "[% data.requestor_mail %]"
subject: Smartcard Enrollment Verification Request for [% data.requestor_name %]
# notifies for the scep server
scep_auth_denied:
requestor:
template: scep_auth_denied
to: "[% data.notify_to %]"
cc: "[% data.notify_cc %]"
subject: SCEP request REJECTED - [% cert_subject %]
scep_approval_pending:
requestor:
template: scep_approval_pending_requestor
to: "[% data.notify_to %]"
cc: "[% data.notify_cc %]"
subject: SCEP request PENDING - [% cert_subject %]
raop:
template: scep_approval_pending_raop
to: reg-office@mycompany.local
cc: ''
subject: SCEP request PENDING - [% cert_subject %]
scep_approval_rejected:
requestor:
template: scep_approval_rejected
to: "[% data.notify_to %]"
cc: "[% data.notify_cc %]"
subject: SCEP request REJECTED - [% cert_subject %]
scep_cert_issued:
requestor:
template: scep_cert_issued
to: "[% data.notify_to %]"
cc: "[% data.notify_cc %]"
subject: SCEP request ISSUED - [% cert_subject %]

View File

@@ -0,0 +1,69 @@
key:
alg:
- rsa
- ec
- dsa
enc:
- aes256
generate: both
rsa:
key_length:
- 2048
- 4096
ec:
curve_name:
- prime256v1
- secp384r1
- secp521r1
dsa:
key_length:
- 2048
- 4096
validity:
notafter: +01
digest: sha256
increasing_serials: 1
randomized_serial_bytes: 8
publish:
- disk
extensions:
basic_constraints:
critical: 1
ca: 0
path_length: 0
subject_key_identifier:
critical: 0
hash: 1
authority_key_identifier:
critical: 0
keyid: 1
issuer: 0
issuer_alt_name:
critical: 0
copy: 0
crl_distribution_points:
critical: 0
uri:
- {{ pki_base_url }}{{ (pki_base_url is search('/^')) | ternary('','/') }}pub/[% ISSUER.CN.0 %]/crl
authority_info_access:
critical: 0
ca_issuers: {{ pki_base_url }}{{ (pki_base_url is search('/^')) | ternary('','/') }}pub/[% ISSUER.CN.0 %]/ca
ocsp: {{ pki_base_url }}
policy_identifier:
critical: 0

View File

@@ -0,0 +1,52 @@
label: Signer
validity:
notafter: +0006
style:
00_user_basic_style:
label: signer
description: Application authenticity and deployment security
ui:
subject:
- username
- realname
- department
- email
info:
- comment
subject:
dn: CN=[% realname %]+UID=[% username %][% IF department %],DC=[% department %][% END %],{{ item.0.subj_suffix }}
san:
email: "[% email.lower %]"
metadata:
requestor: "[% realname %]"
email: "[% email %]"
department: "[% department %]"
extensions:
key_usage:
critical: 1
digital_signature: 1
non_repudiation: 1
key_encipherment: 1
data_encipherment: 0
key_agreement: 0
key_cert_sign: 0
crl_sign: 0
encipher_only: 0
decipher_only: 0
extended_key_usage:
critical: 1
client_auth: 0
server_auth: 0
email_protection: 0
code_signing: 1
time_stamping: 1
ocsp_signing: 0
# MS Smartcard Logon
1.3.6.1.4.1.311.20.2.2: 0

View File

@@ -0,0 +1,58 @@
# The name of the file equals the name of the profile
label: I18N_OPENXPKI_UI_PROFILE_TLS_CLIENT_LABEL
validity:
notafter: +01
style:
00_basic_style:
label: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_LABEL
description: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_DESC
ui:
subject:
- hostname
- application_name
info:
- requestor_gname
- requestor_name
- requestor_email
- requestor_affiliation
- comment
subject:
dn: CN=[% hostname %]:[% application_name %],{{ item.0.subj_suffix }}
metadata:
requestor: "[% requestor_gname %] [% requestor_name %]"
email: "[% requestor_email %]"
entity: "[% hostname FILTER lower %]"
enroll:
subject:
dn: CN=[% CN.0 %],{{ item.0.subj_suffix }}
# Profile extensions - set 0/1 as needed
extensions:
key_usage:
critical: 1
digital_signature: 1
non_repudiation: 0
key_encipherment: 0
data_encipherment: 0
key_agreement: 0
key_cert_sign: 0
crl_sign: 0
encipher_only: 0
decipher_only: 0
extended_key_usage:
critical: 1
client_auth: 1
server_auth: 0
email_protection: 0
code_signing: 0
time_stamping: 0
ocsp_signing: 0

View File

@@ -0,0 +1,123 @@
# The name of the file equals the name of the profile
label: I18N_OPENXPKI_UI_PROFILE_TLS_SERVER_LABEL
validity:
notafter: +0006
style:
00_basic_style:
label: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_LABEL
description: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_DESC
ui:
subject:
- hostname
- hostname2
- port
info:
- requestor_gname
- requestor_name
- requestor_email
- requestor_affiliation
- comment
subject:
dn: CN=[% hostname.lower %][% IF port AND port != 443 %]:[% port %][% END %],{{ item.0.subj_suffix }}
san:
DNS:
- "[% hostname.lower %]"
- "[% FOREACH entry = hostname2 %][% entry.lower %] | [% END %]"
metadata:
requestor: "[% requestor_gname %] [% requestor_name %]"
email: "[% requestor_email %]"
entity: "[% hostname FILTER lower %]"
05_advanced_style:
label: I18N_OPENXPKI_UI_PROFILE_ADVANCED_STYLE_LABEL
description: I18N_OPENXPKI_UI_PROFILE_ADVANCED_STYLE_DESC
ui:
subject:
- cn
- o
- ou
- dc
- c
san:
- san_ipv4
- san_dns
info:
- requestor_gname
- requestor_name
- requestor_email
- requestor_affiliation
- comment
subject:
dn: CN=[% CN %][% IF OU %][% FOREACH entry = OU %],OU=[% entry %][% END %][% END %][% IF O %],O=[% O %][% END %][% FOREACH entry = DC %],DC=[% entry %][% END %][% IF C %],C=[% C %][% END %]
# no san definitions here as items from ui.san are directly written to the SAN
enroll:
subject:
dn: CN=[% CN.0 %],{{ item.0.subj_suffix }}
san:
dns: "[% FOREACH entry = SAN_DNS %][% entry.lower %] | [% END %]"
metadata:
system_id: "[% data.cust_id %]"
server_id: "[% data.server_id %]"
entity: "[% CN.0 FILTER lower %]"
# Profile extensions - set 0/1 as needed
# Also see sections defined in default.yaml
extensions:
key_usage:
critical: 1
digital_signature: 1
non_repudiation: 0
key_encipherment: 1
data_encipherment: 0
key_agreement: 1
key_cert_sign: 0
crl_sign: 0
encipher_only: 0
decipher_only: 0
extended_key_usage:
critical: 1
# these are OIDs, some OIDs are known and have names
client_auth: 0
server_auth: 1
email_protection: 0
code_signing: 0
time_stamping: 0
ocsp_signing: 0
# This is really outdated and should not be used unless really necessary
netscape:
comment:
critical: 0
text: This is a generic certificate. Generated with OpenXPKI trustcenter software.
certificate_type:
critical: 0
ssl_client: 0
smime_client: 0
object_signing: 0
ssl_client_ca: 0
smime_client_ca: 0
object_signing_ca: 0
cdp:
critical: 0
uri: http://localhost/cacrl.crt
ca_uri: http://localhost/cacrl.crt
# end of netscape section
# end of extensions
# Define the input fields you used below here
#template:

View File

@@ -0,0 +1,61 @@
# The name of the file equals the name of the profile
label: I18N_OPENXPKI_UI_PROFILE_USER_LABEL
validity:
notafter: +0006
style:
00_user_basic_style:
label: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_LABEL
description: I18N_OPENXPKI_UI_PROFILE_BASIC_STYLE_DESC
ui:
subject:
- username
- realname
- department
- email
info:
- comment
subject:
dn: CN=[% realname %]+UID=[% username %][% IF department %],DC=[% department %][% END %],{{ item.0.subj_suffix }}
san:
email: "[% email.lower %]"
metadata:
requestor: "[% realname %]"
email: "[% email %]"
department: "[% department %]"
# Profile extensions - set 0/1 as needed
# Also see sections defined in default.yaml
extensions:
key_usage:
critical: 1
digital_signature: 1
non_repudiation: 1
key_encipherment: 1
data_encipherment: 0
key_agreement: 0
key_cert_sign: 0
crl_sign: 0
encipher_only: 0
decipher_only: 0
extended_key_usage:
critical: 1
client_auth: 1
server_auth: 0
email_protection: 1
code_signing: 0
time_stamping: 0
ocsp_signing: 0
# MS Smartcard Logon
1.3.6.1.4.1.311.20.2.2: 1
# Define the input fields you used below here or in template.yaml
#template:

View File

@@ -0,0 +1,28 @@
entity:
disk@: connector:publishing.connectors.local
crl:
crl@: connector:publishing.connectors.cdp
cacert:
disk@: connector:publishing.connectors.cacert
connectors:
local:
class: Connector::Builtin::File::Path
LOCATION: {{ pki_root_dir }}/data/{{ item.0.name }}
file: "[% ARGS.0 %].crt"
content: "[% pem %]"
cdp:
class: Connector::Builtin::File::Path
LOCATION: {{ pki_root_dir }}/data/{{ item.0.name }}
file: "crl.pem"
content: "[% pem %]"
cacert:
class: Connector::Builtin::File::Path
LOCATION: {{ pki_root_dir }}/data/{{ item.0.name }}
file: "ca.pem"
content: "[% pem %]"

View File

@@ -0,0 +1,60 @@
renewal:
notbefore: 000014
notafter: 0
revoke_on_replace:
reason_code: keyCompromise
delay_revocation_time: +000014
workflow:
type: certificate_enroll
param:
transaction_id: transaction_id
signer_cert: signer_cert
pkcs10: pkcs10
_url_params: url_params
key_size:
rsaEncryption: 1020-4096
hash_type:
- sha1
- sha256
- sha512
authorized_signer:
rule1:
subject: CN=.+:scepclient,.*
rule2:
subject: CN=.+:pkiclient,.*
policy:
allow_man_authen: 1
allow_anon_enroll: 0
allow_man_approv: 1
allow_eligibility_recheck: 0
approval_points: 1
max_active_certs: 1
allow_expired_signer: 0
auto_revoke_existing_certs: 1
allow_replace: 1
response:
getcacert_strip_root: 1
profile:
cert_profile: {{ item.0.scep.profile }}
cert_subject_style: enroll
profile_map:
pc-client: I18N_OPENXPKI_PROFILE_USER_AUTHENTICATION
hmac: "{{ item.0.scep.hmac | default(pki_scep_hmac) }}"
challenge:
value: "{{ item.0.scep.challenge | default(pki_scep_challenge) }}"
eligible:
renewal:
value: 1

View File

@@ -0,0 +1,22 @@
class: OpenXPKI::Server::Workflow::Validator::PasswordQuality
arg:
- $_password
param:
checks:
- length
{% if item.0.passwd_quality is string %}
{% if item.0.passwd_quality == 'none' %}
minlen: 1
maxlen: 64
{% elif item.0.passwd_quality == 'normal' %}
- entropy
min_entropy: 20
minlen: 6
maxlen: 64
{% elif item.0.passwd_quality == 'strong' %}
- entropy
min_entropy: 60
minlen: 10
maxlen: 64
{% endif %}
{% endif %}

View File

@@ -0,0 +1,23 @@
tokenapi:
certsign: OpenXPKI::Crypto::Backend::API
crlsign: OpenXPKI::Crypto::Backend::API
datasafe: OpenXPKI::Crypto::Backend::API
scep: OpenXPKI::Crypto::Tool::LibSCEP::API
token:
default:
backend: OpenXPKI::Crypto::Backend::OpenSSL
api: OpenXPKI::Crypto::Backend::API
engine: OpenSSL
key_store: OPENXPKI
shell: /usr/bin/openssl
wrapper: ''
randfile: {{ pki_root_dir }}/data/rand
javaks:
backend: OpenXPKI::Crypto::Tool::CreateJavaKeystore
api: OpenXPKI::Crypto::Tool::CreateJavaKeystore::API
engine: OpenSSL
key_store: OPENXPKI
shell: /usr/bin/keytool
randfile: {{ pki_root_dir }}/data/rand

View File

@@ -0,0 +1,8 @@
main:
debug: 0
type: MySQL
name: '{{ pki_db_name }}'
host: '{{ pki_db_server }}'
port: '{{ pki_db_port }}'
user: '{{ pki_db_user }}'
passwd: '{{ pki_db_pass | regex_replace("'","''") }}'

View File

@@ -0,0 +1,6 @@
{% for realm in pki_realms %}
{{ realm.name }}:
label: {{ realm.description | default(realm.name) }}
baseurl: {{ realm.url | default(pki_base_url) }}
{% endfor %}

View File

@@ -0,0 +1,37 @@
name: main
log4perl: {{ pki_root_dir }}/etc/log.conf
user: {{ pki_user }}
group: apache
socket_file: {{ pki_root_dir }}/run/openxpki.socket
pid_file: {{ pki_root_dir }}/run/openxpkid.pid
stderr: /dev/stdout
tmpdir: {{ pki_root_dir }}/tmp
environment:
PERL5LIB: {{ pki_root_dir }}/lib/perl5
OPENXPKI_CONF_PATH: {{ pki_root_dir }}/etc/config.d
session:
type: Database
table: frontend_session
transport:
Simple: 1
service:
Default:
enabled: 1
idle_timeout: 120
LibSCEP:
enabled: 1
# settings for i18n
i18n:
locale_directory: {{ pki_root_dir }}/locale
default_language: C
prefork:
min_servers: 5
min_spare_servers: 5
max_servers: 25
max_spare_servers: 10

View File

@@ -0,0 +1,15 @@
max_fork_redo: 5
max_exception_threshhold: 10
interval_sleep_exception: 60
max_tries_hanging_workflows: 3
interval_wait_initial: 10
interval_loop_idle: 5
interval_loop_run: 1
interval_sleep_overload: 15
interval_session_purge: 300
# You should not change this unless you know what you are doing
max_instance_count: 1
disabled: 0

View File

@@ -0,0 +1,59 @@
{% if pki_web_alias == '/' %}
{% set pki_web_alias='' %}
{% endif %}
{% for realm in pki_realms %}
{% if realm.scep | default(True) %}
ScriptAlias {{ pki_web_alias }}/scep/{{ realm.name }} {{ pki_root_dir }}/web/cgi-bin/scep_{{ realm.name }}.fcgi
{% endif %}
Alias {{ pki_web_alias }}/pub/{{ realm.name }}/crl {{ pki_root_dir }}/data/{{ realm.name }}/crl.pem
Alias {{ pki_web_alias }}/pub/{{ realm.name }}/ca {{ pki_root_dir }}/data/{{ realm.name }}/ca.pem
{% endfor %}
#ScriptAlias {{ pki_web_alias }}/soap {{ pki_root_dir }}/web/cgi-bin/soap.fcgi
#ScriptAlias {{ pki_web_alias }}/rpc {{ pki_root_dir }}/web/cgi-bin/rpc.fcgi
#ScriptAlias /.well-known/est {{ pki_root_dir }}/web/cgi-bin/est.fcgi
ScriptAlias {{ pki_web_alias }}/cgi-bin/webui.fcgi {{ pki_root_dir }}/web/cgi-bin/webui.fcgi
ScriptAlias {{ pki_web_alias }}/cgi-bin/download.fcgi {{ pki_root_dir }}/web/cgi-bin/download.fcgi
Alias {{ pki_web_alias }}/ {{ pki_root_dir }}/web/htdocs/
FcgidInitialEnv PERL5LIB {{ pki_root_dir }}/lib/perl5
FcgidInitialEnv OPENXPKI_CLIENT_CONF_DIR {{ pki_root_dir }}/etc/
FcgidInitialEnv OPENXPKI_CONF_PATH {{ pki_root_dir }}/etc/config.d
FcgidInitialEnv OPENXPKI_SCEP_CLIENT_CONF_DIR {{ pki_root_dir }}/etc/scep/
FcgidInitialEnv OPENXPKI_WEBUI_CLIENT_CONF_FILE {{ pki_root_dir }}/etc/webui/default.conf
<LocationMatch {{ pki_web_alias }}/pub/\w+/crl>
Header set "Content-disposition" "attachment; filename=crl.pem"
</LocationMatch>
<LocationMatch {{ pki_web_alias }}/pub/\w+/ca>
Header set "Content-disposition" "attachment; filename=ca.crt"
</LocationMatch>
<Directory {{ pki_root_dir }}/data>
Options None
<FilesMatch "(.*\.pem)">
{% if pki_pub_src_ip | length > 0 and '0.0.0.0/0' not in pki_pub_src_ip and '0.0.0.0/0.0.0.0' not in pki_pub_src_ip %}
Require ip {{ pki_pub_src_ip | join(' ') }}
{% else %}
Require all granted
{% endif %}
</FilesMatch>
</Directory>
<Directory {{ pki_root_dir }}/web/htdocs>
AllowOverride FileInfo
Options FollowSymlinks
{% if pki_src_ip | length > 0 and '0.0.0.0/0' not in pki_src_ip and '0.0.0.0/0.0.0.0' not in pki_src_ip %}
Require ip {{ pki_src_ip | join(' ') }}
{% else %}
Require all granted
{% endif %}
</Directory>
<Directory {{ pki_root_dir }}/web/cgi-bin>
AllowOverride None
AddHandler fcgid-script .fcgi
Options +ExecCGI
{% if pki_src_ip | length > 0 and '0.0.0.0/0' not in pki_src_ip and '0.0.0.0/0.0.0.0' not in pki_src_ip %}
Require ip {{ pki_src_ip | join(' ') }}
{% else %}
Require all granted
{% endif %}
</Directory>

View File

@@ -0,0 +1,9 @@
window.Em.Application.initializer({
name: "oxi-localconfig",
initialize: function(container, application) {
var cc = application.ConfigController;
cc.reopen({
url: "cgi-bin/webui.fcgi"
});
}
});

View File

@@ -0,0 +1,88 @@
## This is Log::Log4perl configuration.
##
## Please be careful if you change this and
## please always test all changes.
## The example configuration configures the log for all
## loggers/facilities.
# Catch-all root logger
log4perl.rootLogger = ERROR, CatchAll
# The workflow base logger -
log4perl.logger.Workflow = ERROR, Journal
## FACILITY: AUTH
# Anything related to logging into the system
log4perl.category.openxpki.auth = INFO, Journal
## FACILITY: AUDIT
# mainly usage and access of private key material or secrets
log4perl.category.openxpki.audit = INFO, AuditDBI, AuditFile
## FACILITY: SYSTEM
# internal system management like forking/ending process and usage of
# system components such as notification or crypto backend
# NEVER use the OpenXPKI::DBI logger as target for system, see #223
log4perl.category.openxpki.system = WARN, Journal
## FACILITY: WORKFLOW
# INTERNAL logger for the workflow engine, conditions evaluated, actions taken
# This must not be used by implementors, log your stuff to APPLICATION!
log4perl.category.openxpki.workflow = WARN, Journal
## FACILITY: APPLICATION
# info about the workflows, conditions evaluated, actions taken
log4perl.category.openxpki.application = INFO, ApplicationFile, ApplicationDBI
## FACILITY: DEPRECATED
# receives messages when deprecated code is called
# Errors and warnings should be handled immediatly,
# lower levels are mainly for development and debugging
log4perl.category.openxpki.deprecated = WARN, Deprecated
## FACILITY: Connector (outside OXI!)
# internal logging of the config layer, errors indicate missconfiguration
log4perl.category.connector = ERROR, Journal
## Appenders are the modules which do the real work. Different
## facilities/loggers can use the same appenders.
log4perl.filter.FilterIsWorkflow = Log::Log4perl::Filter::MDC
log4perl.filter.FilterIsWorkflow.KeyToMatch = wfid
log4perl.filter.FilterIsWorkflow.RegexToMatch = \d+
log4perl.appender.Journal = Log::Log4perl::Appender::Screen
log4perl.appender.Journal.layout = Log::Log4perl::Layout::SimpleLayout
log4perl.appender.Journal.utf8 = 1
log4perl.appender.CatchAll = Log::Log4perl::Appender::Screen
log4perl.appender.CatchAll.layout = Log::Log4perl::Layout::SimpleLayout
log4perl.appender.CatchAll.utf8 = 1
log4perl.appender.ApplicationDBI = OpenXPKI::Server::Log::Appender::Database
log4perl.appender.ApplicationDBI.Filter = FilterIsWorkflow
log4perl.appender.ApplicationDBI.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.ApplicationDBI.layout.ConversionPattern = %m (%X{user})
log4perl.appender.ApplicationDBI.table = application_log
log4perl.appender.ApplicationDBI.microseconds = 1
log4perl.appender.ApplicationFile = Log::Log4perl::Appender::Screen
log4perl.appender.ApplicationFile.Filter = FilterIsWorkflow
log4perl.appender.ApplicationFile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.ApplicationFile.layout.ConversionPattern = %X{wfid} %m %n
log4perl.appender.ApplicationFile.utf8 = 1
log4perl.appender.AuditDBI = OpenXPKI::Server::Log::Appender::Audit
log4perl.appender.AuditDBI.layout = OpenXPKI::Server::Log::Layout::Audit
log4perl.appender.AuditDBI.warp_message = 0
log4perl.appender.AuditFile = Log::Log4perl::Appender::Screen
log4perl.appender.AuditFile.layout = OpenXPKI::Server::Log::Layout::Audit
log4perl.appender.AuditFile.layout.ConversionPattern = %c.%p %m [pid=%P|%i]%n
log4perl.appender.AuditFile.utf8 = 1
log4perl.appender.Deprecated = Log::Log4perl::Appender::Screen
log4perl.appender.Deprecated.layout = Log::Log4perl::Layout::SimpleLayout

View File

@@ -0,0 +1 @@
{{ pki_email_footer_html }}

View File

@@ -0,0 +1 @@
{{ pki_email_footer_txt }}

View File

@@ -0,0 +1,97 @@
[ ca ]
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = {{ pki_root_dir }}/etc/ssl/root/
certs = $dir
crl_dir = $dir
new_certs_dir = $dir
database = $dir/index.txt
serial = $dir/serial
RANDFILE = {{ pki_root_dir }}/data/rand
crlnumber = $dir/crlnumber
crl = $dir/crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

View File

@@ -0,0 +1,23 @@
[Unit]
Description=OpenXPKI Trustcenter Backend
After=network.target
[Service]
Type=forking
Environment=PERL5LIB={{ pki_root_dir }}/lib/perl5
ExecStart={{ pki_root_dir }}/bin/openxpkictl --config={{ pki_root_dir }}/etc/config.d/ start
ExecStop={{ pki_root_dir }}/bin/openxpkictl --config={{ pki_root_dir }}/etc/config.d/ stop
ExecReload={{ pki_root_dir }}/bin/openxpkictl --config={{ pki_root_dir }}/etc/config.d/ reload
KillMode=process
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=1024M
Restart=on-failure
StartLimitInterval=0
RestartSec=20
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,8 @@
#!/bin/bash
chown -R {{ pki_user }}:{{ pki_user }} {{ pki_root_dir }}/etc/ssl
chmod 700 {{ pki_root_dir }}/etc/ssl
# The root key is not used by OpenXPKI itself, protect it
chown root:root {{ pki_root_dir }}/etc/ssl/root/signer-key-1.pem
# Restrict access to the different keys
chmod 600 {{ pki_root_dir }}/etc/ssl/*/*key*.pem

View File

@@ -0,0 +1,3 @@
#!/bin/sh
rm -f {{ pki_root_dir }}/backup/*

View File

@@ -0,0 +1,12 @@
#!/bin/sh
set -eo pipefail
/usr/bin/mysqldump \
{% if pki_db_server not in [ '127.0.0.1', 'localhost' ] %}
--user={{ pki_db_user }} \
--password={{ pki_db_pass | quote }} \
--host={{ pki_db_server }} \
{% endif %}
--quick --single-transaction \
--add-drop-table {{ pki_db_name }} | zstd -c > {{ pki_root_dir }}/backup/{{ pki_db_name }}.sql.zst

View File

@@ -0,0 +1,10 @@
[global]
log_config = {{ pki_root_dir }}/etc/scep/log.conf
log_facility = client.scep
service=SCEP
socket={{ pki_root_dir }}/run/openxpki.socket
realm={{ item.name }}
iprange={{ item.scep.iprange | default('0.0.0.0/0') }}
servername=scep-server
encryption_algorithm=3DES
hash_algorithm=SHA256

View File

@@ -0,0 +1,5 @@
log4perl.category.client.scep = DEBUG, Logfile
log4perl.appender.Logfile = Log::Log4perl::Appender::Screen
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Logfile.layout.ConversionPattern = scep
log4perl.appender.Logfile.utf8 = 1

View File

@@ -0,0 +1,24 @@
[global]
log_config = {{ pki_root_dir }}/etc/webui/log.conf
socket = {{ pki_root_dir }}/run/openxpki.socket
scripturl = {{ (pki_web_alias == '/') | ternary('',pki_web_alias) }}/cgi-bin/webui.fcgi
locale_directory = {{ pki_root_dir }}/locale
default_language = en_US
[session]
driver = driver:openxpki
timeout = +20m
cookey = {{ pki_secret_cookie }}
[session_driver]
DataSource = dbi:mysql:dbname={{ pki_db_name }};host={{ pki_db_server }};port={{ pki_db_port }}
User = {{ pki_db_session_user }}
Password = {{ pki_db_session_pass }}
EncryptKey = {{ pki_secret_cookie }}
LogIP = 1
[header]
Strict-Transport-Security = max-age=31536000;
X-Frame-Options = SAMEORIGIN;
X-XSS-Protection = 1; mode=block;

View File

@@ -0,0 +1,6 @@
log4perl.logger = INFO, Journal
log4perl.appender.Journal = Log::Log4perl::Appender::Screen
log4perl.appender.Journal.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Journal.layout.ConversionPattern = OpenXPKI-WebUI %m
log4perl.appender.Journal.utf8 = 1

View File

@@ -0,0 +1,19 @@
---
pki_packages:
- openssl-devel
- openldap-devel
- libxml2-devel
- expat-devel
- mariadb-devel
- libapreq2-devel
- gcc
- perl-App-cpanminus
- gettext # To build I18N files
- pwgen # To generate random secrets
- java-1.8.0-openjdk-headless # For keytool utility
- mariadb # To load the schema
- patch # To apply local patches
- perl-autodie # Provides perl(Fatal), needed to install perl deps
- perl-Config-Std # needed to install perl deps

View File

@@ -0,0 +1,20 @@
---
pki_packages:
- openssl-devel
- openldap-devel
- libxml2-devel
- expat-devel
- mariadb-devel
- libapreq2-devel
- gcc
- perl-App-cpanminus
- gettext # To build I18N files
- pwgen # To generate random secrets
- java-1.8.0-openjdk-headless # For keytool utility
- mariadb # To load the schema
- patch # To apply local patches
- perl-autodie # Provides perl(Fatal), needed to install perl deps
- perl-Config-Std # needed to install perl deps
- glibc-langpack-en