mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-09-30 03:23:12 +00:00
chore(pay): disable weekly-post payroll SES email (PLAT-135) (#248)
Empty PAYROLL_RECIPIENTS and drop ses:SendEmail so Monday Slack posts stay, SES pay mail stops.
This commit is contained in:
parent
23bad9bee6
commit
2dbe99ef0b
2 changed files with 23 additions and 25 deletions
|
|
@ -166,7 +166,7 @@ Resources:
|
|||
SLACK_BOT_TOKEN_SECRET: afterhours-shift-manager/slack-bot-token
|
||||
SHIFT_CHANNEL: !Ref ShiftChannel
|
||||
SES_SENDER: noreply@seahaven.com
|
||||
PAYROLL_RECIPIENTS: payroll@seahaven.com
|
||||
PAYROLL_RECIPIENTS: ""
|
||||
PAY_REPORT_USER: U0A3SC48T47
|
||||
TZ: !Ref Timezone
|
||||
CHECKCOMPONENTS_QUEUE_URL: !Ref CheckcomponentsQueueUrl
|
||||
|
|
@ -180,30 +180,6 @@ Resources:
|
|||
- secretsmanager:GetSecretValue
|
||||
Resource:
|
||||
- !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:afterhours-shift-manager/slack-bot-token-*"
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- ses:SendEmail
|
||||
Resource:
|
||||
# The From address (noreply@seahaven.com) is NOT a standalone
|
||||
# verified SES identity — it is covered by the verified DOMAIN
|
||||
# identity seahaven.com, which is the identity SES authorizes
|
||||
# SendEmail against. Granting identity/noreply@seahaven.com (a
|
||||
# non-existent identity) caused AccessDenied; the domain ARN is
|
||||
# the correct least-privilege resource. Scoped to this one domain,
|
||||
# not identity/* (every identity in the account).
|
||||
- !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/seahaven.com"
|
||||
# The sending identity has a default configuration set
|
||||
# (seahaven-email-events); SES authorizes SendEmail against the
|
||||
# config-set resource too, so it must be granted alongside the
|
||||
# identity or the send is denied. Scoped to the known set name.
|
||||
- !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:configuration-set/seahaven-email-events"
|
||||
# The domain identity covers every address under seahaven.com, so
|
||||
# without this the role could send-as any @seahaven.com mailbox.
|
||||
# Pin the From to the one legitimate sender (matches SES_SENDER) so
|
||||
# a compromised function can't spoof internal senders (BEC).
|
||||
Condition:
|
||||
StringEquals:
|
||||
ses:FromAddress: noreply@seahaven.com
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- sqs:SendMessage
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Tests for the weekly-post Lambda handler orchestration."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
|
@ -253,3 +254,24 @@ def test_payload_skips_fallback_and_zero(weeklypost_app):
|
|||
assert payload["windowEnd"] == "2026-06-07"
|
||||
assert payload["lines"] == [{"extension": "114", "amount": "75.50"}]
|
||||
assert "payPeriodId" not in payload
|
||||
|
||||
|
||||
def test_send_pay_email_skips_when_recipients_empty(weeklypost_app, monkeypatch):
|
||||
monkeypatch.setenv("PAYROLL_RECIPIENTS", "")
|
||||
ses = MagicMock(name="ses")
|
||||
|
||||
def client(svc, **kw):
|
||||
if svc == "ses":
|
||||
return ses
|
||||
return MagicMock(name=svc)
|
||||
|
||||
monkeypatch.setattr(weeklypost_app.boto3, "client", client)
|
||||
weeklypost_app._send_pay_email("Jun 1 to Jun 7", {"totals": {}, "breakdown": []})
|
||||
ses.send_email.assert_not_called()
|
||||
|
||||
|
||||
def test_weekly_post_payroll_recipients_empty_and_no_ses_grant():
|
||||
text = (Path(__file__).resolve().parents[2] / "template.yaml").read_text()
|
||||
assert 'PAYROLL_RECIPIENTS: ""' in text
|
||||
assert "PAYROLL_RECIPIENTS: payroll@seahaven.com" not in text
|
||||
assert "ses:SendEmail" not in text
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue