Add UI support name constraints (#29263)

* add open api params

* support pki name constraints

* fix conditional

* revert helptextwsubtext

* fix typo

* add name constraints to sign intermediate form

* add changelog

* update test
This commit is contained in:
claire bontempo
2025-01-02 11:50:49 -06:00
committed by GitHub
parent 3c15d4b7fa
commit 91d88c3de1
7 changed files with 78 additions and 22 deletions

View File

@@ -419,7 +419,7 @@ Ranges must be specified in the notation of IP address and prefix length, like "
Type: framework.TypeCommaStringSlice,
Description: `Email addresses for which this certificate is allowed to sign or issue child certificates (see https://tools.ietf.org/html/rfc5280#section-4.2.1.10).`,
DisplayAttrs: &framework.DisplayAttributes{
Name: "Permitted email adresses",
Name: "Permitted email addresses",
},
}
fields["excluded_email_addresses"] = &framework.FieldSchema{

3
changelog/29263.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
ui: Add support for the name constraints extension to be fully specified when creating root and intermediate CA certificates.
```

View File

@@ -21,7 +21,6 @@ const validations = {
'notBeforeDuration',
'enforceLeafNotAfterBehavior',
'format',
'permittedDnsDomains',
'maxPathLength',
])
export default class PkiSignIntermediateModel extends PkiCertificateBaseModel {
@@ -58,19 +57,55 @@ export default class PkiSignIntermediateModel extends PkiCertificateBaseModel {
})
enforceLeafNotAfterBehavior;
@attr({
label: 'Permitted DNS domains',
subText:
'DNS domains for which certificates are allowed to be issued or signed by this CA certificate. Enter each value as a new input.',
})
permittedDnsDomains;
@attr({
subText: 'Specifies the maximum path length to encode in the generated certificate. -1 means no limit',
defaultValue: '-1',
})
maxPathLength;
/* Name constraint overrides */
@attr({
subText: 'DNS domains for which certificates are allowed to be issued or signed by this CA certificate.',
})
permittedDnsDomains;
@attr({
subText: 'Domains for which this certificate is not allowed to sign or issue child certificates.',
})
excludedDnsDomains;
@attr({
subText: 'Email addresses for which this certificate is not allowed to sign or issue child certificates.',
})
excludedEmailAddresses;
@attr({
subText:
'IP ranges for which this certificate is not allowed to sign or issue child certificates. Ranges must be specified in the notation of IP address and prefix length, such as "192.0.2.0/24" or "2001:db8::/32", as defined in RFC 4632 and RFC 4291.',
})
excludedIpRanges;
@attr({
subText: 'URI domains for which this certificate is not allowed to sign or issue child certificates.',
})
excludedUriDomains;
@attr({
subText: 'Email addresses for which this certificate is allowed to sign or issue child certificates.',
})
permittedEmailAddresses;
@attr({
subText:
'IP ranges for which this certificate is allowed to sign or issue child certificates. Ranges must be specified in the notation of IP address and prefix length, such as "192.0.2.0/24" or "2001:db8::/32", as defined in RFC 4632 and RFC 4291.',
})
permittedIpRanges;
@attr({
subText: 'URI domains for which this certificate is allowed to sign or issue child certificates.',
})
permittedUriDomains;
/* Signing Options overrides */
@attr({
label: 'Use PSS',

View File

@@ -43,7 +43,6 @@ import { removeFromArray } from 'vault/helpers/remove-from-array';
* @param {Model} model - Ember Data model that `attr` is defined on
* @param {boolean} [disabled=false] - whether the field is disabled
* @param {boolean} [showHelpText=true] - whether to show the tooltip with help text from OpenAPI
* @param {string} [subText] - text to be displayed below the label
* @param {string} [mode] - used when editType is 'kv'
* @param {object} [modelValidations] - Object of errors. If attr.name is in object and has error message display in AlertInline.
* @param {function} [onChange] - called whenever a value on the model changes via the component
@@ -96,12 +95,11 @@ export default class FormFieldComponent extends Component {
get disabled() {
return this.args.disabled || false;
}
get showHelpText() {
return this.args.showHelpText === false ? false : true;
}
get subText() {
return this.args.subText || '';
}
// used in the label element next to the form element
get labelString() {
const label = this.args.attr.options?.label || '';

View File

@@ -43,6 +43,13 @@
etc.) to be protected by a single certificate.
{{else if (eq group "Additional subject fields")}}
These fields provide more information about the client to which the certificate belongs.
{{else if (eq group "Name constraints")}}
These fields create the name constraints extension when generating CA certificates. Specifying any combination of
these parameters will trigger the creation of the name constraints extension as per
<Hds::Link::Inline
@isHrefExternal={{true}}
@href="https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10"
>RFC 5280 section 4.2.1.10</Hds::Link::Inline>.
{{/if}}
</p>
{{#each fields as |fieldName|}}

View File

@@ -49,6 +49,16 @@ export default class PkiSignIntermediateFormComponent extends Component<Args> {
get groups() {
return {
'Name constraints': [
'permittedDnsDomains',
'permittedEmailAddresses',
'permittedIpRanges',
'permittedUriDomains',
'excludedDnsDomains',
'excludedEmailAddresses',
'excludedIpRanges',
'excludedUriDomains',
],
'Signing options': ['usePss', 'skid', 'signatureBits'],
'Subject Alternative Name (SAN) Options': ['altNames', 'ipSans', 'uriSans', 'otherSans'],
'Additional subject fields': [

View File

@@ -14,9 +14,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support';
const selectors = {
form: '[data-test-sign-intermediate-form]',
csrInput: '[data-test-input="csr"]',
toggleSigningOptions: '[data-test-toggle-group="Signing options"]',
toggleSANOptions: '[data-test-toggle-group="Subject Alternative Name (SAN) Options"]',
toggleAdditionalFields: '[data-test-toggle-group="Additional subject fields"]',
toggleGroup: (group) => `[data-test-toggle-group="${group}"]`,
fieldByName: (name) => `[data-test-field="${name}"]`,
saveButton: '[data-test-pki-sign-intermediate-save]',
cancelButton: '[data-test-pki-sign-intermediate-cancel]',
@@ -40,19 +38,24 @@ module('Integration | Component | pki-sign-intermediate-form', function (hooks)
});
test('renders correctly on load', async function (assert) {
assert.expect(9);
assert.expect(10);
await render(hbs`<PkiSignIntermediateForm @onCancel={{this.onCancel}} @model={{this.model}} />`, {
owner: this.engine,
});
assert.dom(selectors.form).exists('Form is rendered');
assert.dom(selectors.resultsContainer).doesNotExist('Results display not rendered');
assert.dom('[data-test-field]').exists({ count: 10 }, '10 default fields shown');
assert.dom(selectors.toggleSigningOptions).exists();
assert.dom(selectors.toggleSANOptions).exists();
assert.dom(selectors.toggleAdditionalFields).exists();
assert.dom('[data-test-field]').exists({ count: 9 }, '9 default fields shown');
[
'Name constraints',
'Signing options',
'Subject Alternative Name (SAN) Options',
'Additional subject fields',
].forEach((group) => {
assert.dom(selectors.toggleGroup(group)).exists(`${group} renders`);
});
await click(selectors.toggleSigningOptions);
await click(selectors.toggleGroup('Signing options'));
['usePss', 'skid', 'signatureBits'].forEach((name) => {
assert.dom(selectors.fieldByName(name)).exists();
});