App-CamelPKI
view release on metacpan or search on metacpan
t/lib/App/CamelPKI/Test.pm view on Meta::CPAN
server_start();
server_stop();
=head1 DESCRIPTION
This module is a library which aims at simplifying App-PKI test writing.
It started as a raw copy of I<Crypt::OpenSSL::CA:Test> you can find in
the C<t/lib> directory of the source L<Crypt::OpenSSL::CA> CPAN source
package.
=head1 EXPORTED FUNCTIONS
All functions described in this section factor some useful test
tactics and are exported by default. The L</SAMPLE INPUTS> may also
be exported upon request.
=over
=cut
use Test::Builder;
use Test::More;
use Test::Group;
use File::Find;
use File::Path ();
use File::Spec::Functions qw(catfile catdir);
use File::Slurp;
use File::Temp ();
use POSIX ":sys_wait_h";
use File::Which ();
use IO::Socket::SSL;
use LWP::UserAgent;
use HTTP::Request;
#pour formulaires
use URI::URL;
use HTTP::Request::Common;
use HTTP::Request::Form;
use HTML::TreeBuilder 3.0;
use base 'Exporter';
BEGIN {
our @EXPORT =
qw(openssl_path run_thru_openssl run_dumpasn1
run_perl run_perl_ok
certificate_looks_ok
certificate_chain_ok certificate_chain_invalid_ok
x509_schema x509_decoder
run_php run_php_script
http_request_prepare http_request_execute
plaintextcall_remote
call_remote formcall_remote formreq_remote
jsoncall_local jsonreq_remote jsoncall_remote
is_php_cli_present);
our @EXPORT_OK = (@EXPORT,
qw(test_simple_utf8 test_bmp_utf8
@test_DN_CAs
%test_der_DNs
%test_public_keys
%test_reqs_SPKAC %test_reqs_PKCS10
%test_keys_plaintext %test_keys_password
%test_self_signed_certs %test_rootca_certs
%test_entity_certs
test_CRL
server_start server_stop server_port
create_camel_pki_conf_php
camel_pki_chain
));
our %EXPORT_TAGS = ("default" => \@EXPORT);
}
=item I<plaintextcall_remote($url)>
Qureies a real Apache server at $url, which must be fully-qualified.
Throws an exception if the HTTP request isn't a success; otherwise,
Returns the C<text/plain> response as a string.
Available named options are:
=over
=item I<< -certificate => $certobj >>
=item I<< -certificate => $certpem >>
The certificate to identify oneself as, as an L<App::CamelPKI::Certificate>
instance or PEM string.
=item I<< -key => $keyobj >>
=item I<< -key => $keypem >>
The private key to use along with the certificate, as an
L<App::CamelPKI::PrivateKey> instance or PEM string.
=cut
sub plaintextcall_remote {
my ($url, @args) = @_;
my $req = http_request_prepare($url, @args);
my $res = http_request_execute($req, @args);
die sprintf("plain request at $url failed with code %d\n%s\n",
$res->code, $res->content)
unless $res->is_success;
die sprintf("plain request at $url returned a %s document\n%s\n",
$res->header("content-type"), $res->content)
unless $res->header("content-type") =~ m|^text/plain|;
return $res->content;
}
=item I<jsoncall_local ($uri, $struct)>
Sends the $struct data structure (which is typically a reference to a
hash) to the Catalyst dispatcher via a JSON request at $url URL, en
returns the return value given by the controller. The
L<Catalyst::Test> must have been loaded previously.
In case of a controller error, triggers an exception with die(),
containing the error text 'as is'.
=cut
t/lib/App/CamelPKI/Test.pm view on Meta::CPAN
=back
More RSA keys can be obtained using the command
openssl genrsa 1024
or similar (e.g. changing the key size)
=cut
our %test_keys_plaintext =
(rsa1024 => <<RSA1024,
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDfGYmlOYbpGkBD/agTUnixLcdh6H1XM13w17RbzaoA7byZD6L+
Dn8MZd69PuXcZAQEUG4Oe6QyAcafsvDb7SHjyJHLoPTOsAZ0ex/0zIJVpw+XyppA
8fZx6bnuHKUabqfj83OLk/ACfQSBX7bcL7Y8hwYcZJcqyjMzt9BT7oCldwIDAQAB
AoGBANWLUi8uUy4IDH+H6jskc5XUJcZXjLHM3xxKu74rq4/b/uvbBb58DavGTl+C
Nu6vZRDkE5QVUOL0xDPUSauY3RerFnMPdTZZ43WAKYbrrNqA0/xEpEAWv4CxXAMI
f3Bf2ypBdFzE268HiaQxv//61ZtIjb7NDu8j6gcRLLVjU0RhAkEA9X0TZScqGLFR
84GsSltkoSzx2Q+6d81yjzC27CtQgwEUCFhvFG69jAUzJASogac0hmkGa1lVzylO
5D2wgL24PwJBAOinC/ey4XE3isah86Kpgfj8yVj5vtLEodBkUmhNOIrgiHt6+QE+
5YwreJikzRB2Bs9idglg+f/0nqlLdKLWBMkCQQDZNxvjRD0+biAKa/IMNUQcTU2N
+BnRictVIhCpdkYeNOUJ4V4gYUB81dkDhM+pMU8Lo4CXmguQa4ev81nrAHQ3AkBh
ffbW4p/0OKkv2Zfl9xBfDVc2sNlVK07/q7qYuJtUHwkybXLBIeFBXsoXdR/1oO/z
obgC8B9zMcf2+4ax4et5AkEAsNLkUpS5EmsdlyuUnHxg5jU30o8XSUznmzR7OX/H
hP36rGgrE4mclD0LgazRRMjmWFzT6/RtiQb5OnfFxXaDTQ==
-----END RSA PRIVATE KEY-----
RSA1024
rsa2048 => <<RSA2048,
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAsbqUS8pGlr4ED9mmZnBBqvf9zl7Z0NR9LZzX2yXsc2GMgjol
NQj/CrDKHjTL3VLp+BcBinnJIxhdXg7joGxodJ2huPjOP+T0wmzmhdqLW/Mz3PqF
Bod7ZoIi4S55VeM0G3kwUQ+v4Ih5xYFFgvhHPz4xJ5g7vde+N9BiNp5w+uvzma/T
Z8sRWDIUpbn8FkRgrUeiy2vUKgwJfg720prxxi/Ru1RQRnBcC22k2FFppL0MBIat
Ncmf26fsgCCacoLJ1jIOpCWoZASOYTRStSlmy2MhfSAyW+k7C/ZkYlvPtAQJGaLA
+Y3ZuEWu0jLYk482PhcjadiEcGd9je9IjRhj2QIDAQABAoIBADh9EvFb4z+6OVRI
W0kn2NdcZwEWyKhFQVwkA7+VuCecE6q4jGbk6xscwcEECt/XoKHHviejObi738Er
flHY4wJdr6849WT9goXhUwusQKsDC7LqtSk0GpakOi3UNaCEzGUHCcJZ+A6nkfyi
b9OG0i5ZuAnbqvFWBxF6XBz8EvDNUdc2OWSr4IWkweBJlFp9Cj3th574b+PzO7Tl
grgX5Uhc137LTqusaT7OkirUyRMHFR1ryvgTYe99OFqSdS6jZpE6GyijqiHlesfd
m+VKMUGf6F3bBfmHS390AQTmKGSq7gB+K1aYNKTQJyDIvTgqhg1otBZ+vcFnrDhu
W7xXYbkCgYEA6AFRdH3gKQBfqcmUf+Jfi8a8vadSM40ggWbHd00fon2D2ZphsXU0
tGR+3zFg+9UzL7kegUApcI5F3vHaihamh2x9T4Dz4Lzsr3EBwCzQo1Cmb9d/xtyn
1inBirrPwSPfB49MgPzy5yokbaVpola23seZfDA5wYE3N6MZ5vElPkMCgYEAxBw2
7+ZWgP2GLSbHHWvxjhk0YRdqiLEisXUV/7Xr0dlr5CAHRiuGwocOBpmBvyXiyfnw
GA0k9yanycRQouQTQSbQ1jV4yCZS4QLTCHsMQ53r1p48TtSB8/RHYK9/HKlrybn4
gRCkvVoJBP3jnFTjLcBktfVTsPbwMqU3TkGUibMCgYBa5tlReVhw+DKDRfYnPT0O
eSnObVap2CvaR7jzp4YzllYo1nJco32pCI8lSCWlxl0t36xyG/+gmD4MIlrsK//H
o9xdYDst3RgnjXGQKH7+3kS4IYlxE1e3c9jfUF7CYBmszpq9F17c8Agh5ePDtZIl
K7OZkxOuG8DUzdUCRY3AHQKBgQCt3jX2y8i15BApx8+RDjrDOSVvT0tslV+k5aHz
bF7/VjyJrLvGQqDfps2QnFikF/rSB34OVNkJJoRsJlk3ke5gPQG6aP4EtbWVOOPR
CQb+i+ykAvaFDXOJznHaDr4rsymVWAQyqYblOgX1HwPFfp1L2t9vU2o34zdiL4ix
IQOIcQKBgBHzLcB2tyyoosIpj88Ke2m2UFt34b6KskjV5CgrKyvgTV8uZUI3bSFU
nXoWRFxNE9jOECDZUFdIwz4tdjKHG3bIXYX3qzDGhbfwxze3G/5g0lEWUabBjtjY
1dzsPX66bnNHT1dwF9K+ZilNKIpUUEPisXEsLZ28n579qZbP1vmL
-----END RSA PRIVATE KEY-----
RSA2048
);
=item I<%test_keys_password>
The same private keys as in L</%test_keys_plaintext>, but
protected with C<secret> as the password. Keys are the same as in
I<%test_keys_plaintext>; values are encrypted using 3DES-CBC,
as if by the command
openssl rsa -des3 -passout pass:secret -in test.key
=cut
our %test_keys_password =
(rsa1024 => <<RSA1024,
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,106A001EF5153939
+rxNdLaRxeXQ0j59ySdfeOeGS0nAYvH9JHaKTwazHg4HO4rt0LiJJ8TF/7hMlNXB
WAPl7Qz3Pynr/NCjgU7QU92K1ZDh6fSoZYgyDqMoZJRQbgwvubRnsqlhgeX2NPE+
FLzn8auohpWiKBHN7EQrIZf7uKfk8G1VmVcMNL6FGQ/1QPCaGoE1+IOizIq3wqxH
bXn2hIy8n8sNnqEBBmBkw2iFqOUMYX3JcfXTQzbKdlgWi4HLozK+wGypNlihSm/s
CcXGL7ucAtt9Kz0pjQ4M2u905Cfk/7ok7YnHpZ31d8Ale7tqXnRu/HlgGz4pQk+D
ba8HNvlza2TKrsezQEiLOKcK6WVG9eUmB7K8/Vuz9w1gr/JVLT1Cl09TqVovnwOz
emWkDZCFS/GwljCEr8xNFhxxkMEicfDxerCuqAYavlohr+UuVBWj2CQCAw1k1uNp
wNiaW3n2Fl9CQEX7K9UK1Wj0xGrmxQcntjZVdM49oQv1EGqES0VuaNp5jE9J2NjN
yUDXDGG0L2AYTEy45bG8QYZsh0omzQW5BQ1xnYFV8nHRbalqg0nF2qqo8XZjlEyg
HzgHYHJScxmA9UpwcEXYrvhOvslzbikVi8BAA5cnvk1ODZv2qdeZJc1qCplLrfqH
q38Uvj0Nc8ZDad3EmO9cPbyv5+KPpj857+Gt6aNJuX9rFQklcdzBW6SqSr8pUpkS
BcIOK68j5tmTUcggfXzIhtSmKdrZRCDtaDRIcfdxAviwwakckdKz8Y+g6gQkrxSQ
WFOdBd3n9h88zS9cX53dRdTWRtFpoqtvQt/APAkkwEDrpgTfnjV8OA==
-----END RSA PRIVATE KEY-----
RSA1024
rsa2048 => <<RSA2048,
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,E3164422C4E0B305
uGlTnFwMuSTot47PzsLknHWRAPC5ZgOubZ6pmiNCF2ljSAx/ut5eS+Ri9VuxNVe3
KHfM096qA4x0yzwwioqRulgo0ZJYajfHQKsrGCZmpRJWTUPPXGADUSfyecnn/2VA
LkCsipovIRnnl3dLje3kEfUagrObUzZG35ohwswwgAHm3Hu/8gQCOk7jFZtaV3/k
0mIHd5v3pNw4LrFCGm8bDGQEJECVCkapLr6kIN7fWLiKtp8SFD5f+eBSdzr17R8T
HBHc/qH8tzBHQpAJ6vBDdOzeS5iC3GUv6cP3RUMIjAcsoyWpYPDQjL7Ay6ALQ6k4
zKq2yI3keW5jv84KtsBCmdytePojKznnytiFFeKPXz9rb20qfs1uNt1fJaDRgvAr
frBUeXOJ1rpgLbWIABS59hnjZeXmUJMWRlp/6fzzfdNnWFYVb09jCdu9PQ6dv0YK
4tDtZRJe3r8aZpvPBGC/6Hx3BrezBYt6kG5DDG5HhISNqOAYgAslRumYmh9+4tDG
TvQklpeha2B7lCwzv9Y4+ZoqSW3oE+O5P3GCbnzJYrXxkWtfZA4dU5iw62gaw28n
7oyULNftrSA9jR37UB10Yyp0MmTmKxGVep1vrvr1L070NHVNEEvtbMVovSe0zQ0g
104k8nBrApwFkYrenQEgs+MvUxFboi1z/PLuMbzObkwj/THfgzez+m/G5+Hl5Whw
Y77O31DDlIhrB2+gfImLuM4Oe6ztPJjopkAQrcHF2KqbJzQnTIxvIe5VC6XLlo/Z
XSD/ftnt3JbCgWe5AeXLhZQVUypQFSWKxrSDtD7IEoRUP7mAMbgFT26x8lC9JkSD
ioW+AaILhwXXb0wyOCjH8gR01jDRUhbzaCLI9up983w0E5bIzYsBxf6GIZNrFas7
Mo5t+v8sLOoPQaMLgCaZJ+9UHVoTFK60d7aRTZvu12++t3G/fQSiZQtNYbO58r0Z
0UmrdcuZwRuHwxXTndQ57sA+QXKy4+S2kk64Ff2YoGCsE34L6UazfT5skt/iS7ct
GHcqKUiR5LGb7b7vZexJ++X7rOGUZVO52NYxQUPVPr4blSbMl8tMHmDez94rUg1X
aJ6+6+uY8lcebr65LCSA/N09qLxAFoi5gku1wS4GQECvsQvA7/GYAp+3O4ytULrE
Cqf5Wx9PBweKkB1h4BLzsKUFCXUgm74dlvs8GtBPTKd58CEeLO2pAbKJhBciUF37
Wuw28zVKX8WaC789HyrTJx8n+hSwaZAqHFiv9TFUF8XwG+Cp9FwRof81V1jbfWWe
AUD+R41bDR8tMmblaSd9GLYWKzeAdk7D1u6dF9RCQu4Tg1hjAKQxCgpg221n3VbE
btAaVBQuTHRrjo7jtwz5sjM3jC9SEhK0I/eP8QOUPut9O+jmP3/k28cBgIAY3RHf
JGpgZSGMB2zzYmYbLOtrbrh5Z9nNhCOhLBQGuRMe+/lO8/Jo4BrC/rYUkV3zkS3d
mwIm/AHPy7+ZLpz3F+zTmSiWOP7oB44hzJTAy/7RbW0RwO4ry4lLRPcbxQ77epjz
vX/Kwjl44H6jnO0zjXutBg/5+3lDxuMxZzcVfCOqF4KENA3vBynJCA==
-----END RSA PRIVATE KEY-----
RSA2048
);
=item I<%test_public_keys>
Public keys obtained from the L</%test_keys_plaintext>
using the following C<openssl> command:
openssl rsa -pubout -in test.key
t/lib/App/CamelPKI/Test.pm view on Meta::CPAN
$crl = test_CRL("rsa2048", -members => [ "0x42" ]);
$crldump = run_thru_openssl($crl, "crl", "-text",
-CAfile => $cafile);
like($crldump, qr/42/);
};
my $cert_pem = $App::CamelPKI::Test::test_self_signed_certs{"rsa1024"};
# REFACTORME into App::CamelPKI::Test::pem2der or something
my $cert_der = do {
use MIME::Base64 ();
local $_ = $cert_pem;
is(scalar(s/^-+(BEGIN|END) CERTIFICATE-+$//gm), 2,
"test PEM certificate looks good") or warn $cert_pem;
MIME::Base64::decode_base64($_);
};
test "x509_decoder" => sub {
use MIME::Base64;
my $decoder = App::CamelPKI::Test::x509_decoder('Certificate');
ok($decoder->can("decode"));
my $tree = $decoder->decode($cert_der);
is($tree->{tbsCertificate}->{subjectPublicKeyInfo}
->{algorithm}->{algorithm},
"1.2.840.113549.1.1.1", "rsaEncryption");
};
=head2 Synopsis tests
=cut
test "synopsis" => sub {
# Thank you Test::Group for being fully reflexive!
eval My::Tests::Below->pod_code_snippet("synopsis");
die $@ if $@;
};
test "synopsis asn1" => sub {
my $synopsis = My::Tests::Below->pod_code_snippet("synopsis-asn1");
ok(defined(my $dn_der =
$App::CamelPKI::Test::test_der_DNs{"CN=Zoinx,C=fr"}),
"\$dn_der defined");
eval $synopsis; die $@ if $@;
pass;
};
=head2 Sample Input Validation
=cut
test "test_simple_utf8 and test_bmp_utf8" => sub {
is(length(App::CamelPKI::Test->test_simple_utf8()), 6);
ok(utf8::is_utf8(App::CamelPKI::Test->test_simple_utf8()));
is(length(App::CamelPKI::Test->test_bmp_utf8()), 3);
ok(utf8::is_utf8(App::CamelPKI::Test->test_bmp_utf8()));
};
test "%test_keys_plaintext and %test_keys_password" => sub {
is_deeply
([sort keys %App::CamelPKI::Test::test_keys_plaintext],
[sort keys %App::CamelPKI::Test::test_keys_password],
"same keys in both");
if (defined(my $openssl_bin = openssl_path)) {
while(my ($k, $v) =
each %App::CamelPKI::Test::test_keys_password) {
my ($out, $err) = run_thru_openssl
($v, qw(rsa -passin pass:secret));
is($out,
$App::CamelPKI::Test::test_keys_plaintext{$k});
}
}
};
test "certificate_chain_ok and test certificates" => sub {
my @keyids = keys %App::CamelPKI::Test::test_rootca_certs;
foreach my $id (@keyids) {
certificate_chain_ok
($App::CamelPKI::Test::test_entity_certs{$id},
[ $App::CamelPKI::Test::test_rootca_certs{$id} ]);
certificate_chain_ok
($App::CamelPKI::Test::test_entity_certs{"${id}_sha256"},
[ $App::CamelPKI::Test::test_rootca_certs{$id} ]);
}
my ($snippet_ok, $snippet_not_ok) =
map { My::Tests::Below->pod_code_snippet($_) }
(qw(certificate_chain_ok certificate_chain_notok));
my $out = run_perl(<<"SCRIPT");
use Test::More qw(no_plan);
use App::CamelPKI::Test qw(certificate_chain_ok
%test_rootca_certs %test_self_signed_certs %test_entity_certs);
foreach my \$key (qw(${\join(" ", @keyids)})) {
$snippet_ok
$snippet_not_ok
}
SCRIPT
for my $i (0..$#keyids) {
my $success = 2 * $i + 1;
my $failure = 2 * $i + 2;
like($out, qr/^ok $success/m);
like($out, qr/^not ok $failure/m);
}
};
test "no collisions in the entity certificates' serial numbers" => sub {
my %serialz;
foreach my $certpem (values %App::CamelPKI::Test::test_entity_certs) {
my ($out, $err) =
run_thru_openssl($certpem, qw(x509 -noout -text));
(my ($serial) = $out =~ m/Serial Number:\n?\s+(.*)\n/)
or die $out;
ok(! $serialz{$serial}++, "duplicate serial $serial");
}
};
use App::CamelPKI::Test qw(server_start server_stop server_port);
sub server_can_connect {
my $ua = LWP::UserAgent->new;
my $port = server_port;
my $response = $ua->get("https://127.0.0.1:$port/");
# TODO : find a solution
# A small bug prevent this from working, no time
# to worry about it, just adapt the test
( run in 1.315 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )