Skip to content

Commit

Permalink
Make storage of certificates more flexible
Browse files Browse the repository at this point in the history
This commit changes the way that SSL certificates are stored within
Brass. It provides much greater flexibility, enabling different
certificate users to have different (or multiple) file locations for
different uses. It also simplifies things, by only requiring a single
use to be specified for a certificate attached to a server, rather than
needing to separately define the keys and certificate files.

As it stands, some configuration is needed directly in the database, to
configure the file locations for the different uses of certificates.
  • Loading branch information
abeverley committed Dec 10, 2023
1 parent e60126d commit 1ac9aa7
Show file tree
Hide file tree
Showing 18 changed files with 4,673 additions and 168 deletions.
23 changes: 12 additions & 11 deletions lib/Brass.pm
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package Brass;

use Brass::Classifications;
use Brass::Config::Certs;
use Brass::Config::CertUses;
use Brass::Config::Domains;
use Brass::Config::Pwd;
use Brass::Config::Pwds;
Expand Down Expand Up @@ -327,8 +325,8 @@ any ['get', 'post'] => '/config/server/?:id?' => require_role 'config' => sub {
servers => Brass::Config::Servers->new(schema => $schema)->all,
domains => Brass::Config::Domains->new(schema => $schema)->all,
types => Brass::Config::Server::Types->new(schema => $schema)->all,
certs => Brass::Config::Certs->new(schema => $schema)->all,
cert_uses => Brass::Config::CertUses->new(schema => $schema)->all,
certs => $schema->resultset('Cert'),
cert_uses => $schema->resultset('CertUse'),
page => 'config/server',
};

Expand Down Expand Up @@ -526,33 +524,36 @@ any ['get', 'post'] => '/config/cert/?:id?' => require_role 'config' => sub {
my $schema = schema;

my $params = {
certs => Brass::Config::Certs->new(schema => $schema)->all,
certs => [$schema->resultset('Cert')->all],
page => 'config/cert',
};

if (defined $id)
{
my $cert = Brass::Config::Cert->new(id => $id, schema => $schema);
my $cert = $id ? $schema->resultset('Cert')->find($id)
: $schema->resultset('Cert')->new({});
if (param 'save')
{
die "No permission to save certificate"
unless user_has_role 'config_write';
$cert->cn(param 'cn');
$cert->type(param 'type');
$cert->set_expiry(param 'expiry');
$cert->usedby(param 'usedby');
$cert->expiry(param('expiry') || undef);
$cert->description(param 'description');
$cert->filename(param 'filename');
$cert->file_user(param 'file_user');
$cert->file_group(param 'file_group');
$cert->content(param 'content');
$cert->write;
$cert->content_cert(param 'content_cert');
$cert->content_key(param 'content_key');
$cert->content_ca(param 'content_ca');
$cert->update_or_insert;
redirect '/config/cert';
}
if (param 'delete')
{
die "No permission to save certificate"
unless user_has_role 'config_write';
$cert->delete;
$cert->delete_cert;
redirect '/config/cert';
}
$params->{cert} = $cert;
Expand Down
73 changes: 34 additions & 39 deletions lib/Brass/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -172,45 +172,51 @@ get 'api/cert/' => sub {
if ($action eq 'summary')
{
$server or error __"Please specify server";
$param or error __"Please specify certificate";
$param or error __"Please specify certificate use";

my @certs = $schema->resultset('ServerCert')->search({
my @certs;
my @uses = $schema->resultset('ServerCert')->search({
'server.name' => $server,
'use.name' => $param,
},{
join => ['server', 'use'],
prefetch => 'cert',
join => ['use', 'server'],
})->all;

my %output;
foreach my $cert (@certs)
error __x"Use {use} not found for server {name}",
use => $param, name => $server
if !@uses;

foreach my $use (@uses)
{
my $full_filename = $cert->cert->filename;
my @filenames = split /\s*,\s*/, $full_filename;
foreach my $filename (@filenames) {
# Add final newline if it doesn't exist
my $content = $cert->cert->content;
$content .= "\n" unless $content =~ /\n$/;
if ($output{$filename})
{
$output{$filename}->{content} .= $content;
}
else {
$output{$filename} = {
type => $cert->cert->type,
filename => $filename,
content => $content,
file_user => $cert->cert->file_user,
file_group => $cert->cert->file_group,
};
}
}
my $cert = $schema->resultset('Cert')->search({
'me.id' => $use->cert_id,
'cert_location_uses.use_id' => $use->get_column('use'),
},{
prefetch => {
cert_locations => 'cert_location_uses',
},
});

error __x"More than one location configured for use \"{use}\" of certificate {id}",
use => $use->use->name, id => $use->cert_id
if $cert->count > 1;

error __x"Location information not configured for use \"{use}\" of certificate {id}",
use => $use->use->name, id => $use->cert_id
if !$cert->count;

push @certs, $cert->next->as_hash_single;
}
$output = [values %output];

$output = \@certs;
}
elsif ($action eq 'servers')
{
$param or error __"Please specify certificate ID";

my $cert = $schema->resultset('Cert')->find($param)
or error __x"Certificate ID {id} not found", id => $param;

my @servers = $schema->resultset('Server')->search({
'cert.id' => $param,
},{
Expand All @@ -219,18 +225,7 @@ get 'api/cert/' => sub {
},
})->all;

my ($server_cert) = $servers[0]->server_certs;
my $cert = $server_cert->cert;
# Add final newline if it doesn't exist
my $content = $cert->content;
$content .= "\n" unless $content =~ /\n$/;
my @server_names = map { $_->name } @servers;
$output = {
filename => $cert->filename,
content => $content,
type => $cert->type,
servers => \@server_names,
};
$output = $cert->as_hash_multiple;
}
else {
error __x"Unknown action {action}", action => $action;
Expand Down
2 changes: 1 addition & 1 deletion lib/Brass/Schema.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ __PACKAGE__->load_namespaces;
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-10-01 11:03:29
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:GqW9kl7MrcAx0vieFGh+cw

our $VERSION = 34;
our $VERSION = 35;

# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
Loading

0 comments on commit 1ac9aa7

Please sign in to comment.