NMS-19723: Mask credentials for Trapd config Rest API and UI#8511
NMS-19723: Mask credentials for Trapd config Rest API and UI#8511synqotik wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements credential masking for SNMPv3 Trapd configuration returned by REST APIs, using DTO field annotations plus a shared SecurityHelper mechanism to (a) mask secrets on GET and (b) preserve existing secrets on update when the client submits the mask. The UI is updated to use protected password inputs and to validate/accept the mask value and SCV expressions.
Changes:
- Add
@MaskedCredentialand server-sideSecurityHelper.maskCredentials/resolveCredentialssupport; annotate SNMPv3 DTO passphrase fields. - Update Trapd REST endpoints to mask passphrases on GET and to resolve masked passphrases on update/upload while keeping SCV expressions unmasked.
- Update UI validation + inputs for SNMPv3 users and add/adjust unit tests.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/tests/lib/trapdValidatorForm.test.ts | Adds unit tests for cross-field SNMPv3 validation including masking/SCV cases. |
| ui/tests/components/TrapdConfiguration/CreateSnmpV3User.test.ts | Updates component tests to match renamed error state and revised validation messaging. |
| ui/src/lib/trapdValidator.ts | Introduces shared validateSnmpV3UserForm logic including masked-password + SCV handling. |
| ui/src/lib/snmpValidator.ts | Refactors SCV prefix detection to use hasScvPrefix. |
| ui/src/lib/securityHelper.ts | Adds UI-side mask constant + helper for recognizing masked passphrases. |
| ui/src/lib/scvValidator.ts | Adds hasScvPrefix helper. |
| ui/src/components/TrapdConfiguration/CreateSnmpV3User.vue | Switches passphrase fields to FeatherProtectedInput and refactors validation error state. |
| opennms-webapp-rest/src/test/java/org/opennms/web/rest/v2/TrapdRestServiceIT.java | Adds/updates integration tests for masking, download behavior, resolve-on-update, and SCV passthrough. |
| opennms-webapp-rest/src/test/java/org/opennms/web/rest/support/SecurityHelperTest.java | Adds unit tests for masking/resolving and SCV detection logic. |
| opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/TrapdRestService.java | Masks credentials on GET and resolves masked credentials on update/upload. |
| opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/model/Snmpv3UserDto.java | Annotates passphrase fields with @MaskedCredential. |
| opennms-webapp-rest/src/main/java/org/opennms/web/rest/support/SecurityHelper.java | Adds masking + resolve helpers and SCV/mask detection. |
| opennms-webapp-rest/src/main/java/org/opennms/web/rest/support/MaskedCredential.java | Adds annotation used to mark credential fields on DTOs. |
| opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/trapd/TrapdConfiguration.java | Adds lookup helper for SNMPv3 user by security name. |
Comments suppressed due to low confidence (1)
opennms-webapp-rest/src/main/java/org/opennms/web/rest/support/SecurityHelper.java:41
isMaskedPasswordtreats any string of 2+ asterisks as a mask (\\*{2,}), while the API/UI contract uses the single canonical mask valueMASKED_PASSWORD("****"). Consider changingisMaskedPasswordto an equality check againstMASKED_PASSWORDto avoid accepting alternate masked values (e.g. "") and to keep server/client behavior consistent.
public static final Pattern pattern = Pattern.compile("\\*{2,}");
public static final String MASKED_PASSWORD = "******";
private static final Pattern SCV_PATTERN = Pattern.compile("^\\$\\{scv:.+}$");
public static void assertUserReadCredentials(SecurityContext securityContext) {
final String currentUser = securityContext.getUserPrincipal().getName();
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
073e596 to
b29ff24
Compare
b29ff24 to
9ad86cc
Compare
| this.snmpv3User = snmpv3UserList; | ||
| } | ||
|
|
||
| public Snmpv3User getSnmpv3UserBySecurityName(final String securityName) { |
There was a problem hiding this comment.
Unfortunately security name is not unique ( there can be duplicate security names in SNMPv3 config).
We may need to find other way to retrieve credentials.
There was a problem hiding this comment.
@cgorantla I think we can use securityName + engineId combo for uniqueness, I can update. Update, not so sure.
marshallmassengill
left a comment
There was a problem hiding this comment.
Seems like a good change overall. Will leave you to address the comments though.
|
|
Mask credentials in the Trap Config Rest API and UI.
Credentials (like SNMP v3 Auth Passphrase and Privacy Passphrase) are masked with
'******'when returned from Rest APIs.Annotations are used on the Java side to mark those fields, and new methods in
SecurityHelperautomatically process them. Any Rest API calls to get items will have those fields masked.If a user edits an SNMP user, if the server receives the mask, it will substitute the actual current credential we have stored in the DB/DAO. If the user wants to change the credential, the credential will be POSTed as-is and the server will know to persist the change.
The system also handles SCV expressions correctly, they are not masked. SCV is the preferred way of handling credentials.
We also reject any credentials starting with
'*'to prevent users from using the mask to bypass credential checking.Upload/download Rest APIs do not mask credentials. If needed we can protect those specific endpoints by roles if needed.
On the UI side, added
FeatherProtectedInputfields which by default mask the credential. you can click the "eye" view icon to view the credential, but only SCV expressions will be shown; any else will still be masked.The annotation and
SecurityHelperpattern can be used in other cases where we want to mask credentials.External References