diff --git a/builtin/credential/aws/path_role.go b/builtin/credential/aws/path_role.go index 60b2359e8..02a0bde38 100644 --- a/builtin/credential/aws/path_role.go +++ b/builtin/credential/aws/path_role.go @@ -87,6 +87,9 @@ auth_type is ec2 or inferred_entity_type is ec2_instance.`, given instance IDs. Can be a list or comma-separated string of EC2 instance IDs. This is only applicable when auth_type is ec2 or inferred_entity_type is ec2_instance.`, + DisplayAttrs: &framework.DisplayAttributes{ + Description: "If set, defines a constraint on the EC2 instances to have one of the given instance IDs. A list of EC2 instance IDs. This is only applicable when auth_type is ec2 or inferred_entity_type is ec2_instance.", + }, }, "resolve_aws_unique_ids": { Type: framework.TypeBool, diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 0e7b7cfa0..03a3e5586 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -77,6 +77,9 @@ Must be x509 PEM encoded.`, Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of OCSP server addresses. If unset, the OCSP server is determined from the AuthorityInformationAccess extension on the certificate being inspected.`, + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of OCSP server addresses. If unset, the OCSP server is determined from the AuthorityInformationAccess extension on the certificate being inspected.", + }, }, "ocsp_fail_open": { Type: framework.TypeBool, @@ -95,7 +98,8 @@ At least one must exist in either the Common Name or SANs. Supports globbing. This parameter is deprecated, please use allowed_common_names, allowed_dns_sans, allowed_email_sans, allowed_uri_sans.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Constraints", + Group: "Constraints", + Description: "A list of names. At least one must exist in either the Common Name or SANs. Supports globbing. This parameter is deprecated, please use allowed_common_names, allowed_dns_sans, allowed_email_sans, allowed_uri_sans.", }, }, @@ -104,7 +108,8 @@ allowed_email_sans, allowed_uri_sans.`, Description: `A comma-separated list of names. At least one must exist in the Common Name. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Constraints", + Group: "Constraints", + Description: "A list of names. At least one must exist in the Common Name. Supports globbing.", }, }, @@ -113,8 +118,9 @@ At least one must exist in the Common Name. Supports globbing.`, Description: `A comma-separated list of DNS names. At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ - Name: "Allowed DNS SANs", - Group: "Constraints", + Name: "Allowed DNS SANs", + Group: "Constraints", + Description: "A list of DNS names. At least one must exist in the SANs. Supports globbing.", }, }, @@ -123,8 +129,9 @@ At least one must exist in the SANs. Supports globbing.`, Description: `A comma-separated list of Email Addresses. At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ - Name: "Allowed Email SANs", - Group: "Constraints", + Name: "Allowed Email SANs", + Group: "Constraints", + Description: "A list of Email Addresses. At least one must exist in the SANs. Supports globbing.", }, }, @@ -133,8 +140,9 @@ At least one must exist in the SANs. Supports globbing.`, Description: `A comma-separated list of URIs. At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ - Name: "Allowed URI SANs", - Group: "Constraints", + Name: "Allowed URI SANs", + Group: "Constraints", + Description: "A list of URIs. At least one must exist in the SANs. Supports globbing.", }, }, @@ -143,7 +151,8 @@ At least one must exist in the SANs. Supports globbing.`, Description: `A comma-separated list of Organizational Units names. At least one must exist in the OU field.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Constraints", + Group: "Constraints", + Description: "A list of Organizational Units names. At least one must exist in the OU field.", }, }, @@ -152,6 +161,9 @@ At least one must exist in the OU field.`, Description: `A comma-separated string or array of extensions formatted as "oid:value". Expects the extension value to be some type of ASN1 encoded string. All values much match. Supports globbing on "value".`, + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of extensions formatted as 'oid:value'. Expects the extension value to be some type of ASN1 encoded string. All values much match. Supports globbing on 'value'.", + }, }, "allowed_metadata_extensions": { @@ -160,6 +172,9 @@ All values much match. Supports globbing on "value".`, Upon successful authentication, these extensions will be added as metadata if they are present in the certificate. The metadata key will be the string consisting of the oid numbers separated by a dash (-) instead of a dot (.) to allow usage in ACL templates.`, + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of OID extensions. Upon successful authentication, these extensions will be added as metadata if they are present in the certificate. The metadata key will be the string consisting of the OID numbers separated by a dash (-) instead of a dot (.) to allow usage in ACL templates.", + }, }, "display_name": { diff --git a/builtin/credential/ldap/path_groups.go b/builtin/credential/ldap/path_groups.go index b5a10df8b..08ac00d7f 100644 --- a/builtin/credential/ldap/path_groups.go +++ b/builtin/credential/ldap/path_groups.go @@ -52,6 +52,9 @@ func pathGroups(b *backend) *framework.Path { "policies": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies associated to the group.", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of policies associated to the group.", + }, }, }, diff --git a/builtin/credential/ldap/path_users.go b/builtin/credential/ldap/path_users.go index 90e945d79..1ce252d1d 100644 --- a/builtin/credential/ldap/path_users.go +++ b/builtin/credential/ldap/path_users.go @@ -53,11 +53,17 @@ func pathUsers(b *backend) *framework.Path { "groups": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of additional groups associated with the user.", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of additional groups associated with the user.", + }, }, "policies": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies associated with the user.", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of policies associated with the user.", + }, }, }, diff --git a/builtin/credential/okta/path_groups.go b/builtin/credential/okta/path_groups.go index 8a156d226..753c1cacd 100644 --- a/builtin/credential/okta/path_groups.go +++ b/builtin/credential/okta/path_groups.go @@ -52,6 +52,9 @@ func pathGroups(b *backend) *framework.Path { "policies": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies associated to the group.", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of policies associated to the group.", + }, }, }, diff --git a/builtin/credential/radius/path_config.go b/builtin/credential/radius/path_config.go index 32a72a583..6bdc29673 100644 --- a/builtin/credential/radius/path_config.go +++ b/builtin/credential/radius/path_config.go @@ -44,9 +44,10 @@ func pathConfig(b *backend) *framework.Path { "unregistered_user_policies": { Type: framework.TypeString, Default: "", - Description: "Comma-separated list of policies to grant upon successful RADIUS authentication of an unregisted user (default: empty)", + Description: "Comma-separated list of policies to grant upon successful RADIUS authentication of an unregistered user (default: empty)", DisplayAttrs: &framework.DisplayAttributes{ - Name: "Policies for unregistered users", + Name: "Policies for unregistered users", + Description: "List of policies to grant upon successful RADIUS authentication of an unregistered user (default: empty)", }, }, "dial_timeout": { diff --git a/builtin/credential/radius/path_users.go b/builtin/credential/radius/path_users.go index 43f90b53c..63ac5bbc2 100644 --- a/builtin/credential/radius/path_users.go +++ b/builtin/credential/radius/path_users.go @@ -53,6 +53,9 @@ func pathUsers(b *backend) *framework.Path { "policies": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies associated to the user.", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of policies associated to the user.", + }, }, }, diff --git a/builtin/credential/userpass/path_user_policies.go b/builtin/credential/userpass/path_user_policies.go index 19f9ef7a9..8c5a9174a 100644 --- a/builtin/credential/userpass/path_user_policies.go +++ b/builtin/credential/userpass/path_user_policies.go @@ -36,6 +36,9 @@ func pathUserPolicies(b *backend) *framework.Path { "token_policies": { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies", + DisplayAttrs: &framework.DisplayAttributes{ + Description: "A list of policies that will apply to the generated token for this user.", + }, }, }, diff --git a/changelog/20163.txt b/changelog/20163.txt new file mode 100644 index 000000000..0b845fbae --- /dev/null +++ b/changelog/20163.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: adds warning for commas in stringArray inputs and updates tooltip help text to remove references to comma separation +``` diff --git a/sdk/framework/path.go b/sdk/framework/path.go index a54bd4a40..e96ba4c41 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -207,6 +207,11 @@ type DisplayAttributes struct { // Name is the name of the field suitable as a label or documentation heading. Name string `json:"name,omitempty"` + // Description of the field that renders as tooltip help text beside the label (name) in the UI. + // This may be used to replace descriptions that reference comma separation but correspond + // to UI inputs where only arrays are valid. For example params with Type: framework.TypeCommaStringSlice + Description string `json:"description,omitempty"` + // Value is a sample value to display for this field. This may be used // to indicate a default value, but it is for display only and completely separate // from any Default member handling. diff --git a/sdk/helper/tokenutil/tokenutil.go b/sdk/helper/tokenutil/tokenutil.go index 0310b9db4..4319bd182 100644 --- a/sdk/helper/tokenutil/tokenutil.go +++ b/sdk/helper/tokenutil/tokenutil.go @@ -78,8 +78,9 @@ func TokenFields() map[string]*framework.FieldSchema { Type: framework.TypeCommaStringSlice, Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`, DisplayAttrs: &framework.DisplayAttributes{ - Name: "Generated Token's Bound CIDRs", - Group: "Tokens", + Name: "Generated Token's Bound CIDRs", + Group: "Tokens", + Description: "A list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.", }, }, @@ -123,8 +124,9 @@ func TokenFields() map[string]*framework.FieldSchema { Type: framework.TypeCommaStringSlice, Description: "Comma-separated list of policies", DisplayAttrs: &framework.DisplayAttributes{ - Name: "Generated Token's Policies", - Group: "Tokens", + Name: "Generated Token's Policies", + Group: "Tokens", + Description: "A list of policies that will apply to the generated token for this user.", }, }, diff --git a/ui/app/components/generated-item.js b/ui/app/components/generated-item.js index 008810b7f..63f56b23e 100644 --- a/ui/app/components/generated-item.js +++ b/ui/app/components/generated-item.js @@ -53,16 +53,6 @@ export default Component.extend({ ), init() { this._super(...arguments); - this.model.fieldGroups.forEach((element) => { - // overwriting the helpText for Token Polices. - // HelpText from the backend says add a comma separated list, which works on the CLI but not here on the UI. - // This effects TLS Certificates, Userpass, and Kubernetes. https://github.com/hashicorp/vault/issues/10346 - if (element.Tokens) { - element.Tokens.find((attr) => attr.name === 'tokenPolicies').options.helpText = - 'Add policies that will apply to the generated token for this user. One policy per row.'; - } - }); - if (this.mode === 'edit') { // For validation to work in edit mode, // reconstruct the model values from field group diff --git a/ui/app/models/pki/certificate/base.js b/ui/app/models/pki/certificate/base.js index ee20c0934..888a43e9b 100644 --- a/ui/app/models/pki/certificate/base.js +++ b/ui/app/models/pki/certificate/base.js @@ -59,7 +59,7 @@ export default class PkiCertificateBaseModel extends Model { @attr('string', { label: 'Subject Alternative Names (SANs)', subText: - 'The requested Subject Alternative Names; if email protection is enabled for the role, this may contain email addresses. Add one per row.', + 'The requested Subject Alternative Names; if email protection is enabled for the role, this may contain email addresses.', editType: 'stringArray', }) altNames; @@ -67,20 +67,18 @@ export default class PkiCertificateBaseModel extends Model { // SANs below are editType: stringArray from openApi @attr('string', { label: 'IP Subject Alternative Names (IP SANs)', - subText: 'Only valid if the role allows IP SANs (which is the default). Add one per row.', + subText: 'Only valid if the role allows IP SANs (which is the default).', }) ipSans; @attr('string', { label: 'URI Subject Alternative Names (URI SANs)', - subText: - 'If any requested URIs do not match role policy, the entire request will be denied. Add one per row.', + subText: 'If any requested URIs do not match role policy, the entire request will be denied.', }) uriSans; @attr('string', { - subText: - 'Requested other SANs with the format ;UTF8: for each entry. Add one per row.', + subText: 'Requested other SANs with the format ;UTF8: for each entry.', }) otherSans; diff --git a/ui/app/models/pki/issuer.js b/ui/app/models/pki/issuer.js index 427221549..96ea66864 100644 --- a/ui/app/models/pki/issuer.js +++ b/ui/app/models/pki/issuer.js @@ -107,7 +107,7 @@ export default class PkiIssuerModel extends Model { @attr('string', { subText: - 'The URL values for the Issuing Certificate field. These are different URLs for the same resource, and should be added individually, not in a comma-separated list.', + 'The URL values for the Issuing Certificate field; these are different URLs for the same resource.', editType: 'stringArray', }) issuingCertificates; diff --git a/ui/app/models/pki/role.js b/ui/app/models/pki/role.js index b4afd4305..f27245613 100644 --- a/ui/app/models/pki/role.js +++ b/ui/app/models/pki/role.js @@ -159,7 +159,7 @@ export default class PkiRoleModel extends Model { /* Overriding OpenApi Domain handling options */ @attr({ label: 'Allowed domains', - subText: 'Specifies the domains this role is allowed to issue certificates for. Add one item per row.', + subText: 'Specifies the domains this role is allowed to issue certificates for.', editType: 'stringArray', }) allowedDomains; @@ -196,7 +196,7 @@ export default class PkiRoleModel extends Model { /* Overriding API Policy identifier option */ @attr({ label: 'Policy identifiers', - subText: 'A comma-separated string or list of policy object identifiers (OIDs). Add one per row. ', + subText: 'A list of policy object identifiers (OIDs).', editType: 'stringArray', }) policyIdentifiers; @@ -213,7 +213,7 @@ export default class PkiRoleModel extends Model { @attr({ label: 'URI Subject Alternative Names (URI SANs)', - subText: 'Defines allowed URI Subject Alternative Names. Add one item per row', + subText: 'Defines allowed URI Subject Alternative Names.', editType: 'stringArray', docLink: '/vault/docs/concepts/policies', }) @@ -229,7 +229,7 @@ export default class PkiRoleModel extends Model { @attr({ label: 'Other SANs', - subText: 'Defines allowed custom OID/UTF8-string SANs. Add one item per row.', + subText: 'Defines allowed custom OID/UTF8-string SANs.', editType: 'stringArray', }) allowedOtherSans; diff --git a/ui/app/models/pki/urls.js b/ui/app/models/pki/urls.js index 528f1286d..76bfa7e22 100644 --- a/ui/app/models/pki/urls.js +++ b/ui/app/models/pki/urls.js @@ -20,7 +20,7 @@ export default class PkiUrlsModel extends Model { @attr({ label: 'Issuing certificates', subText: - 'The URL values for the Issuing Certificate field. These are different URLs for the same resource, and should be added individually, not in a comma-separated list.', + 'The URL values for the Issuing Certificate field; these are different URLs for the same resource.', showHelpText: false, editType: 'stringArray', }) diff --git a/ui/app/styles/core/forms.scss b/ui/app/styles/core/forms.scss index 5a0c471d4..a705cea9f 100644 --- a/ui/app/styles/core/forms.scss +++ b/ui/app/styles/core/forms.scss @@ -341,6 +341,10 @@ fieldset.form-fieldset { border: none; } +.has-warning-border { + border: 1px solid $yellow-500; +} + .has-error-border, select.has-error-border { border: 1px solid $red-500; diff --git a/ui/app/utils/openapi-to-attrs.js b/ui/app/utils/openapi-to-attrs.js index 4a8311d8f..9ad5227ff 100644 --- a/ui/app/utils/openapi-to-attrs.js +++ b/ui/app/utils/openapi-to-attrs.js @@ -16,12 +16,23 @@ export const expandOpenApiProps = function (props) { if (deprecated === true) { continue; } - let { name, value, group, sensitive, editType } = prop['x-vault-displayAttrs'] || {}; + let { + name, + value, + group, + sensitive, + editType, + description: displayDescription, + } = prop['x-vault-displayAttrs'] || {}; if (type === 'integer') { type = 'number'; } + if (displayDescription) { + description = displayDescription; + } + editType = editType || type; if (format === 'seconds') { @@ -50,8 +61,8 @@ export const expandOpenApiProps = function (props) { attrDefn.sensitive = true; } - //only set a label if we have one from OpenAPI - //otherwise the propName will be humanized by the form-field component + // only set a label if we have one from OpenAPI + // otherwise the propName will be humanized by the form-field component if (name) { attrDefn.label = name; } diff --git a/ui/lib/core/addon/components/form-field.hbs b/ui/lib/core/addon/components/form-field.hbs index 895cd019c..212671a3c 100644 --- a/ui/lib/core/addon/components/form-field.hbs +++ b/ui/lib/core/addon/components/form-field.hbs @@ -209,12 +209,11 @@ {{else if (eq @attr.options.sensitive true)}} {{! Masked Input }} diff --git a/ui/lib/core/addon/components/string-list.hbs b/ui/lib/core/addon/components/string-list.hbs index b27d8386b..9ce556a0d 100644 --- a/ui/lib/core/addon/components/string-list.hbs +++ b/ui/lib/core/addon/components/string-list.hbs @@ -9,8 +9,8 @@ {{#if @label}} {{#if @subText}} @@ -19,15 +19,12 @@

{{/if}} {{/if}} - {{#if @warning}} - - {{/if}} {{#each this.inputList as |data index|}}