There was an error attempting to acquire a certificate for {{Domain}}. 12 | 13 | Error 14 | {{Error}} 15 | 16 | Last acquired 17 | {{LastAcquiryText}} 18 | 19 | {{PreviousCertificateDetails}} 20 |21 | 22 | -------------------------------------------------------------------------------- /src/Certera.Core/Notifications/Templates/NotificationCertificateAcquisitionFailureSlack.json: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": [ 3 | { 4 | "type": "section", 5 | "text": { 6 | "type": "mrkdwn", 7 | "text": "There was an error attempting to acquire a certificate for *{{Domain}}*." 8 | } 9 | }, 10 | { 11 | "type": "section", 12 | "text": { 13 | 14 | "type": "mrkdwn", 15 | "text": "*Error:*\n{{Error}}\n\n*Last acquired:*\n{{LastAcquiryText}}\n\n{{PreviousCertificateDetails}}" 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/Certera.Core/Notifications/Templates/NotificationCertificateChangeEmail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 |
Change detected in the {{Domain}} certificate. 12 | 13 | New certificate details 14 | 15 | Thumbprint 16 | {{NewThumbprint}} 17 | 18 | Public Key (hash) 19 | {{NewPublicKey}} 20 | 21 | Valid 22 | {{NewValidFrom}} to {{NewValidTo}} 23 | 24 | Previous certificate details 25 | 26 | Thumbprint 27 | {{PreviousThumbprint}} 28 | 29 | Public Key (hash) 30 | {{PreviousPublicKey}} 31 | 32 | Valid 33 | {{PreviousValidFrom}} to {{PreviousValidTo}} 34 |35 | 36 | 37 | -------------------------------------------------------------------------------- /src/Certera.Core/Notifications/Templates/NotificationCertificateChangeSlack.json: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": [ 3 | { 4 | "type": "section", 5 | "text": { 6 | "type": "mrkdwn", 7 | "text": "Change detected in the *{{Domain}}* certificate." 8 | } 9 | }, 10 | { 11 | "type": "section", 12 | "text": { 13 | 14 | "type": "mrkdwn", 15 | "text": "*New certificate details*\n*Thumbprint:*\n{{NewThumbprint}}\n*Public Key (hash):*\n{{NewPublicKey}}\n*Valid:*\n{{NewValidFrom}} to {{NewValidTo}}\n\n*Previous certificate details*\n*Thumbprint:*\n{{PreviousThumbprint}}\n*Public Key (hash):*\n{{PreviousPublicKey}}\n*Valid:*\n{{PreviousValidFrom}} to {{PreviousValidTo}}" 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/Certera.Core/Notifications/Templates/NotificationCertificateExpirationEmail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 |
{{Domain}} certificate is set to expire on {{DateTime}} ({{DaysText}}). 12 | 13 | Current details 14 | 15 | Thumbprint 16 | {{Thumbprint}} 17 | 18 | Public Key (hash) 19 | {{PublicKey}} 20 | 21 | Valid 22 | {{ValidFrom}} to {{ValidTo}} 23 |24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Certera.Core/Notifications/Templates/NotificationCertificateExpirationSlack.json: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": [ 3 | { 4 | "type": "section", 5 | "text": { 6 | "type": "mrkdwn", 7 | "text": "*{{Domain}}* certificate is set to expire on {{DateTime}} ({{DaysText}})." 8 | } 9 | }, 10 | { 11 | "type": "section", 12 | "text": { 13 | 14 | "type": "mrkdwn", 15 | "text": "*Current details*\n*Thumbprint:*\n{{Thumbprint}}\n*Public Key (hash):*\n{{PublicKey}}\n*Valid:*\n{{ValidFrom}} to {{ValidTo}}" 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/Certera.Data/ApiKeyGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Numerics; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace Certera.Data 7 | { 8 | public static class ApiKeyGenerator 9 | { 10 | public static string CreateApiKey() 11 | { 12 | var bytes = new byte[256 / 8]; 13 | using (var random = RandomNumberGenerator.Create()) 14 | random.GetBytes(bytes); 15 | return ToBase62String(bytes); 16 | } 17 | 18 | private static string ToBase62String(byte[] toConvert) 19 | { 20 | const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; 21 | BigInteger dividend = new BigInteger(toConvert); 22 | var builder = new StringBuilder(); 23 | while (dividend != 0) 24 | { 25 | dividend = BigInteger.DivRem(dividend, alphabet.Length, out BigInteger remainder); 26 | builder.Insert(0, alphabet[Math.Abs(((int)remainder))]); 27 | } 28 | return builder.ToString(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Certera.Data/ApplicationUser.partial.cs: -------------------------------------------------------------------------------- 1 | using Certera.Data.Models; 2 | using Microsoft.AspNetCore.Identity; 3 | using System.Collections.Generic; 4 | 5 | namespace Certera.Data 6 | { 7 | public partial class ApplicationUser : IdentityUser
You do not have access to this resource.
10 |9 | Please check your email to reset your password. 10 |
11 | 12 | -------------------------------------------------------------------------------- /src/Certera.Web/Pages/Account/ForgotPasswordConfirmation.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace Certera.Web.Pages.Account 8 | { 9 | [AllowAnonymous] 10 | public class ForgotPasswordConfirmation : PageModel 11 | { 12 | public void OnGet() 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Certera.Web/Pages/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LockoutModel 3 | @{ 4 | ViewData["Title"] = "Locked out"; 5 | } 6 | 7 |This account has been locked out, please try again later.
10 |Your login is protected with an authenticator app. Enter your authenticator code below.
10 |35 | Don't have access to your authenticator device? You can 36 | log in with a recovery code. 37 |
38 | 39 | @section Scripts { 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/Certera.Web/Pages/Account/LoginRecoveryCode.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LoginRecoveryCodeModel 3 | @{ 4 | ViewData["Title"] = "Recovery code verification"; 5 | } 6 | 7 |10 | You have requested to log in with a recovery code. This login will not be remembered until you provide 11 | an authenticator app code at log in or disable 2FA and log in again. 12 |
13 |You have successfully logged out of the application.
10 |13 | 14 | This action only disables 2FA. 15 |
16 |17 | Disabling 2FA does not change the keys used in authenticator apps. If you wish to change the key 18 | used in an authenticator app you should reset your authenticator keys. 19 |
20 |Scan the QR Code or enter this key @Model.SharedKey into your two factor authenticator app. Spaces and casing do not matter.
16 | 17 | 18 |19 | Once you have scanned the QR code or input the key above, your two factor authentication app will provide you 20 | with a unique code. Enter the code in the confirmation box below. 21 |
22 | 31 |12 | 13 | Put these codes in a safe place. 14 |
15 |16 | If you lose your device and don't have the recovery codes you will lose access to your account. 17 |
18 |19 | Generating new recovery codes does not change the keys used in authenticator apps. If you wish to change the key 20 | used in an authenticator app you should reset your authenticator keys. 21 |
22 |12 | 13 | If you reset your authenticator key your authenticator app will not work until you reconfigure it. 14 |
15 |16 | This process disables 2FA until you verify your authenticator app. 17 | If you do not complete your authenticator app configuration you may lose access to your account. 18 |
19 |12 | Put these codes in a safe place. 13 |
14 |15 | If you lose your device and don't have the recovery codes you will lose access to your account. 16 |
17 |@Model.RecoveryCodes[row]
@Model.RecoveryCodes[row + 1]
You must generate a new set of recovery codes before you can log in with a recovery code.
22 |You can generate a new set of recovery codes.
29 |You should generate a new set of recovery codes.
36 |9 | Your password has been reset. Please click here to log in. 10 |
11 | -------------------------------------------------------------------------------- /src/Certera.Web/Pages/Account/ResetPasswordConfirmation.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace Certera.Web.Pages.Account 9 | { 10 | [AllowAnonymous] 11 | public class ResetPasswordConfirmationModel : PageModel 12 | { 13 | public void OnGet() 14 | { 15 | 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Certera.Web/Pages/Account/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "/Pages/Shared/_Layout.cshtml"; 3 | } 4 | 5 | @section Head { 6 | @RenderSection("Head", false) 7 | } 8 | 9 |20 | ACME Email 21 | | 22 |23 | ToS 24 | | 25 |26 | @Html.DisplayNameFor(model => model.AcmeAccount[0].Key) 27 | | 28 |
---|---|---|
35 |
36 | @item.AcmeContactEmail
37 |
38 | @if (item.IsAcmeStaging)
39 | {
40 | staging
41 | }
42 | |
43 | 44 | accepted 45 | | 46 |47 | @item.Key.Name 48 | | 49 |
20 | @Html.DisplayNameFor(model => model.AcmeCertificate[0].Name) 21 | | 22 |23 | @Html.DisplayNameFor(model => model.AcmeCertificate[0].Subject) 24 | | 25 |26 | @Html.DisplayNameFor(model => model.AcmeCertificate[0].DateCreated) 27 | | 28 |29 | @Html.DisplayNameFor(model => model.AcmeCertificate[0].Key) 30 | | 31 |
---|---|---|---|
38 |
39 | @Html.DisplayFor(modelItem => item.Name)
40 |
41 |
42 | @if (item.AcmeAccount.IsAcmeStaging)
43 | {
44 | staging
45 | }
46 | @Html.DisplayFor(modelItem => item.ChallengeType)
47 |
48 | |
49 |
50 |
51 | @Html.DisplayFor(modelItem => item.Subject)
52 |
53 | @if (!string.IsNullOrWhiteSpace(item.SANs))
54 | {
55 | @Html.DisplayFor(modelItem => item.SANs)
56 | }
57 | |
58 | 59 | @item.DateCreated.ToLocalTime().ToString() 60 | | 61 |62 | @item.Key.Name 63 | | 64 |
13 | Request ID: @Model.RequestId
14 |
@Html.DisplayNameFor(model => model.Key[0].Name) | 20 |@Html.DisplayNameFor(model => model.Key[0].Description) | 21 |@Html.DisplayNameFor(model => model.Key[0].DateCreated) | 22 | @*@Html.DisplayNameFor(model => model.Key[0].DateRotationReminder) | *@ 23 |
---|---|---|---|
30 |
31 | @item.Name
32 |
33 | @Html.DisplayFor(modelItem => item.Algorithm)
34 | |
35 | 36 | @Html.DisplayFor(modelItem => item.Description) 37 | | 38 |39 | @item.DateCreated.ToLocalTime().ToString() 40 | | 41 | @*42 | @Html.DisplayFor(modelItem => item.DateRotationReminder) 43 | | *@ 44 |
29 | We're now ready to get a certificate for "@HttpServerOptions.Value.SiteHostname". Please make sure
30 | port 80 is open to the internet if you haven't already done that.
31 |
32 |
33 | Alright, let's go! This can take a moment, but we'll keep you updated all of the way through.
34 |
27 | Congratulations, setup is done!
28 |
29 |
30 | Make sure port @HttpServerOptions.Value.HttpsPort is accessible from the internet and Certera is ready to go.
31 | Next, login to get started.
32 |