diff --git a/modules/aks/postgresql/buildingblock/logo.png b/modules/aks/postgresql/buildingblock/logo.png index b360079f..b7b245e0 100644 Binary files a/modules/aks/postgresql/buildingblock/logo.png and b/modules/aks/postgresql/buildingblock/logo.png differ diff --git a/modules/aks/starterkit-azuredevops/buildingblock/APP_TEAM_README.md b/modules/aks/starterkit-azuredevops/buildingblock/APP_TEAM_README.md new file mode 100644 index 00000000..b86e55dd --- /dev/null +++ b/modules/aks/starterkit-azuredevops/buildingblock/APP_TEAM_README.md @@ -0,0 +1,514 @@ +# Azure Kubernetes Service (AKS) Starter Kit - Azure DevOps + +## What is it? + +The **AKS Azure DevOps Starter Kit** provides application teams with a pre-configured Kubernetes environment integrated with Azure DevOps. It automates the creation of essential infrastructure, including an Azure DevOps project, Git repository, CI/CD pipelines, and secure Azure service connections using passwordless authentication. + +## When to use it? + +This building block is ideal for teams that: + +- Want to deploy applications on Kubernetes without manual infrastructure setup +- Use Azure DevOps for version control and CI/CD workflows +- Need separate development and production environments with different deployment processes +- Prefer secure, passwordless authentication with Workload Identity Federation (OIDC) +- Want branch-based deployment automation (main → dev, release → prod) + +## Usage Examples + +1. **Deploying a microservice**: A developer creates a complete CI/CD pipeline for a new microservice with separate dev/prod pipelines and namespaces +2. **Team onboarding**: New teams get immediate access to a fully configured Azure DevOps project with AKS integration and role-based access +3. **Multi-stage deployment**: Deploy to dev on every commit to main, deploy to prod on release branch merges with additional safeguards + +## Resources Created + +This building block automates the creation of the following resources: + +- **Azure DevOps Project**: A dedicated project for your application with role-based access control + - **Git Repository**: Initialized with Dockerfile, Kubernetes manifests, and pipeline definitions + - **Dev Pipeline**: Builds and deploys from `main` branch to development environment + - **Prod Pipeline**: Builds and deploys from `release` branch to production environment + +- **Development Project**: You, as the creator, will have Project Admin access + - **AKS Namespace**: A dedicated Kubernetes namespace for development + - **Azure Service Connection**: Connects the pipeline to Azure (auto-authorized for faster iteration) + +- **Production Project**: You, as the creator, will have Project Admin access + - **AKS Namespace**: A dedicated Kubernetes namespace for production + - **Azure Service Connection**: Connects the pipeline to Azure (manual authorization for security) + +## Shared Responsibilities + +| Responsibility | Platform Team | Application Team | +| -------------------------------------------- | ------------- | ---------------- | +| Provision and manage AKS cluster | ✅ | ❌ | +| Create Azure DevOps project | ✅ | ❌ | +| Set up CI/CD pipelines | ✅ | ❌ | +| Configure service connections | ✅ | ❌ | +| Build and scan Docker images | ✅ | ❌ | +| Manage Kubernetes namespaces (dev/prod) | ✅ | ❌ | +| Manage resources inside namespaces | ❌ | ✅ | +| Develop and maintain application source code | ❌ | ✅ | +| Maintain pipeline YAML files | ❌ | ✅ | +| Merge to release branch for prod deployments | ❌ | ✅ | + +--- + +## Getting Started + +### 1. Access Your Azure DevOps Project + +After the starter kit is deployed, you'll receive a summary with links to your Azure DevOps project. Navigate to: + +``` +https://dev.azure.com// +``` + +### 2. Clone Your Repository + +Clone the Git repository to your local machine: + +```bash +git clone https://dev.azure.com///_git/ +cd +``` + +### 3. Understand the Branch Strategy + +- **main branch**: Development work happens here + - Commits trigger the **Dev Pipeline** + - Deploys automatically to the **dev AKS namespace** + +- **release branch**: Production releases happen here + - Commits trigger the **Prod Pipeline** + - Deploys to the **prod AKS namespace** + - Requires manual service connection authorization on first run + +### 4. Make Your First Deployment + +#### Deploy to Development + +```bash +# Make changes to your code +git add . +git commit -m "My first change" +git push origin main +``` + +The Dev Pipeline will automatically: +1. Build your Docker image +2. Run security scans +3. Deploy to your dev AKS namespace +4. Make it available at `https://-dev.likvid-k8s.msh.host` + +#### Deploy to Production + +```bash +# First, ensure your main branch is stable +git checkout release +git merge main +git push origin release +``` + +The Prod Pipeline will: +1. Pause for service connection authorization (first run only) +2. Build your Docker image +3. Run security scans +4. Deploy to your prod AKS namespace +5. Make it available at `https://.likvid-k8s.msh.host` + +**First Run Authorization**: When the prod pipeline runs for the first time, it will pause and ask you to authorize the service connection. Click **View** → **Permit** to continue. + +--- + +## Repository Structure + +Your repository includes the following files: + +``` +├── azure-pipelines-dev.yml # Dev pipeline definition +├── azure-pipelines-prod.yml # Prod pipeline definition +├── Dockerfile # Container image build instructions +├── k8s/ +│ ├── deployment.yaml # Kubernetes deployment manifest +│ ├── service.yaml # Kubernetes service manifest +│ └── ingress.yaml # Kubernetes ingress manifest +└── src/ + └── [your application code] +``` + +--- + +## Pipeline Variables + +Both pipelines have the following variables pre-configured: + +| Variable | Description | Example | +|----------|-------------|---------| +| `AKS_NAMESPACE` | Your dedicated Kubernetes namespace | `myapp-dev-abc123` | +| `ENVIRONMENT` | Environment name (development or production) | `development` | +| `SERVICE_CONNECTION` | Azure service connection name | `Azure-AKS-Dev` | +| `DOMAIN_NAME` | Application subdomain | `myapp-dev` | + +You can reference these in your pipeline YAML: + +```yaml +- script: | + echo "Deploying to $(AKS_NAMESPACE)" + echo "Environment: $(ENVIRONMENT)" +``` + +--- + +## Customizing Your Pipelines + +### Modify Pipeline Steps + +Edit `azure-pipelines-dev.yml` or `azure-pipelines-prod.yml` to customize the build and deployment process: + +```yaml +trigger: + branches: + include: + - main # or 'release' for prod + +pool: + vmImage: 'ubuntu-latest' + +variables: + - name: DOCKER_REGISTRY + value: 'myregistry.azurecr.io' + +steps: + - task: Docker@2 + displayName: 'Build Docker Image' + inputs: + command: build + dockerfile: 'Dockerfile' + tags: | + $(Build.BuildId) + latest + + - task: AzureCLI@2 + displayName: 'Deploy to AKS' + inputs: + azureSubscription: $(SERVICE_CONNECTION) + scriptType: 'bash' + scriptLocation: 'inlineScript' + inlineScript: | + kubectl apply -f k8s/ --namespace=$(AKS_NAMESPACE) +``` + +### Add Environment Secrets + +Store sensitive values in Azure Key Vault and reference them in your pipeline: + +1. Go to **Pipelines** → **Library** +2. Create a **Variable Group** linked to Azure Key Vault +3. Reference in pipeline: + +```yaml +variables: + - group: my-secrets + +steps: + - script: | + echo "Database connection: $(DB_CONNECTION_STRING)" +``` + +--- + +## Monitoring Your Deployments + +### View Pipeline Runs + +Navigate to **Pipelines** in your Azure DevOps project: + +- **Dev Pipeline**: Shows all deployments to development +- **Prod Pipeline**: Shows all deployments to production + +Each run shows: +- Build logs +- Test results +- Deployment status +- Security scan results + +### Access Your Applications + +Once deployed, your applications are available at: + +- **Dev**: `https://-dev.likvid-k8s.msh.host` +- **Prod**: `https://.likvid-k8s.msh.host` + +### View AKS Namespace Resources + +Access your Kubernetes namespaces via meshStack: + +1. Navigate to your **Dev Project** or **Prod Project** +2. Click on the **AKS Tenant** +3. Use `kubectl` or the Azure portal to inspect resources + +--- + +## Security Features + +### Workload Identity Federation (Passwordless Authentication) + +Your service connections use **Workload Identity Federation (OIDC)** for authentication: + +✅ **No secrets to manage** - authentication uses short-lived tokens +✅ **Automatic token rotation** - tokens expire quickly and are refreshed automatically +✅ **Zero maintenance** - no manual credential rotation needed +✅ **Better security** - no long-lived credentials that can leak + +### Branch Policies + +The main branch has policies enforced: + +- **Minimum reviewers**: At least 1 reviewer required for PRs +- **Work item linking**: Encourages linking code changes to work items +- **No direct commits**: All changes go through pull requests + +### Manual Authorization for Production + +Production deployments require explicit authorization: + +- First time a pipeline runs, you must approve the service connection +- Prevents accidental or unauthorized deployments to production +- Can be authorized permanently for trusted pipelines + +--- + +## Team Collaboration + +### Inviting Team Members + +Add team members via meshStack: + +1. Navigate to your **Dev Project** or **Prod Project** +2. Go to **Access Management** → **Role Mapping** +3. Invite users with appropriate roles: + - **Project Admin**: Full control over the project + - **Project User**: Can view and manage resources + - **Project Reader**: Read-only access + +### Azure DevOps Roles + +Team members are automatically assigned Azure DevOps roles based on their meshStack roles: + +| meshStack Role | Azure DevOps Role | +|----------------|------------------| +| Workspace Owner | Project Administrator | +| Workspace Manager | Contributor | +| Workspace Member | Reader | + +--- + +## Best Practices + +### Branch Strategy + +**Recommended Workflow**: + +1. Create feature branches from `main` +2. Develop and test locally +3. Open PR to `main` for code review +4. Merge to `main` → triggers dev deployment +5. Test in dev environment +6. When ready for release, merge `main` to `release` → triggers prod deployment + +**Example**: + +```bash +# Create feature branch +git checkout -b feature/new-api +# ... make changes ... +git commit -m "Add new API endpoint" +git push origin feature/new-api + +# Open PR to main (via Azure DevOps UI) +# After merge, dev deployment happens automatically + +# When ready for production +git checkout release +git merge main +git push origin release +# Prod deployment happens after authorization +``` + +### Service Connection Authorization + +**Development**: +- Auto-authorized for convenience +- Faster iteration and testing + +**Production**: +- Manual authorization required on first use +- Adds security checkpoint +- Can be permanently authorized for specific pipelines after initial approval + +### Resource Management + +**Inside Your Namespace**: +- ✅ Deploy applications +- ✅ Create services, config maps, secrets +- ✅ Manage resource quotas and limits + +**Outside Your Namespace**: +- ❌ Cannot modify cluster-wide resources +- ❌ Cannot access other teams' namespaces +- ❌ Cannot change network policies + +### Cost Optimization + +- Use resource requests and limits in Kubernetes manifests +- Clean up unused resources regularly +- Monitor resource usage via meshStack project tags + +--- + +## Troubleshooting + +### Pipeline Fails: "Service connection not found" + +**Cause**: Service connection name mismatch or not authorized + +**Solution**: +1. Verify service connection name in pipeline YAML matches exactly (case-sensitive) +2. Check if manual authorization is required (go to pipeline run and click "Permit") +3. Ensure service connection exists in **Project Settings** → **Service connections** + +### Pipeline Fails: "Insufficient permissions" + +**Cause**: Service principal lacks required permissions + +**Solution**: Contact the Platform Team to verify service principal role assignment. Required roles: +- **Contributor**: For resource deployment +- **Reader**: For read-only operations + +### Service Connection Shows as Invalid + +**Cause**: Service principal or federated credential configuration issue + +**Solution**: Contact the Platform Team to verify: +- Service principal exists and is active +- Federated identity credential is configured correctly +- Azure AD application is properly set up + +### Cannot Access AKS Namespace + +**Cause**: Missing Kubernetes RBAC permissions + +**Solution**: +1. Verify you have Project Admin or Project User role in meshStack +2. Ensure the tenant (AKS namespace) is fully provisioned +3. Check with Platform Team if custom RBAC policies are in place + +### Application Not Accessible + +**Cause**: Ingress or service misconfiguration + +**Solution**: +1. Check ingress manifest for correct hostname +2. Verify service is targeting correct pods (label selectors) +3. Ensure pods are running: `kubectl get pods -n ` +4. Check ingress controller logs + +### First Production Deployment Stuck + +**Cause**: Service connection requires manual authorization + +**Solution**: This is expected behavior. Go to the pipeline run and: +1. Click **View** next to the authorization request +2. Click **Permit** to authorize the service connection +3. Pipeline will continue automatically + +--- + +## Advanced Configuration + +### Adding Stages and Environments + +Modify your pipeline to add approval gates: + +```yaml +stages: + - stage: Build + jobs: + - job: BuildJob + steps: + - script: docker build -t myapp . + + - stage: DeployDev + dependsOn: Build + jobs: + - deployment: DeployDevJob + environment: development + strategy: + runOnce: + deploy: + steps: + - script: kubectl apply -f k8s/ + + - stage: DeployProd + dependsOn: DeployDev + jobs: + - deployment: DeployProdJob + environment: production # Requires manual approval + strategy: + runOnce: + deploy: + steps: + - script: kubectl apply -f k8s/ +``` + +### Integrating with Azure Container Registry + +Update your pipeline to use ACR: + +```yaml +variables: + - name: ACR_NAME + value: 'myregistry.azurecr.io' + +steps: + - task: Docker@2 + displayName: 'Build and Push to ACR' + inputs: + command: buildAndPush + repository: 'myapp' + containerRegistry: 'Azure-ACR-Connection' + tags: | + $(Build.BuildId) +``` + +### Running Tests Before Deployment + +Add test stages to your pipeline: + +```yaml +steps: + - script: | + npm install + npm test + displayName: 'Run Unit Tests' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'JUnit' + testResultsFiles: '**/test-results.xml' +``` + +--- + +## Related Documentation + +- [Azure DevOps Pipelines](https://learn.microsoft.com/en-us/azure/devops/pipelines/) +- [Workload Identity Federation](https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure) +- [AKS Best Practices](https://learn.microsoft.com/en-us/azure/aks/best-practices) +- [Kubernetes Documentation](https://kubernetes.io/docs/home/) +- [meshStack Documentation](https://docs.meshcloud.io/) + +--- + +🎉 **Happy coding!** Your AKS Azure DevOps environment is ready for production workloads. diff --git a/modules/aks/starterkit-azuredevops/buildingblock/README.md b/modules/aks/starterkit-azuredevops/buildingblock/README.md new file mode 100644 index 00000000..6aff76ec --- /dev/null +++ b/modules/aks/starterkit-azuredevops/buildingblock/README.md @@ -0,0 +1,250 @@ +--- +name: AKS Starter Kit - Azure DevOps +supportedPlatforms: + - aks +description: Provides a complete AKS development environment with Azure DevOps project, Git repository, CI/CD pipelines, and separate dev/prod namespaces with passwordless authentication. +--- + +# AKS Starter Kit - Azure DevOps + +This building block creates a complete AKS application development environment integrated with Azure DevOps, including: + +- **Azure DevOps Project**: Dedicated project with role-based access control +- **Git Repository**: Initialized with application templates and deployment manifests +- **Dev Environment**: meshStack project + AKS namespace + service connection + pipeline +- **Prod Environment**: meshStack project + AKS namespace + service connection + pipeline +- **CI/CD Pipelines**: Automated deployments triggered by branch commits +- **Service Connections**: Passwordless authentication using Workload Identity Federation + +## Architecture + +``` +Azure DevOps Project +├── Git Repository +├── Dev Pipeline (main branch) → Dev AKS Namespace +└── Prod Pipeline (release branch) → Prod AKS Namespace +``` + +## Resources Created + +### Azure DevOps Resources +- **Project**: Container for all Azure DevOps resources +- **Repository**: Git repository with application code and manifests +- **Pipelines**: Two pipelines (dev and prod) with separate triggers + +### meshStack Resources +- **Dev Project + Tenant**: Development AKS namespace +- **Prod Project + Tenant**: Production AKS namespace +- **Service Connections**: Azure service connections for both environments +- **User Bindings**: Creator assigned as Project Admin on both projects + +## Deployment Flow + +### Development +1. Developer commits to `main` branch +2. Dev pipeline triggers automatically +3. Builds container image +4. Scans with security tools +5. Deploys to dev AKS namespace + +### Production +1. Developer creates PR from `main` to `release` +2. PR review and merge +3. Prod pipeline triggers +4. Same build and scan process +5. Requires manual authorization (first run) +6. Deploys to prod AKS namespace + +## Security Features + +- **Workload Identity Federation**: Passwordless authentication between Azure DevOps and Azure +- **Branch Policies**: Enforced code reviews on main branch +- **Manual Authorization**: Production deployments require explicit approval +- **Least Privilege**: Service principals have minimal required permissions +- **Separate Environments**: Isolated dev and prod namespaces + +## Prerequisites + +The following must be configured before using this building block: + +1. **Azure DevOps Organization**: Active organization with PAT token stored in Key Vault +2. **Service Principals**: Pre-created for dev and prod environments with appropriate role assignments +3. **AKS Landing Zones**: Configured landing zones for dev and prod +4. **Building Block Definitions**: Azure DevOps project, repository, pipeline, and service connection definitions must exist + +## Variables + +### Required Variables + +- `workspace_identifier`: meshStack workspace +- `name`: Name for projects, repository, and namespaces +- `full_platform_identifier`: AKS platform identifier +- `landing_zone_dev_identifier`: Dev AKS landing zone +- `landing_zone_prod_identifier`: Prod AKS landing zone +- `azdevops_*_definition_*_uuid`: UUIDs for all Azure DevOps building block definitions +- `azdevops_organization_name`: Azure DevOps organization name +- `creator`: Creator user information for RBAC +- `dev_azure_subscription_id`: Azure subscription for dev +- `dev_service_principal_id`: Service principal for dev +- `dev_application_object_id`: Azure AD app object ID for dev +- `prod_azure_subscription_id`: Azure subscription for prod +- `prod_service_principal_id`: Service principal for prod +- `prod_application_object_id`: Azure AD app object ID for prod +- `azure_tenant_id`: Azure AD tenant ID + +### Optional Variables + +- `project_tags_yaml`: YAML configuration for project tags (default: empty) +- `repository_init_type`: Repository initialization (Clean or Import, default: Clean) +- `enable_branch_policies`: Enable branch policies (default: true) +- `minimum_reviewers`: Minimum PR reviewers (default: 1) + +## Outputs + +- `dev_link`: URL to dev environment application +- `prod_link`: URL to prod environment application +- `azdevops_project_url`: Azure DevOps project URL +- `azdevops_repository_url`: Git repository URL +- `summary`: Detailed summary with next steps and resource links + +## Integration with Other Building Blocks + +This starter kit orchestrates multiple building blocks: + +1. **Azure DevOps Project** (`azuredevops/project`) +2. **Azure DevOps Repository** (`azuredevops/repository`) +3. **Azure DevOps Pipeline** (2x - `azuredevops/pipeline`) +4. **Azure DevOps Service Connection** (2x - `azuredevops/service-connection-subscription`) + +Parent-child relationships ensure proper dependency ordering and resource cleanup. + +## Best Practices + +### Naming Convention +The `name` variable is normalized to create consistent identifiers: +- Special characters removed +- Converted to lowercase +- Spaces/hyphens normalized +- Random suffix added to ensure uniqueness + +### Branch Strategy +- `main`: Development work, auto-deploys to dev +- `release`: Production releases, auto-deploys to prod +- Feature branches: Create from main, merge back to main + +### Service Connections +- Dev: Auto-authorized for faster development iteration +- Prod: Manual authorization for enhanced security + +### Project Tags +Use `project_tags_yaml` to apply consistent tagging across dev and prod projects for cost allocation and governance. + +## Troubleshooting + +### Pipeline Authorization Required +**Symptom**: Prod pipeline pauses asking for resource authorization + +**Solution**: This is expected on first run. Click "View" → "Permit" to authorize the service connection. + +### Service Connection Invalid +**Symptom**: Pipeline fails with authentication error + +**Solution**: Verify service principals exist and have correct role assignments. Contact platform team. + +### Repository Not Initialized +**Symptom**: Empty repository created + +**Solution**: Verify `repository_init_type` is set to "Clean" or "Import". For Import, ensure template repository is accessible. + +## Maintenance + +### Updating Pipeline YAML +Pipelines reference `azure-pipelines-dev.yml` and `azure-pipelines-prod.yml` in the repository. Modify these files to customize the CI/CD process. + +### Adding New Environments +To add staging or other environments: +1. Create new meshStack project and tenant +2. Add service connection building block +3. Add pipeline building block with appropriate branch trigger + +### Service Principal Rotation +Service principals use Workload Identity Federation (OIDC). No credential rotation is required - authentication is passwordless. + +## Related Documentation + +- [Azure DevOps Pipelines](https://learn.microsoft.com/en-us/azure/devops/pipelines/) +- [Workload Identity Federation](https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure) +- [AKS Best Practices](https://learn.microsoft.com/en-us/azure/aks/best-practices) +- [meshStack Building Blocks](https://docs.meshcloud.io/docs/meshstack.building-blocks.html) + + +## Requirements + +| Name | Version | +|------|---------| +| [meshstack](#requirement\_meshstack) | 0.15.0 | +| [random](#requirement\_random) | ~> 3.6 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [meshstack_building_block_v2.azdevops_project](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_building_block_v2.pipeline_dev](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_building_block_v2.pipeline_prod](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_building_block_v2.repository](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_building_block_v2.service_connection_dev](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_building_block_v2.service_connection_prod](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/building_block_v2) | resource | +| [meshstack_project.dev](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/project) | resource | +| [meshstack_project.prod](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/project) | resource | +| [meshstack_project_user_binding.creator_dev_admin](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/project_user_binding) | resource | +| [meshstack_project_user_binding.creator_prod_admin](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/project_user_binding) | resource | +| [meshstack_tenant_v4.dev](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/tenant_v4) | resource | +| [meshstack_tenant_v4.prod](https://registry.terraform.io/providers/meshcloud/meshstack/0.15.0/docs/resources/tenant_v4) | resource | +| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [azdevops\_organization\_name](#input\_azdevops\_organization\_name) | Azure DevOps organization name. Used only for display purposes. | `string` | n/a | yes | +| [azdevops\_pipeline\_definition\_uuid](#input\_azdevops\_pipeline\_definition\_uuid) | UUID of the Azure DevOps pipeline building block definition. | `string` | n/a | yes | +| [azdevops\_pipeline\_definition\_version\_uuid](#input\_azdevops\_pipeline\_definition\_version\_uuid) | UUID of the Azure DevOps pipeline building block definition version. | `string` | n/a | yes | +| [azdevops\_project\_definition\_uuid](#input\_azdevops\_project\_definition\_uuid) | UUID of the Azure DevOps project building block definition. | `string` | n/a | yes | +| [azdevops\_project\_definition\_version\_uuid](#input\_azdevops\_project\_definition\_version\_uuid) | UUID of the Azure DevOps project building block definition version. | `string` | n/a | yes | +| [azdevops\_repository\_definition\_uuid](#input\_azdevops\_repository\_definition\_uuid) | UUID of the Azure DevOps repository building block definition. | `string` | n/a | yes | +| [azdevops\_repository\_definition\_version\_uuid](#input\_azdevops\_repository\_definition\_version\_uuid) | UUID of the Azure DevOps repository building block definition version. | `string` | n/a | yes | +| [azdevops\_service\_connection\_definition\_uuid](#input\_azdevops\_service\_connection\_definition\_uuid) | UUID of the Azure DevOps service connection building block definition. | `string` | n/a | yes | +| [azdevops\_service\_connection\_definition\_version\_uuid](#input\_azdevops\_service\_connection\_definition\_version\_uuid) | UUID of the Azure DevOps service connection building block definition version. | `string` | n/a | yes | +| [azure\_tenant\_id](#input\_azure\_tenant\_id) | Azure AD tenant ID | `string` | n/a | yes | +| [creator](#input\_creator) | Information about the creator of the resources who will be assigned Project Admin role |
object({
type = string
identifier = string
displayName = string
username = optional(string)
email = optional(string)
euid = optional(string)
})
| n/a | yes | +| [dev\_application\_object\_id](#input\_dev\_application\_object\_id) | Azure AD application object ID for the development service principal | `string` | n/a | yes | +| [dev\_azure\_subscription\_id](#input\_dev\_azure\_subscription\_id) | Azure subscription ID for the development environment | `string` | n/a | yes | +| [dev\_service\_principal\_id](#input\_dev\_service\_principal\_id) | Service principal client ID for the development environment | `string` | n/a | yes | +| [enable\_branch\_policies](#input\_enable\_branch\_policies) | Enable branch policies for the main branch (minimum reviewers, work item linking) | `bool` | `true` | no | +| [full\_platform\_identifier](#input\_full\_platform\_identifier) | Full platform identifier of the AKS Namespace platform. | `string` | n/a | yes | +| [landing\_zone\_dev\_identifier](#input\_landing\_zone\_dev\_identifier) | AKS Landing zone identifier for the development tenant. | `string` | n/a | yes | +| [landing\_zone\_prod\_identifier](#input\_landing\_zone\_prod\_identifier) | AKS Landing zone identifier for the production tenant. | `string` | n/a | yes | +| [minimum\_reviewers](#input\_minimum\_reviewers) | Minimum number of reviewers required for pull requests | `number` | `1` | no | +| [name](#input\_name) | This name will be used for the created projects, app subdomain, Azure DevOps project and repository. | `string` | n/a | yes | +| [prod\_application\_object\_id](#input\_prod\_application\_object\_id) | Azure AD application object ID for the production service principal | `string` | n/a | yes | +| [prod\_azure\_subscription\_id](#input\_prod\_azure\_subscription\_id) | Azure subscription ID for the production environment | `string` | n/a | yes | +| [prod\_service\_principal\_id](#input\_prod\_service\_principal\_id) | Service principal client ID for the production environment | `string` | n/a | yes | +| [project\_tags\_yaml](#input\_project\_tags\_yaml) | YAML configuration for project tags that will be applied to dev and prod projects. Expected structure:
yaml
dev:
key1:
- "value1"
- "value2"
key2:
- "value3"
prod:
key1:
- "value4"
key2:
- "value5"
- "value6"
| `string` | `"dev: {}\nprod: {}\n"` | no | +| [repository\_init\_type](#input\_repository\_init\_type) | Repository initialization type (Clean or Import) | `string` | `"Clean"` | no | +| [workspace\_identifier](#input\_workspace\_identifier) | meshStack workspace identifier | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [azdevops\_project\_url](#output\_azdevops\_project\_url) | URL of the created Azure DevOps project | +| [azdevops\_repository\_url](#output\_azdevops\_repository\_url) | URL of the created Azure DevOps repository | +| [dev\_link](#output\_dev\_link) | Link to the dev environment application | +| [prod\_link](#output\_prod\_link) | Link to the prod environment application | +| [summary](#output\_summary) | Summary with next steps and insights into created resources | + \ No newline at end of file diff --git a/modules/aks/starterkit-azuredevops/buildingblock/aks-azuredevops-starterkit.tftest.hcl b/modules/aks/starterkit-azuredevops/buildingblock/aks-azuredevops-starterkit.tftest.hcl new file mode 100644 index 00000000..19536fcf --- /dev/null +++ b/modules/aks/starterkit-azuredevops/buildingblock/aks-azuredevops-starterkit.tftest.hcl @@ -0,0 +1,281 @@ +variables { + workspace_identifier = "likvid-workspace" + name = "MyApp" + full_platform_identifier = "aks.eu-de-central" + landing_zone_dev_identifier = "aks-dev-lz" + landing_zone_prod_identifier = "aks-prod-lz" + azdevops_project_definition_version_uuid = "00000000-0000-0000-0000-000000000001" + azdevops_project_definition_uuid = "00000000-0000-0000-0000-000000000002" + azdevops_repository_definition_version_uuid = "00000000-0000-0000-0000-000000000003" + azdevops_repository_definition_uuid = "00000000-0000-0000-0000-000000000004" + azdevops_pipeline_definition_version_uuid = "00000000-0000-0000-0000-000000000005" + azdevops_pipeline_definition_uuid = "00000000-0000-0000-0000-000000000006" + azdevops_service_connection_definition_version_uuid = "00000000-0000-0000-0000-000000000007" + azdevops_service_connection_definition_uuid = "00000000-0000-0000-0000-000000000008" + azdevops_organization_name = "likvid-bank" + dev_azure_subscription_id = "11111111-1111-1111-1111-111111111111" + dev_service_principal_id = "22222222-2222-2222-2222-222222222222" + dev_application_object_id = "33333333-3333-3333-3333-333333333333" + prod_azure_subscription_id = "44444444-4444-4444-4444-444444444444" + prod_service_principal_id = "55555555-5555-5555-5555-555555555555" + prod_application_object_id = "66666666-6666-6666-6666-666666666666" + azure_tenant_id = "77777777-7777-7777-7777-777777777777" + + creator = { + type = "User" + identifier = "likvid-tom-user" + displayName = "Tom Livkid" + username = "likvid-tom@meshcloud.io" + email = "likvid-tom@meshcloud.io" + euid = "likvid-tom@meshcloud.io" + } +} + +run "valid_starter_kit_creation" { + command = plan + + assert { + condition = meshstack_project.dev.metadata.name == "myapp-dev" + error_message = "Dev project name should be normalized and suffixed with -dev" + } + + assert { + condition = meshstack_project.prod.metadata.name == "myapp-prod" + error_message = "Prod project name should be normalized and suffixed with -prod" + } + + assert { + condition = meshstack_tenant_v4.dev.spec.platform_identifier == var.full_platform_identifier + error_message = "Dev tenant should use correct platform identifier" + } + + assert { + condition = meshstack_tenant_v4.prod.spec.platform_identifier == var.full_platform_identifier + error_message = "Prod tenant should use correct platform identifier" + } + + assert { + condition = meshstack_building_block_v2.azdevops_project.spec.target_ref.kind == "meshWorkspace" + error_message = "Azure DevOps project should target workspace" + } + + assert { + condition = length(meshstack_building_block_v2.repository.spec.parent_building_blocks) == 1 + error_message = "Repository should have Azure DevOps project as parent" + } + + assert { + condition = length(meshstack_building_block_v2.service_connection_dev.spec.parent_building_blocks) == 1 + error_message = "Dev service connection should have Azure DevOps project as parent" + } + + assert { + condition = length(meshstack_building_block_v2.service_connection_prod.spec.parent_building_blocks) == 1 + error_message = "Prod service connection should have Azure DevOps project as parent" + } + + assert { + condition = length(meshstack_building_block_v2.pipeline_dev.spec.parent_building_blocks) == 2 + error_message = "Dev pipeline should have repository and service connection as parents" + } + + assert { + condition = length(meshstack_building_block_v2.pipeline_prod.spec.parent_building_blocks) == 2 + error_message = "Prod pipeline should have repository and service connection as parents" + } + + assert { + condition = meshstack_building_block_v2.service_connection_dev.spec.inputs.authorize_all_pipelines.value_bool == true + error_message = "Dev service connection should auto-authorize pipelines" + } + + assert { + condition = meshstack_building_block_v2.service_connection_prod.spec.inputs.authorize_all_pipelines.value_bool == false + error_message = "Prod service connection should require manual authorization" + } +} + +run "creator_assigned_as_project_admin" { + command = plan + + variables { + creator = { + type = "User" + identifier = "likvid-daniela-user" + displayName = "Daniela Livkid" + username = "likvid-daniela@meshcloud.io" + email = "likvid-daniela@meshcloud.io" + euid = "likvid-daniela@meshcloud.io" + } + } + + assert { + condition = length(meshstack_project_user_binding.creator_dev_admin) == 1 + error_message = "Creator should be assigned as Project Admin on dev project" + } + + assert { + condition = length(meshstack_project_user_binding.creator_prod_admin) == 1 + error_message = "Creator should be assigned as Project Admin on prod project" + } + + assert { + condition = meshstack_project_user_binding.creator_dev_admin[0].role_ref.name == "Project Admin" + error_message = "Creator should have Project Admin role on dev project" + } + + assert { + condition = meshstack_project_user_binding.creator_prod_admin[0].role_ref.name == "Project Admin" + error_message = "Creator should have Project Admin role on prod project" + } + + assert { + condition = meshstack_project_user_binding.creator_dev_admin[0].subject.name == "likvid-daniela@meshcloud.io" + error_message = "Creator username should be correctly assigned" + } +} + +run "non_user_creator_skips_bindings" { + command = plan + + variables { + creator = { + type = "ServiceAccount" + identifier = "system-account" + displayName = "System Account" + } + } + + assert { + condition = length(meshstack_project_user_binding.creator_dev_admin) == 0 + error_message = "Non-user creator should not have user bindings created" + } + + assert { + condition = length(meshstack_project_user_binding.creator_prod_admin) == 0 + error_message = "Non-user creator should not have user bindings created" + } +} + +run "custom_project_tags" { + command = plan + + variables { + project_tags_yaml = <= 0 && var.minimum_reviewers <= 10 + error_message = "minimum_reviewers must be between 0 and 10" + } +} + +variable "dev_azure_subscription_id" { + type = string + description = "Azure subscription ID for the development environment" +} + +variable "dev_service_principal_id" { + type = string + description = "Service principal client ID for the development environment" +} + +variable "dev_application_object_id" { + type = string + description = "Azure AD application object ID for the development service principal" +} + +variable "prod_azure_subscription_id" { + type = string + description = "Azure subscription ID for the production environment" +} + +variable "prod_service_principal_id" { + type = string + description = "Service principal client ID for the production environment" +} + +variable "prod_application_object_id" { + type = string + description = "Azure AD application object ID for the production service principal" +} + +variable "azure_tenant_id" { + type = string + description = "Azure AD tenant ID" +} diff --git a/modules/aks/starterkit-azuredevops/buildingblock/versions.tf b/modules/aks/starterkit-azuredevops/buildingblock/versions.tf new file mode 100644 index 00000000..4f5f052c --- /dev/null +++ b/modules/aks/starterkit-azuredevops/buildingblock/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + meshstack = { + source = "meshcloud/meshstack" + version = "0.15.0" + } + random = { + source = "hashicorp/random" + version = "~> 3.6" + } + } +} diff --git a/modules/aks/starterkit/backplane/README.md b/modules/aks/starterkit-github/backplane/README.md similarity index 100% rename from modules/aks/starterkit/backplane/README.md rename to modules/aks/starterkit-github/backplane/README.md diff --git a/modules/aks/starterkit/backplane/permissions.png b/modules/aks/starterkit-github/backplane/permissions.png similarity index 100% rename from modules/aks/starterkit/backplane/permissions.png rename to modules/aks/starterkit-github/backplane/permissions.png diff --git a/modules/aks/starterkit/buildingblock/APP_TEAM_README.md b/modules/aks/starterkit-github/buildingblock/APP_TEAM_README.md similarity index 100% rename from modules/aks/starterkit/buildingblock/APP_TEAM_README.md rename to modules/aks/starterkit-github/buildingblock/APP_TEAM_README.md diff --git a/modules/aks/starterkit/buildingblock/README.md b/modules/aks/starterkit-github/buildingblock/README.md similarity index 100% rename from modules/aks/starterkit/buildingblock/README.md rename to modules/aks/starterkit-github/buildingblock/README.md diff --git a/modules/aks/starterkit-github/buildingblock/logo.png b/modules/aks/starterkit-github/buildingblock/logo.png new file mode 100644 index 00000000..d58f8ddb Binary files /dev/null and b/modules/aks/starterkit-github/buildingblock/logo.png differ diff --git a/modules/aks/starterkit/buildingblock/main.tf b/modules/aks/starterkit-github/buildingblock/main.tf similarity index 100% rename from modules/aks/starterkit/buildingblock/main.tf rename to modules/aks/starterkit-github/buildingblock/main.tf diff --git a/modules/aks/starterkit/buildingblock/outputs.tf b/modules/aks/starterkit-github/buildingblock/outputs.tf similarity index 100% rename from modules/aks/starterkit/buildingblock/outputs.tf rename to modules/aks/starterkit-github/buildingblock/outputs.tf diff --git a/modules/aks/starterkit-github/buildingblock/provider.tf b/modules/aks/starterkit-github/buildingblock/provider.tf new file mode 100644 index 00000000..c89e3966 --- /dev/null +++ b/modules/aks/starterkit-github/buildingblock/provider.tf @@ -0,0 +1 @@ +provider "meshstack" {} diff --git a/modules/aks/starterkit/buildingblock/variables.tf b/modules/aks/starterkit-github/buildingblock/variables.tf similarity index 100% rename from modules/aks/starterkit/buildingblock/variables.tf rename to modules/aks/starterkit-github/buildingblock/variables.tf diff --git a/modules/aks/starterkit/buildingblock/versions.tf b/modules/aks/starterkit-github/buildingblock/versions.tf similarity index 100% rename from modules/aks/starterkit/buildingblock/versions.tf rename to modules/aks/starterkit-github/buildingblock/versions.tf diff --git a/modules/aks/starterkit/buildingblock/logo.png b/modules/aks/starterkit/buildingblock/logo.png deleted file mode 100644 index af8490f9..00000000 Binary files a/modules/aks/starterkit/buildingblock/logo.png and /dev/null differ diff --git a/modules/aws/agentic-coding-sandbox/buildingblock/logo.png b/modules/aws/agentic-coding-sandbox/buildingblock/logo.png index 23536d50..54083ef2 100644 Binary files a/modules/aws/agentic-coding-sandbox/buildingblock/logo.png and b/modules/aws/agentic-coding-sandbox/buildingblock/logo.png differ diff --git a/modules/aws/budget-alert/buildingblock/logo.png b/modules/aws/budget-alert/buildingblock/logo.png index f33d9c5b..0bad3370 100644 Binary files a/modules/aws/budget-alert/buildingblock/logo.png and b/modules/aws/budget-alert/buildingblock/logo.png differ diff --git a/modules/aws/opt-in-region/buildingblock/logo.png b/modules/aws/opt-in-region/buildingblock/logo.png index 5551c545..b52ec8cb 100644 Binary files a/modules/aws/opt-in-region/buildingblock/logo.png and b/modules/aws/opt-in-region/buildingblock/logo.png differ diff --git a/modules/azure/azure-virtual-machine-starterkit/buildingblock/logo.png b/modules/azure/azure-virtual-machine-starterkit/buildingblock/logo.png new file mode 100644 index 00000000..73deda66 Binary files /dev/null and b/modules/azure/azure-virtual-machine-starterkit/buildingblock/logo.png differ diff --git a/modules/gcp/budget-alert/buildingblock/logo.png b/modules/gcp/budget-alert/buildingblock/logo.png index daa3961f..5378f253 100644 Binary files a/modules/gcp/budget-alert/buildingblock/logo.png and b/modules/gcp/budget-alert/buildingblock/logo.png differ