diff --git a/.github/workflows/generate-email-signature.yml b/.github/workflows/generate-email-signature.yml new file mode 100644 index 0000000..8f38df3 --- /dev/null +++ b/.github/workflows/generate-email-signature.yml @@ -0,0 +1,47 @@ +name: Generate eMail Template +on: + workflow_dispatch: + +jobs: + generate-email-signature: + name: Generate eMail Signature + runs-on: ubuntu-latest + permissions: + # Ignore validation error - this line is necessary + id-token: write + contents: read + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js 18.x + uses: actions/setup-node@v1 + with: + node-version: 18.x + - name: Populate conf.json + working-directory: templates/${{ env.THEME }} + env: + EMAIL_ADDRESS: ${{ secrets.EMAIL_ADDRESS }} + MOBILE_PHONE_COUNTRY_CODE: ${{ secrets.MOBILE_PHONE_COUNTRY_CODE }} + MOBILE_PHONE_NUMBER: ${{ secrets.MOBILE_PHONE_NUMBER }} + THEME: dark + run: | + npm run generate:conf ${{ env.THEME }} + - name: Install NPM and Generate Signature + run: | + npm -v + node -v + npm install + npm run once + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ secrets.GH_GENERATE_EMAIL_ROLE }} + aws-region: eu-central-1 + - name: Upload Signature to S3 + env: + bucket_name: ${{ secrets.BUCKET_NAME }} + local_source_dir: './dist' + remote_dir: generated-email-signatures + run: | + aws s3 cp --recursive $local_source_dir s3://$bucket_name/$remote_dir diff --git a/README.md b/README.md index 5292be7..4e9f198 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Here are some examples: - Run `npm install` - Run `npm start` to generate templates from configuration. This will continue to watch your files and re-make the template until you exit. +> #### 🪄 Building templates can be automated in S3 - [get started here](#automate-signature-creation). + ### Customizing templates - Edit files in _/templates_ @@ -48,6 +50,7 @@ Writing HTML emails & email signatures sucks. Let's make it easier. We can't fix - [x] supports LESS / SASS / PostCSS - [x] autoprefixer, so you don't have to worry about your `-moz-`s or `-webkit-`s - [x] linting, checks for used template config parameters and more! +- [x] allows automatic build & deployment of templates to S3 \*_Some mail clients might have [hard limits](https://support.google.com/a/answer/176652?hl=en) regarding the email size, so don't include large images if possible. If you need to, use a URL instead and host the image somewhere else._ @@ -174,6 +177,29 @@ There's one convention you have to keep in mind: `all files that you wish to inc You are of course encouraged to change the default structure for your use case. +## Automate Signature Creation + +Use the Github Actions Workflow to automatically generate and store your signature in a cloud storage (e.g. S3 Bucket) + +1) Create the bucket to store the signature using [AWS CLI](https://aws.amazon.com/cli/): + + `aws s3 mb s3://` + + > *where BUCKET_NAME is the unique name of your s3 bucket* + +2) Deploy the role with permission to upload signature into your accounts S3 Bucket + + `aws cloudformation deploy --template-file cicd/github_generate_email_role.yaml --stack-name githubOidcGenerateEmail --capabilities CAPABILITY_NAMED_IAM` + + > *details on [Github's OIDC with AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)* + +3) Populate the secret values `EMAIL_ADDRESS`, `MOBILE_PHONE_COUNTRY_CODE`, `BUCKET_NAME`, `MOBILE_PHONE_NUMBER`, and `GH_GENERATE_EMAIL_ROLE` in [the repo's settings tab](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository). + +4) Trigger the [`generate-email-signature`](./.github/workflows/generate-email-signature.yml) workflow via [manual dispatch](https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/) + +5) Congrats! 🥳 Your signature has been uploaded. You can now download it from your S3 Bucket. + + ## Overview of the build process The diagram below shows what happens to your email templates. diff --git a/cicd/get_github_oidc_thumbprint.sh b/cicd/get_github_oidc_thumbprint.sh new file mode 100644 index 0000000..a2af36e --- /dev/null +++ b/cicd/get_github_oidc_thumbprint.sh @@ -0,0 +1,7 @@ +HOST=$(curl https://token.actions.githubusercontent.com/.well-known/openid-configuration | jq -r '.jwks_uri | split("/")[2]') + +echo | openssl s_client -servername $HOST -showcerts -connect $HOST:443 2> /dev/null \ + | sed -n -e '/BEGIN/h' -e '/BEGIN/,/END/H' -e '$x' -e '$p' | tail +2 \ + | openssl x509 -fingerprint -noout \ + | sed -e "s/.*=//" -e "s/://g" \ + | tr "ABCDEF" "abcdef" diff --git a/cicd/github_generate_email_role.yaml b/cicd/github_generate_email_role.yaml new file mode 100644 index 0000000..624f38c --- /dev/null +++ b/cicd/github_generate_email_role.yaml @@ -0,0 +1,65 @@ +Parameters: + GitHubOrg: + Type: String + Default: + RepoName: + Type: String + Default: + OIDCProviderArn: + Description: Arn for the GitHub OIDC Provider. + Default: "" + Type: String + +Conditions: + CreateOIDCProvider: !Equals + - !Ref OIDCProviderArn + - "" + +Resources: + Role: + Type: AWS::IAM::Role + Properties: + RoleName: GithubGenerateEmailRole + Policies: + - PolicyName: GithubGenerateEmailRolePolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - s3:PutObject + - s3:PutObjectAcl + - s3:GetObject + - s3:GetObjectAcl + - s3:AbortMultipartUpload + Resource: + - arn:aws:s3::: + - arn:aws:s3:::/* + Effect: Allow + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Sid: "GithubOIDC" + Action: sts:AssumeRoleWithWebIdentity + Principal: + Federated: !If + - CreateOIDCProvider + - !Ref GithubOidc + - !Ref OIDCProviderArn + Condition: + StringLike: + token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepoName}:* + + + GithubOidc: + Type: AWS::IAM::OIDCProvider + Condition: CreateOIDCProvider + Properties: + Url: https://token.actions.githubusercontent.com + ClientIdList: + - sts.amazonaws.com + ThumbprintList: + - 6938fd4d98bab03faadb97b34396831e3780aea1 + +Outputs: + Role: + Value: !GetAtt Role.Arn diff --git a/generate-conf.json.sh b/generate-conf.json.sh new file mode 100644 index 0000000..53ae9d5 --- /dev/null +++ b/generate-conf.json.sh @@ -0,0 +1,25 @@ +#!bin/sh + +# script for dynamic interactive creation of conf.json file + +# If variable not set or null, set to some exemplary defaults. +theme="${1:-light}" +mobile_phone_country_code="${2:-45}" +mobile_phone_number="${3:-80100100}" +email_address="${4:-info@${theme}.dk}" + +echo $theme + +conf_file_path="./templates/$theme/conf.json" +touch $conf_file_path +echo { > $conf_file_path +echo "\"id"\": "\"$theme"\", >> $conf_file_path +echo "\"signature"\": "\"Best regards,"\", >> $conf_file_path +echo "\"name"\": "\"The $theme mail team"\", >> $conf_file_path +echo "\"contactMain"\": "\"Call ($mobile_phone_country_code) $mobile_phone_number or email us at"\", >> $conf_file_path +echo "\"contactMail"\": "\"$email_address"\", >> $conf_file_path +echo "\"slogan"\": "\"LED Pylon. LED Wall. Digital Signage."\", >> $conf_file_path +echo "\"logoUrl"\": "\"/assets/$theme.png"\", >> $conf_file_path +echo "\"logoAlt"\": "\"$theme logo"\", >> $conf_file_path +echo "\"website"\": "\"http://$theme.dk"\" >> $conf_file_path +echo } >> $conf_file_path diff --git a/package.json b/package.json index 2118578..6e5c2d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "responsive-html-email-signature", - "version": "6.1.1", + "version": "6.2.0", "description": "Responsive template for emails & email signatures.", "main": "index.js", "repository": { @@ -26,6 +26,7 @@ "start": "./node_modules/.bin/gulp", "once": "./node_modules/.bin/gulp run-pipeline", "deploy": "npm run test && cp -r dist demo && git push origin `git subtree split --prefix demo develop`:gh-pages --force", + "generate:conf": "sh generate-conf.json.sh $THEME $MOBILE_PHONE_COUNTRY_CODE $MOBILE_PHONE_NUMBER $EMAIL_ADDRESS", "test": "npm run once && npm run _test", "test:watch": "npm run once && npm run _test:watch", "format": "./node_modules/.bin/prettier {tasks,tests}/**/*.js gulpfile.js .eslintrc.js --write",