meshcloud / collie-hub Goto Github PK
View Code? Open in Web Editor NEWCurated hub with ready to use kit-modules for building landing zones with Collie CLI
Home Page: https://collie.cloudfoundation.org
License: Apache License 2.0
Curated hub with ready to use kit-modules for building landing zones with Collie CLI
Home Page: https://collie.cloudfoundation.org
License: Apache License 2.0
RESOURCE AUTHORIZATION MANAGEMENT is not part of a kit or buildingblock yet but for deploying tenants necessary.
This issue collects various improvements for a simple and consistent workflow to deal with assembling tenants from buildingblocks using a pure IaC workflow using collie. Common examples of building blocks needed in a stage 2 (CFMM) cloudfoundation are a tenant building block (think subscription/account/project) that enforces tags + IAM role model, a budget alert (simple) and a hub+spoke vnet (complex).
The goals for the approach we want to support with collie are
In terragrunt parlance, building blocks are "shared service modules"
A Terraform module that is designed to be standalone and applied directly. These modules are not root modules in that they are still missing the key blocks like backend and provider, but aside from that do not need any additional configuration or composition to deploy
Backplanes add what's necessary to successfully deploy a building block to a tenant in your landing zones. From the perspective of an application team, a building block provides some sort of capability to their application's cloud environment, e.g. an on-prem connected spoke VNet. This spoke VNet however is only the "tip of the iceberg". Application teams can't (and should not have to care about) all of the mechanics that make this spoke VNet work, like the hub network, WAN connection, IPAM and firewall rules.
We will call everything that makes the application-team visible part of the building block work the "backplane". The backplane always includes
We will settle for the following structure for packaging building blocks in collie-hub
kit/$platform/buildingblocks/$block/{README.md, main.tf, ...}
building block backplanes will be normal kit modules
kit/$platform/buildingblocks/$block/buildingblock/{README.md, main.tf, ...}
building block modules will be plain terraform modules
config_tf
output. This output should contain provider
and (optionally?) backend
configuration block. This is the "missing" configuration required to deploy a building block and can be injected e.g. by terragrunt or other terraform automation collie-cli must learn to ignore **/buildingblock/README.md
files when trying to parse configuration objects from the repo or learn to treat buildingblocks as its own concept
some BBs will have a very advanced backplane, e.g. the connectivity block requires the hub deployed from azure/kit/connectivity
- should we go the trouble of always defining a dedicated backplane even if we could reuse the bootstraped SPN?
Deploying building blocks to a cloud tenant becomes a simple terraform composition in a main.tf
that invokes the building blocks as plain terraform modules like
module "subscription" {
source = "github.com/likvid-bank/likvid-cloudfoundation/kit/azure/buildingblocks/subscription/buildingblock"
subscription_name = "glaskugel"
parent_management_group = "likvid-corp"
}
module "connectivity" {
source = "github.com/likvid-bank/likvid-cloudfoundation/kit/azure/buildingblocks/connectivity/buildingblock"
providers = {
azurerm.spoke = azurerm
azurerm.hub = azurerm.hub
}
location = "germanywestcentral"
hub_rg = "hub-vnet-rg"
hub_vnet = "hub-vnet"
name = "glaskugel"
address_space = ["10.1.0.0/24"]
}
Once we have deployed a building block backplane, it's very useful to ensure that this backplane can successfully deploy the building block in isolation. This can be achieved with terraform test
and terragrunt like so
dependency "buildingblock" {
config_path = "../budget-alert"
}
dependency "glaskugel" {
config_path = "../../tenants/glaskugel"
}
generate "config" {
path = "config.tf"
if_exists = "overwrite"
contents = dependency.buildingblock.outputs.config_tf
}
terraform {
source = "${get_repo_root()}//kit/azure/buildingblocks/budget-alert/buildingblock"
}
inputs = {
subscription_id = dependency.glaskugel.outputs.subscription_id
contact_emails = "[email protected], [email protected]"
}
open issues
config.tf
which works very well here, but is not similar to collie-style tenant composition (see above)Note: some of what's discussed in this issue here (especially the design principles) should end up on the collie documentation
One idea to improve the defaults made available with the organization hierarchy module is to restrict allowed Azure services and remove e.g. ExpressRoute as that is commonly in the domain of the cloud foundation team only and provided out of a hub living in the platform Management Group
adding a storage alert for the state bucket as an example storage bucket alert
terraform-azurerm-lz-vending can we learn something or copy from that approach to collie hub for the tenant (subscription) provisioning.
Comparison of the two repos on the topic of policy as code and monitoring alerts in the enterpise scale environment with collie
azure-monitor-baseline-alerts
enterprise-azure-policy-as-code
We should consider including some default queries and alerts/dashboards (via Workbooks, e.g. the "Activity Logs Insights" https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/activity-log-insights)
I have no strong opinion whether we should deploy them via TF or leave this to ClickOps/manual exploration. But I think providing one or two useful alerts as starting points would be helpful
Upstream improvements made in https://github.com/likvid-bank/likvid-cloudfoundation to collie hub
Perhaps it would be more sensible to explore the available built-in roles instead of maintaining custom roles for the CloudFoundation group. The organization hierarchy cannot deploy definition sets due to the lack of a specific role for that purpose. Azure is updating roles more rapidly than we can keep up with through manual maintenance.
Similar to #97, though I'm not sure which module should handle this (maybe organization-hierarchy). Any preferences here @florianow ?
The azuread terraform provider is planing to deprecate some attributes, see hashicorp/terraform-provider-azuread#1214
Together with the lax version constraint we place on the provider this means new collie users see these deprecation warnings.
╷
│ Warning: Deprecated attribute
│
│ on outputs.tf line 2, in output "client_id":
│ 2: value = azuread_service_principal.cloudfoundation_deploy.application_id
│
│ The attribute "application_id" is deprecated. Refer to the provider
│ documentation for details.
│
│ (and 3 more similar warnings elsewhere)
╵
╷
│ Warning: Argument is deprecated
│
│ with data.azuread_service_principal.msgraph,
│ on resources.deploy-spn.tf line 50, in data "azuread_service_principal" "msgraph":
│ 50: application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
│
│ The `application_id` property has been replaced with the `client_id`
│ property and will be removed in version 3.0 of the AzureAD provider
│
│ (and one more similar warning elsewhere)
╵
we do not have a lift and shift landingzone cfmm
The actual permission is just a resource group read, remove the comment
Let's write a motivation for why collie's workflow looks the way it does
The kit module currently collects only Subscription-level activity logs.
We should research and consider how we can add MG level activity logs as well
See e.g. https://sameeraman.github.io/blog/2021/06/20/mgauditlogs/
A new foundation level module could help us include a publishing workflow for "collie foundation docs" to deploy the generated vuepress page on GitHub pages.
This makes a lot of sense after
#109
At meshcloud we are already using this internally to publish documentation for our collie managed landing zones
The current azure bootstrap module implements a very simple deployment workflow by delegating all permissions to an cloudfoundation_tf_deploy
SPN and setting that up as the authentication for collie's platform modules (via terragrunt).
This means controlling access to the terraform state (which contains the secret for the SPN) = controlling access to who can deploy cloud foundation. This is currently done via an azure ad group (platform_engineers
group). Bootstrapping requires an "out of band" admin user.
Where this solution falls short is the following
On GCP we can use ServiceAccount impersonation for this as it lets us get rid of the credential, but Azure does not have this.
PS C:\Users\Johannes\test\0922> collie foundation docs --preview
Tip: To set a default foundation run
$ collie config set-foundation <foundation>"
? Select a foundation » f
generating docs foundation "f" ...
parsing kit modules ...
parsing kit modules DONE 70ms
parsing compliance controls ...
parsing compliance controls DONE 10ms
generating kit module documentation ...
could not find compliance control cfmm/security-and-compliance/shared-responsibility-model-alignment referenced in a compliance statement in kit\foundation\docs\README.md
generating kit module documentation DONE 20ms
generate documentation foundations\f ...
parsing platform modules foundations\f\platforms\az ...
parsing platform modules foundations\f\platforms\az DONE 22ms
generate documentation foundations\f\platforms\az ...
generate documentation foundations\f\platforms\az DONE 12810ms
generate documentation foundations\f DONE 12848ms
generating docs foundation "f" DONE 13174ms
up to date, audited 341 packages in 13s
42 packages are looking for funding
run `npm fund` for details
16 vulnerabilities (5 moderate, 11 high)
To address issues that do not require attention, run:
npm audit fix
To address all issues possible (including breaking changes), run:
npm audit fix --force
Some issues need review, and may require choosing
a different dependency.
Run `npm audit` for details.
> [email protected] docs:dev
> vuepress dev docs
warning plugin @vuepress/plugin-git has been used multiple times, only the last one will take effect
info Initializing VuePress and preparing data...
X [ERROR] [plugin vite:dep-scan] The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received 'C:\\Users\\Johannes\\test\\0922\\foundations\\f\\.docs\\docs\\.vuepress\\.temp\\internal\\node_modules\\C:UsersJohannes\test\x0...
node_modules/resolve/lib/sync.js:31:22:
31 │ var stat = fs.statSync(dir, { throwIfNoEntry: false });
╵ ^
at Object.statSync (node:fs:1706:10)
at isDirectory (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:31:23)
at loadNodeModulesSync (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:200:17)
at Function.resolveSync [as sync] (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:107:17)
at resolveFrom (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:2077:29)
at resolvePackageData (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:28954:19)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29335:15
at Array.find (<anonymous>)
at tryNodeResolve (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29334:44)
at Context.resolveId (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29166:28)
This error came from the "onResolve" callback registered here:
node_modules/vite/dist/node/chunks/dep-9c153816.js:38656:18:
38656 │ build.onResolve({
╵ ~~~~~~~~~
at setup (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:38656:19)
at handlePlugins (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:855:23)
at Object.buildOrServe (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1149:7)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:2110:17
at new Promise (<anonymous>)
at Object.build (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:2109:14)
at Object.build (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1956:51)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:38432:54
at Array.map (<anonymous>)
The plugin "vite:dep-scan" was triggered by this import
docs/.vuepress/.temp/internal/clientAppSetups.js:4:28:
4 │ ...lientAppSetup3 from 'C:\Users\Johannes\test\0922\foundations\f\.docs\docs\.vuepress\theme\plugins\mermaid\client\...
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
X [ERROR] [plugin vite:dep-scan] The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received 'C:\\Users\\Johannes\\test\\0922\\foundations\\f\\.docs\\docs\\.vuepress\\.temp\\internal\\node_modules\\C:UsersJohannes\test\x0...
node_modules/resolve/lib/sync.js:31:22:
31 │ var stat = fs.statSync(dir, { throwIfNoEntry: false });
╵ ^
at Object.statSync (node:fs:1706:10)
at isDirectory (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:31:23)
at loadNodeModulesSync (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:200:17)
at Function.resolveSync [as sync] (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\resolve\lib\sync.js:107:17)
at resolveFrom (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:2077:29)
at resolvePackageData (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:28954:19)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29335:15
at Array.find (<anonymous>)
at tryNodeResolve (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29334:44)
at Context.resolveId (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:29166:28)
This error came from the "onResolve" callback registered here:
node_modules/vite/dist/node/chunks/dep-9c153816.js:38656:18:
38656 │ build.onResolve({
╵ ~~~~~~~~~
at setup (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:38656:19)
at handlePlugins (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:855:23)
at Object.buildOrServe (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1149:7)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:2110:17
at new Promise (<anonymous>)
at Object.build (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:2109:14)
at Object.build (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1956:51)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\vite\dist\node\chunks\dep-9c153816.js:38432:54
at Array.map (<anonymous>)
The plugin "vite:dep-scan" was triggered by this import
docs/.vuepress/.temp/internal/clientAppEnhances.js:5:30:
5 │ ...entAppEnhance4 from 'C:\Users\Johannes\test\0922\foundations\f\.docs\docs\.vuepress\theme\plugins\mermaid\client\...
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error: Build failed with 2 errors:
node_modules/resolve/lib/sync.js:31:22: ERROR: [plugin: vite:dep-scan] The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received 'C:\\Users\\Johannes\\test\\0922\\foundations\\f\\.docs\\docs\\.vuepress\\.temp\\internal\\node_modules\\C:UsersJohannes\test\x0...
node_modules/resolve/lib/sync.js:31:22: ERROR: [plugin: vite:dep-scan] The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received 'C:\\Users\\Johannes\\test\\0922\\foundations\\f\\.docs\\docs\\.vuepress\\.temp\\internal\\node_modules\\C:UsersJohannes\test\x0...
at failureErrorWithLog (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1624:15)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1266:28
at runOnEndCallbacks (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1046:63)
at buildResponseToResult (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1264:7)
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:1377:14
at C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:678:9
at handleIncomingPacket (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:775:9)
at Socket.readFromStdout (C:\Users\Johannes\test\0922\foundations\f\.docs\node_modules\esbuild\lib\main.js:644:7)
at Socket.emit (node:events:514:28)
at addChunk (node:internal/streams/readable:343:12)
Unexpected error executing "(cd foundations\f\.docs && npm run docs:dev)"
Command exited with code 1
Tip: run collie with --verbose and --debug flags for more details
Privileged Identity Management is possible. Could a good fit for our high privileged cloudfoundation-engineers group.
the spoke vnet has no logs similar to those set up in the networking kit. Diagnostic setting could also be switched on. You should also check what else can be activated, e.g. for peering
We should include instructions somewhere on how to best automate documentation publishing pipelines.
likvid-bank/likvid-cloudfoundation#13 for example added a workflow using terraform state storage on Azure and building on GitHub actions. This is probably not easy to deliver as a standard module because
This is why this probably best delivered as a how-to guide in the docs
It's a good practice to enable that so we should do it by default. There's then also the question of retention etc. coming up which is more complex, not sure I'd want to force that config decision on new users. Nonetheless just keeping all versions should be a reasonable default, esp. if users later run into a situation where they need to fix an issue with state.
It would be really cool if collie missed a deployment pipeline. The kits are becoming more and more dependent on each other so that a deployment affects a kit that has not been touched.
I created a management group on the Azure side in which I work. Maybe we could use the likvid-demo account as a prod.
The guidance for the kit module could include additional details about Azure default log retention for activity logs (90 days) and "zero rate" pricing for activity log tables
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.