How can I use Amazon SES with Ghost? - amazon-web-services

I saw at https://ghost.org/docs/config/#mail that SES is allowed.
But I edited my config.production.json and ran ghost restart, but Ghost still says:
Set up Mailgun to start sending newsletters!
The config I used was:
"mail": {
"from": "My Name <example#example.com>",
"transport": "SMTP",
"options": {
"host": "email-smtp.us-east-1.amazonaws.com",
"port": 465,
"service": "SES",
"auth": {
"user": "asdfadsffdsf",
"pass": "asdfasdfadfs"
}
}
},
I got the SMTP-ACCESS-KEY-ID and SES-SMTP-SECRET-ACCESS-KEY from https://us-east-1.console.aws.amazon.com/ses/home?region=us-east-1#/smtp
What did I do wrong?

I also had this issue.
I fixed it by using the below config for Ghost.
"mail": {
"transport": "SMTP",
"options": {
"host": "email-smtp.us-east-1.amazonaws.com",
"port": 2465,
"secure": true,
"service": "SES",
"from": "'Name' email",
"auth": {
"user": "access-key",
"pass": "secret-access-key"
}
}
}
Notice some changes from your config:
"port": 2465,
added "secure": true,
use the IAM secret access key as it is. (Don't convert to SMTP password.)

Related

AWS Certificate Manager Pending Validation when DNS validation is successful

Resolved! - Ended up just needing to contact Amazon Support to push it through.
I'm attempting to renew a certificate created in AWS Certificate Manager (ACM), but I'm stuck in the dreadful PENDING_VALIDATION status; this is a DNS validated certificate where I validated using the CNAME record.
Under domains I can see the domain validation has a status of Success and Renewal Status of Success
If I run aws acm describe-certificate --certificate-arn "examplearn", I get a return showing DomainValidationOptions with the ValidationStatus being success for the CNAME validation.
Replaced with "example" for sensitive values
{
"Certificate": {
"CertificateArn": "arn:aws:acm:us-east-1:example:certificate/certid",
"DomainName": "*.example.com",
"SubjectAlternativeNames": [
"*.example.com"
],
"DomainValidationOptions": [
{
"DomainName": "*.example.com",
"ValidationDomain": "*.example.com",
"ValidationStatus": "SUCCESS",
"ResourceRecord": {
"Name": "examplename",
"Type": "CNAME",
"Value": "examplevalue"
},
"ValidationMethod": "DNS"
}
],
"Serial": "",
"Subject": "CN=*.example.com",
"Issuer": "Amazon",
"CreatedAt": "2019-01-17T12:53:01-08:00",
"IssuedAt": "2021-10-22T21:21:50.177000-07:00",
"Status": "ISSUED",
"NotBefore": "2021-10-22T17:00:00-07:00",
"NotAfter": "2022-11-23T15:59:59-08:00",
"KeyAlgorithm": "RSA-2048",
"SignatureAlgorithm": "SHA256WITHRSA",
"InUseBy": [
"example",
"example",
"example",
"example"
],
"Type": "AMAZON_ISSUED",
"RenewalSummary": {
"RenewalStatus": "PENDING_VALIDATION",
"DomainValidationOptions": [
{
"DomainName": "*.example.com",
"ValidationDomain": "*.example.com",
"ValidationStatus": "SUCCESS",
"ResourceRecord": {
"Name": "examplename",
"Type": "CNAME",
"Value": "examplevalue"
},
"ValidationMethod": "DNS"
}
],
"UpdatedAt": "2022-09-21T23:39:15.161000-07:00"
},
"KeyUsages": [
{
"Name": "DIGITAL_SIGNATURE"
},
{
"Name": "KEY_ENCIPHERMENT"
}
],
"ExtendedKeyUsages": [
{
"Name": "TLS_WEB_SERVER_AUTHENTICATION",
"OID": "1.3.6.1.5.5.7.3.1"
},
{
"Name": "TLS_WEB_CLIENT_AUTHENTICATION",
"OID": "1.3.6.1.5.5.7.3.2"
}
],
"RenewalEligibility": "ELIGIBLE",
"Options": {
"CertificateTransparencyLoggingPreference": "ENABLED"
}
}
}
Followed instructions successfully in https://aws.amazon.com/premiumsupport/knowledge-center/acm-certificate-pending-validation/ (checking cname response exactly matches what is in acm CNAME values when copy pasting)
The site domain registration is in Route 53 with NS pointing to cloudflare, where DNS is managed.
Is there something obvious that pops out to you? Thank you!

posixAccounts API information missing

I'm not seeing my posixAccounts information from the following link:
https://developers.google.com/admin-sdk/directory/reference/rest/v1/users/get
{
"kind": "admin#directory#user",
"id": "8675309",
"etag": "\"UUID\"",
"primaryEmail": "email#example.com",
"name": {
"givenName": "Email",
"familyName": "Account",
"fullName": "Email Account"
},
"isAdmin": true,
"isDelegatedAdmin": false,
"lastLoginTime": "2021-08-04T21:11:17.000Z",
"creationTime": "2021-06-16T14:32:35.000Z",
"agreedToTerms": true,
"suspended": false,
"archived": false,
"changePasswordAtNextLogin": false,
"ipWhitelisted": false,
"emails": [
{
"address": "email#example.com",
"primary": true
},
{
"address": "email#example.com.test-google-a.com"
}
],
"phones": [
{
"value": "123-456-7890",
"type": "work"
}
],
"nonEditableAliases": [
"email#example.com.test-google-a.com"
],
"customerId": "id12345",
"orgUnitPath": "/path/to/org",
"isMailboxSetup": true,
"isEnrolledIn2Sv": false,
"isEnforcedIn2Sv": false,
"includeInGlobalAddressList": true
}
As you can see from the above output, there's no posixAccount information. I can open the ldap information in Apache Directory studio, so I know it's there, but I can't see it from the above output. Since I can see it though, I tried to update this using the update function in the API.
https://developers.google.com/admin-sdk/directory/reference/rest/v1/users/update
I used this for the payload as I'm just testing updating the gid information. I used the documentation below to get the entry details needed. At least as far as I could tell.
{
"posixAccounts": [
{
"gid": "12345",
}
]
}
https://developers.google.com/admin-sdk/directory/reference/rest/v1/users
I'm getting a 200 response, but nothing is actually changing for the user when doing a PUT to update.
I tried a similar update method from another user on here, but no avail: Google Admin SDK - Create posix attributes on existing user
I was able to get this resolved by supplying additional details in my PUT request:
{
"posixAccounts": [
{
"username": "email(excluding #domain.com)",
"uid": "1234",
"gid": "12345",
"operatingSystemType": "unspecified",
"shell": "/bin/bash",
"gecos": "Firstname Lastname"
"systemId": ""
}
]
}
The above wouldn't reflect in LDAP until I put "systemId" in there. So that part is required.

10060 error when connecting MariaDB on VM on Compute Engine of Google Cloud Platform

Created a VM on Compute Engine of Google Cloud Platform.
Installed Maria DB. Configured binding to 0.0.0.0.
Created a firewall rule to allow access to 3306 in the IP ranged 0.0.0.0/0. Tagged it as "mysql-open" and Added it as a network tag in the VM instance detail. I also chose the option to log the connection.
When I try to connect from MySQL workbench to the public address of the VM Instance with 3306 as the Port, I get a
10060 error.
The user ID used to connect was given full GRANT and was like 'testuser'#'%'.
Below is the log entry. Which seems to show that the firewall rule worked.
"insertId": "epk9z8g1zjxknf",
"jsonPayload": {
"instance": {
"project_id": "XXXX",
"vm_name": "XXX",
"region": "us-east4",
"zone": "us-east4-c"
},
"connection": {
"src_port": 44826,
"dest_ip": "10.150.0.5",
"protocol": 6,
"dest_port": 3306,
"src_ip": "198.199.98.246"
},
"remote_location": {
"city": "San Francisco",
"continent": "America",
"country": "usa",
"region": "California"
},
"rule_details": {
"priority": 2000,
"ip_port_info": [
{
"port_range": [
"3306"
],
"ip_protocol": "TCP"
}
],
"source_range": [
"0.0.0.0/0"
],
"reference": "network:default/firewall:mysql-open",
"action": "ALLOW",
"direction": "INGRESS"
},
"vpc": {
"project_id": "XXXX",
"vpc_name": "default",
"subnetwork_name": "default"
},
"disposition": "ALLOWED"
},
"resource": {
"type": "gce_subnetwork",
"labels": {
"subnetwork_id": "2510359252254555075",
"project_id": "XXXX",
"subnetwork_name": "default",
"location": "us-east4-c"
}
},
"timestamp": "2020-11-05T14:12:33.819891417Z",
"logName": "projects/XXXX/logs/compute.googleapis.com%2Ffirewall",
"receiveTimestamp": "2020-11-05T14:12:39.166067521Z"
}

User model giving email validation error in loopback3

I have created a model MyUser based on the User model as follows:
{
"name": "MyUser",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"ownerRelations": true,
"emailVerificationRequired": true,
"hidden": [
"email",
"emailVerified"
],
"properties": {
"firstName": {
"type": "string",
"required": true
},
"lastName": {
"type": "string",
"required": true
},
"email": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"accessTokens": {
"type": "hasMany",
"model": "CustomAccessToken",
"polymorphic": {
"foreignKey": "userId",
"discriminator": "principalType"
},
"options": {
"disableInclude": true
}
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"property": "create"
}
],
"methods": {}
}
It works perfectly on my local server. But when I host it on aws ec2, only the first time user is created. Next time even if I give different email id, I get email verification error as follows:
The 'MyUser' instance is not valid. Details:emailEmail already exists (value: undefined).
Now if I delete the 1st record and try to create user, it works. So, only 1st record is getting inserted and post that for any unique email also, I am getting validation error. I am not sure why this is happening.
I was able to figure out the problem. I have kept email as a hidden field. loopback has "prohibitHiddenPropertiesInQuery": true by default which does not allow hidden properties in query. As a result, during user validation, email was ignored in the query in loopback-juggler/lib/validation.js. Upon setting prohibitHiddenPropertiesInQuery to false, it works.
However, I am still not sure why it was working in development mode on my local server. prohibitHiddenPropertiesInQuery is by default true, so it should not have worked in development mode also. If anyone have any answer to this, please do let me know.

AWS API Gateway Custom Authorizer with Proxy setup - Add Custom Headers to Request

What I have:
AWS API gateway setup as a proxy (/{proxy+})
A custom Auth function which authorizes the incoming request for this proxy setup.
The custom auth function is passing the additional information I want to pass along to the request via the "context" object, like so:
{
"principalId": "yyyyyyyy",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "some arn"
}
]
},
"context": {
"customInfo1": "hello",
"customInfo2": "world"
}
}
What I need:
I need to pass the custom information passed in the context object above into custom headers into the request as it passes along to the target function.
What I know:
If this wasn't a proxy, I could have used a mapping template to get the desired result.
If you check this document, you will find you can create a custom Model to map from body to header and vice versa. You can then assign this model under Method Request -> Request Body.
Figured it out, AWS passes this to Lambda when configured as a proxy:
{
"resource": "/{proxy+}",
"path": "/echo",
"httpMethod": "POST",
"headers": {
"Accept-Type": "application/json",
"Authorization": "Bearer xxx",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "IN",
"Content-Type": "application/json",
"Host": "yyy.execute-api.us-east-1.amazonaws.com",
"User-Agent": "Fiddler",
"Via": "1.1 aaa.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "uuu",
"X-Amzn-Trace-Id": "Root=1-58e5w17a-58ff31a846954e0f2aa7cd2c",
"X-Forwarded-For": "115.112.36.246, 54.182.242.113",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"queryStringParameters": null,
"pathParameters": {
"proxy": "echo"
},
"stageVariables": null,
"requestContext": {
"accountId": "1234567890",
"resourceId": "1t2w8a",
"stage": "dev",
"authorizer": {
"customKey": "1",
"eee": "1",
"principalId": "2",
"otherkey": "hello",
"somekey": "1,2"
},
"requestId": "qqq",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"apiKey": null,
"sourceIp": "aaa.bbb.qq.www",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Fiddler",
"user": null
},
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"apiId": "123"
},
"body": "{\"ola\": \"\"}",
"isBase64Encoded": false
}
In the requestContext section above, all the keys that I passed via my custom authorizer is already present.