mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-09-30 05:33: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
|
SLACK_BOT_TOKEN_SECRET: afterhours-shift-manager/slack-bot-token
|
||||||
SHIFT_CHANNEL: !Ref ShiftChannel
|
SHIFT_CHANNEL: !Ref ShiftChannel
|
||||||
SES_SENDER: noreply@seahaven.com
|
SES_SENDER: noreply@seahaven.com
|
||||||
PAYROLL_RECIPIENTS: payroll@seahaven.com
|
PAYROLL_RECIPIENTS: ""
|
||||||
PAY_REPORT_USER: U0A3SC48T47
|
PAY_REPORT_USER: U0A3SC48T47
|
||||||
TZ: !Ref Timezone
|
TZ: !Ref Timezone
|
||||||
CHECKCOMPONENTS_QUEUE_URL: !Ref CheckcomponentsQueueUrl
|
CHECKCOMPONENTS_QUEUE_URL: !Ref CheckcomponentsQueueUrl
|
||||||
|
|
@ -180,30 +180,6 @@ Resources:
|
||||||
- secretsmanager:GetSecretValue
|
- secretsmanager:GetSecretValue
|
||||||
Resource:
|
Resource:
|
||||||
- !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:afterhours-shift-manager/slack-bot-token-*"
|
- !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
|
- Effect: Allow
|
||||||
Action:
|
Action:
|
||||||
- sqs:SendMessage
|
- sqs:SendMessage
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"""Tests for the weekly-post Lambda handler orchestration."""
|
"""Tests for the weekly-post Lambda handler orchestration."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from pathlib import Path
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
@ -253,3 +254,24 @@ def test_payload_skips_fallback_and_zero(weeklypost_app):
|
||||||
assert payload["windowEnd"] == "2026-06-07"
|
assert payload["windowEnd"] == "2026-06-07"
|
||||||
assert payload["lines"] == [{"extension": "114", "amount": "75.50"}]
|
assert payload["lines"] == [{"extension": "114", "amount": "75.50"}]
|
||||||
assert "payPeriodId" not in payload
|
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