Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sign certificate functionality of PKI secret engine. #192

Merged
merged 3 commits into from
Jun 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a null check on result.Data

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's assigned as in GetCredentialsAsync function. Thought that there will be some exception, error code from Api if there will be no data send. For my purpose i don't even need that CertificateFormat Assigned cause as a caller you already know it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property is not marked with JsonIgnore... Either we should let json set it, or if we are explicitly setting it, it should be marked with json-ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CertificateFormat property is marked as JsonIgnore in AbstractCertificateData class. Or maybe I am referring to wrong property?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. i was looking at the request poco by mistake.


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>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this. redundant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you right. Removed Abstract class and created separate classes for both endpoints so this one is fixed too.

/// <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
{

}
}