Skip to content

Commit

Permalink
Added sign certificate functionality of PKI secret engine. (#192)
Browse files Browse the repository at this point in the history
* Added sign certificate functionality of PKI secret engine. Abstracted CertificateRequestOptions for PKI engine. Added example in README.md and small note in CHANGELOG.md.

* fixed ref copy paste typo in SignCertificateRequestOptions

* Restored original CerificateCredentialsRequestOptions class moved abstracted details to SignCertificateRequestOptions class

Co-authored-by: Stanisław Lutkiewicz <stanislaw.lutkiewicz@softgent.com>
  • Loading branch information
sj-lt and Stanisław Lutkiewicz authored Jun 5, 2021
1 parent 39fe818 commit f6f24ea
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.6.2.3 (June 4, 2021)

**FEATURES:**

* Implemented sign certificate endpoint of PKI secret engine.

## 1.6.2.2 (May 23, 2021)

**FEATURES:**
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,15 @@ Secret<CertificateCredentials> certSecret = await vaultClient.V1.Secrets.PKI.Get
string privateKeyContent = certSecret.Data.PrivateKeyContent;
```

##### Sign Certificate

```cs
var signCertificateRequestOptions = new SignCertificateRequestOptions { // initialize };
Secret<SignedCertificateData> certSecret = await vaultClient.V1.Secrets.PKI.SignCertificateAsync(pkiRoleName, signCertificateRequestOptions);

string certificateContent = certSecret.Data.CertificateContent;
```

##### Revoke Certificate

```cs
Expand Down
24 changes: 24 additions & 0 deletions src/VaultSharp/V1/SecretsEngines/PKI/IPKISecretsEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,30 @@ public interface IPKISecretsEngine
/// </returns>
Task<Secret<CertificateCredentials>> GetCredentialsAsync(string pkiRoleName, CertificateCredentialsRequestOptions certificateCredentialRequestOptions, string pkiBackendMountPoint = null, string wrapTimeToLive = null);

/// <summary>
/// This endpoint signs a new certificate based upon the provided CSR and the supplied parameters,
/// subject to the restrictions contained in the role named in the endpoint.
/// The issuing CA certificate is returned as well, so that only the root CA need be in a client's trust store.
/// </summary>
/// <param name="pkiRoleName"><para>[required]</para>
/// Name of the PKI role.
/// </param>
/// <param name="signCertificateRequestOptions"><para>[required]</para>
/// The sign certificate request options.
/// </param>
/// <param name="pkiBackendMountPoint"><para>[optional]</para>
/// The mount point for the PKI backend. Defaults to <see cref="SecretsEngineMountPoints.PKI" />
/// Provide a value only if you have customized the PKI mount point.
/// </param>
/// <param name="wrapTimeToLive">
/// <para>[required]</para>
/// The TTL for the token and can be either an integer number of seconds or a string duration of seconds.
/// </param>
/// <returns>
/// The secret with the signed Certificate.
/// </returns>
Task<Secret<SignedCertificateData>> SignCertificateAsync(string pkiRoleName, SignCertificatesRequestOptions signCertificateRequestOptions, string pkiBackendMountPoint = null, string wrapTimeToLive = null);

/// <summary>
/// This endpoint revokes a certificate using its serial number.
/// This is an alternative option to the standard method of revoking using Vault lease IDs.
Expand Down
12 changes: 12 additions & 0 deletions src/VaultSharp/V1/SecretsEngines/PKI/PKISecretsEngineProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ public async Task<Secret<CertificateCredentials>> GetCredentialsAsync(string pki

return result;
}

public async Task<Secret<SignedCertificateData>> SignCertificateAsync(string pkiRoleName, SignCertificatesRequestOptions signCertificatesRequestOptions, string pkiBackendMountPoint = null, string wrapTimeToLive = null)
{
Checker.NotNull(pkiRoleName, "pkiRoleName");
Checker.NotNull(signCertificatesRequestOptions, "signCertificatesRequestOptions");

var result = await _polymath.MakeVaultApiRequest<Secret<SignedCertificateData>>(pkiBackendMountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.PKI, "/sign/" + pkiRoleName, HttpMethod.Post, signCertificatesRequestOptions, wrapTimeToLive: wrapTimeToLive).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
result.Data.CertificateFormat = signCertificatesRequestOptions.CertificateFormat;

return result;
}

public async Task<Secret<RevokeCertificateResponse>> RevokeCertificateAsync(string serialNumber, string pkiBackendMountPoint = null)
{
Expand Down Expand Up @@ -54,5 +65,6 @@ public async Task<RawCertificateData> ReadCACertificateAsync(CertificateFormat c
EncodedCertificateFormat = outputFormat
};
}

}
}
122 changes: 122 additions & 0 deletions src/VaultSharp/V1/SecretsEngines/PKI/SignCertificateRequestOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using Newtonsoft.Json;

namespace VaultSharp.V1.SecretsEngines.PKI
{
/// <summary>
/// Represents the Sign Certificate request options.
/// </summary>
public class SignCertificatesRequestOptions
{
/// <summary>
/// <para>[required]</para>
/// Specifies the PEM-encoded CSR
/// </summary>
/// <value>
/// Encoded CSR.
/// </value>
[JsonProperty("csr")]
public string Csr { get; set; }

/// <summary>
/// <para>[required]</para>
/// Gets or sets the requested CN for the certificate.
/// If the CN is allowed by role policy, it will be issued.
/// </summary>
/// <value>
/// The name of the common.
/// </value>
[JsonProperty("common_name")]
public string CommonName { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the requested Subject Alternative Names, in a comma-delimited list.
/// These can be host names or email addresses; they will be parsed into their respective fields.
/// If any requested names do not match role policy, the entire request will be denied.
/// </summary>
/// <value>
/// The subject alternative names.
/// </value>
[JsonProperty("alt_names")]
public string SubjectAlternativeNames { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the requested IP Subject Alternative Names, in a comma-delimited list.
/// Only valid if the role allows IP SANs (which is the default).
/// </summary>
/// <value>
/// The ip subject alternative names.
/// </value>
[JsonProperty("ip_sans")]
public string IPSubjectAlternativeNames { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the requested URI Subject Alternative Names, in a comma-delimited list.
/// </summary>
/// <value>
/// The uri subject alternative names.
/// </value>
[JsonProperty("uri_sans")]
public string URISubjectAlternativeNames { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the custom OID/UTF8-string SANs.
/// These must match values specified on the role in allowed_other_sans (globbing allowed).
/// The format is the same as OpenSSL: [oid];[type]:[value] where the only current valid type is UTF8.
/// This can be a comma-delimited list or a JSON string slice.
/// </summary>
/// <value>
/// The other subject alternative names.
/// </value>
[JsonProperty("other_sans")]
public string OtherSubjectAlternativeNames { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the requested Time To Live.
/// Cannot be greater than the role's max_ttl value.
/// If not provided, the role's ttl value will be used.
/// Note that the role values default to system values if not explicitly set.
/// </summary>
/// <value>
/// The time to live.
/// </value>
[JsonProperty("ttl")]
public string TimeToLive { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets the certificate format for returned data.
/// Can be pem or der; defaults to pem.
/// If der, the output is base64 encoded..
/// </summary>
/// <value>
/// The certificate format.
/// </value>
[JsonProperty("format")]
public CertificateFormat CertificateFormat { get; set; }

/// <summary>
/// <para>[optional]</para>
/// Gets or sets a value indicating whether [exclude common name from subject alternative names].
/// If set, the given common name will not be included in DNS or Email Subject Alternate Names (as appropriate).
/// Useful if the CN is not a hostname or email address, but is instead some human-readable identifier.
/// </summary>
/// <value>
/// <c>true</c> if [exclude common name from subject alternative names]; otherwise, <c>false</c>.
/// </value>
[JsonProperty("exclude_cn_from_sans")]
public bool ExcludeCommonNameFromSubjectAlternativeNames { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="SignCertificatesRequestOptions"/> class.
/// </summary>
public SignCertificatesRequestOptions()
{
CertificateFormat = CertificateFormat.pem;
}
}
}
12 changes: 12 additions & 0 deletions src/VaultSharp/V1/SecretsEngines/PKI/SignedCertificateData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace VaultSharp.V1.SecretsEngines.PKI
{
/// <summary>
/// Represents the signed Certificate.
/// </summary>
public class SignedCertificateData : AbstractCertificateData
{

}
}

0 comments on commit f6f24ea

Please sign in to comment.