Add automatic migration of provisioners

Provisioners stored in the CA configuration file are
automatically migrated to the database.

Currently no cleanup of the provisioners in the
configuration file yet. In certain situations this
may not work as expected, for example if the CA can't
write to the file. But it's probalby good to try it, so
that we can keep the configuration state of the CA consistent.
This commit is contained in:
Herman Slatman 2022-10-06 17:14:02 +02:00
parent 939e60b378
commit cebb7d7ef0
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

View File

@ -600,20 +600,59 @@ func (a *Authority) init() error {
return admin.WrapErrorISE(err, "error loading provisioners to initialize authority") return admin.WrapErrorISE(err, "error loading provisioners to initialize authority")
} }
if len(provs) == 0 && !strings.EqualFold(a.config.AuthorityConfig.DeploymentType, "linked") { if len(provs) == 0 && !strings.EqualFold(a.config.AuthorityConfig.DeploymentType, "linked") {
// Create First Provisioner
prov, err := CreateFirstProvisioner(ctx, a.adminDB, string(a.password)) var firstJWKProvisioner *linkedca.Provisioner
if err != nil { if len(a.config.AuthorityConfig.Provisioners) > 0 {
return admin.WrapErrorISE(err, "error creating first provisioner") log.Printf("Starting migration of provisioners")
// Existing provisioners detected; try migrating them to DB storage
for _, p := range a.config.AuthorityConfig.Provisioners {
lp, err := ProvisionerToLinkedca(p)
if err != nil {
return admin.WrapErrorISE(err, "error transforming provisioner %q while migrating", p.GetName())
}
// Store the provisioner to be migrated
if err := a.adminDB.CreateProvisioner(ctx, lp); err != nil {
return admin.WrapErrorISE(err, "error creating provisioner %q while migrating", p.GetName())
}
// Mark the first JWK provisioner, so that it can be used for administration purposes
if firstJWKProvisioner == nil && lp.Type == linkedca.Provisioner_JWK {
firstJWKProvisioner = lp
log.Printf("Migrated JWK provisioner %q with admin permissions", p.GetName()) // TODO(hs): change the wording?
} else {
log.Printf("Migrated %s provisioner %q", p.GetType(), p.GetName())
}
}
// TODO(hs): try to update ca.json to remove migrated provisioners from the
// file? This may not always be possible though, so we shouldn't fail hard on
// every error. The next time the CA runs, it won't have perform the migration,
// because there'll be at least a JWK provisioner.
log.Printf("Finished migrating provisioners")
} }
// Create first admin // Create first JWK provisioner for remote administration purposes if none exists yet
if firstJWKProvisioner == nil {
firstJWKProvisioner, err = CreateFirstProvisioner(ctx, a.adminDB, string(a.password))
if err != nil {
return admin.WrapErrorISE(err, "error creating first provisioner")
}
log.Printf("Created JWK provisioner %q with admin permissions", firstJWKProvisioner.GetName()) // TODO(hs): change the wording?
}
// Create first super admin, belonging to the first JWK provisioner
firstSuperAdminSubject := "step"
if err := a.adminDB.CreateAdmin(ctx, &linkedca.Admin{ if err := a.adminDB.CreateAdmin(ctx, &linkedca.Admin{
ProvisionerId: prov.Id, ProvisionerId: firstJWKProvisioner.Id,
Subject: "step", Subject: firstSuperAdminSubject,
Type: linkedca.Admin_SUPER_ADMIN, Type: linkedca.Admin_SUPER_ADMIN,
}); err != nil { }); err != nil {
return admin.WrapErrorISE(err, "error creating first admin") return admin.WrapErrorISE(err, "error creating first admin")
} }
log.Printf("Created super admin %q for JWK provisioner %q", firstSuperAdminSubject, firstJWKProvisioner.GetName())
} }
} }