diff --git a/.github/wiki/assets/images/architecture/diagram-complete.svg b/.github/wiki/assets/images/architecture/diagram-complete.svg
index e582dad5..06b104e3 100644
--- a/.github/wiki/assets/images/architecture/diagram-complete.svg
+++ b/.github/wiki/assets/images/architecture/diagram-complete.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/.github/workflows/increment-version.yml b/.github/workflows/increment-version.yml
new file mode 100644
index 00000000..66b849fd
--- /dev/null
+++ b/.github/workflows/increment-version.yml
@@ -0,0 +1,136 @@
+name: Increment version
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+ inputs:
+ newVersion:
+ description: Version to increment
+ required: true
+ default: auto
+ type: string
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ VERSION_FILE: ./package.json
+
+jobs:
+ set-next-version:
+ name: Set next version automatically
+ runs-on: ubuntu-latest
+ if: github.event_name != 'workflow_dispatch' || github.event.inputs.newVersion == 'auto'
+ outputs:
+ version: ${{ steps.set-next-version.outputs.version }}
+
+ steps:
+ - name: Checkout main
+ uses: actions/checkout@v4
+ with:
+ ref: main
+
+ - name: Get version on main
+ id: get-main-version
+ run: |
+ currentVersion=$(node -p -e "require('${{ env.VERSION_FILE }}').version")
+ echo "version=$currentVersion" >> $GITHUB_OUTPUT
+
+ - name: Checkout develop
+ uses: actions/checkout@v4
+ with:
+ ref: develop
+
+ - name: Get version on develop
+ id: get-develop-version
+ run: |
+ currentVersion=$(node -p -e "require('${{ env.VERSION_FILE }}').version")
+ echo "version=$currentVersion" >> $GITHUB_OUTPUT
+
+ - name: Set next version
+ id: set-next-version
+ env:
+ VERSION_DELIMITER: .
+ run: |
+ function ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '${VERSION_DELIMITER}' ' '); }
+
+ echo "main version: $(ver ${{ steps.get-main-version.outputs.version }})"
+ echo "develop version: $(ver ${{ steps.get-develop-version.outputs.version }})"
+
+ if [[ $(ver ${{ steps.get-main-version.outputs.version }}) -gt $(ver ${{ steps.get-develop-version.outputs.version }}) ]]; then
+ echo "main version is greater than develop version"
+
+ echo "version=${{ steps.get-main-version.outputs.version }}" >> $GITHUB_OUTPUT
+ else
+ echo "develop version is greater or equal to main version"
+
+ versionComponents=($(echo "${{ steps.get-develop-version.outputs.version }}" | tr ${VERSION_DELIMITER} '\n'))
+
+ versionComponents[1]=$((versionComponents[1]+1))
+ versionComponents[2]=0
+
+ nextVersion=$(IFS=${VERSION_DELIMITER} ; echo "${versionComponents[*]}")
+
+ echo "version=$nextVersion" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Print next version
+ run: |
+ echo "Next version: ${{ steps.set-next-version.outputs.version }}"
+
+ increment-version:
+ name: Increment version
+ runs-on: ubuntu-latest
+ needs: [set-next-version]
+ permissions:
+ contents: write
+ pull-requests: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: develop
+
+ - name: Set next version
+ id: next-version
+ run: |
+ if [ ${{ github.event_name }} != 'workflow_dispatch' ] || [ ${{ github.event.inputs.newVersion }} == 'auto' ]; then
+ echo "version=${{ needs.set-next-version.outputs.version }}" >> $GITHUB_OUTPUT
+ else
+ echo "version=${{ github.event.inputs.newVersion }}" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Change version in ${{ env.VERSION_FILE }}
+ run: |
+ jq ".version = \"${{ steps.next-version.outputs.version }}\"" ${{ env.VERSION_FILE }} > ${{ env.VERSION_FILE }}.tmp && mv ${{ env.VERSION_FILE }}.tmp ${{ env.VERSION_FILE }}
+
+ - name: Update package-lock.json
+ run: npm install
+
+ - name: Create a new pull request
+ uses: peter-evans/create-pull-request@v5
+ with:
+ token: ${{ github.token }}
+ branch: chore/bump-version-to-${{ steps.next-version.outputs.version }}
+ base: develop
+ delete-branch: true
+ title: "[Chore] Bump version to ${{ steps.next-version.outputs.version }}"
+ commit-message: "Bump version to ${{ steps.next-version.outputs.version }}"
+ labels: |
+ type : chore
+ body: |
+ ## What happened 👀
+
+ Bump version to ${{ steps.next-version.outputs.version }}
+
+ ## Insight 📝
+
+ Automatically created by the GitHub Actions workflow.
+
+ ## Proof Of Work 📹
+
+ On the Files changed tab
diff --git a/package-lock.json b/package-lock.json
index 4cfe26d7..4df7dda9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@nimblehq/infra-template",
- "version": "2.0.2",
+ "version": "2.3.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@nimblehq/infra-template",
- "version": "2.0.2",
+ "version": "2.3.0",
"license": "MIT",
"dependencies": {
"@oclif/core": "^2",
@@ -11605,9 +11605,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.0.5",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
- "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
+ "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
"dev": true,
"dependencies": {
"bs-logger": "0.x",
@@ -11616,7 +11616,7 @@
"json5": "^2.2.3",
"lodash.memoize": "4.x",
"make-error": "1.x",
- "semver": "7.x",
+ "semver": "^7.5.3",
"yargs-parser": "^21.0.1"
},
"bin": {
@@ -11630,7 +11630,7 @@
"@jest/types": "^29.0.0",
"babel-jest": "^29.0.0",
"jest": "^29.0.0",
- "typescript": ">=4.3"
+ "typescript": ">=4.3 <6"
},
"peerDependenciesMeta": {
"@babel/core": {
@@ -22239,9 +22239,9 @@
"integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="
},
"ts-jest": {
- "version": "29.0.5",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
- "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
+ "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
"dev": true,
"requires": {
"bs-logger": "0.x",
@@ -22250,7 +22250,7 @@
"json5": "^2.2.3",
"lodash.memoize": "4.x",
"make-error": "1.x",
- "semver": "7.x",
+ "semver": "^7.5.3",
"yargs-parser": "^21.0.1"
}
},
diff --git a/package.json b/package.json
index 4dbe7bf1..3f2745fc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@nimblehq/infra-template",
- "version": "2.2.0",
+ "version": "2.3.0",
"description": "Nimble Infrastructure Template generator",
"author": "Nimblehq",
"bin": {
diff --git a/src/generators/addons/aws/modules/core/iamUserAndGroup.ts b/src/generators/addons/aws/modules/core/iamUserAndGroup.ts
index 7b7af950..62111ff7 100644
--- a/src/generators/addons/aws/modules/core/iamUserAndGroup.ts
+++ b/src/generators/addons/aws/modules/core/iamUserAndGroup.ts
@@ -15,8 +15,8 @@ const iamVariablesContent = dedent`
type = list(string)
}
- variable "iam_bot_emails" {
- description = "List of bot emails to provision IAM user account"
+ variable "iam_infra_service_account_emails" {
+ description = "List of infra service account emails to provision IAM user account"
type = list(string)
}
@@ -43,35 +43,33 @@ const iamUsersModuleContent = dedent`
usernames = var.iam_developer_emails
}
- module "iam_bot_users" {
+ module "iam_infra_service_account_users" {
source = "../modules/iam_users"
- usernames = var.iam_bot_emails
+ usernames = var.iam_infra_service_account_emails
+ has_login = false
}`;
const iamGroupMembershipModuleContent = dedent`
- module "iam_admin_group_membership" {
+ module "iam_group_membership" {
source = "../modules/iam_group_membership"
- name = "admin-group-membership"
- group = module.iam_groups.admin_group
- users = var.iam_admin_emails
- }
-
- module "iam_bot_group_membership" {
- source = "../modules/iam_group_membership"
-
- name = "bot-group-membership"
- group = module.iam_groups.bot_group
- users = var.iam_bot_emails
- }
-
- module "iam_developer_group_membership" {
- source = "../modules/iam_group_membership"
-
- name = "developer-group-membership"
- group = module.iam_groups.developer_group
- users = var.iam_developer_emails
+ for_each = {
+ admin = { group = module.iam_groups.admin_group, users = var.iam_admin_emails },
+ infra_service_account = { group = module.iam_groups.infra_service_account_group, users = var.iam_infra_service_account_emails },
+ developer = { group = module.iam_groups.developer_group, users = var.iam_developer_emails }
+ }
+
+ name = "\${each.key}-group-membership"
+ group = each.value.group
+ users = each.value.users
+
+ depends_on = [
+ module.iam_groups,
+ module.iam_admin_users,
+ module.iam_developer_users,
+ module.iam_infra_service_account_users,
+ ]
}`;
const iamOutputsContent = dedent`
@@ -83,11 +81,6 @@ const iamOutputsContent = dedent`
output "iam_developer_temporary_passwords" {
description = "List of first time passwords for developer accounts. Must be changed at first time login and will no longer be valid."
value = module.iam_developer_users.temporary_passwords
- }
-
- output "iam_bot_temporary_passwords" {
- description = "List of first time passwords for bot accounts. Must be changed at first time login and will no longer be valid."
- value = module.iam_bot_users.temporary_passwords
}`;
const applyAwsIamUserAndGroup = async ({ projectName }: AwsOptions) => {
diff --git a/src/generators/addons/aws/modules/core/vpc.ts b/src/generators/addons/aws/modules/core/vpc.ts
index 0858abe9..5702bc14 100644
--- a/src/generators/addons/aws/modules/core/vpc.ts
+++ b/src/generators/addons/aws/modules/core/vpc.ts
@@ -20,6 +20,7 @@ const vpcModuleContent = dedent`
source = "../modules/vpc"
env_namespace = local.env_namespace
+ region = var.region
}`;
const applyAwsVpc = async (options: AwsOptions) => {
diff --git a/templates/addons/aws/modules/iam_groups/data.tf b/templates/addons/aws/modules/iam_groups/data.tf
index cb105971..a1e9a593 100644
--- a/templates/addons/aws/modules/iam_groups/data.tf
+++ b/templates/addons/aws/modules/iam_groups/data.tf
@@ -1,10 +1,10 @@
locals {
# Comes from https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage.html
- # This policy allows users to view and edit their own passwords, access keys, MFA devices, X.509 certificates, SSH keys, and Git credentials.
- # In addition, users are required to set up and authenticate using MFA before performing any other operations in AWS.
- # It also means this policy does NOT allow users to reset a password while signing in to the AWS Management Console for the first time.
+ # This policy allows users to view and edit their own passwords, access keys, MFA devices, X.509 certificates, SSH keys, and Git credentials.
+ # In addition, users are required to set up and authenticate using MFA before performing any other operations in AWS.
+ # It also means this policy does NOT allow users to reset a password while signing in to the AWS Management Console for the first time.
# They must first set up their MFA because allowing users to change their password without MFA can be a security risk.
- #
+ #
# The following actions are added to the initial policy from AWS
# - iam:GetLoginProfile: allows the IAM user to view their account information on the security page.
# - iam:GetAccessKeyLastUsed: allows the IAM user to view the last time their access key was used.
@@ -120,16 +120,16 @@ locals {
]
})
- # For the bot account
+ # For the infra-service-account account
# It must be able to manage policies during terraform apply & create/delete users, permissions, etc. during terraform apply
full_iam_access_policy = jsonencode({
- version = "2012-10-17"
- statement = [
+ Version = "2012-10-17"
+ Statement = [
{
- sid = "AllowManageRoleAndPolicy"
- effect = "Allow"
- resources = ["arn:aws:iam::*"]
- actions = ["iam:*"]
+ Sid = "AllowManageRoleAndPolicy"
+ Effect = "Allow"
+ Resource = ["arn:aws:iam::*"]
+ Action = ["iam:*"]
}
]
})
diff --git a/templates/addons/aws/modules/iam_groups/main.tf b/templates/addons/aws/modules/iam_groups/main.tf
index efc7be6e..e4fc4a0b 100644
--- a/templates/addons/aws/modules/iam_groups/main.tf
+++ b/templates/addons/aws/modules/iam_groups/main.tf
@@ -4,8 +4,8 @@ resource "aws_iam_group" "admin" {
}
#tfsec:ignore:aws-iam-enforce-group-mfa
-resource "aws_iam_group" "bot" {
- name = "Bot-group"
+resource "aws_iam_group" "infra-service-account" {
+ name = "Infra-service-account-group"
}
#tfsec:ignore:aws-iam-enforce-group-mfa
@@ -30,12 +30,15 @@ resource "aws_iam_group_policy_attachment" "developer_power_user_access" {
policy_arn = data.aws_iam_policy.power_user_access.arn
}
-resource "aws_iam_group_policy_attachment" "bot_power_user_access" {
- group = aws_iam_group.bot.name
+resource "aws_iam_group_policy_attachment" "infra_service_account_power_user_access" {
+ group = aws_iam_group.infra-service-account.name
policy_arn = data.aws_iam_policy.power_user_access.arn
}
-resource "aws_iam_group_policy" "bot_full_iam_access" {
- group = aws_iam_group.bot.name
+# This IAM policy is needed for the infra-service-account account to manage IAM users & groups
+# tfsec:ignore:aws-iam-no-policy-wildcards
+resource "aws_iam_group_policy" "infra_service_account_full_iam_access" {
+ name = "AllowFullIamAccess"
+ group = aws_iam_group.infra-service-account.name
policy = local.full_iam_access_policy
}
diff --git a/templates/addons/aws/modules/iam_groups/outputs.tf b/templates/addons/aws/modules/iam_groups/outputs.tf
index 95166ff5..d851672d 100644
--- a/templates/addons/aws/modules/iam_groups/outputs.tf
+++ b/templates/addons/aws/modules/iam_groups/outputs.tf
@@ -8,7 +8,7 @@ output "developer_group" {
value = aws_iam_group.developer.name
}
-output "bot_group" {
- description = "IAM Group with bot permissions"
- value = aws_iam_group.bot.name
+output "infra_service_account_group" {
+ description = "IAM Group with infra-service-account permissions"
+ value = aws_iam_group.infra-service-account.name
}
diff --git a/templates/addons/aws/modules/vpc/main.tf b/templates/addons/aws/modules/vpc/main.tf
index f288adba..f3762043 100644
--- a/templates/addons/aws/modules/vpc/main.tf
+++ b/templates/addons/aws/modules/vpc/main.tf
@@ -15,3 +15,22 @@ module "vpc" {
one_nat_gateway_per_az = false
enable_dns_hostnames = true
}
+
+data "aws_route_tables" "private_route_table" {
+ vpc_id = module.vpc.vpc_id
+
+ filter {
+ name = "tag:Name"
+ values = ["${var.env_namespace}-vpc-private"]
+ }
+}
+
+resource "aws_vpc_endpoint" "logs" {
+ vpc_id = module.vpc.vpc_id
+ service_name = "com.amazonaws.${var.region}.logs"
+ route_table_ids = data.aws_route_tables.private_route_table.ids
+
+ tags = {
+ Name = "${var.env_namespace}-vpc-endpoint-logs"
+ }
+}
diff --git a/templates/addons/aws/modules/vpc/variables.tf b/templates/addons/aws/modules/vpc/variables.tf
index aa8b9f5f..b06ba14d 100644
--- a/templates/addons/aws/modules/vpc/variables.tf
+++ b/templates/addons/aws/modules/vpc/variables.tf
@@ -2,3 +2,8 @@ variable "env_namespace" {
description = "The namespace with environment for the VPCs, used as the prefix for the VPC names, e.g. acme-web-staging"
type = string
}
+
+variable "region" {
+ description = "AWS region"
+ type = string
+}