Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
09bb1b48c8 | |||
7a58f7e909 | |||
c7927f49eb | |||
00ee290f29 | |||
959edc9d00 | |||
51bdcc5fc0 |
13 changed files with 225 additions and 40 deletions
16
.forgejo/workflows/main.yaml
Normal file
16
.forgejo/workflows/main.yaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
name: 'main'
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: 'self-hosted'
|
||||
steps:
|
||||
- uses: 'actions/checkout@v4'
|
||||
- uses: "https://git.adyxax.org/adyxax/action-tofu-aws-test@1.0.0"
|
||||
with:
|
||||
aws-access-key-id: "${{ vars.AWS_ACCESS_KEY_ID }}"
|
||||
aws-access-key-secret: "${{ secrets.AWS_ACCESS_KEY_SECRET }}"
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.1.0 - 2025-04-12
|
||||
|
||||
### Added
|
||||
|
||||
- Added default value `[]` to input variable `assume_role_account_names`.
|
||||
|
||||
## 1.0.0 - 2025-04-11
|
||||
|
||||
### Added
|
||||
|
||||
- initial import
|
||||
- Initial import.
|
||||
|
|
1
infrastructure/tofu/.gitignore
vendored
Normal file
1
infrastructure/tofu/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!.terraform.lock.hcl
|
18
infrastructure/tofu/.terraform.lock.hcl
generated
Normal file
18
infrastructure/tofu/.terraform.lock.hcl
generated
Normal file
|
@ -0,0 +1,18 @@
|
|||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/adyxax/forgejo" {
|
||||
version = "1.1.0"
|
||||
constraints = "1.1.0"
|
||||
hashes = [
|
||||
"h1:xa2K1rn2OzQofizev01UBKEgq4WHo3EM5/fiPCxFL/E=",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/aws" {
|
||||
version = "6.2.0"
|
||||
constraints = "6.2.0"
|
||||
hashes = [
|
||||
"h1:UcBl0SyNxOTHOa3Ske3ClmzA7V1S7e/I4+29DLGe85A=",
|
||||
]
|
||||
}
|
34
infrastructure/tofu/main.tf
Normal file
34
infrastructure/tofu/main.tf
Normal file
|
@ -0,0 +1,34 @@
|
|||
locals {
|
||||
name = "tofu-module-aws-iam-user"
|
||||
}
|
||||
|
||||
module "aws_iam_ci_user" {
|
||||
providers = {
|
||||
aws.core = aws.all["core"]
|
||||
aws.root = aws.all["root"]
|
||||
aws.tests = aws.all["tests"]
|
||||
}
|
||||
source = "git::ssh://git@git.adyxax.org/adyxax/tofu-module-aws-iam-ci-user?depth=1&ref=1.1.0"
|
||||
|
||||
forgejo_repository = {
|
||||
name = local.name
|
||||
owner = "adyxax"
|
||||
}
|
||||
name = local.name
|
||||
tests_policy_statements = jsonencode([
|
||||
{
|
||||
Action = "iam:*"
|
||||
Effect = "Allow"
|
||||
Resource = [
|
||||
"arn:aws:iam::*:user/tftest-user",
|
||||
"arn:aws:iam::*:policy/${local.name}-tftest",
|
||||
]
|
||||
},
|
||||
{
|
||||
# Necessary for removing an IAM user
|
||||
Action = "iam:ListVirtualMFADevices",
|
||||
Effect = "Allow"
|
||||
Resource = "*"
|
||||
}
|
||||
])
|
||||
}
|
32
infrastructure/tofu/providers.tf
Normal file
32
infrastructure/tofu/providers.tf
Normal file
|
@ -0,0 +1,32 @@
|
|||
terraform {
|
||||
backend "s3" {
|
||||
bucket = "adyxax-tofu-states"
|
||||
dynamodb_table = "tofu-states"
|
||||
key = "repositories/${local.name}"
|
||||
profile = "core"
|
||||
region = "eu-west-3"
|
||||
}
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "6.2.0"
|
||||
}
|
||||
forgejo = {
|
||||
source = "adyxax/forgejo"
|
||||
version = "1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
for_each = toset(["core", "root", "tests"])
|
||||
|
||||
alias = "all"
|
||||
default_tags { tags = { "managed-by" = "tofu" } }
|
||||
profile = each.key
|
||||
region = "eu-west-3"
|
||||
}
|
||||
|
||||
provider "forgejo" {
|
||||
base_uri = "https://git.adyxax.org/"
|
||||
}
|
83
main.tf
83
main.tf
|
@ -1,9 +1,10 @@
|
|||
data "aws_organizations_organization" "main" {}
|
||||
|
||||
locals {
|
||||
aws_account_ids = { for info in data.aws_organizations_organization.main.accounts :
|
||||
aws_account_ids = length(var.assume_role_account_names) > 0 ? {
|
||||
for info in data.aws_organizations_organization.main.accounts :
|
||||
info.name => info.id
|
||||
}
|
||||
} : {}
|
||||
}
|
||||
|
||||
resource "aws_iam_user" "main" {
|
||||
|
@ -14,43 +15,47 @@ resource "aws_iam_user" "main" {
|
|||
resource "aws_iam_user_policy" "main" {
|
||||
name = var.name
|
||||
policy = jsonencode({
|
||||
Statement = concat([
|
||||
{ # Assume roles in AWS sub-accounts
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Resource = [for name in var.assume_role_account_names :
|
||||
format(
|
||||
"arn:aws:iam::%s:role/%s",
|
||||
local.aws_account_ids[name],
|
||||
var.name,
|
||||
)
|
||||
]
|
||||
},
|
||||
{
|
||||
Action = [
|
||||
# Manage the user's own IAM access key
|
||||
"iam:CreateAccessKey",
|
||||
"iam:DeleteAccessKey",
|
||||
"iam:UpdateAccessKey",
|
||||
# Read only access to the user's IAM object
|
||||
"iam:Get*",
|
||||
"iam:List*",
|
||||
]
|
||||
Effect = "Allow"
|
||||
Resource = aws_iam_user.main.arn
|
||||
},
|
||||
{
|
||||
Action = [
|
||||
# Necessary for removing an IAM user
|
||||
"iam:ListVirtualMFADevices",
|
||||
# Describe and list the organization accounts
|
||||
"organizations:DescribeOrganization",
|
||||
"organizations:List*",
|
||||
]
|
||||
Effect = "Allow"
|
||||
Resource = "*"
|
||||
},
|
||||
])
|
||||
Statement = concat(
|
||||
length(var.assume_role_account_names) > 0 ? [
|
||||
{ # Assume roles in AWS sub-accounts
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Resource = [for name in var.assume_role_account_names :
|
||||
format(
|
||||
"arn:aws:iam::%s:role/%s",
|
||||
local.aws_account_ids[name],
|
||||
var.name,
|
||||
)
|
||||
]
|
||||
}
|
||||
] : [],
|
||||
[
|
||||
{
|
||||
Action = [
|
||||
# Manage the user's own IAM access key
|
||||
"iam:CreateAccessKey",
|
||||
"iam:DeleteAccessKey",
|
||||
"iam:UpdateAccessKey",
|
||||
# Read only access to the user's IAM object
|
||||
"iam:Get*",
|
||||
"iam:List*",
|
||||
]
|
||||
Effect = "Allow"
|
||||
Resource = aws_iam_user.main.arn
|
||||
},
|
||||
{
|
||||
Action = [
|
||||
# Necessary for removing an IAM user
|
||||
"iam:ListVirtualMFADevices",
|
||||
# Describe and list the organization accounts
|
||||
"organizations:DescribeOrganization",
|
||||
"organizations:List*",
|
||||
]
|
||||
Effect = "Allow"
|
||||
Resource = "*"
|
||||
},
|
||||
]
|
||||
)
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
user = aws_iam_user.main.name
|
||||
|
|
14
main.tftest.hcl
Normal file
14
main.tftest.hcl
Normal file
|
@ -0,0 +1,14 @@
|
|||
provider "aws" {
|
||||
profile = "tests"
|
||||
region = "eu-west-3"
|
||||
}
|
||||
|
||||
run "main" {
|
||||
assert {
|
||||
condition = data.external.main.result.Arn == local.expected_arn
|
||||
error_message = "user ARN mismatch"
|
||||
}
|
||||
module {
|
||||
source = "./test"
|
||||
}
|
||||
}
|
4
test/aws_config.tftpl
Normal file
4
test/aws_config.tftpl
Normal file
|
@ -0,0 +1,4 @@
|
|||
[default]
|
||||
aws_access_key_id = ${aws_access_key_id}
|
||||
aws_secret_access_key = ${aws_access_key_secret}
|
||||
region = eu-west-3
|
31
test/main.tf
Normal file
31
test/main.tf
Normal file
|
@ -0,0 +1,31 @@
|
|||
module "main" {
|
||||
source = "../"
|
||||
|
||||
name = "tftest-user"
|
||||
}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
# tflint-ignore: terraform_unused_declarations
|
||||
data "external" "main" {
|
||||
program = ["${path.module}/test.sh"]
|
||||
|
||||
depends_on = [local_file.aws_config]
|
||||
}
|
||||
|
||||
locals {
|
||||
# tflint-ignore: terraform_unused_declarations
|
||||
expected_arn = format(
|
||||
"arn:aws:iam::%s:user/tftest-user",
|
||||
data.aws_caller_identity.current.account_id,
|
||||
)
|
||||
}
|
||||
|
||||
resource "local_file" "aws_config" {
|
||||
filename = "${path.module}/aws_config"
|
||||
file_permission = "0600"
|
||||
content = templatefile("${path.module}/aws_config.tftpl", {
|
||||
aws_access_key_id = module.main.access_key_id
|
||||
aws_access_key_secret = module.main.access_key_secret
|
||||
})
|
||||
}
|
15
test/providers.tf
Normal file
15
test/providers.tf
Normal file
|
@ -0,0 +1,15 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
}
|
||||
external = {
|
||||
source = "hashicorp/external"
|
||||
version = "2.3.4"
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = "2.5.2"
|
||||
}
|
||||
}
|
||||
}
|
8
test/test.sh
Executable file
8
test/test.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Wait a bit for the ACCESS KEY to be usable on AWS
|
||||
sleep 10
|
||||
|
||||
export AWS_CONFIG_FILE="${PWD}/test/aws_config"
|
||||
aws sts get-caller-identity
|
|
@ -1,4 +1,5 @@
|
|||
variable "assume_role_account_names" {
|
||||
default = []
|
||||
description = "The names of the AWS sub-accounts this IAM user can assume roles in."
|
||||
nullable = false
|
||||
type = list(string)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue