Secret updates through ServiceNow, applied automatically

A requester submits the AWS Secrets Manager form. Once it is approved, a Lambda validates the request, updates the secret in the target account, and writes the outcome back to the ticket.

Environment
UAT (ServiceNow test instance, AWS accounts a0023 and a0189)
Where it stands
Core flow tested
Production date
To be confirmed. After the UAT review and the final input test.

UAT status

  • All test cases are tested in UAT and everything is working as expected.
  • Alerts (CloudWatch alarm and SNS) and the scheduler are not set up in UAT. They will be set up in production.
  • The UAT review is pending.
  • Next: once we finalise how input values are passed, we test that final input format in UAT, then move to production.

Architecture

The approved design has four parts: ServiceNow holds the request, a Lambda in a central automation account does the work, a role in the target account lets the Lambda change one secret, and logging and alerts record what happened. Nobody handles the secret values by hand.

Architecture diagram. A requester and approver use ServiceNow. An EventBridge Scheduler triggers a Lambda in the central automation account. The Lambda reads ServiceNow credentials from Secrets Manager, queries ServiceNow, assumes SecretUpdaterRole in the member account through STS, updates the target secret, and writes work notes back to ServiceNow. Logs go to CloudWatch with an alarm that notifies SNS. CloudFormation StackSets deploys the role to every member account.
Approved architecture. Step numbers match the table below.
StepWhat happensIn our build
0One time: CloudFormation StackSets deploys SecretUpdaterRole to every member account.Not yet The UAT role was created manually in a0189.
1The requester submits the request in ServiceNow and the approver approves it.Working In UAT, the ServiceNow team sets Approved from the backend.
2EventBridge Scheduler triggers the Lambda every 5 to 15 minutes.Production only Not needed in UAT, where the Lambda is triggered manually. Set up with the production resources.
3The Lambda reads the ServiceNow credentials from Secrets Manager.Working
4The Lambda queries approved requests and works through each one.Working Reads the custom form table.
5The Lambda assumes the update role in the target account through STS.Working Tested against a0189.
6The role checks the secret, merges the requested keys, and writes the new value. CloudTrail in the member account records it.Working Keys added without touching the others.
7The Lambda adds work notes and closes the request, or marks it failed.Working Work in progress, Closed and Cancelled all confirmed.
8Logs go to CloudWatch, and an error alarm notifies SNS.Partly Lambda logs exist. The alarm and SNS topic are set up with the production resources, not in UAT.

Where the build differs from the diagram

  • The form is a custom application table, not a catalog RITM, so the Lambda reads that table directly.
  • The Lambda validates a request before moving it to Work in progress. A request with a problem goes straight to Cancelled, so a ticket never sits in progress for something that was wrong from the start.
  • Cancelled is a second outcome next to Closed. The work note lists everything that was wrong, and the ServiceNow team handles those requests.
  • The target account is derived from the secret name (aws-a0xxx-use1-...) and cross-checked against the form, so users enter a0xxx and no region field is needed.

What is provisioned in UAT

ComponentWhereDetailsStatus
Main Lambdaa0023 (954473325746)Secret-update. Polls approved requests, validates, updates the secret, writes back to ServiceNow.Provisioned
Lambda execution rolea0023Secret-update-role-lnplog68. May assume the update role and read the ServiceNow credentials.Provisioned
ServiceNow credentialsa0023, Secrets ManagerIntegration user's credentials, read by the Lambda at run time.Provisioned
Secret update rolea0189 (786061192357)secret-manager-update-shruti01. Trusts only the Lambda's execution role. Production uses SecretUpdaterRole rolled out by StackSets.Provisioned
Target accounta0189The account whose secret is updated.Provisioned
Secret Managera0189, us-east-1aws-a0189-use1-00-d-test-demo01Provisioned
ServiceNow formUAT instanceTable x_zsaip_aws_secr_0_aws_secrets_manager, built by the ServiceNow team.Provisioned
Test requestServiceNowAWS0001059 | AWS Secrets Manager | ZSProvisioned
Where the Lambda checksServiceNowApproved requests in AWS Secrets Managers | ZSProvisioned
SchedulerProductionEventBridge Scheduler, every 5 to 15 minutes. Not needed in UAT, where runs are manual.Production only
Alarm and alertsProductionCloudWatch alarm on errors, SNS topic for failure alerts. Not needed in UAT.Production only
Role rolloutManagement accountStackSets deploying the update role to all member accounts.Not yet

Everything above is UAT. Production-ready resources are provisioned after go-live, once validation is complete in UAT (see When it goes to production).

Try a request

Pick a scenario to see what the automation does and which work note lands on the ticket. The notes are the same text the Lambda writes.

Scenario

Test cases in UAT

These cases ran through the Lambda against the UAT ServiceNow instance, and each one behaved as expected. Select a screenshot to enlarge it.

CaseRequestWhat was submittedResult
Valid requestAWS0001079Existing secret, two key/value pairsClosed Both keys added, completion note written
Secret doesn't existAWS0001080Correct name format, but no such secret in a0189Cancelled Nothing changed in AWS, work note explains why
Bad name and no pairsAWS0001076Secret name jhgf, no key/valuesCancelled Both problems listed in one note
No key/value pairsAWS0001069Valid name, key/value box emptyCancelled Note says no key/value pairs were provided

Case 1: valid request, closed by the automation

Request
AWS0001079 | AWS Secrets Manager | ZS
AWS Account
a0189
Secret Manager Name
aws-a0189-use1-00-d-test-demo01
Key/values
12345 = numbers, K = Shrutika
Outcome
Work in progress then Closed. Both keys were added to the secret.
AWS0001079 is Closed. The Activities list shows the two work notes the automation wrote.

AWS Secret Manager (integration user)Work notes, 2026-10-29 02:41:29

All inputs were validated and secret 'aws-a0189-use1-00-d-test-demo01' (a0189, us-east-1) can be updated. Keys to add: 12345, K. Keys to update: none. Updating now.

AWS Secret Manager (integration user)Work notes, 2026-10-29 02:41:29

Completed by automation. Values were added/updated in secret 'aws-a0189-use1-00-d-test-demo01' (a0189, us-east-1). Keys added: 12345, K. Keys updated: none.

Case 2: secret doesn't exist, cancelled by the automation

Request
AWS0001080 | AWS Secrets Manager | ZS
AWS Account
a0189
Secret Manager Name
aws-a0189-use1-00-d-shru-demo02 (does not exist)
Key/values
shdisocdsckdsv = secret, swdbhewfhkjfark.com = number_endpoint
Outcome
Cancelled with a work note. The name and keys were valid, so the Lambda checked AWS, found no such secret, and changed nothing.
AWS0001080 is Cancelled. The work note says what was wrong and asks for the request to be corrected and resubmitted.

AWS Secret Manager (integration user)Work notes, 2026-10-29 02:59:47

Request cancelled by automation. No changes were made to the secret.
Problems found:
1. Secret 'aws-a0189-use1-00-d-shru-demo02' does not exist in account a0189 (us-east-1)
Please correct the request details and resubmit, or contact the Cloud team.

Case 3: no key/value pairs, cancelled before AWS is touched

Request
AWS0001069
AWS Account
a0189
Secret Manager Name
aws-a0189-use1-00-d-shru-app01
Key/values
None provided
Outcome
Cancelled straight from the input checks, with no AWS calls made.
AWS0001069 is Cancelled. The work note lists the one problem found.

Cancelled scenarios

A request is cancelled as soon as any of these is found. All problems found are listed together in the work note, and no secret values are ever written to notes or logs.

Input problems (no AWS calls made)

  • Secret name isn't in the format aws-a0xxx-<use1|usw2|apne1|euw1>-...
  • AWS Account is empty or isn't a single a0xxx code
  • AWS Account doesn't match the account in the secret name
  • Region isn't allowed (us-east-1, us-west-2, ap-northeast-1, eu-west-1)
  • Account isn't onboarded to the automation
  • Key/value pairs are missing, unreadable, invalid JSON or duplicated
  • A key name is invalid or a value is empty

AWS pre-flight (nothing changed yet)

  • The update role is missing or not trusted in the target account
  • The secret doesn't exist in that account and region
  • The secret can't be read (permissions, tag or KMS)
  • The secret is scheduled for deletion or managed by an AWS service
  • The secret isn't a JSON key/value secret

During the update

  • The update itself fails. The note asks for the secret's value to be verified.

Not cancelled

  • Temporary AWS errors (throttling, network): the request stays Approved and is retried on the next poll
  • Values already in the secret: closed with a "no change needed" note
  • A valid but wrong secret: the automation can't tell, so the approver is the control

Form fields used

Form fieldBackend fieldUsed for
NumbernumberRequest number, also the CloudTrail session name
AWS Accountaws_nameAccount code (a0xxx), cross-checked against the secret name
Secret Manager Nameresource_nameSecret name, which also supplies the account code and region
Secret Value And Keyvalue_and_keyKey/value pairs (ServiceNow table text or JSON)
StatestateApproved, Work in progress, Closed, Cancelled
WorknotesworknotesAutomation notes

Security design

Configuration

Set as Lambda environment variables.

VariablePurpose
SN_SECRET_IDSecret holding the ServiceNow credentials
SN_TABLE, SN_QUERYTable to read and the filter for approved requests
F_ACCOUNT, F_SECRET_NAME, F_PAIRS, F_NUMBER, F_WORKNOTESBackend field names
ACCOUNT_MAP_JSONMaps account code to 12-digit account ID (UAT: a0189 only)
TARGET_ROLE_NAMERole assumed in the target account
ALLOWED_REGIONSRegion allowlist
DRY_RUNtrue validates and reports only. false makes real changes.
WRITEBACKtrue updates the ServiceNow request
STATE_IN_PROGRESS, STATE_CLOSED, STATE_CANCELLEDState text written back
CLEAR_PAIRSOptionally blanks the key/value field after completion

Where we hit issues

IssueWhat happened and what we didStatus
Key/value not populatingNew requests (e.g. AWS0001070, AWS0001071) stopped carrying the secret key and value, whether typed as plain text or entered through the key/value box. The ServiceNow team fixed it. New requests carry their key/values again, and AWS0001079 ran end to end.Resolved
Values visible in ServiceNowSecret values appear in plain text on the request and in its Activities history. Needs masked fields, auditing off for them, and ACLs from the ServiceNow team.Open
Approval in UATApproval emails don't work in the UAT environment. The ServiceNow team sets requests to Approved from the backend, and the Lambda doesn't care who set it.Workaround
Request tableThe form is a custom table, not a catalog RITM. We changed the Lambda to read it directly and added a read-only inspect mode to find the backend field names.Resolved
Trust policy principalA Lambda function ARN can't be a trust principal. We used the Lambda's execution role ARN, including its /service-role/ path.Resolved
AssumeRole AccessDeniedCross-account access needs permission on both sides. We checked the Lambda role with the IAM policy simulator and corrected the trust policy on the update role.Resolved
Account lookupsts:AssumeRole needs the 12-digit account ID, but users enter a0xxx. The code comes from the secret name and is mapped to the ID. The map holds only the UAT account so far.Resolved for UAT
Key/value formatThe form produces a text table. We added a parser, JSON is also accepted, and several keys are merged into the existing secret.Resolved
State textServiceNow stores state in lowercase (work in progress). A strict comparison wrongly rejected a successful update, so the check ignores case.Resolved
Environment updatesThe CLI replaces all variables on every update, which wiped existing ones. Updates now merge into the current configuration.Resolved

How far along

All UAT test cases are tested and working as expected. The UAT review is pending.

Next step: complete the UAT review, finalise how input values are passed, test that final format in UAT, then move to production.

Not covered in UAT

  • Alerts (the CloudWatch alarm and SNS failure alerts) are not set up in UAT. They will be set up in production.
  • The EventBridge Scheduler is not used in UAT, where the Lambda is run by hand. It is set up with the production resources.
  • Email triggers for approval and for case closure are not tested. They are not supported in UAT yet.
  • Requests are moved to Approved from the backend in UAT instead.

When it goes to production

Target date: to be confirmed

Next step: complete the UAT review, finalise how input values are passed, test that final format in UAT, then move to production.

Before go-live

After go-live

Waiting on others: the UAT review, the decision on how input values are passed, the ServiceNow team for field security, and the approvers for promoting the application to production.